feat(userscore): 新增用户评分功能

- 添加 UserScore20250801 相关实体、DTO 和 API 控制器
- 实现用户评分列表、专家列表和提交评分的功能- 添加前端页面以展示和提交评分数据
- 优化评分计算逻辑,处理最高分和最低分
This commit is contained in:
路 范
2025-08-02 23:41:25 +08:00
parent d3d393305d
commit d88e4c0bcf
9 changed files with 796 additions and 18 deletions

View File

@@ -33,8 +33,7 @@ namespace Ewide.Core
InitKeyType = InitKeyType.Attribute,
MoreSettings = new ConnMoreSettings()
{
IsAutoRemoveDataCache = true//自动清理缓存
IsAutoRemoveDataCache = true //自动清理缓存
},
ConfigureExternalServices = new ConfigureExternalServices()
{
@@ -50,10 +49,11 @@ namespace Ewide.Core
EntityService = (type, column) =>
{
var attributes = type.GetCustomAttributes(true);
if (attributes.Any(it => it is KeyAttribute))// by attribute set primarykey
if (attributes.Any(it => it is KeyAttribute)) // by attribute set primarykey
{
column.IsPrimarykey = true; //有哪些特性可以看 1.2 特性明细
}
if (attributes.Any(it => it is ColumnAttribute))
{
column.DbColumnName = (attributes.First(it => it is ColumnAttribute) as ColumnAttribute).Name;
@@ -97,19 +97,25 @@ namespace Ewide.Core
{
Console.ForegroundColor = ConsoleColor.Green;
}
if (sql.StartsWith("UPDATE") || sql.StartsWith("INSERT"))
{
Console.ForegroundColor = ConsoleColor.White;
}
if (sql.StartsWith("DELETE"))
{
Console.ForegroundColor = ConsoleColor.Blue;
}
//Console.WriteLine("Sql:" + "\r\n\r\n" + UtilMethods.GetSqlString(c.DbType, sql, pars));
App.PrintToMiniProfiler("SqlSugar", "Info", UtilMethods.GetSqlString(c.DbType, sql, pars));
$"DB:{c.ConfigId}, Sql:\r\n\r\n {UtilMethods.GetSqlString(c.DbType, sql, pars)}".LogInformation();
Debugger.Log(1, "", $"===================CurrentConfigId:{db.CurrentConnectionConfig.ConfigId} SqlSugar log started ===================\r\n");
Debugger.Log(2, "语句:", sql);
Debugger.Log(3, "参数:", string.Join(",", pars?.Select(it => it.ParameterName + ":" + it.Value)));
Debugger.Log(4, "", $"===================CurrentConfigId:{db.CurrentConnectionConfig.ConfigId} SqlSugar log end ===================\r\n");
};
dbProvider.Aop.DataExecuting = (oldValue, entityInfo) =>
@@ -160,7 +166,7 @@ namespace Ewide.Core
//}
};
/*
/*
* 使用 SqlSugarScope 循环配置此项的时候会覆盖整个 ConfigureExternalServices
* 移动到 New ConnectionConfig中配置
*/
@@ -197,7 +203,6 @@ namespace Ewide.Core
// }); //将Lambda传入过滤器
// }
//}
}
});
services.AddSingleton<ISqlSugarClient>(sqlSugarScope);
@@ -235,6 +240,7 @@ namespace Ewide.Core
if (App.User == null) return false;
return App.User.FindFirst(ClaimConst.CLAINM_SUPERADMIN)?.Value == AdminType.SuperAdmin.GetHashCode().ToString();
}
/// <summary>
/// 添加 SqlSugar 拓展
/// </summary>
@@ -280,4 +286,4 @@ namespace Ewide.Core
public bool Enabled { get; set; }
public string ProviderName { get; set; }
}
}
}

View File

@@ -16,8 +16,7 @@ public static class StringExtensions
public static string ToCamelCase(this string str, char split = '_', bool initialsUppder = true)
{
var _ = string.Join("",
str.Split(split).Select(p => p.Length > 1 ?
p.First().ToString().ToUpper() + p[1..] : p.ToUpper()
str.Split(split).Select(p => p.Length > 1 ? p.First().ToString().ToUpper() + p[1..] : p.ToUpper()
)
);
@@ -45,4 +44,9 @@ public static class StringExtensions
return _.ToLower();
}
}
public static DateTime GetNow(this DateTime timestamp)
{
return DateTimeOffset.Now.ToOffset(TimeSpan.FromHours(8)).DateTime;
}
}

