This commit is contained in:
zpc 2026-02-22 23:18:37 +08:00
parent 423b60749a
commit 60132f9ab9
67 changed files with 1623 additions and 70 deletions

View File

@ -933,4 +933,198 @@ public class AssessmentController : BusinessControllerBase
}
#endregion
#region
/// <summary>
/// 获取评分标准列表
/// </summary>
/// <param name="request">查询参数</param>
/// <returns>分页评分标准列表</returns>
[HttpGet("scoreOption/getList")]
[BusinessPermission("assessment:view")]
public async Task<IActionResult> GetScoreOptionList([FromQuery] ScoreOptionQueryRequest request)
{
try
{
var result = await _assessmentService.GetScoreOptionListAsync(request);
return Ok(result);
}
catch (Exception)
{
return Error(ErrorCodes.SystemError, "获取评分标准列表失败");
}
}
/// <summary>
/// 获取评分标准详情
/// </summary>
/// <param name="id">评分标准ID</param>
/// <returns>评分标准详情</returns>
[HttpGet("scoreOption/getDetail")]
[BusinessPermission("assessment:view")]
public async Task<IActionResult> GetScoreOptionDetail([FromQuery] long id)
{
if (id <= 0)
{
return ValidationError("评分标准ID无效");
}
try
{
var result = await _assessmentService.GetScoreOptionByIdAsync(id);
return Ok(result);
}
catch (BusinessException ex)
{
return Error(ex.Code, ex.Message);
}
catch (Exception)
{
return Error(ErrorCodes.SystemError, "获取评分标准详情失败");
}
}
/// <summary>
/// 创建评分标准
/// </summary>
/// <param name="request">创建请求</param>
/// <returns>新创建的评分标准ID</returns>
[HttpPost("scoreOption/create")]
[BusinessPermission("assessment:create")]
public async Task<IActionResult> CreateScoreOption([FromBody] CreateScoreOptionRequest request)
{
if (request.AssessmentTypeId <= 0)
{
return ValidationError("请选择测评类型");
}
if (request.Score < 1 || request.Score > 10)
{
return ValidationError("分值必须在1-10之间");
}
if (string.IsNullOrWhiteSpace(request.Label))
{
return ValidationError("等级标签不能为空");
}
try
{
var id = await _assessmentService.CreateScoreOptionAsync(request);
return Ok(id);
}
catch (BusinessException ex)
{
return Error(ex.Code, ex.Message);
}
catch (Exception)
{
return Error(ErrorCodes.SystemError, "创建评分标准失败");
}
}
/// <summary>
/// 更新评分标准
/// </summary>
/// <param name="request">更新请求</param>
/// <returns>更新结果</returns>
[HttpPost("scoreOption/update")]
[BusinessPermission("assessment:update")]
public async Task<IActionResult> UpdateScoreOption([FromBody] UpdateScoreOptionRequest request)
{
if (request.Id <= 0)
{
return ValidationError("评分标准ID无效");
}
if (request.AssessmentTypeId <= 0)
{
return ValidationError("请选择测评类型");
}
if (request.Score < 1 || request.Score > 10)
{
return ValidationError("分值必须在1-10之间");
}
if (string.IsNullOrWhiteSpace(request.Label))
{
return ValidationError("等级标签不能为空");
}
try
{
var result = await _assessmentService.UpdateScoreOptionAsync(request);
return Ok(result);
}
catch (BusinessException ex)
{
return Error(ex.Code, ex.Message);
}
catch (Exception)
{
return Error(ErrorCodes.SystemError, "更新评分标准失败");
}
}
/// <summary>
/// 删除评分标准(软删除)
/// </summary>
/// <param name="request">删除请求</param>
/// <returns>删除结果</returns>
[HttpPost("scoreOption/delete")]
[BusinessPermission("assessment:delete")]
public async Task<IActionResult> DeleteScoreOption([FromBody] DeleteRequest request)
{
if (request.Id <= 0)
{
return ValidationError("评分标准ID无效");
}
try
{
var result = await _assessmentService.DeleteScoreOptionAsync(request.Id);
return Ok(result);
}
catch (BusinessException ex)
{
return Error(ex.Code, ex.Message);
}
catch (Exception)
{
return Error(ErrorCodes.SystemError, "删除评分标准失败");
}
}
/// <summary>
/// 更新评分标准状态
/// </summary>
/// <param name="request">状态更新请求</param>
/// <returns>更新结果</returns>
[HttpPost("scoreOption/updateStatus")]
[BusinessPermission("assessment:update")]
public async Task<IActionResult> UpdateScoreOptionStatus([FromBody] UpdateStatusRequest request)
{
if (request.Id <= 0)
{
return ValidationError("评分标准ID无效");
}
try
{
var result = await _assessmentService.UpdateScoreOptionStatusAsync(request.Id, request.Status);
return Ok(result);
}
catch (BusinessException ex)
{
return Error(ex.Code, ex.Message);
}
catch (Exception)
{
return Error(ErrorCodes.SystemError, "更新评分标准状态失败");
}
}
#endregion
}

View File

@ -43,6 +43,11 @@ public class AdminBusinessDbContext : DbContext
/// </summary>
public DbSet<AssessmentType> AssessmentTypes { get; set; } = null!;
/// <summary>
/// 评分标准选项表
/// </summary>
public DbSet<ScoreOption> ScoreOptions { get; set; } = null!;
/// <summary>
/// 题目表
/// </summary>
@ -204,6 +209,18 @@ public class AdminBusinessDbContext : DbContext
.HasColumnType("decimal(10,2)");
});
// =============================================
// ScoreOption 配置
// =============================================
modelBuilder.Entity<ScoreOption>(entity =>
{
// (AssessmentTypeId, Score) 复合唯一索引(排除软删除)
entity.HasIndex(e => new { e.AssessmentTypeId, e.Score })
.IsUnique()
.HasDatabaseName("UK_score_options_type_score")
.HasFilter("[IsDeleted] = 0");
});
// =============================================
// Question 配置
// =============================================

View File

@ -0,0 +1,73 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace MiAssessment.Admin.Business.Entities;
/// <summary>
/// 评分标准选项表
/// </summary>
[Table("score_options")]
public class ScoreOption
{
/// <summary>
/// 主键ID
/// </summary>
[Key]
public long Id { get; set; }
/// <summary>
/// 测评类型ID
/// </summary>
public long AssessmentTypeId { get; set; }
/// <summary>
/// 分值1-10
/// </summary>
public int Score { get; set; }
/// <summary>
/// 等级标签(如:极弱、很弱)
/// </summary>
[Required]
[MaxLength(20)]
public string Label { get; set; } = null!;
/// <summary>
/// 描述(如:完全不符合)
/// </summary>
[Required]
[MaxLength(100)]
public string Description { get; set; } = null!;
/// <summary>
/// 排序
/// </summary>
public int Sort { get; set; }
/// <summary>
/// 状态0禁用 1启用
/// </summary>
public int Status { get; set; } = 1;
/// <summary>
/// 创建时间
/// </summary>
public DateTime CreateTime { get; set; }
/// <summary>
/// 更新时间
/// </summary>
public DateTime UpdateTime { get; set; }
/// <summary>
/// 软删除标记
/// </summary>
public bool IsDeleted { get; set; }
/// <summary>
/// 关联的测评类型
/// </summary>
[ForeignKey(nameof(AssessmentTypeId))]
public virtual AssessmentType? AssessmentType { get; set; }
}

View File

@ -0,0 +1,37 @@
namespace MiAssessment.Admin.Business.Models.Assessment;
/// <summary>
/// 创建评分标准请求
/// </summary>
public class CreateScoreOptionRequest
{
/// <summary>
/// 测评类型ID
/// </summary>
public long AssessmentTypeId { get; set; }
/// <summary>
/// 分值1-10
/// </summary>
public int Score { get; set; }
/// <summary>
/// 等级标签
/// </summary>
public string Label { get; set; } = string.Empty;
/// <summary>
/// 描述
/// </summary>
public string Description { get; set; } = string.Empty;
/// <summary>
/// 排序
/// </summary>
public int Sort { get; set; }
/// <summary>
/// 状态0禁用 1启用
/// </summary>
public int Status { get; set; } = 1;
}

View File

@ -0,0 +1,57 @@
namespace MiAssessment.Admin.Business.Models.Assessment;
/// <summary>
/// 评分标准选项 DTO
/// </summary>
public class ScoreOptionDto
{
/// <summary>
/// 主键ID
/// </summary>
public long Id { get; set; }
/// <summary>
/// 测评类型ID
/// </summary>
public long AssessmentTypeId { get; set; }
/// <summary>
/// 测评类型名称
/// </summary>
public string AssessmentTypeName { get; set; } = string.Empty;
/// <summary>
/// 分值
/// </summary>
public int Score { get; set; }
/// <summary>
/// 等级标签
/// </summary>
public string Label { get; set; } = string.Empty;
/// <summary>
/// 描述
/// </summary>
public string Description { get; set; } = string.Empty;
/// <summary>
/// 排序
/// </summary>
public int Sort { get; set; }
/// <summary>
/// 状态0禁用 1启用
/// </summary>
public int Status { get; set; }
/// <summary>
/// 状态名称
/// </summary>
public string StatusName { get; set; } = string.Empty;
/// <summary>
/// 创建时间
/// </summary>
public DateTime CreateTime { get; set; }
}

View File

@ -0,0 +1,17 @@
namespace MiAssessment.Admin.Business.Models.Assessment;
/// <summary>
/// 评分标准查询请求
/// </summary>
public class ScoreOptionQueryRequest : PagedRequest
{
/// <summary>
/// 测评类型ID
/// </summary>
public long? AssessmentTypeId { get; set; }
/// <summary>
/// 状态0禁用 1启用
/// </summary>
public int? Status { get; set; }
}

View File

@ -0,0 +1,42 @@
namespace MiAssessment.Admin.Business.Models.Assessment;
/// <summary>
/// 更新评分标准请求
/// </summary>
public class UpdateScoreOptionRequest
{
/// <summary>
/// 评分标准ID
/// </summary>
public long Id { get; set; }
/// <summary>
/// 测评类型ID
/// </summary>
public long AssessmentTypeId { get; set; }
/// <summary>
/// 分值1-10
/// </summary>
public int Score { get; set; }
/// <summary>
/// 等级标签
/// </summary>
public string Label { get; set; } = string.Empty;
/// <summary>
/// 描述
/// </summary>
public string Description { get; set; } = string.Empty;
/// <summary>
/// 排序
/// </summary>
public int Sort { get; set; }
/// <summary>
/// 状态0禁用 1启用
/// </summary>
public int Status { get; set; }
}

View File

@ -143,6 +143,16 @@ public static class ErrorCodes
/// </summary>
public const int ConclusionNotFound = 3231;
/// <summary>
/// 评分标准不存在
/// </summary>
public const int ScoreOptionNotFound = 3251;
/// <summary>
/// 评分标准分值已存在
/// </summary>
public const int ScoreOptionScoreExists = 3252;
/// <summary>
/// 测评记录不存在
/// </summary>

View File

