feat(userscore): 新增用户评分功能
- 添加 UserScore20250801 相关实体、DTO 和 API 控制器 - 实现用户评分列表、专家列表和提交评分的功能- 添加前端页面以展示和提交评分数据 - 优化评分计算逻辑,处理最高分和最低分
This commit is contained in:
@@ -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; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;"
|
||||
},
|
||||
{
|
||||
//不知道干什么用的
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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);
|
||||
// }
|
||||
}
|
||||
}
|
||||
26
20220330_Vote/Vote.Services/Dto/UserScore20250801.cs
Normal file
26
20220330_Vote/Vote.Services/Dto/UserScore20250801.cs
Normal 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; }
|
||||
}
|
||||
55
20220330_Vote/Vote.Services/Entities/userscore20250801.cs
Normal file
55
20220330_Vote/Vote.Services/Entities/userscore20250801.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
投票记录
|
||||
|
||||
Reference in New Issue
Block a user