View File

@@ -22,7 +22,7 @@
"Id": "118_3310_ewide",
"DBType": 0,
"Enabled": true,
"ConnectionString": ""
"ConnectionString": "Data Source=10.19.94.20;Port=3310;Database=yongjiangbei_vote;User ID=root;Password=Ewide.;pooling=true;sslmode=none;CharSet=utf8;"
},
{
//不知道干什么用的

View File

@@ -26,22 +26,28 @@
}
]
},
"AllowedHosts": "*",
"CorsAccessorSettings": {
"PolicyName": "自定义跨域策略名",
"WithOrigins": [ "http://localhost:8080", "https://mapi.zjzwfw.gov.cn" ]
"WithOrigins": [
"http://localhost:8080",
"https://mapi.zjzwfw.gov.cn"
]
},
"AppSettings": {
"InjectSpecificationDocument1": false
},
"OSSProvider": {
"Provider": "HuaweiCloud", //枚举值支持Minio/Aliyun/QCloud
"Endpoint": "http://10.74.25.87:6020", //腾讯云中表示AppId
"Region": "", //地域
"Provider": "HuaweiCloud",
//枚举值支持Minio/Aliyun/QCloud
"Endpoint": "http://10.74.25.87:6020",
//腾讯云中表示AppId
"Region": "",
//地域
"AccessKey": "C4D30C2801D928AAF687",
"SecretKey": "ooZVXaB1tqIz7DHTv53RILD7o5cAAAGAAdkoqlR2",
"IsEnableCache": true //是否启用缓存,推荐开启
"IsEnableCache": true
//是否启用缓存,推荐开启
},
"NingboZhiChun": {
"OpenSms": 0,
@@ -55,6 +61,8 @@
"SanjuKey": "vPFu7zKB08Uaxuzsc5zozAAT6W0zr3qw",
"GetCommunitys": "http://sjk.test.ky.com/housesafety/statistics/GetCommunitys?searchName={0}",
"GetHouseInfoCitysByCommunity": "http://sjk.test.ky.com/housesafety/statistics/GetHouseInfoCitysByCommunity?communityID={0}"
},
"UserScore": {
"ExpertNumber": 10
}
}

View File