@ -1466,4 +1466,189 @@ public class AssessmentService : IAssessmentService
}
#endregion
#region
/// <inheritdoc />
public async Task<PagedResult<ScoreOptionDto>> GetScoreOptionListAsync(ScoreOptionQueryRequest request)
{
var query = _dbContext.ScoreOptions
.AsNoTracking()
.Where(s => !s.IsDeleted);
// 按测评类型筛选
if (request.AssessmentTypeId.HasValue)
{
query = query.Where(s => s.AssessmentTypeId == request.AssessmentTypeId.Value);
}
// 按状态筛选
if (request.Status.HasValue)
{
query = query.Where(s => s.Status == request.Status.Value);
}
var total = await query.CountAsync();
var items = await query
.OrderBy(s => s.AssessmentTypeId)
.ThenBy(s => s.Sort)
.ThenBy(s => s.Score)
.Skip(request.Skip)
.Take(request.PageSize)
.Select(s => new ScoreOptionDto
{
Id = s.Id,
AssessmentTypeId = s.AssessmentTypeId,
AssessmentTypeName = s.AssessmentType != null ? s.AssessmentType.Name : "",
Score = s.Score,
Label = s.Label,
Description = s.Description,
Sort = s.Sort,
Status = s.Status,
StatusName = s.Status == 1 ? "启用" : "禁用",
CreateTime = s.CreateTime
})
.ToListAsync();
return new PagedResult<ScoreOptionDto>(items, total, request.Page, request.PageSize);
}
/// <inheritdoc />
public async Task<ScoreOptionDto> GetScoreOptionByIdAsync(long id)
{
var entity = await _dbContext.ScoreOptions
.AsNoTracking()
.Include(s => s.AssessmentType)
.FirstOrDefaultAsync(s => s.Id == id && !s.IsDeleted);
if (entity == null)
{
throw new BusinessException(ErrorCodes.ScoreOptionNotFound, "评分标准不存在");
}
return new ScoreOptionDto
{
Id = entity.Id,
AssessmentTypeId = entity.AssessmentTypeId,
AssessmentTypeName = entity.AssessmentType?.Name ?? "",
Score = entity.Score,
Label = entity.Label,
Description = entity.Description,
Sort = entity.Sort,
Status = entity.Status,
StatusName = entity.Status == 1 ? "启用" : "禁用",
CreateTime = entity.CreateTime
};
}
/// <inheritdoc />
public async Task<long> CreateScoreOptionAsync(CreateScoreOptionRequest request)
{
// 检查测评类型是否存在
var typeExists = await _dbContext.AssessmentTypes
.AnyAsync(t => t.Id == request.AssessmentTypeId && !t.IsDeleted);
if (!typeExists)
{
throw new BusinessException(ErrorCodes.AssessmentTypeNotFound, "测评类型不存在");
}
// 检查同一测评类型下分值是否重复
var scoreExists = await _dbContext.ScoreOptions
.AnyAsync(s => s.AssessmentTypeId == request.AssessmentTypeId
&& s.Score == request.Score && !s.IsDeleted);
if (scoreExists)
{
throw new BusinessException(ErrorCodes.ScoreOptionScoreExists, "该测评类型下此分值已存在");
}
var entity = new ScoreOption
{
AssessmentTypeId = request.AssessmentTypeId,
Score = request.Score,
Label = request.Label,
Description = request.Description,
Sort = request.Sort,
Status = request.Status,
CreateTime = DateTime.Now,
UpdateTime = DateTime.Now
};
_dbContext.ScoreOptions.Add(entity);
await _dbContext.SaveChangesAsync();
_logger.LogInformation("创建评分标准成功Id: {Id}, Score: {Score}", entity.Id, entity.Score);
return entity.Id;
}
/// <inheritdoc />
public async Task<bool> UpdateScoreOptionAsync(UpdateScoreOptionRequest request)
{
var entity = await _dbContext.ScoreOptions
.FirstOrDefaultAsync(s => s.Id == request.Id && !s.IsDeleted);
if (entity == null)
{
throw new BusinessException(ErrorCodes.ScoreOptionNotFound, "评分标准不存在");
}
// 检查同一测评类型下分值是否重复(排除自身)
var scoreExists = await _dbContext.ScoreOptions
.AnyAsync(s => s.AssessmentTypeId == request.AssessmentTypeId
&& s.Score == request.Score && s.Id != request.Id && !s.IsDeleted);
if (scoreExists)
{
throw new BusinessException(ErrorCodes.ScoreOptionScoreExists, "该测评类型下此分值已存在");
}
entity.AssessmentTypeId = request.AssessmentTypeId;
entity.Score = request.Score;
entity.Label = request.Label;
entity.Description = request.Description;
entity.Sort = request.Sort;
entity.Status = request.Status;
entity.UpdateTime = DateTime.Now;
await _dbContext.SaveChangesAsync();
_logger.LogInformation("更新评分标准成功Id: {Id}", entity.Id);
return true;
}
/// <inheritdoc />
public async Task<bool> DeleteScoreOptionAsync(long id)
{
var entity = await _dbContext.ScoreOptions
.FirstOrDefaultAsync(s => s.Id == id && !s.IsDeleted);
if (entity == null)
{
throw new BusinessException(ErrorCodes.ScoreOptionNotFound, "评分标准不存在");
}
entity.IsDeleted = true;
entity.UpdateTime = DateTime.Now;
await _dbContext.SaveChangesAsync();
_logger.LogInformation("删除评分标准成功Id: {Id}", id);
return true;
}
/// <inheritdoc />
public async Task<bool> UpdateScoreOptionStatusAsync(long id, int status)
{
var entity = await _dbContext.ScoreOptions
.FirstOrDefaultAsync(s => s.Id == id && !s.IsDeleted);
if (entity == null)
{
throw new BusinessException(ErrorCodes.ScoreOptionNotFound, "评分标准不存在");
}
entity.Status = status;
entity.UpdateTime = DateTime.Now;
await _dbContext.SaveChangesAsync();
_logger.LogInformation("更新评分标准状态成功Id: {Id}, Status: {Status}", id, status);
return true;
}
#endregion
}

View File

@ -236,4 +236,51 @@ public interface IAssessmentService
Task<bool> DeleteConclusionAsync(long id);
#endregion
#region
/// <summary>
/// 获取评分标准列表
/// </summary>
/// <param name="request">查询参数</param>
/// <returns>分页评分标准列表</returns>
Task<PagedResult<ScoreOptionDto>> GetScoreOptionListAsync(ScoreOptionQueryRequest request);
/// <summary>
/// 根据ID获取评分标准
/// </summary>
/// <param name="id">评分标准ID</param>
/// <returns>评分标准信息</returns>
Task<ScoreOptionDto> GetScoreOptionByIdAsync(long id);
/// <summary>
/// 创建评分标准
/// </summary>
/// <param name="request">创建请求</param>
/// <returns>新创建的评分标准ID</returns>
Task<long> CreateScoreOptionAsync(CreateScoreOptionRequest request);
/// <summary>
/// 更新评分标准
/// </summary>
/// <param name="request">更新请求</param>
/// <returns>是否更新成功</returns>
Task<bool> UpdateScoreOptionAsync(UpdateScoreOptionRequest request);
/// <summary>
/// 删除评分标准(软删除)
/// </summary>
/// <param name="id">评分标准ID</param>
/// <returns>是否删除成功</returns>
Task<bool> DeleteScoreOptionAsync(long id);
/// <summary>
/// 更新评分标准状态
/// </summary>
/// <param name="id">评分标准ID</param>
/// <param name="status">状态值0禁用 1启用</param>
/// <returns>是否更新成功</returns>
Task<bool> UpdateScoreOptionStatusAsync(long id, int status);
#endregion
}

View File

@ -593,3 +593,147 @@ export function deleteConclusion(id: number): Promise<ApiResponse<boolean>> {
data: { id }
})
}
// ==================== ScoreOption 类型定义 ====================
/**
*
*/
export interface ScoreOptionItem {
/** 评分标准ID */
id: number
/** 测评类型ID */
assessmentTypeId: number
/** 测评类型名称 */
assessmentTypeName: string
/** 分值 */
score: number
/** 等级标签 */
label: string
/** 描述 */
description: string
/** 排序值 */
sort: number
/** 状态 (0: 禁用, 1: 启用) */
status: number
/** 状态名称 */
statusName: string
/** 创建时间 */
createTime: string
}
/**
*
*/
export interface ScoreOptionQuery extends PagedRequest {
/** 测评类型ID */
assessmentTypeId?: number
/** 状态筛选 */
status?: number
}
/**
*
*/
export interface CreateScoreOptionRequest {
/** 测评类型ID */
assessmentTypeId: number
/** 分值1-10 */
score: number
/** 等级标签 */
label: string
/** 描述 */
description: string
/** 排序值 */
sort: number
/** 状态 */
status: number
}
/**
*
*/
export interface UpdateScoreOptionRequest extends CreateScoreOptionRequest {
/** 评分标准ID */
id: number
}
// ==================== ScoreOption API ====================
/**
*
* @param params
* @returns
*/
export function getScoreOptionList(params: ScoreOptionQuery): Promise<ApiResponse<PagedResult<ScoreOptionItem>>> {
return request<PagedResult<ScoreOptionItem>>({
url: '/admin/assessment/scoreOption/getList',
method: 'get',
params
})
}
/**
*
* @param id ID
* @returns
*/
export function getScoreOptionDetail(id: number): Promise<ApiResponse<ScoreOptionItem>> {
return request<ScoreOptionItem>({
url: '/admin/assessment/scoreOption/getDetail',
method: 'get',
params: { id }
})
}
/**
*
* @param data
* @returns ID
*/
export function createScoreOption(data: CreateScoreOptionRequest): Promise<ApiResponse<number>> {
return request<number>({
url: '/admin/assessment/scoreOption/create',
method: 'post',
data
})
}
/**
*
* @param data
* @returns
*/
export function updateScoreOption(data: UpdateScoreOptionRequest): Promise<ApiResponse<boolean>> {
return request<boolean>({
url: '/admin/assessment/scoreOption/update',
method: 'post',
data
})
}
/**
*
* @param id ID
* @returns
*/
export function deleteScoreOption(id: number): Promise<ApiResponse<boolean>> {
return request<boolean>({
url: '/admin/assessment/scoreOption/delete',
method: 'post',
data: { id }
})
}
/**
*
* @param data
* @returns
*/
export function updateScoreOptionStatus(data: UpdateStatusRequest): Promise<ApiResponse<boolean>> {
return request<boolean>({
url: '/admin/assessment/scoreOption/updateStatus',
method: 'post',
data
})
}

View File

@ -106,6 +106,12 @@ export const businessRoutes: RouteRecordRaw[] = [
name: 'Conclusion',
component: () => import('@/views/business/assessment/conclusion/index.vue'),
meta: { title: '报告结论', permission: 'conclusion:view', keepAlive: true }
},
{
path: 'scoreOption',
name: 'ScoreOption',
component: () => import('@/views/business/assessment/scoreOption/index.vue'),
meta: { title: '评分标准', permission: 'assessment:view', keepAlive: true }
}
]
},

View File

@ -0,0 +1,524 @@
<template>
<div class="score-option-container">
<!-- 页面标题和操作栏 -->
<el-card class="page-header">
<div class="header-content">
<div class="header-left">
<h2 class="page-title">评分标准管理</h2>
<span class="page-description">管理测评评分标准选项配置各分值对应的等级标签和描述</span>
</div>
<div class="header-right">
<el-button type="primary" @click="handleAdd">
<el-icon><Plus /></el-icon>
新增评分标准
</el-button>
</div>
</div>
</el-card>
<!-- 搜索表单 -->
<el-card class="search-card">
<el-form :model="queryParams" inline>
<el-form-item label="测评类型">
<el-select
v-model="queryParams.assessmentTypeId"
placeholder="请选择测评类型"
clearable
style="width: 200px;"
@change="handleSearch"
>
<el-option
v-for="item in state.assessmentTypes"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="状态">
<DictSelect
v-model="queryParams.status"
type="common_status"
placeholder="请选择状态"
clearable
/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSearch">
<el-icon><Search /></el-icon>
搜索
</el-button>
<el-button @click="handleReset">
<el-icon><Refresh /></el-icon>
重置
</el-button>
</el-form-item>
</el-form>
</el-card>
<!-- 数据表格 -->
<el-card v-loading="state.loading" class="table-card">
<el-table :data="state.tableData" row-key="id" stripe>
<el-table-column prop="score" label="分值" width="80" align="center" />
<el-table-column prop="label" label="等级标签" width="120" />
<el-table-column prop="description" label="描述" min-width="200" show-overflow-tooltip />
<el-table-column prop="assessmentTypeName" label="测评类型" width="150" show-overflow-tooltip />
<el-table-column prop="sort" label="排序" width="80" align="center" />
<el-table-column label="状态" width="100" align="center">
<template #default="{ row }">
<el-switch
:model-value="row.status === 1"
@change="(val: boolean) => handleStatusChange(row, val)"
/>
</template>
</el-table-column>
<el-table-column prop="createTime" label="创建时间" width="170" />
<el-table-column label="操作" width="150" fixed="right" align="center">
<template #default="{ row }">
<el-button type="primary" link size="small" @click="handleEdit(row)">
<el-icon><Edit /></el-icon>
编辑
</el-button>
<el-popconfirm
title="确定要删除这条评分标准吗?"
confirm-button-text="确定"
cancel-button-text="取消"
@confirm="handleDelete(row)"
>
<template #reference>
<el-button type="danger" link size="small">
<el-icon><Delete /></el-icon>
删除
</el-button>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<div class="pagination-wrapper">
<el-pagination
v-model:current-page="queryParams.page"
v-model:page-size="queryParams.pageSize"
:page-sizes="[10, 20, 50]"
:total="state.total"
layout="total, sizes, prev, pager, next, jumper"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</el-card>
<!-- 新增/编辑对话框 -->
<el-dialog
v-model="state.dialogVisible"
:title="state.dialogTitle"
width="500px"
:close-on-click-modal="false"
@closed="handleDialogClosed"
>
<el-form
ref="formRef"
:model="state.formData"
:rules="formRules"
label-width="100px"
label-position="right"
>
<el-form-item label="测评类型" prop="assessmentTypeId">
<el-select
v-model="state.formData.assessmentTypeId"
placeholder="请选择测评类型"
style="width: 100%;"
>
<el-option
v-for="item in state.assessmentTypes"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="分值" prop="score">
<el-input-number
v-model="state.formData.score"
:min="1"
:max="10"
placeholder="请输入分值"
style="width: 200px;"
/>
</el-form-item>
<el-form-item label="等级标签" prop="label">
<el-input
v-model="state.formData.label"
placeholder="请输入等级标签,如:极弱、很弱"
maxlength="20"
show-word-limit
/>
</el-form-item>
<el-form-item label="描述" prop="description">
<el-input
v-model="state.formData.description"
placeholder="请输入描述,如:完全不符合"
maxlength="100"
show-word-limit
/>
</el-form-item>
<el-form-item label="排序" prop="sort">
<el-input-number
v-model="state.formData.sort"
:min="0"
:max="9999"
placeholder="数值越小越靠前"
/>
</el-form-item>
<el-form-item label="状态" prop="status" required>
<DictSelect
v-model="state.formData.status"
type="common_status"
placeholder="请选择状态"
/>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="state.dialogVisible = false">取消</el-button>
<el-button type="primary" :loading="state.formLoading" @click="handleSubmit">
确定
</el-button>
</template>
</el-dialog>
</div>
</template>
<script setup lang="ts">
/**
* 评分标准管理页面
* @description 管理测评评分标准选项配置各分值对应的等级标签和描述
*/
import { reactive, ref, computed, onMounted } from 'vue'
import { Plus, Search, Refresh, Edit, Delete } from '@element-plus/icons-vue'
import { ElMessage, type FormInstance, type FormRules } from 'element-plus'
import {
getScoreOptionList,
createScoreOption,
updateScoreOption,
deleteScoreOption,
updateScoreOptionStatus,
getAssessmentTypeList,
type ScoreOptionItem,
type ScoreOptionQuery,
type CreateScoreOptionRequest,
type UpdateScoreOptionRequest,
type AssessmentTypeItem
} from '@/api/business/assessment'
import { DictSelect } from '@/components'
// ============ Types ============
interface ScoreOptionFormData {
id?: number
assessmentTypeId: number | undefined
score: number
label: string
description: string
sort: number
status: number | string
}
interface PageState {
loading: boolean
tableData: ScoreOptionItem[]
total: number
assessmentTypes: AssessmentTypeItem[]
dialogVisible: boolean
dialogTitle: string
formData: ScoreOptionFormData
formLoading: boolean
isEdit: boolean
}
// ============ Refs ============
const formRef = ref<FormInstance>()
// ============ State ============
const queryParams = reactive<ScoreOptionQuery>({
page: 1,
pageSize: 10,
assessmentTypeId: undefined,
status: undefined
})
const state = reactive<PageState>({
loading: false,
tableData: [],
total: 0,
assessmentTypes: [],
dialogVisible: false,
dialogTitle: '新增评分标准',
formData: getDefaultFormData(),
formLoading: false,
isEdit: false
})
// ============ Form Rules ============
const formRules = computed<FormRules>(() => ({
assessmentTypeId: [
{ required: true, message: '请选择测评类型', trigger: 'change' }
],
score: [
{ required: true, message: '请输入分值', trigger: 'blur' }
],
label: [
{ required: true, message: '请输入等级标签', trigger: 'blur' },
{ max: 20, message: '标签不能超过20个字符', trigger: 'blur' }
],
description: [
{ max: 100, message: '描述不能超过100个字符', trigger: 'blur' }
],
status: [
{ required: true, message: '请选择状态', trigger: 'change' }
]
}))
// ============ Helper Functions ============
function getDefaultFormData(): ScoreOptionFormData {
return {
assessmentTypeId: undefined,
score: 1,
label: '',
description: '',
sort: 0,
status: 1
}
}
// ============ API Functions ============
async function loadAssessmentTypes() {
try {
const res = await getAssessmentTypeList({ page: 1, pageSize: 100 })
if (res.code === 0) {
state.assessmentTypes = res.data?.list || []
}
} catch (error) {
console.error('Failed to load assessment types:', error)
}
}
async function loadList() {
state.loading = true
try {
const params: ScoreOptionQuery = {
page: queryParams.page,
pageSize: queryParams.pageSize
}
if (queryParams.assessmentTypeId) {
params.assessmentTypeId = queryParams.assessmentTypeId
}
if (queryParams.status !== undefined && queryParams.status !== '') {
params.status = Number(queryParams.status)
}
const res = await getScoreOptionList(params)
if (res.code === 0) {
state.tableData = res.data?.list || []
state.total = res.data?.total || 0
} else {
throw new Error(res.message || '获取评分标准列表失败')
}
} catch (error) {
const message = error instanceof Error ? error.message : '获取评分标准列表失败'
ElMessage.error(message)
} finally {
state.loading = false
}
}
// ============ Event Handlers ============
function handleSearch() {
queryParams.page = 1
loadList()
}
function handleReset() {
queryParams.page = 1
queryParams.assessmentTypeId = undefined
queryParams.status = undefined
loadList()
}
function handleSizeChange(size: number) {
queryParams.pageSize = size
queryParams.page = 1
loadList()
}
function handleCurrentChange(page: number) {
queryParams.page = page
loadList()
}
function handleAdd() {
state.isEdit = false
state.dialogTitle = '新增评分标准'
state.formData = getDefaultFormData()
state.dialogVisible = true
}
function handleEdit(row: ScoreOptionItem) {
state.isEdit = true
state.dialogTitle = '编辑评分标准'
state.formData = {
id: row.id,
assessmentTypeId: row.assessmentTypeId,
score: row.score,
label: row.label,
description: row.description,
sort: row.sort,
status: row.status
}
state.dialogVisible = true
}
async function handleDelete(row: ScoreOptionItem) {
try {
const res = await deleteScoreOption(row.id)
if (res.code === 0) {
ElMessage.success('删除成功')
loadList()
} else {
throw new Error(res.message || '删除失败')
}
} catch (error) {
const message = error instanceof Error ? error.message : '删除失败'
ElMessage.error(message)
}
}
async function handleStatusChange(row: ScoreOptionItem, val: boolean) {
try {
const res = await updateScoreOptionStatus({ id: row.id, status: val ? 1 : 0 })
if (res.code === 0) {
ElMessage.success('状态更新成功')
loadList()
} else {
throw new Error(res.message || '状态更新失败')
}
} catch (error) {
const message = error instanceof Error ? error.message : '状态更新失败'
ElMessage.error(message)
}
}
async function handleSubmit() {
if (!formRef.value) return
await formRef.value.validate()
state.formLoading = true
try {
if (state.isEdit) {
const data: UpdateScoreOptionRequest = {
id: state.formData.id!,
assessmentTypeId: state.formData.assessmentTypeId!,
score: state.formData.score,
label: state.formData.label,
description: state.formData.description,
sort: state.formData.sort,
status: Number(state.formData.status)
}
const res = await updateScoreOption(data)
if (res.code === 0) {
ElMessage.success('更新成功')
state.dialogVisible = false
loadList()
} else {
throw new Error(res.message || '更新失败')
}
} else {
const data: CreateScoreOptionRequest = {
assessmentTypeId: state.formData.assessmentTypeId!,
score: state.formData.score,
label: state.formData.label,
description: state.formData.description,
sort: state.formData.sort,
status: Number(state.formData.status)
}
const res = await createScoreOption(data)
if (res.code === 0) {
ElMessage.success('创建成功')
state.dialogVisible = false
loadList()
} else {
throw new Error(res.message || '创建失败')
}
}
} catch (error) {
const message = error instanceof Error ? error.message : '操作失败'
ElMessage.error(message)
} finally {
state.formLoading = false
}
}
function handleDialogClosed() {
formRef.value?.resetFields()
state.formData = getDefaultFormData()
}
// ============ Lifecycle ============
onMounted(() => {
loadAssessmentTypes()
loadList()
})
</script>
<style scoped>
.score-option-container {
padding: 20px;
}
.page-header {
margin-bottom: 16px;
.header-content {
display: flex;
justify-content: space-between;
align-items: center;
}
.page-title {
margin: 0 0 4px 0;
font-size: 18px;
font-weight: 600;
}
.page-description {
color: #999;
font-size: 13px;
}
}
.search-card {
margin-bottom: 16px;
}
.table-card {
.pagination-wrapper {
display: flex;
justify-content: flex-end;
margin-top: 16px;
}
}
</style>

View File

@ -1 +1 @@
import{d as r,c as a,b as t,e as p,w as _,g as l,t as d,i as c,k as u,_ as i}from"./index-Cz1Ax9N2.js";const m={class:"error-page"},f={class:"error-content"},x=r({__name:"404",setup(k){const o=c(),s=()=>{o.push("/")};return(v,e)=>{const n=l("el-button");return u(),a("div",m,[t("div",f,[e[1]||(e[1]=t("h1",null,"404",-1)),e[2]||(e[2]=t("p",null,"抱歉,您访问的页面不存在",-1)),p(n,{type:"primary",onClick:s},{default:_(()=>[...e[0]||(e[0]=[d("返回首页",-1)])]),_:1})])])}}}),b=i(x,[["__scopeId","data-v-7e9f7d47"]]);export{b as default};
import{d as r,c as a,b as t,e as p,w as _,g as l,t as d,i as c,k as u,_ as i}from"./index-Bc3fuv0D.js";const m={class:"error-page"},f={class:"error-content"},x=r({__name:"404",setup(k){const o=c(),s=()=>{o.push("/")};return(v,e)=>{const n=l("el-button");return u(),a("div",m,[t("div",f,[e[1]||(e[1]=t("h1",null,"404",-1)),e[2]||(e[2]=t("p",null,"抱歉,您访问的页面不存在",-1)),p(n,{type:"primary",onClick:s},{default:_(()=>[...e[0]||(e[0]=[d("返回首页",-1)])]),_:1})])])}}}),b=i(x,[["__scopeId","data-v-7e9f7d47"]]);export{b as default};

View File