@@ -0,0 +1,347 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0,
maximum-scale=1.0, user-scalable=no"/>
<link rel="stylesheet" href="../../lib/element-ui/theme-chalk/index.css">
<script src="../../lib/vue2/vue.min.js"></script>
<script src="../../lib/element-ui/theme-chalk/index.js"></script>
<script src="../../lib/axios/axios.min.js"></script>
<script src="../../lib/qs/qs.min.js"></script>
</head>
<body>
<div id="app" v-loading="loading">
<h3 style="text-align:center;">2025年度XXXXXXXXXXXXX打分</h3>
<el-table v-loading="loading" :data="detailList" border>
<el-table-column label="编号" align="center" width="60">
<template slot-scope="scope">
<span>{{scope.row.no}}</span>
</template>
</el-table-column>
<el-table-column label="姓名" align="center" width="80">
<template slot-scope="scope">
<span>{{scope.row.name}}</span>
</template>
</el-table-column>
<el-table-column label="岗位" align="center">
<template slot-scope="scope">
<span>{{scope.row.postion}}</span>
</template>
</el-table-column>
<el-table-column label="标语" align="center">
<template slot-scope="scope">
<span>{{scope.row.title}}</span>
</template>
</el-table-column>
<el-table-column width="100"
v-for="column in dynamicColumns"
:key="column.prop"
:prop="column.prop"
:label="column.label"
>
<template #default="scope">
<el-input
v-model="scope.row[column.prop]"
@blur="handleBlur(scope.row, column.prop)"
:style="getScoreStyle(scope.row, column.prop)"
class="score-input"
/>
</template>
</el-table-column>
<el-table-column label="最终得分" align="center" width="100">
<template slot-scope="scope">
<span>{{scope.row.finalscore || '0'}}</span>
</template>
</el-table-column>
<el-table-column label="排名" align="center" width="80" :cell-class-name="rankCellClass">
<template slot-scope="scope">
<span>{{ getRank(scope.row) }}</span>
</template>
</el-table-column>
<!-- <el-table-column label="操作" align="center" class-name="small-padding fixed-width">-->
<!-- <template slot-scope="scope">-->
<!-- <el-button-->
<!-- size="mini"-->
<!-- type="text"-->
<!-- icon="el-icon-edit"-->
<!-- @click="handleUpdate(scope.row)"-->
<!-- v-hasPermi="['detail:bill:edit']"-->
<!-- >修改-->
<!-- </el-button>-->
<!-- <el-button-->
<!-- size="mini"-->
<!-- type="text"-->
<!-- icon="el-icon-delete"-->
<!-- @click="handleDelete(scope.row)"-->
<!-- v-hasPermi="['detail:bill:remove']"-->
<!-- >删除-->
<!-- </el-button>-->
<!-- </template>-->
<!-- </el-table-column>-->
</el-table>
<!-- <h3 style="text-align:center;">-->
<!-- <el-input v-model="logincode" placeholder="请输入提交码"></el-input>-->
<!-- </h3>-->
<h3 style="text-align:center;">
<!-- <el-button @click="alltrue">重置</el-button>-->
<el-button type="primary" @click="submit">提交</el-button>
</h3>
</div>
</body>
<script>
new Vue({
el: '#app',
data: function () {
return {
detailList: [],
dynamicColumns: [],
confirm_title: '',
loading: false,
logincode: ''
}
},
created: function () {
this.loading = true;
this.load_projects();
},
methods: {
rankCellClass({ row }) {
const rank = this.getRank(row);
if (rank === 1) return 'rank-1';
if (rank === 2) return 'rank-2';
if (rank === 3) return 'rank-3';
return '';
},
getRank(row) {
// 创建分数副本并排序
const sorted = [...this.detailList]
.sort((a, b) => (b.finalscore || 0) - (a.finalscore || 0))
.map(item => item.finalscore || 0);
// 处理相同分数排名90,90,85 显示为1,1,3
const score = parseFloat(row.finalscore) || 0;
const firstIndex = sorted.findIndex(s => s === score);
return firstIndex >= 0 ? firstIndex + 1 : '-';
},
// 新增方法:获取最高分和最低分
getMinMaxScores(row) {
const scores = this.dynamicColumns
.map(expert => {
const val = row[expert.prop];
// 处理空字符串和无效值
return val === '' ? 0 : parseFloat(val) || 0;
})
.filter(score => score > 0);
if (scores.length < 1) return {min: 0, max: 0};
const sorted = [...scores].sort((a, b) => a - b);
return {
min: sorted[0],
max: sorted[sorted.length - 1]
};
},
// 新增方法:计算最终得分
calculateFinalScore(row) {
const scores = this.dynamicColumns
.map(expert => parseFloat(row[expert.prop]) || 0)
.filter(score => score > 0);
// if (scores.length <= 2) return '0';
if (scores.length < 3) return '0';
const sorted = [...scores].sort((a, b) => a - b);
sorted.pop(); // 去掉最高分
sorted.shift(); // 去掉最低分
const avg = sorted.reduce((a, b) => a + b, 0) / sorted.length;
return avg.toFixed(2);
},
// 新增方法:设置分数颜色
getScoreStyle(row, prop) {
const score = parseFloat(row[prop]) || 0;
const {min, max} = this.getMinMaxScores(row);
// 精确到小数点后两位比较
const current = Number(score.toFixed(2));
const minVal = Number(min.toFixed(2));
const maxVal = Number(max.toFixed(2));
if (current === maxVal && current > 0) {
return row[prop]?.toString() === maxVal?.toString() ?
{'--bg-color': '#ffd8d8', '--text-color': '#ff0000'} : {};
}
if (current === minVal && current > 0) {
return row[prop]?.toString() === minVal?.toString() ?
{'--bg-color': '#d8e3ff', '--text-color': '#0000ff'} : {};
}
return {};
},
handleBlur(row, prop) {
const score = parseFloat(row[prop]);
if (isNaN(score) || score < 0 || score > 100) {
this.$message.error('请输入0-100之间的数字');
row[prop] = ''; // 清除非法输入
} else {
// 实时更新最终得分
row.finalscore = this.calculateFinalScore(row);
}
// 强制更新视图
this.$set(row, prop, row[prop]);
},
alltrue() {
this.projects.map(a => {
a.data.map(b => {
b.vote = "true";
return b;
})
});
},
async submit() {
let _this = this;
this.$confirm('确定保存吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
_this.loading = true;
// 构建提交数据结构
const submitData = _this.detailList.map(user => ({
userId: user.id,
scores: _this.dynamicColumns.map(expert => ({
expertId: expert.prop,
score: parseFloat(user[expert.prop]) || ''
})),
finalscore: user.finalscore // 携带最终得分
}));
axios({
headers: {'Content-Type': 'application/json;charset=UTF-8'},
method: 'post',
url: '/gb/yjb/api/userscore20250801/submit',
data: submitData,
responseType: "json",
}).then(async response => {
if (response.data.data != true) {
alert(response.data.message);
} else {
alert("保存成功");
}
_this.loading = false;
}).catch(async error => {
console.log(error)
_this.$message({
type: 'error',
message: error.message
})
_this.loading = false;
})
}).catch(() => {
});
},
load_projects() {
let _this = this;
Promise.all([
axios.post('/gb/yjb/api/userscore20250801/list'),
axios.post('/gb/yjb/api/userscore20250801/Experts')
]).then(([usersRes, expertsRes]) => {
_this.detailList = usersRes.data.data.map(user => {
// 解析历史分数
const scores = JSON.parse(user.scoresjson || '[]');
const scoreMap = Object.fromEntries(
scores.map(s => [s.expertId, s.score])
);
return {
...user,
// 初始化动态列字段(保留历史值)
...Object.fromEntries(expertsRes.data.data.map(expert => [
expert.prop,
scoreMap[expert.prop] || ''
]))
};
// ...user,
// // 初始化动态列字段
// ...Object.fromEntries(expertsRes.data.data.map(expert =>
// [expert.prop, user[expert.prop] || ''])
// )
});
_this.dynamicColumns = expertsRes.data.data;
}).finally(() => {
_this.loading = false;
});
// let _this = this;
// axios({
// headers: {'Content-Type': 'application/json;charset=UTF-8'},
// method: 'post',
// url: '/gb/yjb/api/userscore20250801/list',
// data: {},
// responseType: "json",
// }).then(function (response) {
// console.log(response);
// let _data = response.data.data
// _this.detailList = _data;
// _this.loading = false;
// }).catch(function (error) {
// console.log(error)
// _this.$message({
// type: 'error',
// message: error.message
// })
// _this.loading = false;
// })
// axios({
// headers: {'Content-Type': 'application/json;charset=UTF-8'},
// method: 'post',
// url: '/gb/yjb/api/userscore20250801/Experts',
// data: {},
// responseType: "json",
// }).then(function (response) {
// console.log(response);
// let _data = response.data.data
// _this.dynamicColumns = _data;
// _this.loading = false;
// }).catch(function (error) {
// console.log(error)
// _this.$message({
// type: 'error',
// message: error.message
// })
// _this.loading = false;
// })
},
loading_false() {
this.loading = false
},
}
})
</script>
<style scoped>
.score-input > .el-input__inner {
background-color: var(--bg-color, inherit) !important;
color: var(--text-color, inherit) !important;
/*text-align: center;*/
font-weight: bold;
}
/* 新增排名样式 */
.el-table /deep/ .rank-1 {
background-color: #e1f3d8 !important;
font-weight: bold;
text-align: center;
}
.el-table /deep/ .rank-2 {
background-color: #f0f9eb !important;
text-align: center;
}
.el-table /deep/ .rank-3 {
background-color: #fdf6ec !important;
text-align: center;
}
</style>
</html>