@ -1 +0,0 @@
import{R as t}from"./index-Cz1Ax9N2.js";function n(e){return t({url:"/admin/assessment/type/getList",method:"get",params:e})}function a(e){return t({url:"/admin/assessment/type/create",method:"post",data:e})}function o(e){return t({url:"/admin/assessment/type/update",method:"post",data:e})}function u(e){return t({url:"/admin/assessment/type/delete",method:"post",data:{id:e}})}function r(e){return t({url:"/admin/assessment/type/updateStatus",method:"post",data:e})}function m(e){return t({url:"/admin/assessment/question/getList",method:"get",params:e})}function i(e){return t({url:"/admin/assessment/question/create",method:"post",data:e})}function d(e){return t({url:"/admin/assessment/question/update",method:"post",data:e})}function p(e){return t({url:"/admin/assessment/question/delete",method:"post",data:{id:e}})}function c(e){return t({url:"/admin/assessment/question/batchImport",method:"post",data:e,headers:{"Content-Type":"multipart/form-data"}})}function l(e){return t({url:"/admin/assessment/category/getTree",method:"get",params:{assessmentTypeId:e}})}function g(e){return t({url:"/admin/assessment/category/create",method:"post",data:e})}function h(e){return t({url:"/admin/assessment/category/update",method:"post",data:e})}function f(e){return t({url:"/admin/assessment/category/delete",method:"post",data:{id:e}})}function y(e){return t({url:"/admin/assessment/mapping/getByQuestion",method:"get",params:{questionId:e}})}function C(e){return t({url:"/admin/assessment/mapping/batchUpdate",method:"post",data:e})}function T(e){return t({url:"/admin/assessment/conclusion/getList",method:"get",params:{categoryId:e}})}function q(e){return t({url:"/admin/assessment/conclusion/create",method:"post",data:e})}function Q(e){return t({url:"/admin/assessment/conclusion/update",method:"post",data:e})}function L(e){return t({url:"/admin/assessment/conclusion/delete",method:"post",data:{id:e}})}export{l as a,L as b,g as c,f as d,Q as e,q as f,n as g,T as h,m as i,p as j,d as k,i as l,C as m,c as n,y as o,r as p,u as q,o as r,a as s,h as u};

View File

@ -0,0 +1 @@
import{R as e}from"./index-Bc3fuv0D.js";function n(t){return e({url:"/admin/assessment/type/getList",method:"get",params:t})}function a(t){return e({url:"/admin/assessment/type/create",method:"post",data:t})}function o(t){return e({url:"/admin/assessment/type/update",method:"post",data:t})}function r(t){return e({url:"/admin/assessment/type/delete",method:"post",data:{id:t}})}function u(t){return e({url:"/admin/assessment/type/updateStatus",method:"post",data:t})}function i(t){return e({url:"/admin/assessment/question/getList",method:"get",params:t})}function m(t){return e({url:"/admin/assessment/question/create",method:"post",data:t})}function d(t){return e({url:"/admin/assessment/question/update",method:"post",data:t})}function p(t){return e({url:"/admin/assessment/question/delete",method:"post",data:{id:t}})}function c(t){return e({url:"/admin/assessment/question/batchImport",method:"post",data:t,headers:{"Content-Type":"multipart/form-data"}})}function l(t){return e({url:"/admin/assessment/category/getTree",method:"get",params:{assessmentTypeId:t}})}function g(t){return e({url:"/admin/assessment/category/create",method:"post",data:t})}function h(t){return e({url:"/admin/assessment/category/update",method:"post",data:t})}function f(t){return e({url:"/admin/assessment/category/delete",method:"post",data:{id:t}})}function y(t){return e({url:"/admin/assessment/mapping/getByQuestion",method:"get",params:{questionId:t}})}function O(t){return e({url:"/admin/assessment/mapping/batchUpdate",method:"post",data:t})}function C(t){return e({url:"/admin/assessment/conclusion/getList",method:"get",params:{categoryId:t}})}function S(t){return e({url:"/admin/assessment/conclusion/create",method:"post",data:t})}function L(t){return e({url:"/admin/assessment/conclusion/update",method:"post",data:t})}function T(t){return e({url:"/admin/assessment/conclusion/delete",method:"post",data:{id:t}})}function q(t){return e({url:"/admin/assessment/scoreOption/getList",method:"get",params:t})}function Q(t){return e({url:"/admin/assessment/scoreOption/create",method:"post",data:t})}function b(t){return e({url:"/admin/assessment/scoreOption/update",method:"post",data:t})}function A(t){return e({url:"/admin/assessment/scoreOption/delete",method:"post",data:{id:t}})}function x(t){return e({url:"/admin/assessment/scoreOption/updateStatus",method:"post",data:t})}export{l as a,T as b,g as c,f as d,L as e,S as f,n as g,C as h,i,p as j,d as k,m as l,O as m,c as n,y as o,q as p,A as q,x as r,b as s,Q as t,h as u,u as v,r as w,o as x,a as y};

View File

@ -1 +1 @@
import{R as t}from"./index-Cz1Ax9N2.js";function e(){return t({url:"/admin/config/upload/get",method:"get"})}function i(n){return t({url:"/admin/config/upload/update",method:"post",data:n})}function r(n){return t({url:"/admin/config/upload/testConnection",method:"post",data:n})}function u(){return t({url:"/admin/config/miniprogram/get",method:"get"})}function a(n){return t({url:"/admin/config/miniprogram/update",method:"post",data:n})}function g(){return t({url:"/admin/config/weixinpay/get",method:"get"})}function d(n){return t({url:"/admin/config/weixinpay/update",method:"post",data:n})}function f(){return t({url:"/admin/config/user/get",method:"get"})}function m(n){return t({url:"/admin/config/user/update",method:"post",data:n})}export{g as a,d as b,e as c,i as d,f as e,m as f,u as g,r as t,a as u};
import{R as t}from"./index-Bc3fuv0D.js";function e(){return t({url:"/admin/config/upload/get",method:"get"})}function i(n){return t({url:"/admin/config/upload/update",method:"post",data:n})}function r(n){return t({url:"/admin/config/upload/testConnection",method:"post",data:n})}function u(){return t({url:"/admin/config/miniprogram/get",method:"get"})}function a(n){return t({url:"/admin/config/miniprogram/update",method:"post",data:n})}function g(){return t({url:"/admin/config/weixinpay/get",method:"get"})}function d(n){return t({url:"/admin/config/weixinpay/update",method:"post",data:n})}function f(){return t({url:"/admin/config/user/get",method:"get"})}function m(n){return t({url:"/admin/config/user/update",method:"post",data:n})}export{g as a,d as b,e as c,i as d,f as e,m as f,u as g,r as t,a as u};

View File

@ -1 +1 @@
import{R as n}from"./index-Cz1Ax9N2.js";function o(t){return n({url:"/admin/content/banner/getList",method:"get",params:t})}function r(t){return n({url:"/admin/content/banner/create",method:"post",data:t})}function a(t){return n({url:"/admin/content/banner/update",method:"post",data:t})}function u(t){return n({url:"/admin/content/banner/delete",method:"post",data:{id:t}})}function d(t){return n({url:"/admin/content/banner/updateStatus",method:"post",data:t})}function i(t){return n({url:"/admin/content/banner/updateSort",method:"post",data:t})}function m(t){return n({url:"/admin/content/promotion/getList",method:"get",params:t})}function s(t){return n({url:"/admin/content/promotion/create",method:"post",data:t})}function c(t){return n({url:"/admin/content/promotion/update",method:"post",data:t})}function p(t){return n({url:"/admin/content/promotion/delete",method:"post",data:{id:t}})}function l(t){return n({url:"/admin/content/promotion/updateStatus",method:"post",data:t})}export{d as a,a as b,r as c,u as d,m as e,l as f,o as g,p as h,c as i,s as j,i as u};
import{R as n}from"./index-Bc3fuv0D.js";function o(t){return n({url:"/admin/content/banner/getList",method:"get",params:t})}function r(t){return n({url:"/admin/content/banner/create",method:"post",data:t})}function a(t){return n({url:"/admin/content/banner/update",method:"post",data:t})}function u(t){return n({url:"/admin/content/banner/delete",method:"post",data:{id:t}})}function d(t){return n({url:"/admin/content/banner/updateStatus",method:"post",data:t})}function i(t){return n({url:"/admin/content/banner/updateSort",method:"post",data:t})}function m(t){return n({url:"/admin/content/promotion/getList",method:"get",params:t})}function s(t){return n({url:"/admin/content/promotion/create",method:"post",data:t})}function c(t){return n({url:"/admin/content/promotion/update",method:"post",data:t})}function p(t){return n({url:"/admin/content/promotion/delete",method:"post",data:{id:t}})}function l(t){return n({url:"/admin/content/promotion/updateStatus",method:"post",data:t})}export{d as a,a as b,r as c,u as d,m as e,l as f,o as g,p as h,c as i,s as j,i as u};

View File

@ -1 +1 @@
import{R as t}from"./index-Cz1Ax9N2.js";function m(){return t({url:"/admin/departments",method:"get"})}function a(e){return t({url:"/admin/departments",method:"post",data:e})}function u(e,n){return t({url:`/admin/departments/${e}`,method:"put",data:n})}function d(e){return t({url:`/admin/departments/${e}`,method:"delete"})}function s(e){return t({url:`/admin/departments/${e}/menus`,method:"get"})}function p(e){return t({url:`/admin/departments/${e.departmentId}/menus`,method:"put",data:{menuIds:e.menuIds}})}export{s as a,p as b,a as c,d,m as g,u};
import{R as t}from"./index-Bc3fuv0D.js";function m(){return t({url:"/admin/departments",method:"get"})}function a(e){return t({url:"/admin/departments",method:"post",data:e})}function u(e,n){return t({url:`/admin/departments/${e}`,method:"put",data:n})}function d(e){return t({url:`/admin/departments/${e}`,method:"delete"})}function s(e){return t({url:`/admin/departments/${e}/menus`,method:"get"})}function p(e){return t({url:`/admin/departments/${e.departmentId}/menus`,method:"put",data:{menuIds:e.menuIds}})}export{s as a,p as b,a as c,d,m as g,u};

View File

@ -1 +1 @@
import{R as i}from"./index-Cz1Ax9N2.js";function n(t){return i({url:"/admin/distribution/inviteCode/getList",method:"get",params:t})}function o(t){return i({url:"/admin/distribution/inviteCode/generate",method:"post",data:t})}function r(t){return i({url:"/admin/distribution/inviteCode/assign",method:"post",data:t})}function s(t){return i({url:"/admin/distribution/inviteCode/export",method:"get",params:t,responseType:"blob"})}function a(t){return i({url:"/admin/distribution/commission/getList",method:"get",params:t})}function d(t){return i({url:"/admin/distribution/commission/getDetail",method:"get",params:{id:t}})}function u(t){return i({url:"/admin/distribution/commission/getStatistics",method:"get",params:t})}function m(t){return i({url:"/admin/distribution/commission/export",method:"get",params:t,responseType:"blob"})}function l(t){return i({url:"/admin/distribution/withdrawal/getList",method:"get",params:t})}function h(t){return i({url:"/admin/distribution/withdrawal/getDetail",method:"get",params:{id:t}})}function p(t){return i({url:"/admin/distribution/withdrawal/approve",method:"post",data:t})}function g(t){return i({url:"/admin/distribution/withdrawal/reject",method:"post",data:t})}function c(t){return i({url:"/admin/distribution/withdrawal/complete",method:"post",data:t})}function b(t){return i({url:"/admin/distribution/withdrawal/export",method:"get",params:t,responseType:"blob"})}export{a,d as b,n as c,o as d,m as e,r as f,u as g,s as h,l as i,h as j,p as k,c as l,b as m,g as r};
import{R as i}from"./index-Bc3fuv0D.js";function n(t){return i({url:"/admin/distribution/inviteCode/getList",method:"get",params:t})}function o(t){return i({url:"/admin/distribution/inviteCode/generate",method:"post",data:t})}function r(t){return i({url:"/admin/distribution/inviteCode/assign",method:"post",data:t})}function s(t){return i({url:"/admin/distribution/inviteCode/export",method:"get",params:t,responseType:"blob"})}function a(t){return i({url:"/admin/distribution/commission/getList",method:"get",params:t})}function d(t){return i({url:"/admin/distribution/commission/getDetail",method:"get",params:{id:t}})}function u(t){return i({url:"/admin/distribution/commission/getStatistics",method:"get",params:t})}function m(t){return i({url:"/admin/distribution/commission/export",method:"get",params:t,responseType:"blob"})}function l(t){return i({url:"/admin/distribution/withdrawal/getList",method:"get",params:t})}function h(t){return i({url:"/admin/distribution/withdrawal/getDetail",method:"get",params:{id:t}})}function p(t){return i({url:"/admin/distribution/withdrawal/approve",method:"post",data:t})}function g(t){return i({url:"/admin/distribution/withdrawal/reject",method:"post",data:t})}function c(t){return i({url:"/admin/distribution/withdrawal/complete",method:"post",data:t})}function b(t){return i({url:"/admin/distribution/withdrawal/export",method:"get",params:t,responseType:"blob"})}export{a,d as b,n as c,o as d,m as e,r as f,u as g,s as h,l as i,h as j,p as k,c as l,b as m,g as r};

View File

@ -1 +1 @@
import{d as R,u as z,r as d,a as U,o as B,c as _,b as l,e as a,w as o,f as E,g as n,h as F,E as x,i as I,j as N,k as h,l as c,m as M,n as S,p as j,q as L,s as T,t as A,_ as D}from"./index-Cz1Ax9N2.js";const G={class:"login-container"},H={class:"login-box"},J={class:"captcha-container"},O=["src"],P={key:1,class:"captcha-loading"},Q=R({__name:"index",setup(W){const C=I(),V=N(),b=z(),u=d(),p=d(!1),m=d(""),v=d(""),s=U({username:"",password:"",captchaCode:""}),k={username:[{required:!0,message:"请输入用户名",trigger:"blur"}],password:[{required:!0,message:"请输入密码",trigger:"blur"},{min:6,message:"密码至少6个字符",trigger:"blur"}],captchaCode:[{required:!0,message:"请输入验证码",trigger:"blur"},{min:4,max:6,message:"验证码为4-6位字符",trigger:"blur"}]},f=async()=>{try{const t=await F();v.value=t.data.captchaKey,m.value=t.data.captchaImage}catch{x.error("获取验证码失败,请重试")}},y=async()=>{u.value&&await u.value.validate(async t=>{if(t){p.value=!0;try{await b.login({username:s.username,password:s.password,captchaKey:v.value,captchaCode:s.captchaCode}),x.success("登录成功");const e=V.query.redirect;C.push(e||"/")}catch{s.captchaCode="",await f()}finally{p.value=!1}}})};return B(()=>{f()}),(t,e)=>{const g=n("el-input"),i=n("el-form-item"),w=n("el-icon"),q=n("el-button"),K=n("el-form");return h(),_("div",G,[l("div",H,[e[4]||(e[4]=l("div",{class:"login-header"},[l("h1",null,"学业邑规划 后台管理系统")],-1)),a(K,{ref_key:"loginFormRef",ref:u,model:s,rules:k,class:"login-form",onKeyup:E(y,["enter"])},{default:o(()=>[a(i,{prop:"username"},{default:o(()=>[a(g,{modelValue:s.username,"onUpdate:modelValue":e[0]||(e[0]=r=>s.username=r),placeholder:"请输入用户名","prefix-icon":c(M),size:"large"},null,8,["modelValue","prefix-icon"])]),_:1}),a(i,{prop:"password"},{default:o(()=>[a(g,{modelValue:s.password,"onUpdate:modelValue":e[1]||(e[1]=r=>s.password=r),type:"password",placeholder:"请输入密码","prefix-icon":c(S),size:"large","show-password":""},null,8,["modelValue","prefix-icon"])]),_:1}),a(i,{prop:"captchaCode"},{default:o(()=>[l("div",J,[a(g,{modelValue:s.captchaCode,"onUpdate:modelValue":e[2]||(e[2]=r=>s.captchaCode=r),placeholder:"请输入验证码","prefix-icon":c(j),size:"large",class:"captcha-input"},null,8,["modelValue","prefix-icon"]),l("div",{class:"captcha-image-wrapper",onClick:f},[m.value?(h(),_("img",{key:0,src:m.value,alt:"验证码",class:"captcha-image",title:"点击刷新验证码"},null,8,O)):(h(),_("div",P,[a(w,{class:"is-loading"},{default:o(()=>[a(c(L))]),_:1})])),a(w,{class:"refresh-icon"},{default:o(()=>[a(c(T))]),_:1})])])]),_:1}),a(i,null,{default:o(()=>[a(q,{type:"primary",size:"large",loading:p.value,class:"login-btn",onClick:y},{default:o(()=>[...e[3]||(e[3]=[A(" 登 录 ",-1)])]),_:1},8,["loading"])]),_:1})]),_:1},8,["model"])])])}}}),Y=D(Q,[["__scopeId","data-v-d12e50e6"]]);export{Y as default};
import{d as R,u as z,r as d,a as U,o as B,c as _,b as l,e as a,w as o,f as E,g as n,h as F,E as x,i as I,j as N,k as h,l as c,m as M,n as S,p as j,q as L,s as T,t as A,_ as D}from"./index-Bc3fuv0D.js";const G={class:"login-container"},H={class:"login-box"},J={class:"captcha-container"},O=["src"],P={key:1,class:"captcha-loading"},Q=R({__name:"index",setup(W){const C=I(),V=N(),b=z(),u=d(),p=d(!1),m=d(""),v=d(""),s=U({username:"",password:"",captchaCode:""}),k={username:[{required:!0,message:"请输入用户名",trigger:"blur"}],password:[{required:!0,message:"请输入密码",trigger:"blur"},{min:6,message:"密码至少6个字符",trigger:"blur"}],captchaCode:[{required:!0,message:"请输入验证码",trigger:"blur"},{min:4,max:6,message:"验证码为4-6位字符",trigger:"blur"}]},f=async()=>{try{const t=await F();v.value=t.data.captchaKey,m.value=t.data.captchaImage}catch{x.error("获取验证码失败,请重试")}},y=async()=>{u.value&&await u.value.validate(async t=>{if(t){p.value=!0;try{await b.login({username:s.username,password:s.password,captchaKey:v.value,captchaCode:s.captchaCode}),x.success("登录成功");const e=V.query.redirect;C.push(e||"/")}catch{s.captchaCode="",await f()}finally{p.value=!1}}})};return B(()=>{f()}),(t,e)=>{const g=n("el-input"),i=n("el-form-item"),w=n("el-icon"),q=n("el-button"),K=n("el-form");return h(),_("div",G,[l("div",H,[e[4]||(e[4]=l("div",{class:"login-header"},[l("h1",null,"学业邑规划 后台管理系统")],-1)),a(K,{ref_key:"loginFormRef",ref:u,model:s,rules:k,class:"login-form",onKeyup:E(y,["enter"])},{default:o(()=>[a(i,{prop:"username"},{default:o(()=>[a(g,{modelValue:s.username,"onUpdate:modelValue":e[0]||(e[0]=r=>s.username=r),placeholder:"请输入用户名","prefix-icon":c(M),size:"large"},null,8,["modelValue","prefix-icon"])]),_:1}),a(i,{prop:"password"},{default:o(()=>[a(g,{modelValue:s.password,"onUpdate:modelValue":e[1]||(e[1]=r=>s.password=r),type:"password",placeholder:"请输入密码","prefix-icon":c(S),size:"large","show-password":""},null,8,["modelValue","prefix-icon"])]),_:1}),a(i,{prop:"captchaCode"},{default:o(()=>[l("div",J,[a(g,{modelValue:s.captchaCode,"onUpdate:modelValue":e[2]||(e[2]=r=>s.captchaCode=r),placeholder:"请输入验证码","prefix-icon":c(j),size:"large",class:"captcha-input"},null,8,["modelValue","prefix-icon"]),l("div",{class:"captcha-image-wrapper",onClick:f},[m.value?(h(),_("img",{key:0,src:m.value,alt:"验证码",class:"captcha-image",title:"点击刷新验证码"},null,8,O)):(h(),_("div",P,[a(w,{class:"is-loading"},{default:o(()=>[a(c(L))]),_:1})])),a(w,{class:"refresh-icon"},{default:o(()=>[a(c(T))]),_:1})])])]),_:1}),a(i,null,{default:o(()=>[a(q,{type:"primary",size:"large",loading:p.value,class:"login-btn",onClick:y},{default:o(()=>[...e[3]||(e[3]=[A(" 登 录 ",-1)])]),_:1},8,["loading"])]),_:1})]),_:1},8,["model"])])])}}}),Y=D(Q,[["__scopeId","data-v-d12e50e6"]]);export{Y as default};

View File

@ -1 +1 @@
import s from"./upload-Ddl3xidv.js";import p from"./miniprogram-C8Qt5L_5.js";import i from"./payment-BL1IfAh1.js";import _ from"./user-CFzw0-AN.js";import{d,r as c,g as r,c as f,k as u,e,w as a,_ as b}from"./index-Cz1Ax9N2.js";import"./config-D_k0iQpg.js";const g={class:"config-container"},C=d({__name:"index",setup(v){const t=c("miniprogram");return(x,n)=>{const o=r("el-tab-pane"),l=r("el-tabs");return u(),f("div",g,[e(l,{modelValue:t.value,"onUpdate:modelValue":n[0]||(n[0]=m=>t.value=m),type:"border-card"},{default:a(()=>[e(o,{label:"小程序配置",name:"miniprogram"},{default:a(()=>[e(p)]),_:1}),e(o,{label:"支付配置",name:"payment"},{default:a(()=>[e(i)]),_:1}),e(o,{label:"上传配置",name:"upload"},{default:a(()=>[e(s)]),_:1}),e(o,{label:"用户配置",name:"user"},{default:a(()=>[e(_)]),_:1})]),_:1},8,["modelValue"])])}}}),h=b(C,[["__scopeId","data-v-1c246f87"]]);export{h as default};
import s from"./upload-ki9gELQx.js";import p from"./miniprogram-DUIHdIvd.js";import i from"./payment-B-hLh6lw.js";import _ from"./user-KXeZCWFt.js";import{d,r as c,g as r,c as f,k as u,e,w as a,_ as b}from"./index-Bc3fuv0D.js";import"./config-C0dNYBjY.js";const g={class:"config-container"},C=d({__name:"index",setup(v){const t=c("miniprogram");return(x,n)=>{const o=r("el-tab-pane"),l=r("el-tabs");return u(),f("div",g,[e(l,{modelValue:t.value,"onUpdate:modelValue":n[0]||(n[0]=m=>t.value=m),type:"border-card"},{default:a(()=>[e(o,{label:"小程序配置",name:"miniprogram"},{default:a(()=>[e(p)]),_:1}),e(o,{label:"支付配置",name:"payment"},{default:a(()=>[e(i)]),_:1}),e(o,{label:"上传配置",name:"upload"},{default:a(()=>[e(s)]),_:1}),e(o,{label:"用户配置",name:"user"},{default:a(()=>[e(_)]),_:1})]),_:1},8,["modelValue"])])}}}),h=b(C,[["__scopeId","data-v-1c246f87"]]);export{h as default};

View File