View File

@@ -0,0 +1,289 @@
using Ewide.Core.Util;
using Furion.DatabaseAccessor;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Furion;
using Newtonsoft.Json;
using SqlSugar;
using Vote.Services.Dto;
namespace Vote.Services.ApiController
{
/// <summary>
/// 项目
/// </summary>
[ApiDescriptionSettings("userscore", Order = 0)]
[Route("/gb/yjb/api/userscore20250801")]
public class UserScore20250801Service : IDynamicApiController
{
private readonly IRepository<Entities.userscores20250801> repuserscore20250801;
private readonly Ewide.Core.SqlSugarRepository<Entities.userscores20250801> repuserscore;
public UserScore20250801Service(IRepository<Entities.userscores20250801> _repuserscore20250801
, Ewide.Core.SqlSugarRepository<Entities.userscores20250801> _repuserscore)
{
repuserscore20250801 = _repuserscore20250801;
repuserscore = _repuserscore;
}
/// <summary>
/// 列表
/// </summary>
/// <returns></returns>
[HttpPost]
[Microsoft.AspNetCore.Authorization.AllowAnonymous]
public async Task<dynamic> List()
{
var data = await repuserscore.AsQueryable()
.OrderBy(a => a.No)
.ToListAsync();
// var data = await repuserscore20250801.DetachedEntities
// .OrderBy(a => a.No)
// .ToListAsync();
return data;
}
[HttpPost]
[Microsoft.AspNetCore.Authorization.AllowAnonymous]
public async Task<dynamic> Experts()
{
var list = new List<ExpertColumn>();
var number = App.GetConfig<int>("UserScore:ExpertNumber");
for (int i = 1; i < number + 1; i++)
{
list.Add(new ExpertColumn() { prop = "expert" + i, label = "专家" + i });
}
return list;
}
/// <summary>
/// 提交
/// </summary>
/// <returns></returns>
[HttpPost]
[UnitOfWork]
[Microsoft.AspNetCore.Authorization.AllowAnonymous]
public async Task<dynamic> SubmitSubmit(List<SubmitEntity> args)
{
var list = await repuserscore.AsQueryable().ToListAsync();
foreach (var entity in list)
{
var submituser = args.FirstOrDefault(a => a.userId == entity.Id);
if (submituser == null)
continue;
entity.scoresjson = JsonConvert.SerializeObject(submituser.scores);
entity.finalscore = submituser.finalscore;
entity.UpdatedTime = DateTime.Now.GetNow();
}
var r = await repuserscore.UpdateAsync(list); //.AsUpdateable(list) //.UpdateColumns(it => new { it.scoresjson, it.finalscore, it.UpdatedTime })
// .ExecuteCommandAsync();
// args.ForEach(async submituser =>
// {
// //计算平均分
// var scores = submituser.scores;
// // // 修正排序逻辑:先按分数升序排列,再排除首尾元素
// // var sortedScores = scores.OrderBy(x => x.score).ToList();
// // if (sortedScores.Count > 2)
// // {
// // sortedScores.RemoveAt(sortedScores.Count - 1); // 移除最高分
// // sortedScores.RemoveAt(0); // 移除最低分
// // }
// //
// // //取2位小数使用处理后的分数
// // var finalscore = Math.Round(sortedScores.Sum(a => a.score) / sortedScores.Count, 2);
// //根据id更新
// var entity = list.FirstOrDefault(a => a.Id == submituser.userId);
// entity.scoresjson = JsonConvert.SerializeObject(submituser.scores);
// entity.finalscore = submituser.finalscore;
// entity.UpdatedTime = DateTime.Now.GetNow();
// });
// var r = await repuserscore.AsUpdateable(entity).UpdateColumns(it => new { it.scoresjson, it.finalscore }).ExecuteCommandAsync();
//
return r == list.Count;
}
// /// <summary>
// /// 检验提交码
// /// </summary>
// /// <returns></returns>
// [HttpPost]
// [Microsoft.AspNetCore.Authorization.AllowAnonymous]
// public async Task<dynamic> CheckSubmitCode(CheckSubmitCodeInput args)
// {
// var data = await rep_Experts.DetachedEntities.Where(p => !p.IsDeleted)
// .Where(a => a.login_code == args.code)
// .FirstOrDefaultAsync();
// return data != null;
// }
//
//
// /// <summary>
// /// 提交
// /// </summary>
// /// <returns></returns>
// [HttpPost]
// [UnitOfWork]
// [Microsoft.AspNetCore.Authorization.AllowAnonymous]
// public async Task<dynamic> SubmitSubmitVote(SubmitInput args)
// {
// var data = await rep_Experts.DetachedEntities.Where(p => !p.IsDeleted)
// .Where(a => a.login_code == args.code)
// .FirstOrDefaultAsync();
// _ = (data == null) ? throw Oops.Oh("提交码错误") : 1;
// //var list = args.projects.Adapt<List<Entities.VoteRecords>>();
// //删除这个专家上次提交的结果
// //或者提示不能再次提交
// _ = (await rep_VoteRecords.DetachedEntities.Where(a => !a.IsDeleted && a.expert_login_code == args.code).CountAsync() > 0) ? throw Oops.Oh("已提交,无需再次提交") : 1;
// var now = DateTime.Now;
// args.projects.ForEach(async a =>
// {
// var model = new Entities.VoteRecords
// {
// expert_login_code = args.code,
// project_id = a.id,
// is_agree = a.vote,
// vote_time = now
// };
// await model.InsertOrUpdate();
// });
// return true;
// }
//
// private async Task<List<ProjectsList2Output>> GetVoteData()
// {
// var query = from a in rep_Projects.DetachedEntities
// join b in rep_VoteRecords.DetachedEntities
// on a.Id equals b.project_id into grouping
// from p in grouping.DefaultIfEmpty()
// group new { a, p } by new { a.Id, a.name, a.serial_number, a.type }
// into pp
// select new ProjectsList2Output
// {
// serial_number = pp.Key.serial_number,
// id = pp.Key.Id,
// name = pp.Key.name,
// yes_count = pp.Where(a => a.p.is_agree).Count(),
// no_count = pp.Where(a => !a.p.is_agree).Count(),
// type = pp.Key.type
// };
// return await query.OrderBy(a => a.serial_number).ToListAsync();
// }
//
// /// <summary>
// /// 列表
// /// </summary>
// /// <returns></returns>
// [HttpPost]
// public async Task<dynamic> List2()
// {
// //var data = rep_Projects.DetachedEntities.Where(p => !p.IsDeleted)
// // //.Where(args.type != null, a => (int)a.type == args.type)
// // .Join(rep_VoteRecords.DetachedEntities, a => a.Id, a => a.project_id, (a, b) =>
// // new
// // {
// // //a.Id,
// // //type = (int)a.type,
// // //serial_number = a.serial_number,
// // //name = a.name,
// // //no_count = b.Where(bb => !bb.is_agree).Count(),
// // //yes_count = b.Where(bb => bb.is_agree).Count(),
// // }).ToList();
// ////.ProjectToType<ProjectsList2Output>()
// ////.OrderBy(a => a.serial_number)
// ////.ToListAsync();
// var data = await GetVoteData();
// //var data0 = data.Where(a => a.type == Entities.EnumProjectType.FangJian).ToList();
// //var data1 = data.Where(a => a.type == Entities.EnumProjectType.ShiZheng).ToList();
// //var data2 = data.Where(a => a.type == Entities.EnumProjectType.GuiDaoGongCheng).ToList();
// //var data3 = data.Where(a => a.type == Entities.EnumProjectType.DianLiGongCheng).ToList();
// //var data4 = data.Where(a => a.type == Entities.EnumProjectType.JiaoTongGongCheng).ToList();
// //var data5 = data.Where(a => a.type == Entities.EnumProjectType.ShuiLiGongCheng).ToList();
// //return new
// //{
// // data0,
// // data1,
// // data2,
// // data3,
// // data4,
// // data5
// //};
// var typeList = new List<string> { "房建工程", "市政工程", "轨道交通工程" }; //, "电力工程", "交通工程", "水利工程" };
// return new { data, typeList };
// }
//
// /// <summary>
// ///
// /// </summary>
// /// <returns></returns>
// public async Task<dynamic> Download()
// {
// var data = await GetVoteData();
// //var filepath = Tools.ExcelHelper.WriteTemplate(data, 4, "C");
// string template_name = "2024年度宁波市结构优质认定项目投票结果.xlsx";
// var filepath = Tools.ExcelHelper.WriteTemplate(template_name, data, 5, "C");
// return new FileStreamResult(new FileStream(filepath, FileMode.Open), "application/octet-stream") { FileDownloadName = filepath };
// }
//
// /// <summary>
// ///
// /// </summary>
// /// <returns></returns>
// public async Task<dynamic> ExpertVote()
// {
// var list = await rep_Experts.DetachedEntities.GroupJoin(rep_VoteRecords.DetachedEntities, a => a.login_code, a => a.expert_login_code, (a, b) => new { a, b })
// .SelectMany(a => a.b.DefaultIfEmpty(), (a, b) => new { a.a.Id, a.a.login_code, is_vote = b != null })
// .Distinct()
// .OrderBy(a => a.Id)
// .ToListAsync();
// return list;
// //var query = from a in rep_Experts.DetachedEntities
// // join b in rep_VoteRecords.DetachedEntities on a.login_code equals b.expert_login_code into temp
// // from tt in temp.DefaultIfEmpty()
// // select new
// // {
// // a.Id,
// // a.login_code,
// // is_vote = tt == null
// // };
// //return await query.ToListAsync();
// }
//
// /// <summary>
// /// 新增专家
// /// </summary>
// /// <returns></returns>
// [HttpPost]
// public async Task AddExpert(AddExpertInput args)
// {
// if (args == null || args.expertnum <= 0)
// throw Oops.Oh("参数异常");
// var list = new List<Experts>();
// for (int i = 0; i < args.expertnum; i++)
// {
// var newid = Ulid.NewUlid().ToString();
// var newidsimple = newid.ToUpper().Replace("I", "").Replace("L", "").Replace("0", "").Replace("O", "").Replace("1", "");
// list.Add(new Experts
// {
// Id = newid,
// login_code = newidsimple.Substring(newidsimple.Length - 6, 6),
// CreatedTime = DateTime.Now
// });
// }
//
// await rep_Experts.InsertAsync(list);
// }
}
}