@ -0,0 +1 @@
.score-option-container[data-v-85a8541d]{padding:20px}.page-header[data-v-85a8541d]{margin-bottom:16px}.page-header .header-content[data-v-85a8541d]{display:flex;justify-content:space-between;align-items:center}.page-header .page-title[data-v-85a8541d]{margin:0 0 4px;font-size:18px;font-weight:600}.page-header .page-description[data-v-85a8541d]{color:#999;font-size:13px}.search-card[data-v-85a8541d]{margin-bottom:16px}.table-card .pagination-wrapper[data-v-85a8541d]{display:flex;justify-content:flex-end;margin-top:16px}

View File

@ -1 +1 @@
import{d as P,r as w,a as b,c as v,e as s,w as a,g as d,t as x,b as V,A as y,E as i,k as h,_ as k}from"./index-Cz1Ax9N2.js";const C={class:"page-container"},E=P({__name:"index",setup(q){const u=w(),n=w(!1),o=b({oldPassword:"",newPassword:"",confirmPassword:""}),p={oldPassword:[{required:!0,message:"请输入原密码",trigger:"blur"},{min:6,max:20,message:"密码长度在 6 到 20 个字符",trigger:"blur"}],newPassword:[{required:!0,message:"请输入新密码",trigger:"blur"},{min:6,max:20,message:"密码长度在 6 到 20 个字符",trigger:"blur"}],confirmPassword:[{required:!0,message:"请再次输入新密码",trigger:"blur"},{validator:(m,e,r)=>{e!==o.newPassword?r(new Error("两次输入密码不一致")):r()},trigger:"blur"}]},f=async()=>{var e;if(await((e=u.value)==null?void 0:e.validate())){n.value=!0;try{await y({oldPassword:o.oldPassword,newPassword:o.newPassword}),i.success("密码修改成功"),o.oldPassword="",o.newPassword="",o.confirmPassword=""}catch(r){i.error(r.message||"修改失败")}finally{n.value=!1}}};return(m,e)=>{const r=d("el-input"),t=d("el-form-item"),c=d("el-button"),_=d("el-form"),g=d("el-card");return h(),v("div",C,[s(g,null,{header:a(()=>[...e[3]||(e[3]=[V("span",null,"修改密码",-1)])]),default:a(()=>[s(_,{ref_key:"formRef",ref:u,model:o,rules:p,"label-width":"100px",style:{"max-width":"400px"}},{default:a(()=>[s(t,{label:"原密码",prop:"oldPassword"},{default:a(()=>[s(r,{modelValue:o.oldPassword,"onUpdate:modelValue":e[0]||(e[0]=l=>o.oldPassword=l),type:"password",placeholder:"请输入原密码","show-password":""},null,8,["modelValue"])]),_:1}),s(t,{label:"新密码",prop:"newPassword"},{default:a(()=>[s(r,{modelValue:o.newPassword,"onUpdate:modelValue":e[1]||(e[1]=l=>o.newPassword=l),type:"password",placeholder:"请输入新密码","show-password":""},null,8,["modelValue"])]),_:1}),s(t,{label:"确认密码",prop:"confirmPassword"},{default:a(()=>[s(r,{modelValue:o.confirmPassword,"onUpdate:modelValue":e[2]||(e[2]=l=>o.confirmPassword=l),type:"password",placeholder:"请再次输入新密码","show-password":""},null,8,["modelValue"])]),_:1}),s(t,null,{default:a(()=>[s(c,{type:"primary",onClick:f,loading:n.value},{default:a(()=>[...e[4]||(e[4]=[x(" 确认修改 ",-1)])]),_:1},8,["loading"])]),_:1})]),_:1},8,["model"])]),_:1})])}}}),N=k(E,[["__scopeId","data-v-928c0ade"]]);export{N as default};
import{d as P,r as w,a as b,c as v,e as s,w as a,g as d,t as x,b as V,A as y,E as i,k as h,_ as k}from"./index-Bc3fuv0D.js";const C={class:"page-container"},E=P({__name:"index",setup(q){const u=w(),n=w(!1),o=b({oldPassword:"",newPassword:"",confirmPassword:""}),p={oldPassword:[{required:!0,message:"请输入原密码",trigger:"blur"},{min:6,max:20,message:"密码长度在 6 到 20 个字符",trigger:"blur"}],newPassword:[{required:!0,message:"请输入新密码",trigger:"blur"},{min:6,max:20,message:"密码长度在 6 到 20 个字符",trigger:"blur"}],confirmPassword:[{required:!0,message:"请再次输入新密码",trigger:"blur"},{validator:(m,e,r)=>{e!==o.newPassword?r(new Error("两次输入密码不一致")):r()},trigger:"blur"}]},f=async()=>{var e;if(await((e=u.value)==null?void 0:e.validate())){n.value=!0;try{await y({oldPassword:o.oldPassword,newPassword:o.newPassword}),i.success("密码修改成功"),o.oldPassword="",o.newPassword="",o.confirmPassword=""}catch(r){i.error(r.message||"修改失败")}finally{n.value=!1}}};return(m,e)=>{const r=d("el-input"),t=d("el-form-item"),c=d("el-button"),_=d("el-form"),g=d("el-card");return h(),v("div",C,[s(g,null,{header:a(()=>[...e[3]||(e[3]=[V("span",null,"修改密码",-1)])]),default:a(()=>[s(_,{ref_key:"formRef",ref:u,model:o,rules:p,"label-width":"100px",style:{"max-width":"400px"}},{default:a(()=>[s(t,{label:"原密码",prop:"oldPassword"},{default:a(()=>[s(r,{modelValue:o.oldPassword,"onUpdate:modelValue":e[0]||(e[0]=l=>o.oldPassword=l),type:"password",placeholder:"请输入原密码","show-password":""},null,8,["modelValue"])]),_:1}),s(t,{label:"新密码",prop:"newPassword"},{default:a(()=>[s(r,{modelValue:o.newPassword,"onUpdate:modelValue":e[1]||(e[1]=l=>o.newPassword=l),type:"password",placeholder:"请输入新密码","show-password":""},null,8,["modelValue"])]),_:1}),s(t,{label:"确认密码",prop:"confirmPassword"},{default:a(()=>[s(r,{modelValue:o.confirmPassword,"onUpdate:modelValue":e[2]||(e[2]=l=>o.confirmPassword=l),type:"password",placeholder:"请再次输入新密码","show-password":""},null,8,["modelValue"])]),_:1}),s(t,null,{default:a(()=>[s(c,{type:"primary",onClick:f,loading:n.value},{default:a(()=>[...e[4]||(e[4]=[x(" 确认修改 ",-1)])]),_:1},8,["loading"])]),_:1})]),_:1},8,["model"])]),_:1})])}}}),N=k(E,[["__scopeId","data-v-928c0ade"]]);export{N as default};

View File

@ -1,4 +1,4 @@
var a_=Object.defineProperty;var o_=(r,t,e)=>t in r?a_(r,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):r[t]=e;var iv=(r,t,e)=>o_(r,typeof t!="symbol"?t+"":t,e);import{d as ig,a0 as pu,a1 as _o,a2 as s_,v as Tr,a3 as So,a4 as bo,a5 as ng,o as Ff,a6 as l_,a7 as gu,W as u_,a8 as Us,a9 as f_,aa as h_,ab as v_,R as zf,u as c_,r as d_,a as p_,g as Ae,B as g_,c as Ys,k as Le,z as Gr,G as m_,e as O,w as H,t as ge,C as hr,b as Z,l as Tt,m as nv,x as Ie,ac as av,ad as y_,ae as ov,af as __,ag as S_,ah as sv,ai as lv,aj as b_,O as w_,ak as x_,E as Xs,_ as T_}from"./index-Cz1Ax9N2.js";/*! *****************************************************************************
var a_=Object.defineProperty;var o_=(r,t,e)=>t in r?a_(r,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):r[t]=e;var iv=(r,t,e)=>o_(r,typeof t!="symbol"?t+"":t,e);import{d as ig,a0 as pu,a1 as _o,a2 as s_,v as Tr,a3 as So,a4 as bo,a5 as ng,o as Ff,a6 as l_,a7 as gu,W as u_,a8 as Us,a9 as f_,aa as h_,ab as v_,R as zf,u as c_,r as d_,a as p_,g as Ae,B as g_,c as Ys,k as Le,z as Gr,G as m_,e as O,w as H,t as ge,C as hr,b as Z,l as Tt,m as nv,x as Ie,ac as av,ad as y_,ae as ov,af as __,ag as S_,ah as sv,ai as lv,aj as b_,O as w_,ak as x_,E as Xs,_ as T_}from"./index-Bc3fuv0D.js";/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any

View File

@ -1 +1 @@
import{d as v,u as x,v as b,c as u,e as t,w as a,g as r,t as n,x as o,F as g,y as k,b as N,k as c,z as h,_ as y}from"./index-Cz1Ax9N2.js";const B={class:"page-container"},C=v({__name:"index",setup(I){const i=x(),s=b(()=>i.userInfo);return(S,_)=>{const l=r("el-descriptions-item"),p=r("el-tag"),m=r("el-descriptions"),f=r("el-card");return c(),u("div",B,[t(f,null,{header:a(()=>[..._[0]||(_[0]=[N("span",null,"个人中心",-1)])]),default:a(()=>[t(m,{column:2,border:""},{default:a(()=>[t(l,{label:"用户名"},{default:a(()=>{var e;return[n(o((e=s.value)==null?void 0:e.username),1)]}),_:1}),t(l,{label:"姓名"},{default:a(()=>{var e;return[n(o(((e=s.value)==null?void 0:e.realName)||"-"),1)]}),_:1}),t(l,{label:"手机号"},{default:a(()=>{var e;return[n(o(((e=s.value)==null?void 0:e.phone)||"-"),1)]}),_:1}),t(l,{label:"邮箱"},{default:a(()=>{var e;return[n(o(((e=s.value)==null?void 0:e.email)||"-"),1)]}),_:1}),t(l,{label:"部门"},{default:a(()=>{var e;return[n(o(((e=s.value)==null?void 0:e.departmentName)||"-"),1)]}),_:1}),t(l,{label:"角色"},{default:a(()=>{var e;return[(c(!0),u(g,null,k((e=s.value)==null?void 0:e.roles,d=>(c(),h(p,{key:d,size:"small",style:{"margin-right":"4px"}},{default:a(()=>[n(o(d),1)]),_:2},1024))),128))]}),_:1})]),_:1})]),_:1})])}}}),w=y(C,[["__scopeId","data-v-e4ec3187"]]);export{w as default};
import{d as v,u as x,v as b,c as u,e as t,w as a,g as r,t as n,x as o,F as g,y as k,b as N,k as c,z as h,_ as y}from"./index-Bc3fuv0D.js";const B={class:"page-container"},C=v({__name:"index",setup(I){const i=x(),s=b(()=>i.userInfo);return(S,_)=>{const l=r("el-descriptions-item"),p=r("el-tag"),m=r("el-descriptions"),f=r("el-card");return c(),u("div",B,[t(f,null,{header:a(()=>[..._[0]||(_[0]=[N("span",null,"个人中心",-1)])]),default:a(()=>[t(m,{column:2,border:""},{default:a(()=>[t(l,{label:"用户名"},{default:a(()=>{var e;return[n(o((e=s.value)==null?void 0:e.username),1)]}),_:1}),t(l,{label:"姓名"},{default:a(()=>{var e;return[n(o(((e=s.value)==null?void 0:e.realName)||"-"),1)]}),_:1}),t(l,{label:"手机号"},{default:a(()=>{var e;return[n(o(((e=s.value)==null?void 0:e.phone)||"-"),1)]}),_:1}),t(l,{label:"邮箱"},{default:a(()=>{var e;return[n(o(((e=s.value)==null?void 0:e.email)||"-"),1)]}),_:1}),t(l,{label:"部门"},{default:a(()=>{var e;return[n(o(((e=s.value)==null?void 0:e.departmentName)||"-"),1)]}),_:1}),t(l,{label:"角色"},{default:a(()=>{var e;return[(c(!0),u(g,null,k((e=s.value)==null?void 0:e.roles,d=>(c(),h(p,{key:d,size:"small",style:{"margin-right":"4px"}},{default:a(()=>[n(o(d),1)]),_:2},1024))),128))]}),_:1})]),_:1})]),_:1})])}}}),w=y(C,[["__scopeId","data-v-e4ec3187"]]);export{w as default};

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
import{R as s}from"./index-Cz1Ax9N2.js";function r(){return s({url:"/admin/permissions",method:"get"})}function t(){return s({url:"/admin/permissions/by-module",method:"get"})}function o(e){return s({url:"/admin/permissions",method:"post",data:e})}function m(e,i){return s({url:`/admin/permissions/${e}`,method:"put",data:i})}function u(e){return s({url:`/admin/permissions/${e}`,method:"delete"})}export{r as a,o as c,u as d,t as g,m as u};
import{R as s}from"./index-Bc3fuv0D.js";function r(){return s({url:"/admin/permissions",method:"get"})}function t(){return s({url:"/admin/permissions/by-module",method:"get"})}function o(e){return s({url:"/admin/permissions",method:"post",data:e})}function m(e,i){return s({url:`/admin/permissions/${e}`,method:"put",data:i})}function u(e){return s({url:`/admin/permissions/${e}`,method:"delete"})}export{r as a,o as c,u as d,t as g,m as u};

View File

@ -1 +1 @@
import{R as t}from"./index-Cz1Ax9N2.js";function a(n){return t({url:"/admin/planner/getList",method:"get",params:n})}function r(n){return t({url:"/admin/planner/create",method:"post",data:n})}function o(n){return t({url:"/admin/planner/update",method:"post",data:n})}function u(n){return t({url:"/admin/planner/delete",method:"post",data:{id:n}})}function i(n){return t({url:"/admin/planner/updateStatus",method:"post",data:n})}function d(n){return t({url:"/admin/planner/booking/getList",method:"get",params:n})}function l(n){return t({url:"/admin/planner/booking/getDetail",method:"get",params:{id:n}})}function s(n){return t({url:"/admin/planner/booking/updateStatus",method:"post",data:n})}function p(n){return t({url:"/admin/planner/booking/export",method:"get",params:n,responseType:"blob"})}export{d as a,l as b,o as c,r as d,p as e,i as f,a as g,u as h,s as u};
import{R as t}from"./index-Bc3fuv0D.js";function a(n){return t({url:"/admin/planner/getList",method:"get",params:n})}function r(n){return t({url:"/admin/planner/create",method:"post",data:n})}function o(n){return t({url:"/admin/planner/update",method:"post",data:n})}function u(n){return t({url:"/admin/planner/delete",method:"post",data:{id:n}})}function i(n){return t({url:"/admin/planner/updateStatus",method:"post",data:n})}function d(n){return t({url:"/admin/planner/booking/getList",method:"get",params:n})}function l(n){return t({url:"/admin/planner/booking/getDetail",method:"get",params:{id:n}})}function s(n){return t({url:"/admin/planner/booking/updateStatus",method:"post",data:n})}function p(n){return t({url:"/admin/planner/booking/export",method:"get",params:n,responseType:"blob"})}export{d as a,l as b,o as c,r as d,p as e,i as f,a as g,u as h,s as u};

View File

@ -1 +1 @@
import{R as s}from"./index-Cz1Ax9N2.js";function r(e){return s({url:"/admin/roles",method:"get",params:e})}function t(){return s({url:"/admin/roles/all",method:"get"})}function u(e){return s({url:"/admin/roles",method:"post",data:e})}function l(e,n){return s({url:`/admin/roles/${e}`,method:"put",data:n})}function i(e){return s({url:`/admin/roles/${e}`,method:"delete"})}function m(e){return s({url:`/admin/roles/${e}/menus`,method:"get"})}function d(e){return s({url:`/admin/roles/${e.roleId}/menus`,method:"put",data:{menuIds:e.menuIds}})}function a(e){return s({url:`/admin/roles/${e}/permissions`,method:"get"})}function c(e){return s({url:`/admin/roles/${e.roleId}/permissions`,method:"put",data:{permissionCodes:e.permissionCodes}})}export{m as a,d as b,u as c,i as d,a as e,c as f,r as g,t as h,l as u};
import{R as s}from"./index-Bc3fuv0D.js";function r(e){return s({url:"/admin/roles",method:"get",params:e})}function t(){return s({url:"/admin/roles/all",method:"get"})}function u(e){return s({url:"/admin/roles",method:"post",data:e})}function l(e,n){return s({url:`/admin/roles/${e}`,method:"put",data:n})}function i(e){return s({url:`/admin/roles/${e}`,method:"delete"})}function m(e){return s({url:`/admin/roles/${e}/menus`,method:"get"})}function d(e){return s({url:`/admin/roles/${e.roleId}/menus`,method:"put",data:{menuIds:e.menuIds}})}function a(e){return s({url:`/admin/roles/${e}/permissions`,method:"get"})}function c(e){return s({url:`/admin/roles/${e.roleId}/permissions`,method:"put",data:{permissionCodes:e.permissionCodes}})}export{m as a,d as b,u as c,i as d,a as e,c as f,r as g,t as h,l as u};

View File

@ -1 +1 @@
import{R as t}from"./index-Cz1Ax9N2.js";function u(e){return t({url:"/admin/user/getList",method:"get",params:e})}function s(e){return t({url:"/admin/user/getDetail",method:"get",params:{id:e}})}function a(e){return t({url:"/admin/user/updateStatus",method:"post",data:e})}function n(e){return t({url:"/admin/user/updateLevel",method:"post",data:e})}function o(e){return t({url:"/admin/user/export",method:"get",params:e,responseType:"blob"})}function d(e){return t({url:"/admin/user/delete",method:"post",data:{id:e}})}export{n as a,s as b,d,o as e,u as g,a as u};
import{R as t}from"./index-Bc3fuv0D.js";function u(e){return t({url:"/admin/user/getList",method:"get",params:e})}function s(e){return t({url:"/admin/user/getDetail",method:"get",params:{id:e}})}function a(e){return t({url:"/admin/user/updateStatus",method:"post",data:e})}function n(e){return t({url:"/admin/user/updateLevel",method:"post",data:e})}function o(e){return t({url:"/admin/user/export",method:"get",params:e,responseType:"blob"})}function d(e){return t({url:"/admin/user/delete",method:"post",data:{id:e}})}export{n as a,s as b,d,o as e,u as g,a as u};

View File

@ -1 +1 @@
import{d as C,a as I,v as k,o as B,g as s,B as N,c as E,k as v,e as t,C as M,w as l,b as n,z as S,t as r,Q as z,E as u,_ as L}from"./index-Cz1Ax9N2.js";import{e as Q,f as R}from"./config-D_k0iQpg.js";const T={class:"user-config-container"},j={class:"avatar-config"},q={class:"form-actions"},A=C({__name:"user",setup(F){const a=I({loading:!1,saving:!1,formData:{uid_type:"2",uid_length:"6",default_nickname_prefix:"用户",default_avatar:""}}),m=k({get:()=>parseInt(a.formData.uid_length||"6")||6,set:o=>{a.formData.uid_length=String(o)}});async function p(){a.loading=!0;try{const o=await Q();o.code===0&&o.data&&(a.formData=o.data)}catch(o){console.error("加载用户配置失败:",o),u.error("加载配置失败")}finally{a.loading=!1}}async function D(){a.saving=!0;try{const o=await R(a.formData);o.code===0?u.success("保存成功"):u.error(o.message||"保存失败")}catch(o){console.error("保存用户配置失败:",o),u.error("保存失败")}finally{a.saving=!1}}function V(){p()}return B(()=>{p()}),(o,e)=>{const _=s("el-card"),f=s("el-radio"),b=s("el-radio-group"),d=s("el-form-item"),U=s("el-input-number"),c=s("el-divider"),x=s("el-input"),y=s("el-form"),g=s("el-button"),w=N("loading");return v(),E("div",T,[t(_,{class:"page-header"},{default:l(()=>[...e[4]||(e[4]=[n("div",{class:"header-content"},[n("h2",{class:"page-title"},"用户配置"),n("span",{class:"page-description"},"配置新用户注册时的UID生成规则、默认昵称前缀和默认头像")],-1)])]),_:1}),M((v(),S(_,{class:"config-form-card"},{default:l(()=>[t(y,{"label-width":"140px","label-position":"right"},{default:l(()=>[e[10]||(e[10]=n("div",{class:"section-title"},"UID 配置",-1)),t(d,{label:"UID类型"},{default:l(()=>[t(b,{modelValue:a.formData.uid_type,"onUpdate:modelValue":e[0]||(e[0]=i=>a.formData.uid_type=i)},{default:l(()=>[t(f,{value:"1"},{default:l(()=>[...e[5]||(e[5]=[r("真实ID",-1)])]),_:1}),t(f,{value:"2"},{default:l(()=>[...e[6]||(e[6]=[r("数字ID",-1)])]),_:1}),t(f,{value:"3"},{default:l(()=>[...e[7]||(e[7]=[r("随机字符和数字",-1)])]),_:1})]),_:1},8,["modelValue"])]),_:1}),t(d,{label:"UID长度"},{default:l(()=>[t(U,{modelValue:m.value,"onUpdate:modelValue":e[1]||(e[1]=i=>m.value=i),modelModifiers:{number:!0},min:4,max:12,"controls-position":"right"},null,8,["modelValue"]),e[8]||(e[8]=n("div",{class:"form-item-tip"},"新用户UID的位数建议6位",-1))]),_:1}),t(c),e[11]||(e[11]=n("div",{class:"section-title"},"默认昵称",-1)),t(d,{label:"昵称前缀"},{default:l(()=>[t(x,{modelValue:a.formData.default_nickname_prefix,"onUpdate:modelValue":e[2]||(e[2]=i=>a.formData.default_nickname_prefix=i),placeholder:"请输入默认昵称前缀",maxlength:"10","show-word-limit":"",clearable:"",style:{width:"300px"}},null,8,["modelValue"]),e[9]||(e[9]=n("div",{class:"form-item-tip"},'新用户注册时的昵称前缀系统会自动拼接6位随机数字如"用户123456"',-1))]),_:1}),t(c),e[12]||(e[12]=n("div",{class:"section-title"},"默认头像",-1)),t(d,{label:"默认头像"},{default:l(()=>[n("div",j,[t(z,{modelValue:a.formData.default_avatar,"onUpdate:modelValue":e[3]||(e[3]=i=>a.formData.default_avatar=i),placeholder:"点击上传默认头像","show-url-input":!1,tip:"上传图片作为所有新用户的默认头像,不上传则系统自动生成唯一头像"},null,8,["modelValue"])])]),_:1})]),_:1}),n("div",q,[t(g,{type:"primary",loading:a.saving,onClick:D},{default:l(()=>[...e[13]||(e[13]=[r("保存配置",-1)])]),_:1},8,["loading"]),t(g,{onClick:V},{default:l(()=>[...e[14]||(e[14]=[r("重置",-1)])]),_:1})])]),_:1})),[[w,a.loading]])])}}}),J=L(A,[["__scopeId","data-v-5ef730fd"]]);export{J as default};
import{d as C,a as I,v as k,o as B,g as s,B as N,c as E,k as v,e as t,C as M,w as l,b as n,z as S,t as r,Q as z,E as u,_ as L}from"./index-Bc3fuv0D.js";import{e as Q,f as R}from"./config-C0dNYBjY.js";const T={class:"user-config-container"},j={class:"avatar-config"},q={class:"form-actions"},A=C({__name:"user",setup(F){const a=I({loading:!1,saving:!1,formData:{uid_type:"2",uid_length:"6",default_nickname_prefix:"用户",default_avatar:""}}),m=k({get:()=>parseInt(a.formData.uid_length||"6")||6,set:o=>{a.formData.uid_length=String(o)}});async function p(){a.loading=!0;try{const o=await Q();o.code===0&&o.data&&(a.formData=o.data)}catch(o){console.error("加载用户配置失败:",o),u.error("加载配置失败")}finally{a.loading=!1}}async function D(){a.saving=!0;try{const o=await R(a.formData);o.code===0?u.success("保存成功"):u.error(o.message||"保存失败")}catch(o){console.error("保存用户配置失败:",o),u.error("保存失败")}finally{a.saving=!1}}function V(){p()}return B(()=>{p()}),(o,e)=>{const _=s("el-card"),f=s("el-radio"),b=s("el-radio-group"),d=s("el-form-item"),U=s("el-input-number"),c=s("el-divider"),x=s("el-input"),y=s("el-form"),g=s("el-button"),w=N("loading");return v(),E("div",T,[t(_,{class:"page-header"},{default:l(()=>[...e[4]||(e[4]=[n("div",{class:"header-content"},[n("h2",{class:"page-title"},"用户配置"),n("span",{class:"page-description"},"配置新用户注册时的UID生成规则、默认昵称前缀和默认头像")],-1)])]),_:1}),M((v(),S(_,{class:"config-form-card"},{default:l(()=>[t(y,{"label-width":"140px","label-position":"right"},{default:l(()=>[e[10]||(e[10]=n("div",{class:"section-title"},"UID 配置",-1)),t(d,{label:"UID类型"},{default:l(()=>[t(b,{modelValue:a.formData.uid_type,"onUpdate:modelValue":e[0]||(e[0]=i=>a.formData.uid_type=i)},{default:l(()=>[t(f,{value:"1"},{default:l(()=>[...e[5]||(e[5]=[r("真实ID",-1)])]),_:1}),t(f,{value:"2"},{default:l(()=>[...e[6]||(e[6]=[r("数字ID",-1)])]),_:1}),t(f,{value:"3"},{default:l(()=>[...e[7]||(e[7]=[r("随机字符和数字",-1)])]),_:1})]),_:1},8,["modelValue"])]),_:1}),t(d,{label:"UID长度"},{default:l(()=>[t(U,{modelValue:m.value,"onUpdate:modelValue":e[1]||(e[1]=i=>m.value=i),modelModifiers:{number:!0},min:4,max:12,"controls-position":"right"},null,8,["modelValue"]),e[8]||(e[8]=n("div",{class:"form-item-tip"},"新用户UID的位数建议6位",-1))]),_:1}),t(c),e[11]||(e[11]=n("div",{class:"section-title"},"默认昵称",-1)),t(d,{label:"昵称前缀"},{default:l(()=>[t(x,{modelValue:a.formData.default_nickname_prefix,"onUpdate:modelValue":e[2]||(e[2]=i=>a.formData.default_nickname_prefix=i),placeholder:"请输入默认昵称前缀",maxlength:"10","show-word-limit":"",clearable:"",style:{width:"300px"}},null,8,["modelValue"]),e[9]||(e[9]=n("div",{class:"form-item-tip"},'新用户注册时的昵称前缀系统会自动拼接6位随机数字如"用户123456"',-1))]),_:1}),t(c),e[12]||(e[12]=n("div",{class:"section-title"},"默认头像",-1)),t(d,{label:"默认头像"},{default:l(()=>[n("div",j,[t(z,{modelValue:a.formData.default_avatar,"onUpdate:modelValue":e[3]||(e[3]=i=>a.formData.default_avatar=i),placeholder:"点击上传默认头像","show-url-input":!1,tip:"上传图片作为所有新用户的默认头像,不上传则系统自动生成唯一头像"},null,8,["modelValue"])])]),_:1})]),_:1}),n("div",q,[t(g,{type:"primary",loading:a.saving,onClick:D},{default:l(()=>[...e[13]||(e[13]=[r("保存配置",-1)])]),_:1},8,["loading"]),t(g,{onClick:V},{default:l(()=>[...e[14]||(e[14]=[r("重置",-1)])]),_:1})])]),_:1})),[[w,a.loading]])])}}}),J=L(A,[["__scopeId","data-v-5ef730fd"]]);export{J as default};

View File

@ -5,7 +5,7 @@
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>学业邑规划 - 后台管理系统</title>
<script type="module" crossorigin src="/assets/index-Cz1Ax9N2.js"></script>
<script type="module" crossorigin src="/assets/index-Bc3fuv0D.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-DzyxRPPz.css">
</head>
<body>

View File

@ -374,4 +374,36 @@ public class AssessmentController : ControllerBase
}
#endregion
/// <summary>
/// 获取评分标准选项
/// </summary>
/// <remarks>
/// GET /api/assessment/getScoreOptions?typeId=1
///
/// 根据测评类型ID返回所有启用的评分标准选项按Sort升序排列
/// 不需要用户登录认证
/// </remarks>
/// <param name="typeId">测评类型ID</param>
/// <returns>评分标准选项列表</returns>
[HttpGet("getScoreOptions")]
[ProducesResponseType(typeof(ApiResponse<List<ScoreOptionDto>>), StatusCodes.Status200OK)]
public async Task<ApiResponse<List<ScoreOptionDto>>> GetScoreOptions([FromQuery] long typeId)
{
try
{
if (typeId <= 0)
{
return ApiResponse<List<ScoreOptionDto>>.Fail("测评类型ID无效");
}
var options = await _assessmentService.GetScoreOptionsAsync(typeId);
return ApiResponse<List<ScoreOptionDto>>.Success(options);
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to get score options, typeId: {TypeId}", typeId);
return ApiResponse<List<ScoreOptionDto>>.Fail("获取评分标准失败");
}
}
}

View File

@ -101,4 +101,15 @@ public interface IAssessmentService
/// <param name="pageSize">每页数量</param>
/// <returns>分页的测评历史记录列表</returns>
Task<PagedResult<AssessmentHistoryDto>> GetHistoryListAsync(long userId, int page, int pageSize);
/// <summary>
/// 获取评分标准选项列表
/// </summary>
/// <remarks>
/// 根据测评类型ID返回所有启用的评分标准选项按Sort升序排列。
/// 不需要用户登录认证。
/// </remarks>
/// <param name="typeId">测评类型ID</param>
/// <returns>评分标准选项列表</returns>
Task<List<ScoreOptionDto>> GetScoreOptionsAsync(long typeId);
}

View File

@ -593,4 +593,25 @@ public class AssessmentService : IAssessmentService
_ => "未知"
};
}
/// <inheritdoc />
public async Task<List<ScoreOptionDto>> GetScoreOptionsAsync(long typeId)
{
_logger.LogDebug("获取评分标准选项typeId: {TypeId}", typeId);
var options = await _dbContext.ScoreOptions
.AsNoTracking()
.Where(s => s.AssessmentTypeId == typeId && s.Status == 1 && !s.IsDeleted)
.OrderBy(s => s.Sort)
.ThenBy(s => s.Score)
.Select(s => new ScoreOptionDto
{
Score = s.Score,
Label = s.Label,
Description = s.Description
})
.ToListAsync();
return options;
}
}

View File

@ -57,6 +57,8 @@ public partial class MiAssessmentDbContext : DbContext
public virtual DbSet<ReportCategory> ReportCategories { get; set; }
public virtual DbSet<ScoreOption> ScoreOptions { get; set; }
public virtual DbSet<Order> Orders { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
@ -990,6 +992,23 @@ public partial class MiAssessmentDbContext : DbContext
.HasComment("创建时间");
});
// ==================== 评分标准表配置 ====================
modelBuilder.Entity<ScoreOption>(entity =>
{
entity.HasKey(e => e.Id);
entity.ToTable("score_options");
entity.HasIndex(e => new { e.AssessmentTypeId, e.Score })
.IsUnique()
.HasFilter("([IsDeleted] = 0)");
entity.Property(e => e.Label).HasMaxLength(20);
entity.Property(e => e.Description).HasMaxLength(100);
entity.Property(e => e.Status).HasDefaultValue(1);
entity.Property(e => e.CreateTime).HasDefaultValueSql("(getdate())");
entity.Property(e => e.UpdateTime).HasDefaultValueSql("(getdate())");
});
OnModelCreatingPartial(modelBuilder);
}

View File

@ -0,0 +1,67 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace MiAssessment.Model.Entities;
/// <summary>
/// 评分标准选项表
/// </summary>
[Table("score_options")]
public class ScoreOption
{
/// <summary>
/// 主键ID
/// </summary>
[Key]
public long Id { get; set; }
/// <summary>
/// 测评类型ID
/// </summary>
public long AssessmentTypeId { get; set; }
/// <summary>
/// 分值1-10
/// </summary>
public int Score { get; set; }
/// <summary>
/// 等级标签(如:极弱、很弱)
/// </summary>
[Required]
[MaxLength(20)]
public string Label { get; set; } = null!;
/// <summary>
/// 描述(如:完全不符合)
/// </summary>
[Required]
[MaxLength(100)]
public string Description { get; set; } = null!;
/// <summary>
/// 排序
/// </summary>
public int Sort { get; set; }
/// <summary>
/// 状态0禁用 1启用
/// </summary>
public int Status { get; set; } = 1;
/// <summary>
/// 创建时间
/// </summary>
public DateTime CreateTime { get; set; }
/// <summary>
/// 更新时间
/// </summary>
public DateTime UpdateTime { get; set; }
/// <summary>
/// 软删除标记
/// </summary>
public bool IsDeleted { get; set; }
}

View File

@ -0,0 +1,22 @@
namespace MiAssessment.Model.Models.Assessment;
/// <summary>
/// 评分标准选项 DTO小程序端
/// </summary>
public class ScoreOptionDto
{
/// <summary>
/// 分值
/// </summary>
public int Score { get; set; }
/// <summary>
/// 等级标签
/// </summary>
public string Label { get; set; } = string.Empty;
/// <summary>
/// 描述
/// </summary>
public string Description { get; set; } = string.Empty;
}

View File

@ -72,6 +72,15 @@ export function getHistoryList(params = {}) {
return get('/assessment/getHistoryList', params)
}
/**
* 获取评分标准选项
* @param {number} typeId - 测评类型ID
* @returns {Promise<Object>}
*/
export function getScoreOptions(typeId) {
return get('/assessment/getScoreOptions', { typeId })
}
export default {
getIntro,
getQuestionList,
@ -79,5 +88,6 @@ export default {
getResultStatus,
getResult,
verifyInviteCode,
getHistoryList
getHistoryList,
getScoreOptions
}

View File

@ -12,7 +12,7 @@
import { ref, computed } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { useUserStore } from '@/store/user.js'
import { getQuestionList, submitAnswers } from '@/api/assessment.js'
import { getQuestionList, submitAnswers, getScoreOptions } from '@/api/assessment.js'
import Navbar from '@/components/Navbar/index.vue'
const userStore = useUserStore()
@ -38,8 +38,8 @@ const unansweredQuestions = ref([])
// scroll-view
const scrollTarget = ref('')
//
const scoreOptions = [
//
const scoreOptions = ref([
{ score: 1, label: '极弱', desc: '完全不符合' },
{ score: 2, label: '很弱', desc: '几乎不符合' },
{ score: 3, label: '较弱', desc: '偶尔符合' },
@ -50,7 +50,7 @@ const scoreOptions = [
{ score: 8, label: '较强', desc: '绝大多数情况符合' },
{ score: 9, label: '很强', desc: '偶尔不符合' },
{ score: 10, label: '极强', desc: '完全符合' }
]
])
/** 已答题数量 */
const answeredCount = computed(() => Object.keys(answers.value).length)
@ -62,14 +62,30 @@ const totalCount = computed(() => questions.value.length)
async function loadQuestions() {
pageLoading.value = true
try {
const res = await getQuestionList(typeId.value)
if (res && res.code === 0 && res.data) {
questions.value = res.data.list || res.data || []
//
const [questionsRes, scoreRes] = await Promise.all([
getQuestionList(typeId.value),
getScoreOptions(typeId.value)
])
//
if (questionsRes && questionsRes.code === 0 && questionsRes.data) {
questions.value = questionsRes.data.list || questionsRes.data || []
} else {
questions.value = generateMockQuestions()
}
//
if (scoreRes && scoreRes.code === 0 && scoreRes.data && scoreRes.data.length > 0) {
scoreOptions.value = scoreRes.data.map(item => ({
score: item.score,
label: item.label,
desc: item.description
}))
}
//
} catch (error) {
console.error('加载题目失败:', error)
console.error('加载数据失败:', error)
questions.value = generateMockQuestions()
} finally {
pageLoading.value = false
@ -125,7 +141,7 @@ async function handleSubmit() {
const answerList = questions.value.map((q, index) => {
const qId = q.id || index + 1
const scoreIndex = answers.value[qId]
return { questionId: qId, score: scoreOptions[scoreIndex].score }
return { questionId: qId, score: scoreOptions.value[scoreIndex].score }
})
const res = await submitAnswers({