View File

@@ -0,0 +1,26 @@
using System.Collections.Generic;
namespace Vote.Services.Dto;
public class UserScore20250801
{
}
public class ExpertColumn
{
public string prop { get; set; }
public string label { get; set; }
}
public class SubmitEntity
{
public string userId { get; set; }
public List<UserScoreInput> scores { get; set; }
public decimal finalscore { get; set; }
}
public class UserScoreInput
{
public string expertId { get; set; }
public decimal? score { get; set; }
}

View File

@@ -0,0 +1,55 @@
using System;
using System.ComponentModel;
using Ewide.Core;
using SqlSugar;
namespace Vote.Services.Entities;
[SqlSugar.SugarTable]
[Serializable]
public class userscores20250801 : DEntityBase
{
public userscores20250801()
{
this.No = 0;
this.Title = "";
this.Postion = "";
this.Name = "";
}
/// <summary>
///
/// </summary>
[Description("")]
public int? No { get; set; }
/// <summary>
///
/// </summary>
[Description("")]
public string Title { get; set; }
/// <summary>
///
/// </summary>
[Description("")]
public string Postion { get; set; }
/// <summary>
///
/// </summary>
[Description("")]
public string Name { get; set; }
public string scoresjson { get; set; }
public decimal? finalscore { get; set; }
/// <summary>
/// 创建默认的主键值
/// <para>当构造函数执行时如果Id为空则会自动执行该函数</para>
/// </summary>
public void GenerateDefaultKeyVal()
{
Id = Ulid.NewUlid().ToString(); // Guid.NewGuid().ToString();
}
}

View File

@@ -297,6 +297,23 @@
</summary>
<returns></returns>
</member>
<member name="T:Vote.Services.ApiController.UserScore20250801Service">
<summary>
项目
</summary>
</member>
<member name="M:Vote.Services.ApiController.UserScore20250801Service.List">
<summary>
列表
</summary>
<returns></returns>
</member>
<member name="M:Vote.Services.ApiController.UserScore20250801Service.SubmitSubmit(System.Collections.Generic.List{Vote.Services.Dto.SubmitEntity})">
<summary>
提交
</summary>
<returns></returns>
</member>
<member name="T:Vote.Services.ApiController.WxService">
<summary>
微信
@@ -1068,6 +1085,32 @@
</summary>
</member>
<member name="P:Vote.Services.Entities.userscores20250801.No">
<summary>
</summary>
</member>
<member name="P:Vote.Services.Entities.userscores20250801.Title">
<summary>
</summary>
</member>
<member name="P:Vote.Services.Entities.userscores20250801.Postion">
<summary>
</summary>
</member>
<member name="P:Vote.Services.Entities.userscores20250801.Name">
<summary>
</summary>
</member>
<member name="M:Vote.Services.Entities.userscores20250801.GenerateDefaultKeyVal">
<summary>
创建默认的主键值
<para>当构造函数执行时如果Id为空则会自动执行该函数</para>
</summary>
</member>
<member name="T:Vote.Services.Entities.VoteRecords">
<summary>
投票记录