initial
commit
60131e4608
|
|
@ -0,0 +1,25 @@
|
|||
**/.classpath
|
||||
**/.dockerignore
|
||||
**/.env
|
||||
**/.git
|
||||
**/.gitignore
|
||||
**/.project
|
||||
**/.settings
|
||||
**/.toolstarget
|
||||
**/.vs
|
||||
**/.vscode
|
||||
**/*.*proj.user
|
||||
**/*.dbmdl
|
||||
**/*.jfm
|
||||
**/azds.yaml
|
||||
**/bin
|
||||
**/charts
|
||||
**/docker-compose*
|
||||
**/Dockerfile*
|
||||
**/node_modules
|
||||
**/npm-debug.log
|
||||
**/obj
|
||||
**/secrets.dev.yaml
|
||||
**/values.dev.yaml
|
||||
LICENSE
|
||||
README.md
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
kind: pipeline
|
||||
type: docker
|
||||
name: build
|
||||
|
||||
|
||||
steps:
|
||||
- name: build
|
||||
image: docker
|
||||
commands:
|
||||
- docker build -t eva-nx-backend .
|
||||
|
||||
volumes:
|
||||
- name: cache
|
||||
path: /var/run/docker.sock
|
||||
|
||||
trigger:
|
||||
branch:
|
||||
- master
|
||||
- dev
|
||||
event:
|
||||
- push
|
||||
- pull_request
|
||||
- rollback
|
||||
|
||||
volumes:
|
||||
- name: cache
|
||||
host:
|
||||
path: /var/run/docker.sock
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
type: exec
|
||||
name: deploy
|
||||
|
||||
platform:
|
||||
os: linux
|
||||
arзуh: amd64
|
||||
|
||||
steps:
|
||||
- name: deploy
|
||||
commands:
|
||||
- cd /app/dockerapps/joinus-backend-2021/
|
||||
- docker-compose up -d
|
||||
- docker image prune -f
|
||||
|
||||
depends_on:
|
||||
- build
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
###############################################################################
|
||||
# Set default behavior to automatically normalize line endings.
|
||||
###############################################################################
|
||||
* text=auto
|
||||
|
||||
###############################################################################
|
||||
# Set default behavior for command prompt diff.
|
||||
#
|
||||
# This is need for earlier builds of msysgit that does not have it on by
|
||||
# default for csharp files.
|
||||
# Note: This is only used by command line
|
||||
###############################################################################
|
||||
#*.cs diff=csharp
|
||||
|
||||
###############################################################################
|
||||
# Set the merge driver for project and solution files
|
||||
#
|
||||
# Merging from the command prompt will add diff markers to the files if there
|
||||
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
||||
# the diff markers are never inserted). Diff markers may cause the following
|
||||
# file extensions to fail to load in VS. An alternative would be to treat
|
||||
# these files as binary and thus will always conflict and require user
|
||||
# intervention with every merge. To do so, just uncomment the entries below
|
||||
###############################################################################
|
||||
#*.sln merge=binary
|
||||
#*.csproj merge=binary
|
||||
#*.vbproj merge=binary
|
||||
#*.vcxproj merge=binary
|
||||
#*.vcproj merge=binary
|
||||
#*.dbproj merge=binary
|
||||
#*.fsproj merge=binary
|
||||
#*.lsproj merge=binary
|
||||
#*.wixproj merge=binary
|
||||
#*.modelproj merge=binary
|
||||
#*.sqlproj merge=binary
|
||||
#*.wwaproj merge=binary
|
||||
|
||||
###############################################################################
|
||||
# behavior for image files
|
||||
#
|
||||
# image files are treated as binary by default.
|
||||
###############################################################################
|
||||
#*.jpg binary
|
||||
#*.png binary
|
||||
#*.gif binary
|
||||
|
||||
###############################################################################
|
||||
# diff behavior for common document formats
|
||||
#
|
||||
# Convert binary document formats to text before diffing them. This feature
|
||||
# is only available from the command line. Turn it on by uncommenting the
|
||||
# entries below.
|
||||
###############################################################################
|
||||
#*.doc diff=astextplain
|
||||
#*.DOC diff=astextplain
|
||||
#*.docx diff=astextplain
|
||||
#*.DOCX diff=astextplain
|
||||
#*.dot diff=astextplain
|
||||
#*.DOT diff=astextplain
|
||||
#*.pdf diff=astextplain
|
||||
#*.PDF diff=astextplain
|
||||
#*.rtf diff=astextplain
|
||||
#*.RTF diff=astextplain
|
||||
|
|
@ -0,0 +1,349 @@
|
|||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
##
|
||||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
[Aa][Rr][Mm]/
|
||||
[Aa][Rr][Mm]64/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
|
||||
# Visual Studio 2015/2017 cache/options directory
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# Visual Studio 2017 auto generated files
|
||||
Generated\ Files/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# NUNIT
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# Benchmark Results
|
||||
BenchmarkDotNet.Artifacts/
|
||||
|
||||
# .NET Core
|
||||
project.lock.json
|
||||
project.fragment.lock.json
|
||||
artifacts/
|
||||
|
||||
# StyleCop
|
||||
StyleCopReport.xml
|
||||
|
||||
# Files built by Visual Studio
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_h.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.iobj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.ipdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*_wpftmp.csproj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# Visual Studio Trace Files
|
||||
*.e2e
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# JustCode is a .NET coding add-in
|
||||
.JustCode
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# AxoCover is a Code Coverage Tool
|
||||
.axoCover/*
|
||||
!.axoCover/settings.json
|
||||
|
||||
# Visual Studio code coverage results
|
||||
*.coverage
|
||||
*.coveragexml
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
nCrunchTemp_*
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||
# in these scripts will be unencrypted
|
||||
PublishScripts/
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/[Pp]ackages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/[Pp]ackages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/[Pp]ackages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignorable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
|
||||
# Windows Store app package directories and files
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
Package.StoreAssociation.xml
|
||||
_pkginfo.txt
|
||||
*.appx
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!?*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.jfm
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
orleans.codegen.cs
|
||||
|
||||
# Including strong name files can present a security risk
|
||||
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||
#*.snk
|
||||
|
||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||
#bower_components/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
ServiceFabricBackup/
|
||||
*.rptproj.bak
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
*.ndf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
*.rptproj.rsuser
|
||||
*- Backup*.rdl
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
node_modules/
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||
*.vbw
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# Paket dependency
|
||||
|
||||
|
||||
.paket/paket.exe
|
||||
paket-files/
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
# JetBrains Rider
|
||||
.idea/
|
||||
*.sln.iml
|
||||
|
||||
# CodeRush personal settings
|
||||
.cr/personal
|
||||
|
||||
# Python Tools for Visual Studio (PTVS)
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Cake - Uncomment if you are using it
|
||||
# tools/**
|
||||
# !tools/packages.config
|
||||
|
||||
# Tabs Studio
|
||||
*.tss
|
||||
|
||||
# Telerik's JustMock configuration file
|
||||
*.jmconfig
|
||||
|
||||
# BizTalk build output
|
||||
*.btp.cs
|
||||
*.btm.cs
|
||||
*.odx.cs
|
||||
*.xsd.cs
|
||||
|
||||
# OpenCover UI analysis results
|
||||
OpenCover/
|
||||
|
||||
# Azure Stream Analytics local run output
|
||||
ASALocalRun/
|
||||
|
||||
# MSBuild Binary and Structured Log
|
||||
*.binlog
|
||||
|
||||
# NVidia Nsight GPU debugger configuration file
|
||||
*.nvuser
|
||||
|
||||
# MFractors (Xamarin productivity tool) working folder
|
||||
.mfractor/
|
||||
|
||||
# Local History for Visual Studio
|
||||
.localhistory/
|
||||
|
||||
# BeatPulse healthcheck temp database
|
||||
healthchecksdb
|
||||
|
||||
assets/*
|
||||
exports/*
|
||||
exports
|
||||
photos
|
||||
students.zip
|
||||
photos/*
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<RootNamespace>_2021_backend</RootNamespace>
|
||||
<UserSecretsId>2023ab1c-9547-4989-a343-cd3428e085fe</UserSecretsId>
|
||||
<StartupObject>_2021_backend.Program</StartupObject>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<WarningLevel>0</WarningLevel>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="exports\**" />
|
||||
<Content Remove="exports\**" />
|
||||
<EmbeddedResource Remove="exports\**" />
|
||||
<None Remove="exports\**" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="itext7" Version="7.1.16" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.ViewFeatures" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.9" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.9" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.9" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="5.0.9">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="5.0.2" />
|
||||
<PackageReference Include="Nancy" Version="2.0.0" />
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="5.0.7" />
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL.Design" Version="1.1.0" />
|
||||
<PackageReference Include="NPOI" Version="2.5.4" />
|
||||
<PackageReference Include="TencentCloudSDK" Version="3.0.362" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.0.31612.314
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "2021-backend", "2021-backend.csproj", "{879DE3A8-39AB-47D1-A39A-448477C1285A}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{879DE3A8-39AB-47D1-A39A-448477C1285A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{879DE3A8-39AB-47D1-A39A-448477C1285A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{879DE3A8-39AB-47D1-A39A-448477C1285A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{879DE3A8-39AB-47D1-A39A-448477C1285A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {25338145-8695-4879-B267-5940D14DEE33}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
using _2021_backend.Data;
|
||||
using _2021_backend.Models;
|
||||
using _2021_backend.Utils;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace _2021_backend.Controllers
|
||||
{
|
||||
[Route("api/submit")]
|
||||
public class SubmissionController : Controller
|
||||
{
|
||||
public BackendContext Context;
|
||||
|
||||
public SubmissionController(BackendContext context)
|
||||
{
|
||||
Context = context;
|
||||
}
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> Post([FromForm] string dto)
|
||||
{
|
||||
var aDto = JsonSerializer.Deserialize<SubmissionDto>(dto);
|
||||
string ip = Request.Headers["X-Real-IP"].FirstOrDefault();
|
||||
if (aDto.Iscomplete() == false)
|
||||
return StatusCode(400, ApiResponse.Error("TICKET_INFO_INCOMPLETE"));
|
||||
if (aDto.Check() == false)
|
||||
return StatusCode(400, ApiResponse.Error("TICKET_NOT_LEGEAL"));
|
||||
Submission sub = new Submission(aDto, ip);
|
||||
foreach (var tm in Context.Sessions)
|
||||
{
|
||||
if (aDto.Timelist.Any(it => it.Day.Day == tm.Day.Day && it.BeginTime.TimeOfDay == tm.BeginTime.TimeOfDay))
|
||||
{
|
||||
sub.Timelist.Add(tm.Guid);
|
||||
}
|
||||
}
|
||||
var q = Context.Students.Where(stu => (stu.Name == aDto.Name || stu.Stuid == aDto.Stuid));
|
||||
Student stu;
|
||||
if (q.Count() == 0)
|
||||
{
|
||||
stu = Student.create(sub);
|
||||
stu.Status = status.刚报名;
|
||||
Context.Students.Add(stu);
|
||||
}
|
||||
else
|
||||
{
|
||||
stu = q.FirstOrDefault();
|
||||
stu.Update(sub);
|
||||
}
|
||||
sub.Host = stu.Guid;
|
||||
Context.Submissions.Add(sub);
|
||||
Context.SaveChanges();
|
||||
|
||||
//await TencentSMS.Send(Context, SMSType.Signed, stu, _2021_backend.Models.User.Bot.stuID);
|
||||
return Ok(ApiResponse.Success("success"));
|
||||
|
||||
}
|
||||
}
|
||||
[ApiController]
|
||||
[Route("api/sessionlist")]
|
||||
public class SessionlistContoller : Controller
|
||||
{
|
||||
private readonly BackendContext _context;
|
||||
public SessionlistContoller(BackendContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
[HttpGet]
|
||||
|
||||
public IActionResult GetSessions()
|
||||
{
|
||||
var query = _context.Sessions.OrderBy(r => r.Day).ThenBy(r => r.BeginTime).ThenBy(r => r.Place).Where(e => e.Capacity > e.Students.Count + 1).Select(r => new SessionDto
|
||||
{
|
||||
BeginTime = r.BeginTime,
|
||||
Day = r.Day,
|
||||
});
|
||||
return Ok(ApiResponse.Success(query.ToList().FindAll(it => it.Day.Add(it.BeginTime.TimeOfDay).CompareTo(DateTime.Now) > 0).Distinct(new SessionDtoComparer()).ToList()));
|
||||
//return Ok(ApiResponse.Success("报名结束了"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
using _2021_backend.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace _2021_backend.Data
|
||||
{
|
||||
public class BackendContext : DbContext
|
||||
{
|
||||
public BackendContext(DbContextOptions<BackendContext> options)
|
||||
: base(options)
|
||||
{
|
||||
}
|
||||
public DbSet<User> Users { get; set; }
|
||||
public DbSet<Submission> Submissions { get; set; }
|
||||
public DbSet<Comment> Comments { get; set; }
|
||||
public DbSet<Session> Sessions { get; set; }
|
||||
public DbSet<Student> Students { get; set; }
|
||||
public DbSet<SMS> SMS { get; set; }
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder mb)
|
||||
{
|
||||
mb.Entity<Submission>()
|
||||
.HasKey(r => r.Guid);
|
||||
mb.Entity<User>()
|
||||
.HasKey(u => u.Guid);
|
||||
mb.Entity<Comment>()
|
||||
.HasKey(u => u.Guid);
|
||||
mb.Entity<Session>()
|
||||
.HasKey(u => u.Guid);
|
||||
mb.Entity<SMS>()
|
||||
.HasKey(u => u.Guid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base
|
||||
WORKDIR /app
|
||||
EXPOSE 80
|
||||
EXPOSE 443
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
|
||||
WORKDIR /src
|
||||
COPY ["2021-backend.csproj", ""]
|
||||
RUN dotnet restore "./2021-backend.csproj"
|
||||
|
||||
COPY . .
|
||||
WORKDIR "/src/."
|
||||
RUN dotnet build "2021-backend.csproj" -c Release -o /app/build
|
||||
|
||||
FROM build AS publish
|
||||
RUN dotnet publish "2021-backend.csproj" -c Release -o /app/publish
|
||||
|
||||
FROM base AS final
|
||||
WORKDIR /app
|
||||
COPY --from=publish /app/publish .
|
||||
|
||||
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
|
||||
RUN echo 'Asia/Shanghai' >/etc/timezone
|
||||
|
||||
ENTRYPOINT ["dotnet", "2021-backend.dll"]
|
||||
|
|
@ -0,0 +1,251 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using _2021_backend.Data;
|
||||
|
||||
namespace _2021_backend.Migrations
|
||||
{
|
||||
[DbContext(typeof(BackendContext))]
|
||||
[Migration("20211018220015_Initial")]
|
||||
partial class Initial
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63)
|
||||
.HasAnnotation("ProductVersion", "5.0.9")
|
||||
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
|
||||
|
||||
modelBuilder.Entity("_2021_backend.Models.Comment", b =>
|
||||
{
|
||||
b.Property<Guid>("Guid")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("AddTime")
|
||||
.HasColumnType("timestamp without time zone");
|
||||
|
||||
b.Property<string>("Content")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<Guid>("Operator")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("Student")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Guid");
|
||||
|
||||
b.ToTable("Comments");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("_2021_backend.Models.SMS", b =>
|
||||
{
|
||||
b.Property<Guid>("Guid")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<List<string>>("Data")
|
||||
.HasColumnType("text[]");
|
||||
|
||||
b.Property<Guid>("Host")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("SendTime")
|
||||
.HasColumnType("timestamp without time zone");
|
||||
|
||||
b.Property<string>("Sender")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Tel")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int>("Type")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.HasKey("Guid");
|
||||
|
||||
b.ToTable("SMS");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("_2021_backend.Models.Session", b =>
|
||||
{
|
||||
b.Property<Guid>("Guid")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("BeginTime")
|
||||
.HasColumnType("timestamp without time zone");
|
||||
|
||||
b.Property<int>("Capacity")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<List<Guid>>("Chiefs")
|
||||
.HasColumnType("uuid[]");
|
||||
|
||||
b.Property<DateTime>("Day")
|
||||
.HasColumnType("timestamp without time zone");
|
||||
|
||||
b.Property<string>("Place")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<bool>("SendSMS")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<List<Guid>>("Students")
|
||||
.HasColumnType("uuid[]");
|
||||
|
||||
b.HasKey("Guid");
|
||||
|
||||
b.ToTable("Sessions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("_2021_backend.Models.Student", b =>
|
||||
{
|
||||
b.Property<Guid>("Guid")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<List<Guid>>("Comments")
|
||||
.HasColumnType("uuid[]");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int>("Exp")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("Grade")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<Guid>("InterviewTime")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("LastSubmission")
|
||||
.HasColumnType("timestamp without time zone");
|
||||
|
||||
b.Property<string>("Major")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<List<Guid>>("Messages")
|
||||
.HasColumnType("uuid[]");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTime>("RegisterTime")
|
||||
.HasColumnType("timestamp without time zone");
|
||||
|
||||
b.Property<int>("Score")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("Sex")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("Status")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("Stuid")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<List<Guid>>("Submissions")
|
||||
.HasColumnType("uuid[]");
|
||||
|
||||
b.Property<string>("Tel")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<List<Guid>>("Timelist")
|
||||
.HasColumnType("uuid[]");
|
||||
|
||||
b.Property<int>("Yard")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.HasKey("Guid");
|
||||
|
||||
b.ToTable("Students");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("_2021_backend.Models.Submission", b =>
|
||||
{
|
||||
b.Property<Guid>("Guid")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Address")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int>("Exp")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("Grade")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<Guid>("Host")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Major")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int>("Sex")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("Stuid")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTime>("SubmitTime")
|
||||
.HasColumnType("timestamp without time zone");
|
||||
|
||||
b.Property<string>("Tel")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<List<Guid>>("Timelist")
|
||||
.HasColumnType("uuid[]");
|
||||
|
||||
b.Property<int>("Yard")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.HasKey("Guid");
|
||||
|
||||
b.ToTable("Submissions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("_2021_backend.Models.User", b =>
|
||||
{
|
||||
b.Property<Guid>("Guid")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Secret")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<bool>("isManager")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<string>("stuID")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Guid");
|
||||
|
||||
b.ToTable("Users");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,151 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace _2021_backend.Migrations
|
||||
{
|
||||
public partial class Initial : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Comments",
|
||||
columns: table => new
|
||||
{
|
||||
Guid = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
Operator = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
Content = table.Column<string>(type: "text", nullable: false),
|
||||
AddTime = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
|
||||
Student = table.Column<Guid>(type: "uuid", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Comments", x => x.Guid);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Sessions",
|
||||
columns: table => new
|
||||
{
|
||||
Guid = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
Day = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
|
||||
BeginTime = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
|
||||
Place = table.Column<string>(type: "text", nullable: false),
|
||||
Chiefs = table.Column<List<Guid>>(type: "uuid[]", nullable: true),
|
||||
Capacity = table.Column<int>(type: "integer", nullable: false),
|
||||
SendSMS = table.Column<bool>(type: "boolean", nullable: false),
|
||||
Students = table.Column<List<Guid>>(type: "uuid[]", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Sessions", x => x.Guid);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "SMS",
|
||||
columns: table => new
|
||||
{
|
||||
Guid = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
Host = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
Tel = table.Column<string>(type: "text", nullable: true),
|
||||
Data = table.Column<List<string>>(type: "text[]", nullable: true),
|
||||
Type = table.Column<int>(type: "integer", nullable: false),
|
||||
Sender = table.Column<string>(type: "text", nullable: true),
|
||||
SendTime = table.Column<DateTime>(type: "timestamp without time zone", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_SMS", x => x.Guid);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Students",
|
||||
columns: table => new
|
||||
{
|
||||
Guid = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
Name = table.Column<string>(type: "text", nullable: true),
|
||||
Stuid = table.Column<string>(type: "text", nullable: true),
|
||||
Sex = table.Column<int>(type: "integer", nullable: false),
|
||||
Grade = table.Column<int>(type: "integer", nullable: false),
|
||||
Yard = table.Column<int>(type: "integer", nullable: false),
|
||||
Major = table.Column<string>(type: "text", nullable: true),
|
||||
Email = table.Column<string>(type: "text", nullable: true),
|
||||
Tel = table.Column<string>(type: "text", nullable: true),
|
||||
Exp = table.Column<int>(type: "integer", nullable: false),
|
||||
InterviewTime = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
Submissions = table.Column<List<Guid>>(type: "uuid[]", nullable: true),
|
||||
Messages = table.Column<List<Guid>>(type: "uuid[]", nullable: true),
|
||||
Timelist = table.Column<List<Guid>>(type: "uuid[]", nullable: true),
|
||||
Comments = table.Column<List<Guid>>(type: "uuid[]", nullable: true),
|
||||
Score = table.Column<int>(type: "integer", nullable: false),
|
||||
Status = table.Column<int>(type: "integer", nullable: false),
|
||||
LastSubmission = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
|
||||
RegisterTime = table.Column<DateTime>(type: "timestamp without time zone", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Students", x => x.Guid);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Submissions",
|
||||
columns: table => new
|
||||
{
|
||||
Guid = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
Host = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
Name = table.Column<string>(type: "text", nullable: true),
|
||||
Stuid = table.Column<string>(type: "text", nullable: true),
|
||||
Sex = table.Column<int>(type: "integer", nullable: false),
|
||||
Yard = table.Column<int>(type: "integer", nullable: false),
|
||||
Grade = table.Column<int>(type: "integer", nullable: false),
|
||||
Major = table.Column<string>(type: "text", nullable: true),
|
||||
Email = table.Column<string>(type: "text", nullable: true),
|
||||
Tel = table.Column<string>(type: "text", nullable: true),
|
||||
Exp = table.Column<int>(type: "integer", nullable: false),
|
||||
Timelist = table.Column<List<Guid>>(type: "uuid[]", nullable: true),
|
||||
Address = table.Column<string>(type: "text", nullable: true),
|
||||
SubmitTime = table.Column<DateTime>(type: "timestamp without time zone", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Submissions", x => x.Guid);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Users",
|
||||
columns: table => new
|
||||
{
|
||||
Guid = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
stuID = table.Column<string>(type: "text", nullable: true),
|
||||
Name = table.Column<string>(type: "text", nullable: true),
|
||||
Secret = table.Column<string>(type: "text", nullable: true),
|
||||
isManager = table.Column<bool>(type: "boolean", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Users", x => x.Guid);
|
||||
});
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "Comments");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Sessions");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "SMS");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Students");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Submissions");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Users");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,249 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using _2021_backend.Data;
|
||||
|
||||
namespace _2021_backend.Migrations
|
||||
{
|
||||
[DbContext(typeof(BackendContext))]
|
||||
partial class BackendContextModelSnapshot : ModelSnapshot
|
||||
{
|
||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63)
|
||||
.HasAnnotation("ProductVersion", "5.0.9")
|
||||
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
|
||||
|
||||
modelBuilder.Entity("_2021_backend.Models.Comment", b =>
|
||||
{
|
||||
b.Property<Guid>("Guid")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("AddTime")
|
||||
.HasColumnType("timestamp without time zone");
|
||||
|
||||
b.Property<string>("Content")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<Guid>("Operator")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("Student")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Guid");
|
||||
|
||||
b.ToTable("Comments");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("_2021_backend.Models.SMS", b =>
|
||||
{
|
||||
b.Property<Guid>("Guid")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<List<string>>("Data")
|
||||
.HasColumnType("text[]");
|
||||
|
||||
b.Property<Guid>("Host")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("SendTime")
|
||||
.HasColumnType("timestamp without time zone");
|
||||
|
||||
b.Property<string>("Sender")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Tel")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int>("Type")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.HasKey("Guid");
|
||||
|
||||
b.ToTable("SMS");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("_2021_backend.Models.Session", b =>
|
||||
{
|
||||
b.Property<Guid>("Guid")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("BeginTime")
|
||||
.HasColumnType("timestamp without time zone");
|
||||
|
||||
b.Property<int>("Capacity")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<List<Guid>>("Chiefs")
|
||||
.HasColumnType("uuid[]");
|
||||
|
||||
b.Property<DateTime>("Day")
|
||||
.HasColumnType("timestamp without time zone");
|
||||
|
||||
b.Property<string>("Place")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<bool>("SendSMS")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<List<Guid>>("Students")
|
||||
.HasColumnType("uuid[]");
|
||||
|
||||
b.HasKey("Guid");
|
||||
|
||||
b.ToTable("Sessions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("_2021_backend.Models.Student", b =>
|
||||
{
|
||||
b.Property<Guid>("Guid")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<List<Guid>>("Comments")
|
||||
.HasColumnType("uuid[]");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int>("Exp")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("Grade")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<Guid>("InterviewTime")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("LastSubmission")
|
||||
.HasColumnType("timestamp without time zone");
|
||||
|
||||
b.Property<string>("Major")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<List<Guid>>("Messages")
|
||||
.HasColumnType("uuid[]");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTime>("RegisterTime")
|
||||
.HasColumnType("timestamp without time zone");
|
||||
|
||||
b.Property<int>("Score")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("Sex")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("Status")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("Stuid")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<List<Guid>>("Submissions")
|
||||
.HasColumnType("uuid[]");
|
||||
|
||||
b.Property<string>("Tel")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<List<Guid>>("Timelist")
|
||||
.HasColumnType("uuid[]");
|
||||
|
||||
b.Property<int>("Yard")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.HasKey("Guid");
|
||||
|
||||
b.ToTable("Students");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("_2021_backend.Models.Submission", b =>
|
||||
{
|
||||
b.Property<Guid>("Guid")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Address")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int>("Exp")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("Grade")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<Guid>("Host")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Major")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int>("Sex")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("Stuid")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTime>("SubmitTime")
|
||||
.HasColumnType("timestamp without time zone");
|
||||
|
||||
b.Property<string>("Tel")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<List<Guid>>("Timelist")
|
||||
.HasColumnType("uuid[]");
|
||||
|
||||
b.Property<int>("Yard")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.HasKey("Guid");
|
||||
|
||||
b.ToTable("Submissions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("_2021_backend.Models.User", b =>
|
||||
{
|
||||
b.Property<Guid>("Guid")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Secret")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<bool>("isManager")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<string>("stuID")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Guid");
|
||||
|
||||
b.ToTable("Users");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
namespace _2021_backend.Models
|
||||
{
|
||||
public class Comment
|
||||
{
|
||||
public Comment()
|
||||
{
|
||||
Guid = Guid.NewGuid();
|
||||
AddTime = DateTime.Now;
|
||||
}
|
||||
|
||||
[Key]
|
||||
public Guid Guid { get; set; }
|
||||
[Required()]
|
||||
[Display(Name ="评论者")]
|
||||
public Guid Operator { get; set; }
|
||||
|
||||
[Required()]
|
||||
[Display(Name ="内容")]
|
||||
public string Content { get; set; }
|
||||
[Display(Name = "评论时间")]
|
||||
[DataType(DataType.DateTime)]
|
||||
public DateTime AddTime { get; set; }
|
||||
[Display(Name ="被评论者")]
|
||||
public Guid Student { get; set; }
|
||||
public Comment(Guid opid,string content, Guid stuguid)
|
||||
{
|
||||
Guid = Guid.NewGuid();
|
||||
Operator = opid;
|
||||
Content = content;
|
||||
Student = stuguid;
|
||||
AddTime = DateTime.Now;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
|
||||
namespace _2021_backend.Models
|
||||
{
|
||||
public enum SMSType
|
||||
{
|
||||
Accept,
|
||||
Reject,
|
||||
TimeSelect,
|
||||
TimeSet,
|
||||
Signed,
|
||||
Reply
|
||||
}
|
||||
public class SMS
|
||||
{
|
||||
public SMS()
|
||||
{
|
||||
Guid = Guid.NewGuid();
|
||||
Tel = "";
|
||||
Data = new List<string> { };
|
||||
Type = SMSType.Accept;
|
||||
Sender = "";
|
||||
SendTime = DateTime.Now;
|
||||
}
|
||||
public SMS(SMSPartialDto dto, Guid host)
|
||||
{
|
||||
Guid = Guid.NewGuid();
|
||||
Tel = dto.SubscriberNumber;
|
||||
Host = host;
|
||||
Sender = dto.SubscriberNumber.ToString();
|
||||
Data = (new string[] { dto.ReplyContent }).ToList<string>();
|
||||
Type = SMSType.Reply;
|
||||
var tm = (new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).AddSeconds(dto.ReplyTime).ToLocalTime();
|
||||
SendTime = tm;
|
||||
}
|
||||
[Key]
|
||||
public Guid Guid { get; set; }
|
||||
[Display(Name ="Host")]
|
||||
public Guid Host { get; set; }
|
||||
[Display(Name ="电话号码")]
|
||||
public string Tel { get; set; }
|
||||
|
||||
[Display(Name ="短信内容")]
|
||||
public List<string> Data { get; set; }
|
||||
[Display(Name ="短信类型")]
|
||||
public SMSType Type { get; set; }
|
||||
[Display(Name ="发送者")]
|
||||
public string Sender { get; set; }
|
||||
[Display(Name = "发送时间")]
|
||||
[DisplayFormat(DataFormatString = "{0:g}", ApplyFormatInEditMode = true)]
|
||||
public DateTime SendTime { get; set; }
|
||||
}
|
||||
|
||||
public class SMSResponseDto
|
||||
{
|
||||
public class error
|
||||
{
|
||||
public string Code;
|
||||
public string Message;
|
||||
}
|
||||
public List<SMSPartialDto> PullSmsReplyStatusSet { get; set; }
|
||||
public string RequestId { get; set; }
|
||||
error Error { get; set; }
|
||||
}
|
||||
|
||||
public class SMSPartialDto
|
||||
{
|
||||
public string CountryCode { get; set; }
|
||||
public string ReplyContent { get; set; }
|
||||
public string SubscriberNumber { get; set; }
|
||||
public string ExtendCode { get; set; }
|
||||
public ulong ReplyTime { get; set; }
|
||||
public string PhoneNumber { get; set; }
|
||||
public string SignName { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
using NPOI.SS.Formula.Functions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace _2021_backend.Models
|
||||
{
|
||||
public class Session
|
||||
{
|
||||
|
||||
public Session()
|
||||
{
|
||||
Guid = Guid.NewGuid();
|
||||
}
|
||||
[Key]
|
||||
[Required()]
|
||||
[Display(Name = "场次GUID")]
|
||||
public Guid Guid { get; set; }
|
||||
[Required()]
|
||||
[Display(Name = "活动日期")]
|
||||
[DataType(DataType.Date)]
|
||||
[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
|
||||
public DateTime Day { get; set; }
|
||||
[Display(Name = "开始时间")]
|
||||
[DataType(DataType.Time)]
|
||||
[DisplayFormat(DataFormatString = "{0:t}", ApplyFormatInEditMode = true)]
|
||||
[Required()]
|
||||
public DateTime BeginTime { get; set; }
|
||||
[RegularExpression(@"^20[04]$", ErrorMessage = "200或204")]
|
||||
[Display(Name = "地点")]
|
||||
[Required()]
|
||||
public string Place { get; set; }
|
||||
[Display(Name = "主活动官")]
|
||||
public List<Guid> Chiefs { get; set; }
|
||||
|
||||
[Display(Name = "可容纳人数")]
|
||||
public int Capacity { get; set; }
|
||||
|
||||
[Display(Name = "短信通知")]
|
||||
public bool SendSMS { get; set; }
|
||||
[Display(Name = "活动的人")]
|
||||
public List<Guid> Students { get; set; }
|
||||
|
||||
}
|
||||
public class SessionDto
|
||||
{
|
||||
|
||||
public DateTime Day { get; set; }
|
||||
public DateTime BeginTime { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class SessionDtoComparer : IEqualityComparer<SessionDto>
|
||||
{
|
||||
#region IEqualityComparer<user> Members
|
||||
public bool Equals(SessionDto a,SessionDto b)
|
||||
{
|
||||
return a.Day == b.Day && a.BeginTime == b.BeginTime;
|
||||
}
|
||||
public int GetHashCode(SessionDto a)
|
||||
{
|
||||
return a.Day.GetHashCode() + a.BeginTime.GetHashCode();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,145 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace _2021_backend.Models
|
||||
{
|
||||
public enum status
|
||||
{
|
||||
刚报名,
|
||||
通过,
|
||||
已选时间,
|
||||
需调整时间,
|
||||
已确认时间,
|
||||
不通过,
|
||||
已评分,
|
||||
暂缺
|
||||
}
|
||||
|
||||
public enum yard
|
||||
{
|
||||
暂缺 = 0,
|
||||
丹青 = 1,
|
||||
蓝田 = 2,
|
||||
云峰 = 3,
|
||||
竺院 = 4,
|
||||
其他 = 5,
|
||||
}
|
||||
|
||||
public enum sex
|
||||
{
|
||||
Boy = 1,
|
||||
Girl = 0,
|
||||
Unknown = 2
|
||||
}
|
||||
public enum grade
|
||||
{
|
||||
暂缺 = 0,
|
||||
大一 = 1,
|
||||
大二 = 2,
|
||||
大三 = 3,
|
||||
大四 = 4,
|
||||
}
|
||||
public enum experience
|
||||
{
|
||||
暂缺 = 0,
|
||||
萌新 = 1,
|
||||
略有了解 = 2,
|
||||
了解较多 = 3,
|
||||
轻车熟路 = 4
|
||||
}
|
||||
|
||||
public class Student
|
||||
{
|
||||
public void Update(Submission sub)
|
||||
{
|
||||
Name = sub.Name;
|
||||
Email = sub.Email;
|
||||
Tel = sub.Tel;
|
||||
Stuid = sub.Stuid;
|
||||
Sex = sub.Sex;
|
||||
Grade = sub.Grade;
|
||||
Major = sub.Major;
|
||||
Yard = sub.Yard;
|
||||
Exp = sub.Exp;
|
||||
Timelist = sub.Timelist;
|
||||
Submissions.Add(sub.Guid);
|
||||
}
|
||||
public Student()
|
||||
{
|
||||
Guid = Guid.NewGuid();
|
||||
Comments = new List<Guid>();
|
||||
Messages = new List<Guid>();
|
||||
Submissions = new List<Guid>();
|
||||
Timelist = new List<Guid>();
|
||||
}
|
||||
|
||||
public static Student create(Submission sub)
|
||||
{
|
||||
Student student = new Student();
|
||||
student.Guid = Guid.NewGuid();
|
||||
student.Name = sub.Name;
|
||||
student.Email = sub.Email;
|
||||
student.Tel = sub.Tel;
|
||||
student.Stuid = sub.Stuid;
|
||||
student.Sex = sub.Sex;
|
||||
student.Grade = sub.Grade;
|
||||
student.Major = sub.Major;
|
||||
student.Yard = sub.Yard;
|
||||
student.Exp = sub.Exp;
|
||||
student.Timelist = sub.Timelist;
|
||||
student.Submissions.Add(sub.Guid);
|
||||
student.RegisterTime = sub.SubmitTime;
|
||||
return student;
|
||||
}
|
||||
[Key]
|
||||
[Display(Name = "ID")]
|
||||
public Guid Guid { get; set; }
|
||||
[Display(Name = "姓名")]
|
||||
public string Name { get; set; }
|
||||
[Display(Name = "学号")]
|
||||
public string Stuid { get; set; }
|
||||
[Display(Name = "性别")]
|
||||
public sex Sex { get; set; }
|
||||
[Display(Name = "年级")]
|
||||
public grade Grade { get; set; }
|
||||
|
||||
[Display(Name = "学园")]
|
||||
public yard Yard { get; set; }
|
||||
[Display(Name = "专业")]
|
||||
public string Major { get; set; }
|
||||
[Display(Name = "电子邮件")]
|
||||
public string Email { get; set; }
|
||||
[Display(Name = "电话")]
|
||||
public string Tel { get; set; }
|
||||
|
||||
[Display(Name = "经验程度")]
|
||||
public experience Exp { get; set; }
|
||||
|
||||
[Display(Name = "最终场次")]
|
||||
public Guid InterviewTime { get; set; }
|
||||
[Display(Name = "提交记录")]
|
||||
public List<Guid> Submissions { get; set; }
|
||||
[Display(Name = "短信记录")]
|
||||
public List<Guid> Messages { get; set; }
|
||||
[Display(Name = "可选场次")]
|
||||
public List<Guid> Timelist { get; set; }
|
||||
[Display(Name = "评论")]
|
||||
public List<Guid> Comments { get; set; }
|
||||
[Display(Name = "打分")]
|
||||
public int Score { get; set; }
|
||||
|
||||
[Display(Name = "状态")]
|
||||
public status Status { get; set; }
|
||||
|
||||
[Display(Name = "最近一次提交时间")]
|
||||
[DataType(DataType.DateTime)]
|
||||
[DisplayFormat(DataFormatString = "{0:g}", ApplyFormatInEditMode = true)]
|
||||
public DateTime LastSubmission { get; set; }
|
||||
[Display(Name = "报名时间")]
|
||||
[DataType(DataType.DateTime)]
|
||||
public DateTime RegisterTime { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Org.BouncyCastle.Asn1.Cms;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace _2021_backend.Models
|
||||
{
|
||||
public class Submission
|
||||
{
|
||||
public Submission() {
|
||||
Guid = Guid.NewGuid();
|
||||
SubmitTime = DateTime.Now;
|
||||
}
|
||||
public Submission(SubmissionDto Dto, string ip)
|
||||
{
|
||||
Email = Dto.Email;
|
||||
Grade = (grade)(Dto.Grade);
|
||||
Sex = (sex)Dto.Sex;
|
||||
Stuid = Dto.Stuid;
|
||||
Major = Dto.Major;
|
||||
Name = Dto.Name;
|
||||
Tel = Dto.Tel;
|
||||
Exp = (experience)Dto.Exp;
|
||||
Yard = (yard)Dto.Yard;
|
||||
Timelist = new List<Guid>();
|
||||
Guid = System.Guid.NewGuid();
|
||||
SubmitTime = DateTime.Now;
|
||||
Address = ip;
|
||||
}
|
||||
[Key]
|
||||
[Display(Name = "ID")]
|
||||
public Guid Guid { get; set; }
|
||||
[Display(Name ="Host")]
|
||||
public Guid Host { get; set; }
|
||||
[Display(Name = "姓名")]
|
||||
public string Name { get; set; }
|
||||
[Display(Name = "学号")]
|
||||
public string Stuid { get; set; }
|
||||
[Display(Name = "性别")]
|
||||
public sex Sex { get; set; }
|
||||
|
||||
[Display(Name = "学园")]
|
||||
public yard Yard { get; set; }
|
||||
[Display(Name = "年级")]
|
||||
public grade Grade { get; set; }
|
||||
[Display(Name = "专业")]
|
||||
public string Major { get; set; }
|
||||
[Display(Name = "电子邮件")]
|
||||
public string Email { get; set; }
|
||||
[Display(Name = "电话")]
|
||||
public string Tel { get; set; }
|
||||
|
||||
[Display(Name = "经验程度")]
|
||||
public experience Exp { get; set; }
|
||||
|
||||
[Display(Name = "时间列表")]
|
||||
public List<Guid> Timelist { get; set; }
|
||||
[Display(Name ="Ip Address")]
|
||||
public string Address { get; set; }
|
||||
[Display(Name = "提交时间")]
|
||||
[DisplayFormat(DataFormatString = "{0:g}", ApplyFormatInEditMode = true)]
|
||||
public DateTime SubmitTime { get; set; }
|
||||
//活动场次ID
|
||||
|
||||
}
|
||||
public class TimeSpec
|
||||
{
|
||||
public DateTime Day { get; set; }
|
||||
public DateTime BeginTime { get; set; }
|
||||
}
|
||||
|
||||
public class SubmissionDto
|
||||
{
|
||||
[Required()]
|
||||
public string Name { get; set; }
|
||||
[Required()]
|
||||
public string Stuid { get; set; }
|
||||
[Required()]
|
||||
public int Sex { get; set; }
|
||||
[Required()]
|
||||
public int Grade { get; set; }
|
||||
[Required()]
|
||||
public int Yard { get; set; }
|
||||
[Required()]
|
||||
public string Major { get; set; }
|
||||
[Required()]
|
||||
public string Email { get; set; }
|
||||
[Required()]
|
||||
public string Tel { get; set; }
|
||||
|
||||
|
||||
[Required()]
|
||||
public int Exp { get; set; }
|
||||
[Required()]
|
||||
public List<TimeSpec> Timelist { get; set; }
|
||||
|
||||
|
||||
public static Regex r = new Regex("^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$");
|
||||
public static Regex phone_regex = new Regex("^1\\d{10}$");
|
||||
|
||||
public bool Iscomplete() => Name != null && Stuid != null && (Sex == 0 || Sex == 1) && Major != null && Email != null && Tel != null && Yard > 0 && Yard < 6;
|
||||
public bool Check()
|
||||
{
|
||||
if (Name.Length > 15)
|
||||
return false;
|
||||
if (Regex.Matches(Name, @"\d").Count > 0)
|
||||
return false;
|
||||
if (Stuid.Length > 10 || Stuid.Length < 7)
|
||||
return false;
|
||||
if (Sex > 1 || Sex < 0)
|
||||
return false;
|
||||
if (Grade < 0 || Grade > 4)
|
||||
return false;
|
||||
if (Major.Length > 20)
|
||||
return false;
|
||||
if (Yard >= 6 && Yard <= 0) return false;
|
||||
if(Exp >= 5 && Exp <= 0) return false;
|
||||
if (!r.IsMatch(Email))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!phone_regex.IsMatch(Tel))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Newtonsoft.Json;
|
||||
using Microsoft.EntityFrameworkCore.Internal;
|
||||
|
||||
namespace _2021_backend.Models
|
||||
{
|
||||
|
||||
public class User
|
||||
{
|
||||
public User()
|
||||
{
|
||||
Guid = Guid.NewGuid();
|
||||
}
|
||||
|
||||
public static User Bot;
|
||||
[Key]
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
[Display(Name ="ID")]
|
||||
public Guid Guid { get; set; }
|
||||
[Display(Name = "学号")]
|
||||
public string stuID { get; set; }
|
||||
[Display(Name ="姓名")]
|
||||
public string Name { get; set; }
|
||||
[Display(Name ="密码")]
|
||||
public string Secret { get; set; }
|
||||
[Display(Name ="是否管理员")]
|
||||
public bool isManager { get; set; }
|
||||
|
||||
}
|
||||
public class Login
|
||||
{
|
||||
private readonly string[] Manager = { "3200102610", "3190104611", "3190104698", "3190103719", "3190104143", "3190100494", "3190103301", "3190102034", "3190100151", "3190103577", "3190105399", "3190100133" };
|
||||
[JsonProperty("username")]
|
||||
public string id_student { get; set; }
|
||||
[JsonProperty("password")]
|
||||
public string Password { get; set; }
|
||||
public Login(string name,string pwd)
|
||||
{
|
||||
id_student = name;
|
||||
Password = pwd;
|
||||
}
|
||||
public string GetSHASecret() => _2021_backend.Utils.EvaCryptoHelper.Password2Secret(Password);
|
||||
public bool isManager()
|
||||
{
|
||||
if (Array.IndexOf(Manager,id_student) != -1)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
|
||||
namespace _2021_backend.OldModels
|
||||
{
|
||||
public class InterviewTime
|
||||
{
|
||||
public int ID { get; set; }
|
||||
public string Day { get; set; }
|
||||
public string BeginTime { get; set; }
|
||||
public string Place { get; set; }
|
||||
public string Chief { get; set; }
|
||||
public int TakenNum { get; set; }
|
||||
public int NowNum { get; set; }
|
||||
public bool SendSMS { get; set; }
|
||||
public List<int> Students { get; set; }
|
||||
}
|
||||
|
||||
public class Notes
|
||||
{
|
||||
public int ID { get; set; }
|
||||
public string OperatorId { get; set; }
|
||||
public string OperatorName { get; set; }
|
||||
|
||||
public string Content { get; set; }
|
||||
public DateTime AddTime { get; set; }
|
||||
public int RecordId { get; set; }
|
||||
public Notes() { }
|
||||
|
||||
|
||||
}
|
||||
|
||||
public enum Status
|
||||
{
|
||||
Pending,
|
||||
Pass,
|
||||
Fail
|
||||
}
|
||||
public enum Department
|
||||
{
|
||||
电脑部 = 1,
|
||||
电器部 = 2,
|
||||
文宣部,
|
||||
人资部,
|
||||
财外部
|
||||
}
|
||||
public enum Grade
|
||||
{
|
||||
大一 = 1,
|
||||
大二 = 2,
|
||||
大三,
|
||||
大四
|
||||
}
|
||||
|
||||
|
||||
public class Record
|
||||
{
|
||||
|
||||
public int rid { get; set; }
|
||||
public string name { get; set; }
|
||||
public string id_student { get; set; }
|
||||
public bool sex { get; set; }
|
||||
public int grade { get; set; }
|
||||
public string major { get; set; }
|
||||
public string email { get; set; }
|
||||
public string phone { get; set; }
|
||||
public int firstWish { get; set; }
|
||||
public int secondWish { get; set; }
|
||||
public int thirdWish { get; set; }
|
||||
public bool adjustment { get; set; }
|
||||
public string firstReason { get; set; }
|
||||
public string secondReason { get; set; }
|
||||
public string thirdReason { get; set; }
|
||||
public string question1 { get; set; }
|
||||
public string question2 { get; set; }
|
||||
public string strguid { get; set; }
|
||||
|
||||
public List<int> Times { get; set; }
|
||||
|
||||
|
||||
public DateTime addedDate { get; set; }
|
||||
public Status status { get; set; }
|
||||
public string ip { get; set; }
|
||||
//活动场次ID
|
||||
public int InterviewID { get; set; }
|
||||
public string InterviewTime { get; set; }
|
||||
|
||||
public int FinalResult { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class SMS
|
||||
{
|
||||
public int ID { get; set; }
|
||||
|
||||
public string id_student { get; set; }
|
||||
|
||||
public DateTime sendTime { get; set; }
|
||||
|
||||
public string type { get; set; }
|
||||
public string OperatorName { get; set; }
|
||||
public int Status { get; set; }
|
||||
|
||||
public SMS() { }
|
||||
}
|
||||
|
||||
public class User
|
||||
{
|
||||
public string Uid { get; set; }
|
||||
public long stuID { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Secret { get; set; }
|
||||
public bool isManager { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
@page
|
||||
@model _2021_backend.Pages.Account.AccessDeniedModel
|
||||
@{
|
||||
ViewData["Title"] = "认证失败";
|
||||
}
|
||||
|
||||
<h1>权限不足</h1>
|
||||
<h3>认证失败,您没有足够的权限进行操作,请联系系统管理员</h3>
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
|
||||
namespace _2021_backend.Pages.Account
|
||||
{
|
||||
public class AccessDeniedModel : PageModel
|
||||
{
|
||||
public void OnGet()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
@page
|
||||
@model _2021_backend.Pages.Account.DeniedModel
|
||||
@{
|
||||
ViewData["Title"] = "登录";
|
||||
}
|
||||
|
||||
<h1>登录</h1>
|
||||
<h3>认证失败,请重新登录或联系系统管理员</h3>
|
||||
<button class="btn btn-primary" asp-area="/" asp-page="/Account/Login">重新登录</button>
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
|
||||
namespace _2021_backend.Pages.Account
|
||||
{
|
||||
public class DeniedModel : PageModel
|
||||
{
|
||||
public void OnGet()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
@page
|
||||
@model _2021_backend.Pages.Account.LoginModel
|
||||
@{
|
||||
ViewData["Title"] = "登录";
|
||||
}
|
||||
|
||||
<h1>登录</h1>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<section>
|
||||
<form asp-controller="Account" asp-action="Login" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" class="form-horizontal" role="form">
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">学号</label>
|
||||
<div class="col-md-10">
|
||||
<input type="text" name="username" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label">密码</label>
|
||||
<div class="col-md-10">
|
||||
<input type="password" name="password" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-md-offset-2 col-md-10">
|
||||
<button type="submit" class="btn btn-primary">冲!</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,148 @@
|
|||
using _2021_backend.Data;
|
||||
using _2021_backend.Models;
|
||||
using _2021_backend.Utils;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace _2021_backend.Pages.Account
|
||||
{
|
||||
public class LoginModel : PageModel
|
||||
{
|
||||
private readonly string LoginURL = "https://xms.zjueva.net/api/auth/login";
|
||||
private readonly IConfiguration config;
|
||||
private readonly BackendContext context;
|
||||
public LoginModel(IConfiguration configuration, BackendContext context)
|
||||
{
|
||||
config = configuration;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public IActionResult OnGet(string returnUrl = null)
|
||||
{
|
||||
ViewData["ReturnUrl"] = returnUrl;
|
||||
return Page();
|
||||
}
|
||||
[BindProperty]
|
||||
public string username { get; set; }
|
||||
[BindProperty]
|
||||
public string password { get; set; }
|
||||
|
||||
public async Task<IActionResult> OnPostAsync()
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return Page();
|
||||
}
|
||||
var NowSecret = EvaCryptoHelper.Password2Secret(password);
|
||||
string stuID = username;
|
||||
var query = from _user in context.Users
|
||||
where _user.stuID == stuID
|
||||
select _user;
|
||||
var user = await query.AsNoTracking().FirstOrDefaultAsync();
|
||||
|
||||
//need use xms login service
|
||||
if (user == null)
|
||||
{
|
||||
Login login_Stu = new Login(username, password);
|
||||
|
||||
//post login information to xms.zjueva.net and receive the response with string
|
||||
|
||||
string ansString = LoginHelper.PostMoths(LoginURL, login_Stu);
|
||||
JObject ansJson = (JObject)JsonConvert.DeserializeObject(ansString);
|
||||
|
||||
//error and Denied
|
||||
if (ansJson["status"].ToString() == "error")
|
||||
{
|
||||
return RedirectToPage("/Account/Denied");
|
||||
}
|
||||
else if (ansJson["status"].ToString() == "success")
|
||||
{
|
||||
User add_user = new User()
|
||||
{
|
||||
stuID = ansJson["data"]["stuid"].ToString(),
|
||||
Name = ansJson["data"]["name"].ToString(),
|
||||
Secret = login_Stu.GetSHASecret(),
|
||||
isManager = login_Stu.isManager()
|
||||
};
|
||||
context.Users.Add(add_user);
|
||||
await context.SaveChangesAsync();
|
||||
//add new user to DB and now continue to create cookie;
|
||||
user = add_user;
|
||||
//this user is correct and don't use the follow "else"
|
||||
}
|
||||
}
|
||||
if (user.Secret == NowSecret)
|
||||
{
|
||||
var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme, ClaimTypes.Name, ClaimTypes.Role);
|
||||
identity.AddClaim(new Claim(ClaimTypes.Name, user.Name));
|
||||
identity.AddClaim(new Claim(ClaimTypes.Sid, user.Guid.ToString()));
|
||||
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, username));
|
||||
if (user.isManager)
|
||||
{
|
||||
identity.AddClaim(new Claim(EvaClaimTypes.IsManager, "true"));
|
||||
identity.AddClaim(new Claim(ClaimTypes.Role, "manager"));
|
||||
}
|
||||
else
|
||||
{
|
||||
identity.AddClaim(new Claim(ClaimTypes.Role, "user"));
|
||||
}
|
||||
var Iprinciple = new ClaimsPrincipal(identity);
|
||||
await HttpContext.SignInAsync(
|
||||
CookieAuthenticationDefaults.AuthenticationScheme,
|
||||
Iprinciple,
|
||||
new AuthenticationProperties
|
||||
{
|
||||
IsPersistent = true,
|
||||
AllowRefresh = true
|
||||
}
|
||||
);
|
||||
return RedirectToPage("/Students/Index");
|
||||
}
|
||||
|
||||
//if user change his secret in XMS
|
||||
else
|
||||
{
|
||||
Login login_Stu = new Login(username, password);
|
||||
|
||||
//post login information to xms.zjueva.net and receive the response with string
|
||||
|
||||
string ansString = LoginHelper.PostMoths(LoginURL, login_Stu);
|
||||
JObject ansJson = (JObject)JsonConvert.DeserializeObject(ansString);
|
||||
|
||||
//error and Denied
|
||||
if (ansJson["status"].ToString() == "error")
|
||||
{
|
||||
return RedirectToPage("/Account/Denied");
|
||||
}
|
||||
else
|
||||
{
|
||||
//change the secret in DB
|
||||
user = await context.Users.FirstOrDefaultAsync(r => r.stuID == stuID);
|
||||
user.Secret = login_Stu.GetSHASecret();
|
||||
context.Attach(user).State = EntityState.Modified;
|
||||
try
|
||||
{
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
catch (DbUpdateConcurrencyException)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return RedirectToPage("/Index");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
@page
|
||||
@model _2021_backend.Pages.Account.LogoutModel
|
||||
@{
|
||||
ViewData["Title"] = "登出";
|
||||
}
|
||||
|
||||
<h1>正在登出</h1>
|
||||
<h3>请稍后</h3>
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
namespace _2021_backend.Pages.Account
|
||||
{
|
||||
public class LogoutModel : PageModel
|
||||
{
|
||||
public async Task<IActionResult> OnGet()
|
||||
{
|
||||
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
|
||||
return RedirectToPage("/Index");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
@page
|
||||
@model ErrorModel
|
||||
@{
|
||||
ViewData["Title"] = "Error";
|
||||
}
|
||||
|
||||
<h1 class="text-danger">Error.</h1>
|
||||
<h2 class="text-danger">An error occurred while processing your request.</h2>
|
||||
|
||||
@if (Model.ShowRequestId)
|
||||
{
|
||||
<p>
|
||||
<strong>Request ID:</strong> <code>@Model.RequestId</code>
|
||||
</p>
|
||||
}
|
||||
|
||||
<h3>Development Mode</h3>
|
||||
<p>
|
||||
Swapping to the <strong>Development</strong> environment displays detailed information about the error that occurred.
|
||||
</p>
|
||||
<p>
|
||||
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
|
||||
It can result in displaying sensitive information from exceptions to end users.
|
||||
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
|
||||
and restarting the app.
|
||||
</p>
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace _2021_backend.Pages
|
||||
{
|
||||
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
||||
public class ErrorModel : PageModel
|
||||
{
|
||||
public string RequestId { get; set; }
|
||||
|
||||
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
|
||||
|
||||
private readonly ILogger<ErrorModel> _logger;
|
||||
|
||||
public ErrorModel(ILogger<ErrorModel> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public void OnGet()
|
||||
{
|
||||
RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
@page
|
||||
@model IndexModel
|
||||
@{
|
||||
ViewData["Title"] = "首页";
|
||||
}
|
||||
|
||||
<div class="text-center">
|
||||
<h1 class="display-4">欢迎使用</h1>
|
||||
|
||||
</div>
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace _2021_backend.Pages
|
||||
{
|
||||
public class IndexModel : PageModel
|
||||
{
|
||||
private readonly ILogger<IndexModel> _logger;
|
||||
|
||||
public IndexModel(ILogger<IndexModel> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public void OnGet()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
@page
|
||||
@model _2021_backend.Pages.Message.IndexModel
|
||||
@{
|
||||
}
|
||||
@{
|
||||
ViewData["Title"] = "发送短信";
|
||||
}
|
||||
<h5 class="text-red">
|
||||
<strong>@Html.DisplayFor(model => Model.Errmsg)</strong>
|
||||
</h5>
|
||||
<h3><strong>发送短信</strong></h3>
|
||||
<form method="post">
|
||||
<input type="hidden" asp-for="pageid" />
|
||||
<input type="submit" value="拉取5天内的回复短信" class="btn btn-primary" asp-page-handler="Pull" />
|
||||
<input type="submit" value="发送报名确认短信" class="btn btn-primary" asp-page-handler="Sign" />
|
||||
<input type="submit" value="发送确认短信" class="btn btn-primary" asp-page-handler="ResultAccept" />
|
||||
<input type="submit" value="发送拒绝短信" class="btn btn-primary" asp-page-handler="ResultReject" />
|
||||
</form>
|
||||
<br />
|
||||
<h3><strong>短信记录</strong></h3>
|
||||
<hr />
|
||||
<form method="post" class="form-inline">
|
||||
<input type="hidden" asp-for="pageid" />
|
||||
<div class="m-2">
|
||||
<label class="form-check-label">
|
||||
<input class="form-check-input" asp-for="showSend" />发出的短信
|
||||
</label>
|
||||
</div>
|
||||
<div class="m-2">
|
||||
<label class="form-check-label">
|
||||
<input class="form-check-input" asp-for="showReceive" /> 收到的短信
|
||||
</label>
|
||||
</div>
|
||||
<label asp-for="SearchString" class="control-label">按名字筛选</label>
|
||||
<div class="m-2">
|
||||
<input type="text" class="form-control" id="searchString" placeholder="输入部分姓名" asp-for="SearchString" name="SearchString">
|
||||
</div>
|
||||
<input type="submit" class="btn btn-primary" value="Go!" />
|
||||
</form>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
发送者
|
||||
</th>
|
||||
<th>
|
||||
学生姓名
|
||||
</th>
|
||||
<th>
|
||||
发送时间
|
||||
</th>
|
||||
<th>
|
||||
短信类型
|
||||
</th>
|
||||
<th>
|
||||
短信内容
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@if (Model.Messages.Count == 0)
|
||||
{
|
||||
@:暂无短信
|
||||
}
|
||||
else
|
||||
{
|
||||
@foreach (var e in Model.Messages)
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
@Html.DisplayFor(it => e.Sender)
|
||||
</td>
|
||||
<td>
|
||||
@{
|
||||
var stu = Model.Context.Students.Find(e.Host);
|
||||
string name = stu.Name;
|
||||
@Html.DisplayFor(it => name)
|
||||
|
||||
}
|
||||
</td>
|
||||
<td>
|
||||
@{
|
||||
var str = e.SendTime.ToString("MM月dd日 hh:mm:ss");
|
||||
@Html.DisplayFor(it => str)
|
||||
|
||||
}
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(it => e.Type)
|
||||
</td>
|
||||
<td>
|
||||
@if (e.Type == _2021_backend.Models.SMSType.Reply)
|
||||
{
|
||||
@Html.DisplayFor(it => e.Data[0])
|
||||
}
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
}
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<nav>
|
||||
<ul class="pagination">
|
||||
<li class="page-item @(Model.pageid==0 ? "disabled" : "")"><a class="page-link" asp-route-pageId="@(Model.pageid-1) " >Prev</a></li>
|
||||
@for (int i = 0; i < Model.PageCount; i++)
|
||||
{
|
||||
<li class="page-item @(Model.pageid==i ? "active" : "")"><a class="page-link" asp-route-pageId="@i" >@i</a></li>
|
||||
}
|
||||
<li class="page-item @(Model.pageid>=Model.PageCount -1? "disabled" : "")"><a class="page-link" asp-route-pageId="@(Model.pageid+1)" >Next</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
|
@ -0,0 +1,135 @@
|
|||
using _2021_backend.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
namespace _2021_backend.Pages.Message
|
||||
{
|
||||
public class IndexModel : PageModel
|
||||
{
|
||||
|
||||
public readonly _2021_backend.Data.BackendContext Context;
|
||||
|
||||
[BindProperty]
|
||||
public string Errmsg { get; set; }
|
||||
|
||||
[BindProperty]
|
||||
public string SearchString { get; set; }
|
||||
|
||||
[BindProperty]
|
||||
public bool showSend { get; set; }
|
||||
|
||||
[BindProperty]
|
||||
public bool showReceive { get; set; }
|
||||
|
||||
[BindProperty]
|
||||
public int pageid { get; set; }
|
||||
|
||||
public static int pageSize = 30;
|
||||
public List<SMS> Messages { get; set; }
|
||||
|
||||
public int PageCount { get; set; }
|
||||
|
||||
public IndexModel(_2021_backend.Data.BackendContext context)
|
||||
{
|
||||
Context = context;
|
||||
}
|
||||
|
||||
public IActionResult Construct(int PageId)
|
||||
{
|
||||
List<Guid> stus;
|
||||
IQueryable<Guid> q;
|
||||
if (!String.IsNullOrEmpty(SearchString)) q = from e in Context.Students where e.Name.Contains(SearchString) select e.Guid;
|
||||
else q = from e in Context.Students select e.Guid;
|
||||
stus = q.ToList();
|
||||
var q2 = from e in Context.SMS where stus.Contains(e.Host) select e;
|
||||
if (showReceive && !showSend) q2 = from e in q2 where e.Type == SMSType.Reply select e;
|
||||
else if (!showReceive && showSend) q2 = from e in q2 where e.Type != SMSType.Reply select e;
|
||||
Messages = q2.ToList();
|
||||
Messages.Sort((SMS a, SMS b) => b.SendTime.CompareTo(a.SendTime));
|
||||
|
||||
|
||||
int cnt = Messages.Count;
|
||||
PageCount = (int)Math.Ceiling((double)cnt / (double)pageSize);
|
||||
if (PageId >= PageCount) PageId = PageCount - 1;
|
||||
if (PageId < 0) PageId = 0;
|
||||
pageid = PageId;
|
||||
int count = (PageId + 1) * pageSize > cnt ? (cnt - PageId * pageSize) : pageSize;
|
||||
Messages = Messages.GetRange(PageId * pageSize, count);
|
||||
|
||||
return Page();
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnGetAsync(int PageId)
|
||||
{
|
||||
return Construct(PageId);
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPostAsync(int PageId)
|
||||
{
|
||||
return Construct(PageId);
|
||||
}
|
||||
|
||||
public async void OnPostPullAsync(int PageId)
|
||||
{
|
||||
|
||||
var stu = Context.Students.ToList();
|
||||
foreach (var e in stu)
|
||||
{
|
||||
await Utils.TencentSMS.Pull(Context, e, true);
|
||||
}
|
||||
|
||||
Construct(PageId);
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPostSignAsync(int PageId)
|
||||
{
|
||||
|
||||
var stu = Context.Students.ToList();
|
||||
foreach (var e in stu)
|
||||
{
|
||||
if (e.Status == status.刚报名)
|
||||
await Utils.TencentSMS.Send(Context, SMSType.Signed, e, Context.Users.Find(Guid.Parse(User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Sid).Value)).Name);
|
||||
}
|
||||
|
||||
return Construct(PageId);
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPostResultRejectAsync(int PageId)
|
||||
{
|
||||
var stu = Context.Students.ToList();
|
||||
foreach (var e in stu)
|
||||
{
|
||||
if (e.Status == status.不通过)
|
||||
{
|
||||
if (!Context.SMS.Any(it => it.Host == e.Guid && it.Type == SMSType.Reject))
|
||||
await Utils.TencentSMS.Send(Context, SMSType.Reject, e, Context.Users.Find(Guid.Parse(User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Sid).Value)).Name);
|
||||
}
|
||||
}
|
||||
return Construct(PageId);
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPostResultAccpetAsync(int PageId)
|
||||
{
|
||||
var stu = Context.Students.ToList();
|
||||
foreach (var e in stu)
|
||||
{
|
||||
if (e.Status == status.通过)
|
||||
{
|
||||
if (!Context.SMS.Any(it => it.Host == e.Guid && it.Type == SMSType.Accept))
|
||||
await Utils.TencentSMS.Send(Context, SMSType.Accept, e, Context.Users.Find(Guid.Parse(User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Sid).Value)).Name);
|
||||
}
|
||||
|
||||
}
|
||||
return Construct(PageId);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
@page
|
||||
@model _2021_backend.Pages.MigrateModel
|
||||
@{
|
||||
ViewData["Title"] = "Migrate";
|
||||
}
|
||||
|
||||
<h1>Migrate</h1>
|
||||
<form method="post">
|
||||
<input type="submit" value="Migrate" class="btn btn-danger"/>
|
||||
</form>
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
using _2021_backend.Data;
|
||||
using _2021_backend.Models;
|
||||
using _2021_backend.Utils;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NPOI.HPSF;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace _2021_backend.Pages
|
||||
{
|
||||
public class MigrateModel : PageModel
|
||||
{
|
||||
private readonly BackendContext _context;
|
||||
public MigrateModel(BackendContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPost(string value)
|
||||
{
|
||||
_context.Database.Migrate();
|
||||
return RedirectToPage("./Index");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
@page
|
||||
@model PrivacyModel
|
||||
@{
|
||||
ViewData["Title"] = "关于";
|
||||
}
|
||||
<h1>@ViewData["Title"]</h1>
|
||||
|
||||
<p>该后端由<a href="https://itszzz.top">Azuk 443</a>设计开发,2021技术小组合作贡献,使用问题请联系EVA Tech</p>
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace _2021_backend.Pages
|
||||
{
|
||||
public class PrivacyModel : PageModel
|
||||
{
|
||||
private readonly ILogger<PrivacyModel> _logger;
|
||||
|
||||
public PrivacyModel(ILogger<PrivacyModel> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public void OnGet()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
@page
|
||||
@model _2021_backend.Pages.Sessions.CreateModel
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Create";
|
||||
}
|
||||
|
||||
<h1>Create</h1>
|
||||
|
||||
<h4>InterviewTime</h4>
|
||||
<hr />
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<form method="post">
|
||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||
<div class="form-group">
|
||||
<label asp-for="InterviewTime.Day" class="control-label"></label>
|
||||
<input asp-for="InterviewTime.Day" class="form-control" />
|
||||
<span asp-validation-for="InterviewTime.Day" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label asp-for="InterviewTime.BeginTime" class="control-label"></label>
|
||||
<input asp-for="InterviewTime.BeginTime" class="form-control" />
|
||||
<span asp-validation-for="InterviewTime.BeginTime" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="InterviewTime.Place" class="control-label"></label>
|
||||
<select asp-for="InterviewTime.Place" class="form-control">
|
||||
<option value="200">200</option>
|
||||
<option value="204">204</option>
|
||||
</select>
|
||||
<span asp-validation-for="InterviewTime.Place" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="InterviewTime.Capacity" class="control-label"></label>
|
||||
<input asp-for="InterviewTime.Capacity" class="form-control" />
|
||||
<span asp-validation-for="InterviewTime.Capacity" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group form-check">
|
||||
<label class="form-check-label">
|
||||
<input class="form-check-input" asp-for="InterviewTime.SendSMS" /> @Html.DisplayNameFor(model => model.InterviewTime.SendSMS)
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group form-check">
|
||||
<label class="form-check-label">
|
||||
<input class="form-check-input" asp-for="CreateTwo" /> @Html.DisplayNameFor(model => model.CreateTwo)
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="submit" value="Create" class="btn btn-primary" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<a asp-page="Index">Back to List</a>
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
using _2021_backend.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace _2021_backend.Pages.Sessions
|
||||
{
|
||||
public class CreateModel : PageModel
|
||||
{
|
||||
private readonly _2021_backend.Data.BackendContext Context;
|
||||
|
||||
[Display(Name = "同时创建200和204场次")]
|
||||
[BindProperty]
|
||||
public bool CreateTwo { get; set; }
|
||||
[BindProperty]
|
||||
public Session InterviewTime { get; set; }
|
||||
|
||||
[BindProperty]
|
||||
[Display(Name = "活动官")]
|
||||
public string ChiefGuid { get; set; }
|
||||
|
||||
|
||||
public List<SelectListItem> ChiefList { get; set; }
|
||||
|
||||
public CreateModel(_2021_backend.Data.BackendContext context)
|
||||
{
|
||||
Context = context;
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnGet()
|
||||
{
|
||||
var qlst = from e in Context.Users select (new SelectListItem { Value = e.Guid.ToString(), Text = e.Name, Selected = false, Disabled = false });
|
||||
var lst = qlst.ToList().Distinct().ToList();
|
||||
ChiefList = lst;
|
||||
return Page();
|
||||
}
|
||||
|
||||
// To protect from overposting attacks, enable the specific properties you want to bind to, for
|
||||
// more details, see https://aka.ms/RazorPagesCRUD.
|
||||
public async Task<IActionResult> OnPostAsync()
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return Page();
|
||||
}
|
||||
InterviewTime.Students = new List<Guid>();
|
||||
InterviewTime.Chiefs = new List<Guid>();
|
||||
Session interviewTimeSecond = new Session();
|
||||
if (CreateTwo)
|
||||
{
|
||||
string anotherPlace = InterviewTime.Place == "200" ? "204" : "200";
|
||||
Session tmp = Context.Sessions.FirstOrDefault(r => r.Place == anotherPlace && r.Day == InterviewTime.Day && InterviewTime.BeginTime == r.BeginTime);
|
||||
if (tmp == null)
|
||||
{
|
||||
interviewTimeSecond = new Session()
|
||||
{
|
||||
Day = InterviewTime.Day,
|
||||
BeginTime = InterviewTime.BeginTime,
|
||||
Place = anotherPlace,
|
||||
Chiefs = new List<Guid>(),
|
||||
SendSMS = InterviewTime.SendSMS,
|
||||
Students = new List<Guid>(),
|
||||
Capacity = InterviewTime.Capacity
|
||||
};
|
||||
Context.Add(interviewTimeSecond);
|
||||
Context.SaveChanges();
|
||||
}
|
||||
}
|
||||
Context.Sessions.Add(InterviewTime);
|
||||
Context.SaveChanges();
|
||||
|
||||
return RedirectToPage("./Index");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
@page
|
||||
@model _2021_backend.Pages.Sessions.DeleteModel
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Delete";
|
||||
}
|
||||
|
||||
<h1>Delete</h1>
|
||||
|
||||
<h3>你确定要把这场删掉吗?</h3>
|
||||
<div>
|
||||
<h4>删除场次</h4>
|
||||
<hr />
|
||||
<dl class="row">
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.InterviewTime.Day)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.InterviewTime.Day)
|
||||
</dd>
|
||||
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.InterviewTime.BeginTime)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.InterviewTime.BeginTime)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.InterviewTime.Capacity)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.InterviewTime.Capacity)
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<form method="post">
|
||||
<input type="hidden" asp-for="InterviewTime.Guid" />
|
||||
<input type="submit" value="确定删除" class="btn btn-danger" /> |
|
||||
<a asp-page="./Index">Back to List</a>
|
||||
</form>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
using _2021_backend.Data;
|
||||
using _2021_backend.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace _2021_backend.Pages.Sessions
|
||||
{
|
||||
public class DeleteModel : PageModel
|
||||
{
|
||||
private readonly _2021_backend.Data.BackendContext Context;
|
||||
|
||||
public DeleteModel(_2021_backend.Data.BackendContext context)
|
||||
{
|
||||
Context = context;
|
||||
}
|
||||
|
||||
[BindProperty]
|
||||
public Session InterviewTime { get; set; }
|
||||
|
||||
public async Task<IActionResult> OnGetAsync(string? id)
|
||||
{
|
||||
Guid guid = Guid.Parse(id);
|
||||
if (id == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
InterviewTime = Context.Sessions.Find(guid);
|
||||
|
||||
if (InterviewTime == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return Page();
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPostAsync(string? id)
|
||||
{
|
||||
Guid guid = Guid.Parse(id);
|
||||
if (id == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
InterviewTime = await Context.Sessions.FindAsync(guid);
|
||||
|
||||
if (InterviewTime != null)
|
||||
{
|
||||
if (InterviewTime.Students.Count > 0)
|
||||
{
|
||||
foreach (var x in InterviewTime.Students)
|
||||
{
|
||||
Student stu = Context.Students.Find(x);
|
||||
if (stu != null)
|
||||
{
|
||||
stu.InterviewTime = Guid.Empty;
|
||||
stu.Timelist.RemoveAll(it => it == guid);
|
||||
}
|
||||
Context.SaveChanges();
|
||||
}
|
||||
}
|
||||
foreach(var x in Context.Students)
|
||||
{
|
||||
x.Timelist.RemoveAll(it => it == guid);
|
||||
}
|
||||
Context.Sessions.Remove(InterviewTime);
|
||||
Context.SaveChanges();
|
||||
}
|
||||
|
||||
return RedirectToPage("./Index");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
@page
|
||||
@model _2021_backend.Pages.Sessions.DetailsModel
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Details";
|
||||
}
|
||||
|
||||
<h1>Details</h1>
|
||||
|
||||
<div>
|
||||
<h4>InterviewTime</h4>
|
||||
<hr />
|
||||
<dl class="row">
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.CurSession.Day)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.CurSession.Day)
|
||||
</dd>
|
||||
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.CurSession.BeginTime)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.CurSession.BeginTime)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.CurSession.Place)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.CurSession.Place)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.CurSession.Chiefs)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@{
|
||||
var nm = "";
|
||||
foreach (var e in Model.CurSession.Chiefs)
|
||||
{
|
||||
nm += Model.Context.Users.Find(e).Name + " ";
|
||||
}
|
||||
@Html.DisplayFor(model => nm);
|
||||
}
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.CurSession.Capacity)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.CurSession.Capacity)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
已经报名人数
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.CurSession.Students.Count)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.CurSession.SendSMS)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.CurSession.SendSMS)
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div>
|
||||
<a asp-page="./Edit" asp-route-id="@Model.CurSession.Guid">Edit</a> |
|
||||
<a asp-page="./Index">Back to List</a>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
using _2021_backend.Data;
|
||||
using _2021_backend.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace _2021_backend.Pages.Sessions
|
||||
{
|
||||
public class DetailsModel : PageModel
|
||||
{
|
||||
public _2021_backend.Data.BackendContext Context;
|
||||
|
||||
public DetailsModel(_2021_backend.Data.BackendContext context)
|
||||
{
|
||||
Context = context;
|
||||
}
|
||||
|
||||
public Session CurSession { get; set; }
|
||||
|
||||
public async Task<IActionResult> OnGetAsync(string? id)
|
||||
{
|
||||
Guid guid = Guid.Parse(id);
|
||||
if (id == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
CurSession = Context.Sessions.Find(guid);
|
||||
if (CurSession == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return Page();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,152 @@
|
|||
@page
|
||||
@model _2021_backend.Pages.Sessions.EditModel
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Edit";
|
||||
}
|
||||
|
||||
<h1>编辑</h1>
|
||||
|
||||
<h4>InterviewTime</h4>
|
||||
<hr />
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<form method="post">
|
||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||
<input type="hidden" asp-for="CurSession.Guid" />
|
||||
<input type="hidden" asp-for="CurGuid">
|
||||
<div class="form-group">
|
||||
<label asp-for="newDay" class="control-label"></label>
|
||||
<input asp-for="newDay" class="form-control" />
|
||||
<span asp-validation-for="CurSession.Day" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="newTime" class="control-label"></label>
|
||||
<input asp-for="newTime" class="form-control" />
|
||||
<span asp-validation-for="CurSession.BeginTime" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="newPlace" class="control-label"></label>
|
||||
<input asp-for="newPlace" class="form-control" />
|
||||
<span asp-validation-for="CurSession.Place" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="newCapacity" class="control-label"></label>
|
||||
<input asp-for="newCapacity" class="form-control" />
|
||||
<span asp-validation-for="CurSession.Capacity" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group form-check">
|
||||
<label class="form-check-label">
|
||||
<input class="form-check-input" asp-for="CurSession.SendSMS" /> @Html.DisplayNameFor(model => model.CurSession.SendSMS)
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="submit" value="Save" class="btn btn-primary" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<h4>该时段的活动者</h4>
|
||||
<form method="post">
|
||||
<label class="col-sm-2">添加一个</label>
|
||||
<select asp-items=Model.Stulist id="stuselect" asp-for="addedStu" class="col-sm-2"></select>
|
||||
<input type="hidden" asp-for="CurGuid" />
|
||||
<input type="submit" value="Go!" class="btn btn-primary" style="margin-left:5px" asp-page-handler="Add" />
|
||||
</form>
|
||||
<br />
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>学号</th>
|
||||
<th>姓名</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var it in Model.CurSession.Students)
|
||||
{
|
||||
<tr>
|
||||
@{
|
||||
var stu = Model.Context.Students.Find(it);
|
||||
if (stu != null)
|
||||
{
|
||||
var id = stu.Stuid;
|
||||
<td>@Html.DisplayFor(model=>id)</td>
|
||||
<td>@Html.DisplayFor(model=>stu.Name)</td>
|
||||
<td>
|
||||
|
||||
<a asp-page="/Students/Details" asp-route-idstr=@stu.Guid.ToString() class="btn btn-primary">详细信息</a>
|
||||
<div style="float:left">
|
||||
<form method="post">
|
||||
<input type="hidden" asp-for="CurGuid">
|
||||
<input type="submit" value="删除" class="btn btn-danger" asp-page-handler="Delete" asp-route-id=@stu.Guid.ToString() />
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</td>
|
||||
}
|
||||
}
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
|
||||
<hr />
|
||||
<h4>活动官们</h4>
|
||||
<form method="post">
|
||||
<label class="col-sm-2">添加一个</label>
|
||||
<select id="chiefselect"asp-items=Model.ChiefList asp-for="addedChief" class="col-sm-2"></select>
|
||||
<input type="hidden" asp-for="CurGuid" />
|
||||
<input type="submit" value="Go!" class="btn btn-primary" style="margin-left:5px" asp-page-handler="AddChief" />
|
||||
</form>
|
||||
<br />
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>姓名</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var it in Model.CurSession.Chiefs)
|
||||
{
|
||||
<tr>
|
||||
@{
|
||||
var chf = Model.Context.Users.Find(it);
|
||||
if (chf != null)
|
||||
{
|
||||
<td>@Html.DisplayFor(model=>chf.Name)</td>
|
||||
<td>
|
||||
<div style="float:left">
|
||||
<form method="post">
|
||||
<input type="hidden" asp-for="CurGuid">
|
||||
<input type="submit" value="删除" class="btn btn-danger" asp-page-handler="DeleteChief" asp-route-id=@chf.Guid.ToString() />
|
||||
</form>
|
||||
</div>
|
||||
</td>
|
||||
}
|
||||
}
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
|
||||
<div>
|
||||
<a asp-page="./Index">Back to List</a>
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
|
||||
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
|
||||
<script type="text/javascirpt" src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" />
|
||||
<script>
|
||||
$(function(){
|
||||
$("#chiefselect").select2();
|
||||
$("#stuselect").select2();
|
||||
});
|
||||
</script>
|
||||
}
|
||||
|
|
@ -0,0 +1,188 @@
|
|||
using _2021_backend.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace _2021_backend.Pages.Sessions
|
||||
{
|
||||
public class EditModel : PageModel
|
||||
{
|
||||
public _2021_backend.Data.BackendContext Context;
|
||||
|
||||
public EditModel(_2021_backend.Data.BackendContext context)
|
||||
{
|
||||
Context = context;
|
||||
}
|
||||
|
||||
[BindProperty]
|
||||
public Session CurSession { get; set; }
|
||||
|
||||
[BindProperty]
|
||||
public string CurGuid { get; set; }
|
||||
|
||||
[BindProperty]
|
||||
public string ChiefSearch { get; set; }
|
||||
|
||||
public List<SelectListItem> ChiefList { get; set; }
|
||||
|
||||
public List<SelectListItem> Stulist { get; set; }
|
||||
|
||||
[BindProperty]
|
||||
public Guid addedChief { get; set; }
|
||||
|
||||
[BindProperty]
|
||||
public string addedStu { get; set; }
|
||||
|
||||
[BindProperty]
|
||||
public string ChiefName { get; set; }
|
||||
|
||||
|
||||
|
||||
|
||||
[BindProperty]
|
||||
[Display(Name ="活动地点")]
|
||||
[RegularExpression(@"^20[04]$", ErrorMessage = "200或204")]
|
||||
[Required()]
|
||||
public string newPlace { get; set; }
|
||||
|
||||
|
||||
[BindProperty]
|
||||
[DataType(DataType.Date)]
|
||||
[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
|
||||
[Required()]
|
||||
public DateTime newDay { get; set; }
|
||||
[BindProperty]
|
||||
[DataType(DataType.Time)]
|
||||
[DisplayFormat(DataFormatString = "{0:t}", ApplyFormatInEditMode = true)]
|
||||
[Required()]
|
||||
public DateTime newTime { get; set; }
|
||||
|
||||
[BindProperty]
|
||||
[Required()]
|
||||
public bool sendSMS { get; set; }
|
||||
[BindProperty]
|
||||
public int newCapacity { get; set; }
|
||||
|
||||
public IActionResult Construct(string id)
|
||||
{
|
||||
Guid guid = Guid.Parse(id);
|
||||
if (id == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
CurGuid = id;
|
||||
CurSession = Context.Sessions.Find(guid);
|
||||
|
||||
newDay = CurSession.Day;
|
||||
newTime = CurSession.BeginTime;
|
||||
newCapacity = CurSession.Capacity;
|
||||
sendSMS = CurSession.SendSMS;
|
||||
newPlace = CurSession.Place;
|
||||
|
||||
if (CurSession == null) return RedirectToPage("./Index", new { errmsg = "未找到该活动场次" });
|
||||
var qlst = from e in Context.Users select (new SelectListItem { Value = e.Guid.ToString(), Text = e.Name, Selected = false, Disabled = false });
|
||||
ChiefList = qlst.ToList().Distinct().ToList();
|
||||
|
||||
var slst = from e in Context.Students where e.InterviewTime == Guid.Empty select new SelectListItem { Value = e.Guid.ToString(), Text = e.Name, Selected = false, Disabled = false };
|
||||
Stulist = slst.ToList().Distinct().ToList();
|
||||
return Page();
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnGetAsync(string id)
|
||||
{
|
||||
return Construct(id);
|
||||
}
|
||||
|
||||
// To protect from overposting attacks, enable the specific properties you want to bind to, for
|
||||
// more details, see https://aka.ms/RazorPagesCRUD.
|
||||
public async Task<IActionResult> OnPostAsync()
|
||||
{
|
||||
var ssn = Context.Sessions.Find(Guid.Parse(CurGuid));
|
||||
ssn.SendSMS = sendSMS;
|
||||
ssn.Day = newDay;
|
||||
ssn.BeginTime = newTime;
|
||||
ssn.Capacity = newCapacity;
|
||||
ssn.Place = newPlace;
|
||||
Context.SaveChanges();
|
||||
|
||||
return RedirectToPage("./Index");
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPostDeleteAsync(string id)
|
||||
{
|
||||
CurSession = Context.Sessions.Find(Guid.Parse(CurGuid));
|
||||
var guid = Guid.Parse(id);
|
||||
if (!string.IsNullOrEmpty(id))
|
||||
{
|
||||
if (Context.Students.Any(it => it.Guid == guid))
|
||||
{
|
||||
Context.Students.Find(guid).InterviewTime = Guid.Empty;
|
||||
CurSession.Students.RemoveAll(it => it == guid);
|
||||
}
|
||||
Context.SaveChanges();
|
||||
}
|
||||
return Construct(CurGuid);
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPostAddAsync()
|
||||
{
|
||||
CurSession = Context.Sessions.Find(Guid.Parse(CurGuid));
|
||||
var guid = Guid.Parse(addedStu);
|
||||
if (!string.IsNullOrEmpty(addedStu))
|
||||
{
|
||||
if (Context.Students.Any(it => it.Guid == guid))
|
||||
{
|
||||
var stu = Context.Students.Find(guid);
|
||||
if(stu.InterviewTime != Guid.Empty)
|
||||
{
|
||||
var oldtime = Context.Sessions.Find(stu.InterviewTime);
|
||||
if(oldtime != null)
|
||||
{
|
||||
oldtime.Students.RemoveAll(s => s == stu.Guid);
|
||||
Context.SaveChanges();
|
||||
}
|
||||
}
|
||||
stu.InterviewTime = CurSession.Guid;
|
||||
stu.Status = status.已选时间;
|
||||
CurSession.Students.Add(guid);
|
||||
}
|
||||
Context.SaveChanges();
|
||||
}
|
||||
return Construct(CurGuid);
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPostAddChiefAsync()
|
||||
{
|
||||
CurSession = Context.Sessions.Find(Guid.Parse(CurGuid));
|
||||
if (Context.Users.Any(it => it.Guid == addedChief))
|
||||
{
|
||||
CurSession.Chiefs.Add(addedChief);
|
||||
}
|
||||
Context.SaveChanges();
|
||||
return Construct(CurGuid);
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPostDeleteChiefAsync(string id)
|
||||
{
|
||||
var guid = Guid.Parse(id);
|
||||
CurSession = Context.Sessions.Find(Guid.Parse(CurGuid));
|
||||
if (CurSession.Chiefs.Contains(guid))
|
||||
{
|
||||
CurSession.Chiefs.Remove(guid);
|
||||
}
|
||||
Context.SaveChanges();
|
||||
return Construct(CurGuid);
|
||||
}
|
||||
|
||||
private bool InterviewTimeExists(Guid id)
|
||||
{
|
||||
return Context.Sessions.Any(e => e.Guid == id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,167 @@
|
|||
@page
|
||||
@model _2021_backend.Pages.Sessions.IndexModel
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "活动时间管理";
|
||||
}
|
||||
|
||||
<h5 class="text-red">
|
||||
<strong>@Html.DisplayFor(model => Model.Errmsg)</strong>
|
||||
</h5>
|
||||
<h5><strong>全部活动场次</strong></h5>
|
||||
<a asp-page="./Create" class="btn btn-outline-info m-2">创建新的场次</a>
|
||||
<a asp-page="./Export" class="btn btn-outline-info m-2">导出</a>
|
||||
<form class="form-inline" method="post">
|
||||
<div class="m-2">
|
||||
筛选日期
|
||||
<select asp-for="Day" asp-items="Model.DayList" class="form-control">
|
||||
<option value="">全部</option>
|
||||
|
||||
</select>
|
||||
</div>
|
||||
<div class="m-2">
|
||||
筛选场次
|
||||
<select asp-for="Room" class="form-control">
|
||||
<option value="">全部</option>
|
||||
<option value="200">200</option>
|
||||
<option value="204">204</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="m-2">
|
||||
<label class="form-check-label">
|
||||
只显示未满场次
|
||||
<input class="form-check-input" asp-for="onlyShowUnFull" />
|
||||
</label>
|
||||
</div>
|
||||
<input type="submit" value="筛选" class="btn btn-outline-primary m-2" />
|
||||
<input type="submit" value="自动生成新的排班" class="btn btn-outline-warning m-2" asp-page-handler="Arrange" />
|
||||
<input type="submit" value="全部清空" class="btn btn-outline-danger m-2" asp-page-handler="ClearAll" />
|
||||
<input type="submit" value="整理一下" class="btn btn-outline-info m-2" asp-page-handler="Tidy" />
|
||||
<input type="submit" value="重置全部场次" class="btn btn-outline-danger m-2" asp-page-handler="ResetAll" />
|
||||
<input type="submit" value="保存当前结果" class="btn btn-outline-danger m-2" asp-page-handler="Save" />
|
||||
<div class="m-2">
|
||||
加载存档
|
||||
<select asp-for="savename" class="form-control" asp-items="Model.Files">
|
||||
</select>
|
||||
</div>
|
||||
<input type="submit" value="Go!" class="btn btn-outline-danger m-2" asp-page-handler="Load" />
|
||||
|
||||
@*<input type="submit" value="保存这个结果!" class="btn btn-outline-warning m-2" asp-page-handler="Save"/>
|
||||
<div class="m-2">
|
||||
加载以前的结果
|
||||
<select asp-for="TargetIndex" class="form-control" asp-items="@Model.SaveNames">
|
||||
</select>
|
||||
</div>*@
|
||||
@*<input type="submit" value="Load!" class="btn btn-outline-primary m-2" asp-page-handler="Load"/>*@
|
||||
|
||||
</form>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
序号
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.LoadedSessions[0].Day)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.LoadedSessions[0].BeginTime)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.LoadedSessions[0].Place)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.LoadedSessions[0].Chiefs)
|
||||
</th>
|
||||
<th>
|
||||
剩余可用人数
|
||||
</th>
|
||||
<th>
|
||||
容量
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.LoadedSessions[0].SendSMS)
|
||||
</th>
|
||||
<th>
|
||||
参与者
|
||||
</th>
|
||||
<th>
|
||||
操作
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@{
|
||||
var idx = 0;
|
||||
}
|
||||
@foreach (var item in Model.LoadedSessions)
|
||||
{
|
||||
<tr class="@{
|
||||
if (item.Day.Date.Add(item.BeginTime.TimeOfDay).CompareTo(DateTime.Now) < 0)
|
||||
@("table-secondary")
|
||||
else if (item.Students.Count == item.Capacity)
|
||||
@("table-warning")
|
||||
else if(item.Place=="200")
|
||||
@("table-success")
|
||||
else
|
||||
@("table-info")
|
||||
} ">
|
||||
<td>
|
||||
@{
|
||||
idx++;
|
||||
@Html.DisplayFor(mi => idx)
|
||||
}
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => item.Day)
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => item.BeginTime)
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => item.Place)
|
||||
</td>
|
||||
<td>
|
||||
@{
|
||||
var str = "";
|
||||
foreach (var i in item.Chiefs)
|
||||
{
|
||||
str += Model.Context.Users.Find(i).Name + " ";
|
||||
}
|
||||
@Html.DisplayFor(modelItem => str)
|
||||
;
|
||||
}
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => item.Capacity)
|
||||
</td>
|
||||
<td>
|
||||
@{
|
||||
var cnt = item.Capacity - item.Students.Count;
|
||||
@Html.DisplayFor(modelItem => cnt)
|
||||
}
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => item.SendSMS)
|
||||
</td>
|
||||
<td>
|
||||
|
||||
@foreach (var it in item.Students)
|
||||
{
|
||||
var q = Model.Context.Students.Find(it);
|
||||
var s = q.Name;
|
||||
<a asp-page="/Students/Details" asp-route-idstr=@it.ToString()>@Html.DisplayFor(modelItem => s)</a>
|
||||
@: 
|
||||
|
||||
}
|
||||
</td>
|
||||
<td>
|
||||
<a asp-page="./Edit" asp-route-id="@item.Guid">编辑</a> |
|
||||
<a asp-page="./Delete" asp-route-id="@item.Guid">删除</a> |
|
||||
<a asp-page-handler="Reset" asp-route-id="@item.Guid">重置</a>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
@ -0,0 +1,283 @@
|
|||
using _2021_backend.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Text.Json;
|
||||
using System.IO;
|
||||
|
||||
namespace _2021_backend.Pages.Sessions
|
||||
{
|
||||
public class IndexModel : PageModel
|
||||
{
|
||||
public readonly _2021_backend.Data.BackendContext Context;
|
||||
public IndexModel(_2021_backend.Data.BackendContext context)
|
||||
{
|
||||
Context = context;
|
||||
}
|
||||
public List<Session> LoadedSessions { get; set; }
|
||||
public SelectList DayList { get; set; }
|
||||
[BindProperty(SupportsGet = true)]
|
||||
public string Room { get; set; }
|
||||
|
||||
[BindProperty]
|
||||
public string Errmsg { get;set; }
|
||||
|
||||
[BindProperty]
|
||||
public string savename { get; set; }
|
||||
|
||||
[BindProperty(SupportsGet = true)]
|
||||
public bool onlyShowUnFull { get; set; }
|
||||
|
||||
[BindProperty(SupportsGet = true)]
|
||||
public DateTime Day { get; set; }
|
||||
|
||||
[BindProperty]
|
||||
public int TargetIndex { get; set; }
|
||||
|
||||
|
||||
public SelectList Files { get; set; }
|
||||
|
||||
public IActionResult Construct(string errmsg)
|
||||
{
|
||||
Errmsg = errmsg;
|
||||
var q = from s in Context.Sessions select s;
|
||||
if (Day != DateTime.MinValue)
|
||||
{
|
||||
q = from t in q where t.Day == Day select t;
|
||||
}
|
||||
if (Room == "200" || Room == "204")
|
||||
{
|
||||
q = from t in q where t.Place == Room select t;
|
||||
}
|
||||
if (onlyShowUnFull)
|
||||
{
|
||||
q = from t in q where t.Capacity != t.Students.Count select t;
|
||||
}
|
||||
LoadedSessions = q.ToList();
|
||||
LoadedSessions.Sort((Session a, Session b) =>
|
||||
{
|
||||
var x = a.Day.Date.Add(a.BeginTime.TimeOfDay).CompareTo(DateTime.Now);
|
||||
var y = b.Day.Date.Add(b.BeginTime.TimeOfDay).CompareTo(DateTime.Now);
|
||||
if (x != y) return y - x;
|
||||
else
|
||||
{
|
||||
var z = a.Day.Date.Add(a.BeginTime.TimeOfDay).CompareTo(b.Day.Date.Add(b.BeginTime.TimeOfDay));
|
||||
if (z != 0) return z;
|
||||
else
|
||||
{
|
||||
if (a.BeginTime < b.BeginTime) return -1;
|
||||
else if (a.BeginTime > b.BeginTime) return 1;
|
||||
else if (a.Place == "200") return -1;
|
||||
else if (a.Place == "204") return 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
});
|
||||
var l = from it in LoadedSessions select it.Day;
|
||||
DayList = new SelectList(l.Distinct());
|
||||
if (!Directory.Exists("./saves")) Directory.CreateDirectory("./saves");
|
||||
Files = new SelectList(Directory.GetFiles("./saves").ToList());
|
||||
//Console.WriteLine(Files);
|
||||
return Page();
|
||||
}
|
||||
public async Task<IActionResult> OnGetAsync(string errmsg)
|
||||
{
|
||||
return Construct(errmsg);
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnGetResetAsync(Guid id)
|
||||
{
|
||||
if(Context.Sessions.Any(it => it.Guid == id))
|
||||
{
|
||||
var s = Context.Sessions.Find(id);
|
||||
foreach(var st in s.Students)
|
||||
{
|
||||
var e = Context.Students.Find(st);
|
||||
e.Status = status.需调整时间;
|
||||
e.InterviewTime = Guid.Empty;
|
||||
}
|
||||
s.Students.Clear();
|
||||
}
|
||||
Context.SaveChanges();
|
||||
return Construct("");
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPost()
|
||||
{
|
||||
return Construct("");
|
||||
}
|
||||
|
||||
//public async Task<IActionResult> OnPostLoadAsync()
|
||||
//{
|
||||
|
||||
// return Construct("");
|
||||
//}
|
||||
//public async Task<IActionResult> OnPostSaveAsync()
|
||||
//{
|
||||
|
||||
// return Construct("");
|
||||
//}
|
||||
|
||||
public async Task<IActionResult> OnPostArrangeAsync()
|
||||
{
|
||||
if (Utils.Arranger.Arrange(Context)) return Construct("");
|
||||
else return Construct("排班失败,无法满足条件");
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPostClearAllAsync()
|
||||
{
|
||||
foreach(var s in Context.Students)
|
||||
{
|
||||
s.InterviewTime = Guid.Empty;
|
||||
s.Status = status.需调整时间;
|
||||
s.Timelist.Clear();
|
||||
}
|
||||
Context.SaveChanges();
|
||||
foreach(var s in Context.Sessions)
|
||||
{
|
||||
Context.Sessions.Remove(s);
|
||||
}
|
||||
Context.SaveChanges();
|
||||
return Construct("");
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPostResetAllAsync()
|
||||
{
|
||||
var stus = Context.Students.ToList();
|
||||
foreach (var s in stus)
|
||||
{
|
||||
if(s.Status == status.已选时间)
|
||||
{
|
||||
s.InterviewTime = Guid.Empty;
|
||||
s.Timelist.RemoveAll(it => !Context.Sessions.Any(k => k.Guid == it));
|
||||
s.Timelist.Sort((Guid a, Guid b) =>
|
||||
{
|
||||
var x = Context.Sessions.Find(a);
|
||||
var y = Context.Sessions.Find(b);
|
||||
var k1 = x.Day.CompareTo(y.Day);
|
||||
var k2 = x.BeginTime.CompareTo(y.BeginTime);
|
||||
return k1 != 0 ? k1 : k2;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
Context.SaveChanges();
|
||||
foreach (var s in Context.Sessions)
|
||||
{
|
||||
s.Students.Clear();
|
||||
}
|
||||
Context.SaveChanges();
|
||||
return Construct("");
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPostSaveAsync()
|
||||
{
|
||||
var lst = Context.Sessions.ToList();
|
||||
var str = JsonSerializer.Serialize(lst);
|
||||
Console.WriteLine("Saving arrangement: " + str);
|
||||
if(!Directory.Exists("./saves")) Directory.CreateDirectory("./saves/");
|
||||
System.IO.File.WriteAllText($"./saves/{DateTime.Now.ToString("MM-dd-hh-mm-ss")}.txt", str);
|
||||
return Construct("");
|
||||
}
|
||||
public async Task<IActionResult> OnPostTidyAsync()
|
||||
{
|
||||
var stus = Context.Students.ToList();
|
||||
var sess = Context.Sessions.ToList();
|
||||
foreach(var i in stus)
|
||||
{
|
||||
var tm = i.Timelist;
|
||||
var ntm = new List<Session>();
|
||||
foreach(var j in tm)
|
||||
{
|
||||
var k = sess.Find(it => it.Guid == j);
|
||||
ntm.Add(k);
|
||||
}
|
||||
ntm.Sort((Session a,Session b) =>
|
||||
{
|
||||
var x = a.Day.CompareTo(b.Day);
|
||||
var y = a.BeginTime.CompareTo(b.BeginTime);
|
||||
return x != 0 ? x : y;
|
||||
});
|
||||
List<Guid> nl = new List<Guid>();
|
||||
foreach(var j in ntm)
|
||||
{
|
||||
if(i.Status != status.不通过 && i.Status != status.通过 && i.Status != status.已确认时间)
|
||||
{
|
||||
if (j.Day.Date.Add(j.BeginTime.TimeOfDay).CompareTo(DateTime.Now) < 0 || (j.Students.Count >= j.Capacity && !j.Students.Any(k => k ==i.Guid) )) continue;
|
||||
nl.Add(j.Guid);
|
||||
}
|
||||
else
|
||||
{
|
||||
nl.Add(j.Guid);
|
||||
}
|
||||
|
||||
}
|
||||
i.Timelist = nl;
|
||||
}
|
||||
Context.SaveChanges();
|
||||
return Construct("");
|
||||
}
|
||||
|
||||
|
||||
public async Task<IActionResult> OnPostLoadAsync()
|
||||
{
|
||||
var str = "";
|
||||
|
||||
List<Session> loads = new List<Session>();
|
||||
if (!string.IsNullOrEmpty(savename)) str = System.IO.File.ReadAllText(savename);
|
||||
loads = JsonSerializer.Deserialize<List<Session>>(str);
|
||||
|
||||
var stus = Context.Students.ToList();
|
||||
foreach (var s in stus)
|
||||
{
|
||||
if (s.Status == status.已选时间)
|
||||
{
|
||||
s.InterviewTime = Guid.Empty;
|
||||
s.Timelist.RemoveAll(it => !Context.Sessions.Any(k => k.Guid == it));
|
||||
s.Timelist.Sort((Guid a, Guid b) =>
|
||||
{
|
||||
var x = Context.Sessions.Find(a);
|
||||
var y = Context.Sessions.Find(b);
|
||||
var k1 = x.Day.CompareTo(y.Day);
|
||||
var k2 = x.BeginTime.CompareTo(y.BeginTime);
|
||||
return k1 != 0 ? k1 : k2;
|
||||
});
|
||||
}
|
||||
}
|
||||
Context.SaveChanges();
|
||||
foreach (var s in Context.Sessions)
|
||||
{
|
||||
s.Students.Clear();
|
||||
}
|
||||
Context.SaveChanges();
|
||||
foreach(var item in loads)
|
||||
{
|
||||
Session s = Context.Sessions.Find(item.Guid);
|
||||
if(s != null)
|
||||
{
|
||||
s.BeginTime = item.BeginTime;
|
||||
s.Day = item.Day;
|
||||
s.Capacity = item.Capacity;
|
||||
s.SendSMS = item.SendSMS;
|
||||
s.Chiefs = item.Chiefs;
|
||||
s.Students = new List<Guid>();
|
||||
foreach(var s2 in item.Students)
|
||||
{
|
||||
if (Context.Students.Any(k => k.Guid == s2))
|
||||
{
|
||||
Context.Students.Find(s2).InterviewTime = item.Guid;
|
||||
s.Students.Add(s2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Context.SaveChanges();
|
||||
return Construct("");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
@using _2021_backend.Utils;
|
||||
@using System.Security.Claims;
|
||||
@inject Microsoft.AspNetCore.Http.IHttpContextAccessor HttpContextAccessor
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>@ViewData["Title"] - 2021 精品活动后台</title>
|
||||
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
|
||||
<link rel="stylesheet" href="~/css/site.css" />
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" asp-area="" asp-page="/Index">2021纳新后台</a>
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
|
||||
aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
|
||||
@if (HttpContextAccessor.HttpContext.User.Identity.IsAuthenticated)
|
||||
{
|
||||
<div class="form-inline my-2 my-lg-0 nav-item">
|
||||
<a class="nav-link text-dark" asp-area="" asp-page="/Account/Logout">登出</a>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="form-inline my-2 my-lg-0 nav-item">
|
||||
<a class="nav-link text-dark" asp-area="" asp-page="/Account/Login">登录</a>
|
||||
</div>
|
||||
}
|
||||
@if (HttpContextAccessor.HttpContext.User.Identity.IsAuthenticated)
|
||||
{
|
||||
<div class="form-inline my-2 my-lg-0">
|
||||
<span class="nav-item">欢迎您,@(HttpContextAccessor.HttpContext.User.FindFirst(ClaimTypes.Name).Value)</span>
|
||||
</div>
|
||||
}
|
||||
<ul class="navbar-nav flex-grow-1">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link text-dark" asp-area="" asp-page="/Index">首页</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link text-dark" asp-area="" asp-page="/Students/Index">已报名学生</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link text-dark" asp-area="" asp-page="/Submissions/Index">提交记录</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link text-dark" asp-area="" asp-page="/Message/Index">短信</a>
|
||||
</li>
|
||||
@if (HttpContextAccessor.HttpContext.User.HasClaim(EvaClaimTypes.IsManager, "true"))
|
||||
{
|
||||
<li class="nav-item">
|
||||
<a class="nav-link text-dark" asp-area="" asp-page="/Users/Index">后台用户管理</a>
|
||||
</li>
|
||||
}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link text-dark" asp-area="" asp-page="/Sessions/Index">活动排班</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
<div class="container-fluid">
|
||||
<main role="main" class="pb-3">
|
||||
@RenderBody()
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="border-top footer text-muted">
|
||||
<div class="container">
|
||||
© 2021-backend <a asp-area="" asp-page="/Privacy">关于</a>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="~/lib/jquery/dist/jquery.min.js"></script>
|
||||
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="~/js/site.js" asp-append-version="true"></script>
|
||||
|
||||
@RenderSection("Scripts", required: false)
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
|
||||
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
@page
|
||||
@model _2021_backend.Pages.Students.CreateModel
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Create";
|
||||
}
|
||||
|
||||
<h1>创建</h1>
|
||||
|
||||
<h4>学生</h4>
|
||||
<hr />
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<form method="post">
|
||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Student.Name" class="control-label"></label>
|
||||
<input asp-for="Student.Name" class="form-control" />
|
||||
<span asp-validation-for="Student.Name" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Student.Stuid" class="control-label"></label>
|
||||
<input asp-for="Student.Stuid" class="form-control" />
|
||||
<span asp-validation-for="Student.Stuid" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Student.Sex" class="control-label"></label>
|
||||
<select asp-for="Student.Sex" class="form-control" asp-items="@Html.GetEnumSelectList(typeof(_2021_backend.Models.sex))"></select>
|
||||
<span asp-validation-for="Student.Sex" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Student.Yard" class="control-label"></label>
|
||||
<select asp-for="Student.Yard" class="form-control" asp-items="@Html.GetEnumSelectList(typeof(_2021_backend.Models.yard))"></select>
|
||||
<span asp-validation-for="Student.Yard" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Student.Grade" class="control-label"></label>
|
||||
<select asp-for="Student.Grade" class="form-control" asp-items="@Html.GetEnumSelectList(typeof(_2021_backend.Models.grade))"></select>
|
||||
<span asp-validation-for="Student.Grade" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Student.Major" class="control-label"></label>
|
||||
<input asp-for="Student.Major" class="form-control" />
|
||||
<span asp-validation-for="Student.Major" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Student.Email" class="control-label"></label>
|
||||
<input asp-for="Student.Email" class="form-control" />
|
||||
<span asp-validation-for="Student.Email" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Student.Tel" class="control-label"></label>
|
||||
<input asp-for="Student.Tel" class="form-control" />
|
||||
<span asp-validation-for="Student.Tel" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Student.Status" class="control-label"></label>
|
||||
<select asp-for="Student.Status" class="form-control" asp-items="@Html.GetEnumSelectList(typeof(_2021_backend.Models.status))"></select>
|
||||
<span asp-validation-for="Student.Status" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Student.RegisterTime" class="control-label"></label>
|
||||
<input asp-for="Student.RegisterTime" class="form-control" />
|
||||
<span asp-validation-for="Student.RegisterTime" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="submit" value="Create" class="btn btn-primary" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<a asp-page="Index">返回列表</a>
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
using _2021_backend.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace _2021_backend.Pages.Students
|
||||
{
|
||||
public class CreateModel : PageModel
|
||||
{
|
||||
private readonly _2021_backend.Data.BackendContext Context;
|
||||
|
||||
public CreateModel(_2021_backend.Data.BackendContext context)
|
||||
{
|
||||
Context = context;
|
||||
}
|
||||
|
||||
public IActionResult OnGet()
|
||||
{
|
||||
Student = new Student();
|
||||
return Page();
|
||||
}
|
||||
|
||||
|
||||
|
||||
[BindProperty]
|
||||
[Required(ErrorMessage = "该项不能为空")]
|
||||
public Student Student { get; set; }
|
||||
|
||||
// To protect from overposting attacks, see https://aka.ms/RazorPagesCRUD
|
||||
public async Task<IActionResult> OnPostAsync()
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return Page();
|
||||
}
|
||||
if (Context.Students.Any(t => (t.Name == Student.Name || t.Stuid == Student.Stuid || t.Tel == Student.Tel)))
|
||||
{
|
||||
return RedirectToPage("./Index", new { pageId = 0, errInfo = "该学生已经存在" });
|
||||
}
|
||||
Context.Students.Add(Student);
|
||||
await Context.SaveChangesAsync();
|
||||
|
||||
return RedirectToPage("./Index");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
@page
|
||||
@model _2021_backend.Pages.Students.DeleteModel
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Delete";
|
||||
}
|
||||
|
||||
<h1>删除</h1>
|
||||
|
||||
<h3>你确定要删除该项目吗?</h3>
|
||||
<div>
|
||||
<h4>学生</h4>
|
||||
<hr />
|
||||
<dl class="row">
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Student.Name)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.Student.Name)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Student.Stuid)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.Student.Stuid)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Student.Sex)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.Student.Sex)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Student.Grade)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.Student.Grade)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Student.Major)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.Student.Major)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Student.Email)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.Student.Email)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Student.Tel)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.Student.Tel)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Student.Status)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.Student.Status)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Student.LastSubmission)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.Student.LastSubmission)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Student.RegisterTime)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.Student.RegisterTime)
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<form method="post">
|
||||
<input type="hidden" asp-for="Student.Guid" />
|
||||
<input type="submit" value="删除" class="btn btn-danger" /> |
|
||||
<a asp-page="./Index">返回列表</a>
|
||||
</form>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using _2021_backend.Data;
|
||||
using _2021_backend.Models;
|
||||
|
||||
namespace _2021_backend.Pages.Students
|
||||
{
|
||||
public class DeleteModel : PageModel
|
||||
{
|
||||
private readonly _2021_backend.Data.BackendContext Context;
|
||||
|
||||
public DeleteModel(_2021_backend.Data.BackendContext context)
|
||||
{
|
||||
Context = context;
|
||||
}
|
||||
|
||||
[BindProperty]
|
||||
public Student Student { get; set; }
|
||||
|
||||
public async Task<IActionResult> OnGetAsync(string? idstr)
|
||||
{
|
||||
if (idstr == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
Guid id = Guid.Parse(idstr);
|
||||
|
||||
Student = await Context.Students.FirstOrDefaultAsync(m => m.Guid == id);
|
||||
|
||||
if (Student == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return Page();
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPostAsync(string? idstr)
|
||||
{
|
||||
if (idstr == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
Guid id = Guid.Parse(idstr);
|
||||
|
||||
Student = await Context.Students.FindAsync(id);
|
||||
|
||||
if (Student != null)
|
||||
{
|
||||
var q = from e in Context.Sessions where e.Students.Contains(id) select e;
|
||||
var lst = q.ToList();
|
||||
foreach(var it in lst)
|
||||
{
|
||||
it.Students.RemoveAll(k => k == id);
|
||||
}
|
||||
Context.Students.Remove(Student);
|
||||
Context.SaveChanges();
|
||||
}
|
||||
|
||||
return RedirectToPage("./Index");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,370 @@
|
|||
@page
|
||||
@model _2021_backend.Pages.Students.DetailsModel
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Details";
|
||||
}
|
||||
|
||||
<h1>@Html.DisplayFor(model=> Model.Student.Name)</h1>
|
||||
|
||||
<div>
|
||||
<h4>详细信息</h4>
|
||||
<hr />
|
||||
<dl class="row">
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Student.Name)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.Student.Name)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Student.Stuid)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.Student.Stuid)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Student.Sex)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.Student.Sex)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Student.Grade)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.Student.Grade)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Student.Major)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.Student.Major)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Student.Email)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.Student.Email)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Student.Tel)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.Student.Tel)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Student.Status)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.Student.Status)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Student.RegisterTime)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.Student.RegisterTime)
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
<h5>此人的最终得分 : @Html.DisplayFor(model => model.Student.Score)</h5>
|
||||
<form method="post" class="form-inline m-2">
|
||||
<input type="hidden" asp-for="Student.Guid" />
|
||||
<div class="mb-2">
|
||||
操作
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<input type="submit" value="通过" class="btn btn-info" style="margin:5px" asp-page-handler="Accept" />
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<input type="submit" value="拒绝" class="btn btn-danger" style="margin:5px" asp-page-handler="Reject" />
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
给他打分
|
||||
<input asp-for="score" class="form-control"/>
|
||||
<input type="submit" value="打" class="btn btn-warning" style="margin:5px" asp-page-handler="Rank" />
|
||||
</div>
|
||||
</form>
|
||||
<br />
|
||||
|
||||
<h4>
|
||||
看看大家怎么说
|
||||
</h4>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th> @Html.DisplayNameFor(model => model.CommentSample.Operator)</th>
|
||||
<th> @Html.DisplayNameFor(model => model.CommentSample.Content)</th>
|
||||
<th> @Html.DisplayNameFor(model => model.CommentSample.AddTime)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var cmt in Model.CurComments)
|
||||
{
|
||||
<tr>
|
||||
@{
|
||||
var usr = Model.Context.Users.Find(cmt.Operator);
|
||||
<td>
|
||||
@Html.DisplayFor(model => usr.Name)
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(model => cmt.Content)
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(model => cmt.AddTime)
|
||||
</td>
|
||||
}
|
||||
</tr>
|
||||
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h4>
|
||||
添加评论
|
||||
</h4>
|
||||
<form method="post">
|
||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||
<div class="form-group">
|
||||
<textarea asp-for="NewComment" class="form-control" rows="5"></textarea>
|
||||
<span asp-validation-for="NewComment" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="hidden" asp-for="Student.Guid" />
|
||||
<input type="submit" value="→" class="btn btn-primary btn-sm" />
|
||||
</div>
|
||||
</form>
|
||||
<br />
|
||||
|
||||
<h4>
|
||||
场次
|
||||
</h4>
|
||||
|
||||
<h4>
|
||||
最终场次 : @{
|
||||
if (Model.Interviewtime == null)
|
||||
{
|
||||
<div class="text-danger">尚未确定活动场次</div>
|
||||
<hr />
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="text-info">
|
||||
@{
|
||||
var val = Model.Interviewtime.Place + " " + Model.Interviewtime.Day.ToString("MM月dd日") + " " + Model.Interviewtime.BeginTime.ToString("hh:mm");
|
||||
@Html.DisplayFor(model => val)
|
||||
}
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</h4>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr >
|
||||
<th>地点</th>
|
||||
<th>日期</th>
|
||||
<th>时间</th>
|
||||
<th>总容量</th>
|
||||
<th>剩余人数</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@for (int i = 0; i < Model.Student.Timelist.Count; i++)
|
||||
{
|
||||
var it = Model.Student.Timelist[i];
|
||||
var dt = Model.Context.Sessions.Find(it);
|
||||
if (dt.Capacity > dt.Students.Count || dt.Students.Contains(Model.Student.Guid))
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
@{
|
||||
|
||||
@Html.DisplayFor(model => dt.Place)
|
||||
}
|
||||
</td>
|
||||
<td>
|
||||
@{
|
||||
var s1 = dt.Day.ToString("MM-dd");
|
||||
@Html.DisplayFor(model => s1)
|
||||
}
|
||||
</td>
|
||||
<td>
|
||||
@{
|
||||
var s2 = dt.BeginTime.ToString("hh-mm");
|
||||
@Html.DisplayFor(model => s2)
|
||||
}
|
||||
</td>
|
||||
<td>
|
||||
@{
|
||||
var s4 = dt.Capacity.ToString();
|
||||
@Html.DisplayFor(model => s4)
|
||||
}
|
||||
</td>
|
||||
|
||||
<td>
|
||||
@{
|
||||
var num = (dt.Capacity - dt.Students.Count()).ToString();
|
||||
@Html.DisplayFor(model => num)
|
||||
}
|
||||
</td>
|
||||
<td>
|
||||
<form method="post" class="form-inline">
|
||||
<input type="hidden" asp-for="Student.Guid" />
|
||||
<a asp-page="/Sessions/Edit" asp-route-id="@it.ToString()" class="btn btn-sm btn-primary">场次详情</a>
|
||||
<input type="submit" asp-page-handler="Select" asp-route-stu="@Model.Student.Guid" asp-route-time="@it.ToString()" class="btn btn-sm btn-warning" value="选择这个" />
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
<h4>
|
||||
Ta的短信
|
||||
</h4>
|
||||
<form method="post">
|
||||
<input type="hidden" asp-for="Student.Guid" />
|
||||
<input type="submit" value="拉取5天内的回复短信" class="btn btn-primary" asp-page-handler="Pull" />
|
||||
<input type="submit" value="发送报名确认短信" class="btn btn-primary" asp-page-handler="Sign" />
|
||||
<input type="submit" value="发送活动场次确认短信" class="btn btn-primary" asp-page-handler="Time" />
|
||||
<input type="submit" value="发送活动结果短信" class="btn btn-primary" asp-page-handler="Result" />
|
||||
</form>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
发送时间
|
||||
</th>
|
||||
<th>
|
||||
短信类型
|
||||
</th>
|
||||
<th>
|
||||
短信内容
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var msg in Model.Messages)
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
@{
|
||||
var str = msg.SendTime.ToString("MM-dd hh:mm:ss");
|
||||
@Html.DisplayFor(it => str)
|
||||
}
|
||||
</td>
|
||||
<td>
|
||||
@{
|
||||
var s = Enum.GetName(typeof(_2021_backend.Models.SMSType), msg.Type);
|
||||
@Html.DisplayFor(it=> s)
|
||||
}
|
||||
</td>
|
||||
<td>
|
||||
@{
|
||||
string s2 = "";
|
||||
foreach (var e in msg.Data)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(e)) s2 += " " + e;
|
||||
}
|
||||
@Html.DisplayFor(it => s2)
|
||||
}
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
<h4>
|
||||
Ta的提交记录
|
||||
</h4>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.SubmissionSample.Name)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.SubmissionSample.Stuid)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.SubmissionSample.Sex)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.SubmissionSample.Yard)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.SubmissionSample.Grade)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.SubmissionSample.Major)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.SubmissionSample.Email)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.SubmissionSample.Tel)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.SubmissionSample.Address)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.SubmissionSample.SubmitTime)
|
||||
</th>
|
||||
<th>
|
||||
Operation
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var item in Model.Student.Submissions)
|
||||
{
|
||||
var sub = Model.Context.Submissions.Find(item);
|
||||
<tr>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => sub.Name)
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => sub.Stuid)
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => sub.Sex)
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => sub.Yard)
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => sub.Grade)
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => sub.Major)
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => sub.Email)
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => sub.Tel)
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => sub.Address)
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => sub.SubmitTime)
|
||||
</td>
|
||||
<td>
|
||||
<a asp-page="/Submissions/Edit" asp-route-strid="@sub.Guid">Edit</a> |
|
||||
<a asp-page="/Submissions/Details" asp-route-strid="@sub.Guid">Details</a>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
<div>
|
||||
<a asp-page="./Edit" asp-route-idstr="@Model.Student.Guid">编辑信息</a> |
|
||||
<a asp-page="./Index">返回列表</a>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,204 @@
|
|||
using _2021_backend.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace _2021_backend.Pages.Students
|
||||
{
|
||||
public class DetailsModel : PageModel
|
||||
{
|
||||
public _2021_backend.Data.BackendContext Context;
|
||||
|
||||
public DetailsModel(_2021_backend.Data.BackendContext context)
|
||||
{
|
||||
Context = context;
|
||||
}
|
||||
[BindProperty]
|
||||
public Student Student { get; set; }
|
||||
|
||||
[BindProperty]
|
||||
public int score { get; set; }
|
||||
public List<Session> Sessions { get; set; }
|
||||
|
||||
public List<Submission> Submissions { get; set; }
|
||||
|
||||
public List<Comment> CurComments { get; set; }
|
||||
public Session Interviewtime { get; set; }
|
||||
public Comment CommentSample { get; set; }
|
||||
public Submission SubmissionSample { get; set; }
|
||||
[Display(Name = "评论内容")]
|
||||
[BindProperty]
|
||||
[Required(ErrorMessage = "该项不能为空")]
|
||||
public string NewComment { get; set; }
|
||||
|
||||
public List<SMS> Messages { get; set; }
|
||||
|
||||
public IActionResult Construct(string? idstr)
|
||||
{
|
||||
if (idstr == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
Guid id = Guid.Parse(idstr);
|
||||
Student = Context.Students.Find(id);
|
||||
if (Student == null)
|
||||
{
|
||||
Console.WriteLine("Student not found.");
|
||||
return NotFound();
|
||||
}
|
||||
Sessions = new List<Session>();
|
||||
Submissions = new List<Submission>();
|
||||
Interviewtime = Context.Sessions.Find(Student.InterviewTime);
|
||||
foreach (var it in Student.Timelist)
|
||||
{
|
||||
var tm = Context.Sessions.Find(it);
|
||||
if (tm == null) Console.WriteLine("null encountered in timelist!");
|
||||
Sessions.Add(tm);
|
||||
}
|
||||
Messages = Context.SMS.Where(it => it.Host == id).ToList();
|
||||
CurComments = Context.Comments.Where(cmt => cmt.Student == Student.Guid).ToList();
|
||||
Sessions.Sort((Session a, Session b) => {
|
||||
var x = a.Day.CompareTo(b.Day);
|
||||
var y = a.BeginTime.CompareTo(b.BeginTime);
|
||||
var z = a.Place.CompareTo(b.Place);
|
||||
return (x != 0 ? x : y != 0 ? y : z != 0 ? z : 0);
|
||||
|
||||
});
|
||||
Console.WriteLine("Page construction finished.");
|
||||
return Page();
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnGetAsync(string? idstr)
|
||||
{
|
||||
Console.WriteLine("getting student " + idstr);
|
||||
return Construct(idstr);
|
||||
}
|
||||
public async Task<IActionResult> OnPostAsync()
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(NewComment))
|
||||
{
|
||||
var cmt = new Comment();
|
||||
cmt.Student = Student.Guid;
|
||||
cmt.Content = NewComment;
|
||||
cmt.Operator = Guid.Parse(User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Sid).Value);
|
||||
var stu = Context.Students.Find(Student.Guid);
|
||||
stu.Comments.Add(cmt.Guid);
|
||||
Context.Comments.Add(cmt);
|
||||
Context.SaveChanges();
|
||||
}
|
||||
Construct(Student.Guid.ToString());
|
||||
return RedirectToPage(new { idstr = Student.Guid.ToString() });
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPostAcceptAsync()
|
||||
{
|
||||
Student = Context.Students.Find(Student.Guid);
|
||||
Student.Status = status.通过;
|
||||
Context.SaveChanges();
|
||||
CurComments = Context.Comments.Where(cmt => cmt.Student == Student.Guid).ToList();
|
||||
Messages = Context.SMS.Where(it => it.Host == Student.Guid).ToList();
|
||||
Construct(Student.Guid.ToString());
|
||||
return RedirectToPage(new { idstr = Student.Guid.ToString() });
|
||||
}
|
||||
|
||||
|
||||
|
||||
public async Task<IActionResult> OnPostRejectAsync()
|
||||
{
|
||||
Student = Context.Students.Find(Student.Guid);
|
||||
Student.Status = status.不通过;
|
||||
Context.SaveChanges();
|
||||
Student.Score = 0;
|
||||
CurComments = Context.Comments.Where(cmt => cmt.Student == Student.Guid).ToList();
|
||||
Messages = Context.SMS.Where(it => it.Host == Student.Guid).ToList();
|
||||
Construct(Student.Guid.ToString());
|
||||
return RedirectToPage(new { idstr = Student.Guid.ToString() });
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPostSelectAsync(Guid stu, Guid time)
|
||||
{
|
||||
var st = Context.Students.Find(stu);
|
||||
if (st != null)
|
||||
{
|
||||
|
||||
if (Context.Sessions.Any(it => it.Guid == time))
|
||||
{
|
||||
var tm = Context.Sessions.Find(time);
|
||||
if (tm.Students.Count < tm.Capacity)
|
||||
{
|
||||
if (st.InterviewTime != Guid.Empty)
|
||||
{
|
||||
var tmold = Context.Sessions.Find(st.InterviewTime);
|
||||
if (tmold != null)
|
||||
{
|
||||
tmold.Students.RemoveAll(it => it == st.Guid);
|
||||
Context.SaveChanges();
|
||||
}
|
||||
}
|
||||
tm.Students.Add(stu);
|
||||
st.InterviewTime = time;
|
||||
if (st.Status != status.不通过 && st.Status != status.通过) st.Status = status.已选时间;
|
||||
Context.SaveChanges();
|
||||
}
|
||||
}
|
||||
}
|
||||
return Construct(Student.Guid.ToString());
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPostPullAsync()
|
||||
{
|
||||
await Utils.TencentSMS.Pull(Context, Context.Students.Find(Student.Guid), true);
|
||||
return Construct(Student.Guid.ToString());
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPostRankAsync()
|
||||
{
|
||||
var s = Context.Students.Find(Student.Guid);
|
||||
s.Score = score;
|
||||
s.Status = status.已评分;
|
||||
Context.SaveChanges();
|
||||
return Construct(Student.Guid.ToString());
|
||||
}
|
||||
|
||||
|
||||
public async Task<IActionResult> OnPostResultAsync()
|
||||
{
|
||||
var stu = Context.Students.Find(Student.Guid);
|
||||
if (stu.Status == status.通过)
|
||||
await Utils.TencentSMS.Send(Context, SMSType.Accept, stu, Context.Users.Find(Guid.Parse(User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Sid).Value)).Name);
|
||||
else if (stu.Status == status.不通过)
|
||||
await Utils.TencentSMS.Send(Context, SMSType.Reject, stu, Context.Users.Find(Guid.Parse(User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Sid).Value)).Name);
|
||||
return Construct(Student.Guid.ToString());
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPostSignAsync()
|
||||
{
|
||||
var stu = Context.Students.Find(Student.Guid);
|
||||
await Utils.TencentSMS.Send(Context, SMSType.Signed, stu, Context.Users.Find(Guid.Parse(User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Sid).Value)).Name);
|
||||
return Construct(Student.Guid.ToString());
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPostSelectTimeAsync()
|
||||
{
|
||||
var stu = Context.Students.Find(Student.Guid);
|
||||
await Utils.TencentSMS.Send(Context, SMSType.TimeSelect, stu, Context.Users.Find(Guid.Parse(User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Sid).Value)).Name);
|
||||
stu.Status = status.需调整时间;
|
||||
return Construct(Student.Guid.ToString());
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPostTimeAsync()
|
||||
{
|
||||
var stu = Context.Students.Find(Student.Guid);
|
||||
await Utils.TencentSMS.Send(Context, SMSType.TimeSet, stu, Context.Users.Find(Guid.Parse(User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Sid).Value)).Name);
|
||||
stu.Status = status.已确认时间;
|
||||
Context.SaveChanges();
|
||||
return Construct(Student.Guid.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
@page
|
||||
@model _2021_backend.Pages.Students.EditModel
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Edit";
|
||||
}
|
||||
|
||||
<h1>编辑详细信息</h1>
|
||||
|
||||
<h4>学生</h4>
|
||||
<hr />
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<form method="post">
|
||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||
<input type="hidden" asp-for="Student.Guid" />
|
||||
<div class="form-group">
|
||||
<label asp-for="Student.Name" class="control-label"></label>
|
||||
<input asp-for="Student.Name" class="form-control" />
|
||||
<span asp-validation-for="Student.Name" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Student.Stuid" class="control-label"></label>
|
||||
<input asp-for="Student.Stuid" class="form-control" />
|
||||
<span asp-validation-for="Student.Stuid" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Student.Sex" class="control-label"></label>
|
||||
<select asp-for="Student.Sex" class="form-control" asp-items="@Html.GetEnumSelectList(typeof(_2021_backend.Models.sex))"></select>
|
||||
<span asp-validation-for="Student.Sex" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Student.Yard" class="control-label"></label>
|
||||
<select asp-for="Student.Yard" class="form-control" asp-items="@Html.GetEnumSelectList(typeof(_2021_backend.Models.yard))"></select>
|
||||
<span asp-validation-for="Student.Yard" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Student.Grade" class="control-label"></label>
|
||||
<select asp-for="Student.Grade" class="form-control" asp-items="@Html.GetEnumSelectList(typeof(_2021_backend.Models.grade))"></select>
|
||||
<span asp-validation-for="Student.Grade" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Student.Major" class="control-label"></label>
|
||||
<input asp-for="Student.Major" class="form-control" />
|
||||
<span asp-validation-for="Student.Major" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Student.Email" class="control-label"></label>
|
||||
<input asp-for="Student.Email" class="form-control" />
|
||||
<span asp-validation-for="Student.Email" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Student.Tel" class="control-label"></label>
|
||||
<input asp-for="Student.Tel" class="form-control" />
|
||||
<span asp-validation-for="Student.Tel" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Student.RegisterTime" class="control-label"></label>
|
||||
<input asp-for="Student.RegisterTime" class="form-control" />
|
||||
<span asp-validation-for="Student.RegisterTime" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Student.Status" class="control-label"></label>
|
||||
<select asp-for="Student.Status" class="form-control" asp-items="@Html.GetEnumSelectList(typeof(_2021_backend.Models.status))"></select>
|
||||
<span asp-validation-for="Student.Status" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="submit" value="Save" class="btn btn-primary" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<a asp-page="./Index">返回列表</a>
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
using _2021_backend.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace _2021_backend.Pages.Students
|
||||
{
|
||||
public class EditModel : PageModel
|
||||
{
|
||||
public readonly _2021_backend.Data.BackendContext Context;
|
||||
|
||||
public EditModel(_2021_backend.Data.BackendContext context)
|
||||
{
|
||||
Context = context;
|
||||
}
|
||||
|
||||
[BindProperty]
|
||||
public Student Student { get; set; }
|
||||
|
||||
public async Task<IActionResult> OnGetAsync(string? idstr)
|
||||
{
|
||||
if (idstr == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
Guid id = Guid.Parse(idstr);
|
||||
Student = await Context.Students.AsNoTracking().FirstOrDefaultAsync(m => m.Guid == id);
|
||||
|
||||
if (Student == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return Page();
|
||||
}
|
||||
|
||||
// To protect from overposting attacks, enable the specific properties you want to bind to.
|
||||
// For more details, see https://aka.ms/RazorPagesCRUD.
|
||||
public async Task<IActionResult> OnPostAsync()
|
||||
{
|
||||
var stu = Context.Students.Find(Student.Guid);
|
||||
stu.Status = Student.Status;
|
||||
stu.Email = Student.Email;
|
||||
stu.Name = Student.Name;
|
||||
stu.Stuid = Student.Stuid;
|
||||
stu.Tel = Student.Tel;
|
||||
stu.Grade = Student.Grade;
|
||||
stu.Sex = Student.Sex;
|
||||
stu.Yard = Student.Yard;
|
||||
Context.SaveChanges();
|
||||
return RedirectToPage("./Index");
|
||||
}
|
||||
|
||||
private bool StudentExists(Guid id)
|
||||
{
|
||||
return Context.Students.Any(e => e.Guid == id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
@page
|
||||
@model _2021_backend.Pages.Students.IndexModel
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Index";
|
||||
}
|
||||
|
||||
<h1>报了名的xpy们</h1>
|
||||
|
||||
<p>
|
||||
<a asp-page="Create">手动添加一个</a>
|
||||
</p>
|
||||
<h5 class="text-red">
|
||||
<strong>@Html.DisplayFor(model => Model.errmsg)</strong>
|
||||
</h5>
|
||||
<form class="form-inline m-2" method="post">
|
||||
<div class="form-group mx-sm-0 m-2">
|
||||
<input type="text" class="form-control" id="searchString" placeholder="输入部分学号或姓名" asp-for="SearchString" name="SearchString">
|
||||
</div>
|
||||
<div class="form-group mx-sm-0 m-2">
|
||||
<input type="text" class="form-control" id="SearchTel" placeholder="电话号码" asp-for="SearchTel" name="SearchTel">
|
||||
</div>
|
||||
<div class="form-group mx-sm-0 m-2">
|
||||
<input type="text" class="form-control" id="SearchQQ" placeholder="QQ号码" asp-for="SearchQQ" name="SearchQQ">
|
||||
</div>
|
||||
<div class="m-2">
|
||||
年级
|
||||
<select asp-for="Grade" asp-items="@Html.GetEnumSelectList(typeof(_2021_backend.Models.grade))" class="form-control">
|
||||
</select>
|
||||
</div>
|
||||
<div class="m-2">
|
||||
状态
|
||||
<select asp-for="StatusSel" asp-items="@Html.GetEnumSelectList(typeof(_2021_backend.Models.status))" class="form-control">
|
||||
</select>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-outline-primary m-2">搜索</button>
|
||||
</form>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
Index
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.Student[0].Name)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.Student[0].Stuid)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.Student[0].Sex)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.Student[0].Yard)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.Student[0].Grade)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.Student[0].Major)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.Student[0].Status)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.Student[0].Exp)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.Student[0].Score)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.Student[0].RegisterTime)
|
||||
</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@{
|
||||
var n = 0;
|
||||
@foreach (var item in Model.Student)
|
||||
{
|
||||
n++;
|
||||
<tr class="@{
|
||||
switch(item.Status){
|
||||
case _2021_backend.Models.status.不通过:
|
||||
@("table-danger")
|
||||
break;
|
||||
case _2021_backend.Models.status.通过:
|
||||
@("table-success")
|
||||
break;
|
||||
case _2021_backend.Models.status.刚报名:
|
||||
@("")
|
||||
break;
|
||||
case _2021_backend.Models.status.已评分:
|
||||
@("table-primary")
|
||||
break;
|
||||
}
|
||||
}">
|
||||
<td>
|
||||
@{
|
||||
var s = (Model.PageId * IndexModel.PageSize + n).ToString();
|
||||
@Html.DisplayFor(it => s)
|
||||
}
|
||||
</td>
|
||||
<td>
|
||||
<a asp-page="./Details" asp-route-idstr="@item.Guid.ToString()"> @Html.DisplayFor(modelItem => item.Name)</a>
|
||||
</td>
|
||||
<td>
|
||||
<a asp-page="./Details" asp-route-idstr="@item.Guid.ToString()"> @Html.DisplayFor(modelItem => item.Stuid)</a>
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => item.Sex)
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => item.Yard)
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => item.Grade)
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => item.Major)
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => item.Status)
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => item.Exp)
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => item.Score)
|
||||
</td>
|
||||
<th>
|
||||
@Html.DisplayFor(modelItem => item.RegisterTime)
|
||||
</th>
|
||||
<td>
|
||||
<a asp-page="./Edit" asp-route-idstr="@item.Guid.ToString()">编辑资料</a> |
|
||||
<a asp-page="./Details" asp-route-idstr="@item.Guid.ToString()">审阅</a> |
|
||||
<a asp-page="./Delete" asp-route-idstr="@item.Guid.ToString()">删除</a>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
}
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
<nav>
|
||||
<ul class="pagination">
|
||||
<li class="page-item @(Model.PageId==0 ? "disabled" : "")"><a class="page-link" asp-route-pageId="@(Model.PageId-1) " asp-route-Grade="@Model.Grade" asp-route-SearchString="@Model.SearchString" asp-route-StatusSel="@Model.StatusSel" asp-route-SearchQQ="@Model.SearchQQ">Prev</a></li>
|
||||
@for (int i = 0; i < Model.PageCount; i++)
|
||||
{
|
||||
<li class="page-item @(Model.PageId==i ? "active" : "")"><a class="page-link" asp-route-pageId="@i" asp-route-Grade="@Model.Grade" asp-route-SearchString="@Model.SearchString" asp-route-StatusSel="@Model.StatusSel" asp-route-SearchQQ="@Model.SearchQQ">@i</a></li>
|
||||
}
|
||||
<li class="page-item @(Model.PageId>=Model.PageCount -1? "disabled" : "")"><a class="page-link" asp-route-pageId="@(Model.PageId+1)" asp-route-Grade="@Model.Grade" asp-route-SearchString="@Model.SearchString" asp-route-StatusSel="@Model.StatusSel" asp-route-SearchQQ="@Model.SearchQQ">Next</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
using _2021_backend.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.IO.Compression;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using _2021_backend.Utils;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace _2021_backend.Pages.Students
|
||||
{
|
||||
public class IndexModel : PageModel
|
||||
{
|
||||
private readonly _2021_backend.Data.BackendContext Context;
|
||||
public static int PageSize { get; set; }
|
||||
public int PageCount { get; set; }
|
||||
public int PageId { get; set; }
|
||||
public string errmsg { get; set; }
|
||||
|
||||
[BindProperty(SupportsGet = true)]
|
||||
public string SearchString { get; set; }
|
||||
[BindProperty(SupportsGet = true)]
|
||||
public grade Grade { get; set; }
|
||||
|
||||
[BindProperty(SupportsGet = true)]
|
||||
public string SearchQQ { get; set; }
|
||||
|
||||
[BindProperty(SupportsGet = true)]
|
||||
public string SearchTel { get; set; }
|
||||
|
||||
[BindProperty(SupportsGet = true)]
|
||||
public status StatusSel { get; set; } = status.暂缺;
|
||||
|
||||
|
||||
|
||||
public IndexModel(_2021_backend.Data.BackendContext context)
|
||||
{
|
||||
Context = context;
|
||||
}
|
||||
|
||||
public List<Student> Student { get; set; }
|
||||
public IActionResult Construct(int pageId, string errInfo)
|
||||
{
|
||||
PageSize = 30;
|
||||
if (string.IsNullOrEmpty(errInfo))
|
||||
{
|
||||
errmsg = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
errmsg = errInfo;
|
||||
}
|
||||
if (pageId == null) pageId = 0;
|
||||
IQueryable<Student> q;
|
||||
if (!string.IsNullOrEmpty(SearchString))
|
||||
{
|
||||
q = Context.Students.Where(s => (s.Name.Contains(SearchString) || s.Stuid.Contains(SearchString)));
|
||||
}
|
||||
else
|
||||
{
|
||||
q = Context.Students;
|
||||
}
|
||||
if (Grade != grade.暂缺) q = q.Where(it => it.Grade == Grade);
|
||||
if (StatusSel != status.暂缺) q = q.Where(it => it.Status == StatusSel);
|
||||
if (!String.IsNullOrEmpty(SearchTel)) q = q.Where(it => it.Tel.Contains(SearchTel));
|
||||
if (!String.IsNullOrEmpty(SearchQQ)) q = q.Where(it => it.Email.Contains(SearchQQ));
|
||||
Student = q.ToList();
|
||||
|
||||
Student.Sort((Student a, Student b) =>
|
||||
{
|
||||
return -a.RegisterTime.CompareTo(b.RegisterTime);
|
||||
});
|
||||
int cnt = Student.Count;
|
||||
PageCount = (int)Math.Ceiling((double)cnt / (double)PageSize);
|
||||
if (pageId >= PageCount) pageId = PageCount - 1;
|
||||
if (pageId < 0) pageId = 0;
|
||||
PageId = (int)pageId;
|
||||
int count = (PageId + 1) * PageSize > cnt ? (cnt - PageId * PageSize) : PageSize;
|
||||
Student = Student.GetRange(PageId * PageSize, count);
|
||||
return Page();
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnGetAsync(int? pageId, string errInfo)
|
||||
{
|
||||
if (pageId == null) pageId = 0;
|
||||
return Construct((int)pageId, errInfo);
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPostAsync(int? pageId, string errInfo)
|
||||
{
|
||||
if (pageId == null) pageId = 0;
|
||||
return Construct((int)pageId, errInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
@page
|
||||
@model _2021_backend.Pages.Submissions.CreateModel
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Create";
|
||||
}
|
||||
|
||||
<h1>创建</h1>
|
||||
|
||||
<h4>提交记录</h4>
|
||||
<hr />
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<form method="post">
|
||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Submission.Name" class="control-label"></label>
|
||||
<input asp-for="Submission.Name" class="form-control" />
|
||||
<span asp-validation-for="Submission.Name" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Submission.Stuid" class="control-label"></label>
|
||||
<input asp-for="Submission.Stuid" class="form-control" />
|
||||
<span asp-validation-for="Submission.Stuid" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Submission.Sex" class="control-label"></label>
|
||||
<select asp-for="Submission.Sex" class="form-control" asp-items="@Html.GetEnumSelectList(typeof(_2021_backend.Models.sex))"></select>
|
||||
<span asp-validation-for="Submission.Sex" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Submission.Yard" class="control-label"></label>
|
||||
<select asp-for="Submission.Yard" class="form-control" asp-items="@Html.GetEnumSelectList(typeof(_2021_backend.Models.yard))"></select>
|
||||
<span asp-validation-for="Submission.Yard" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Submission.Grade" class="control-label"></label>
|
||||
<select asp-for="Submission.Grade" class="form-control" asp-items="@Html.GetEnumSelectList(typeof(_2021_backend.Models.grade))"></select>
|
||||
<span asp-validation-for="Submission.Grade" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Submission.Major" class="control-label"></label>
|
||||
<input asp-for="Submission.Major" class="form-control" />
|
||||
<span asp-validation-for="Submission.Major" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Submission.Email" class="control-label"></label>
|
||||
<input asp-for="Submission.Email" class="form-control" />
|
||||
<span asp-validation-for="Submission.Email" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Submission.Tel" class="control-label"></label>
|
||||
<input asp-for="Submission.Tel" class="form-control" />
|
||||
<span asp-validation-for="Submission.Tel" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Submission.Address" class="control-label"></label>
|
||||
<input asp-for="Submission.Address" class="form-control" />
|
||||
<span asp-validation-for="Submission.Address" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="submit" value="Create" class="btn btn-primary" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<a asp-page="Index">返回列表</a>
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
using _2021_backend.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace _2021_backend.Pages.Submissions
|
||||
{
|
||||
public class CreateModel : PageModel
|
||||
{
|
||||
private readonly _2021_backend.Data.BackendContext Context;
|
||||
|
||||
public CreateModel(_2021_backend.Data.BackendContext context)
|
||||
{
|
||||
Context = context;
|
||||
}
|
||||
|
||||
public IActionResult OnGet()
|
||||
{
|
||||
Submission = new Submission();
|
||||
return Page();
|
||||
}
|
||||
|
||||
[BindProperty]
|
||||
public Submission Submission { get; set; }
|
||||
|
||||
// To protect from overposting attacks, see https://aka.ms/RazorPagesCRUD
|
||||
public async Task<IActionResult> OnPostAsync()
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return Page();
|
||||
}
|
||||
var q = Context.Students.Where(stu => (stu.Name == Submission.Name || stu.Tel == Submission.Tel || stu.Stuid == Submission.Stuid));
|
||||
Student stu;
|
||||
if (q.Count() == 0)
|
||||
{
|
||||
stu = Student.create(Submission);
|
||||
stu.Status = status.刚报名;
|
||||
var q2 = from e in Context.Sessions select e.Guid;
|
||||
var lst = q2.ToList();
|
||||
stu.Timelist = lst;
|
||||
Context.Students.Add(stu);
|
||||
}
|
||||
else
|
||||
{
|
||||
stu = q.FirstOrDefault();
|
||||
stu.Update(Submission);
|
||||
}
|
||||
Submission.Host = stu.Guid;
|
||||
Context.Submissions.Add(Submission);
|
||||
Context.SaveChanges();
|
||||
|
||||
return RedirectToPage("./Index");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
@page
|
||||
@model _2021_backend.Pages.Submissions.DeleteModel
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Delete";
|
||||
}
|
||||
|
||||
<h1>删除</h1>
|
||||
|
||||
<h3>你确定要删除该项目吗?</h3>
|
||||
<div>
|
||||
<h4>提交记录</h4>
|
||||
<hr />
|
||||
<dl class="row">
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Submission.Name)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.Submission.Name)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Submission.Stuid)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.Submission.Stuid)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Submission.Sex)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.Submission.Sex)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Submission.Grade)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.Submission.Grade)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Submission.Major)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.Submission.Major)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Submission.Email)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.Submission.Email)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Submission.Tel)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.Submission.Tel)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Submission.Address)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.Submission.Address)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Submission.SubmitTime)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.Submission.SubmitTime)
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<form method="post">
|
||||
<input type="hidden" asp-for="Submission.Guid" />
|
||||
<input type="submit" value="删除" class="btn btn-danger" asp-route-id="@Model.Submission.Guid.ToString()"/> |
|
||||
<a asp-page="./Index">返回列表</a>
|
||||
</form>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using _2021_backend.Data;
|
||||
using _2021_backend.Models;
|
||||
|
||||
namespace _2021_backend.Pages.Submissions
|
||||
{
|
||||
public class DeleteModel : PageModel
|
||||
{
|
||||
private readonly _2021_backend.Data.BackendContext Context;
|
||||
|
||||
public DeleteModel(_2021_backend.Data.BackendContext context)
|
||||
{
|
||||
Context = context;
|
||||
}
|
||||
|
||||
[BindProperty]
|
||||
public Submission Submission { get; set; }
|
||||
|
||||
public async Task<IActionResult> OnGetAsync(string? strid)
|
||||
{
|
||||
Guid id = Guid.Parse(strid);
|
||||
if (id == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
Submission = Context.Submissions.FirstOrDefault(m => m.Guid == id);
|
||||
|
||||
if (Submission == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return Page();
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPostAsync(Guid? id)
|
||||
{
|
||||
if (id == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
Submission = Context.Submissions.Find(id);
|
||||
|
||||
if (Submission != null)
|
||||
{
|
||||
var stu = Context.Students.Find(Submission.Host);
|
||||
if (stu != null)
|
||||
{
|
||||
stu.Submissions.Remove(Submission.Guid);
|
||||
}
|
||||
Context.Submissions.Remove(Submission);
|
||||
Context.SaveChanges();
|
||||
}
|
||||
|
||||
return RedirectToPage("./Index");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
@page
|
||||
@model _2021_backend.Pages.Submissions.DetailsModel
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Details";
|
||||
}
|
||||
|
||||
<h1>Details</h1>
|
||||
|
||||
<div>
|
||||
<h4>Submission</h4>
|
||||
<hr />
|
||||
<dl class="row">
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Submission.Name)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.Submission.Name)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Submission.Stuid)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.Submission.Stuid)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Submission.Sex)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.Submission.Sex)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Submission.Yard)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.Submission.Yard)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Submission.Grade)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.Submission.Grade)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Submission.Major)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.Submission.Major)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Submission.Email)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.Submission.Email)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Submission.Tel)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.Submission.Tel)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Submission.Address)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.Submission.Address)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.Submission.SubmitTime)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.Submission.SubmitTime)
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div>
|
||||
<a asp-page="./Edit" asp-route-id="@Model.Submission.Guid">Edit</a> |
|
||||
<a asp-page="./Index">返回列表</a>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using _2021_backend.Data;
|
||||
using _2021_backend.Models;
|
||||
|
||||
namespace _2021_backend.Pages.Submissions
|
||||
{
|
||||
public class DetailsModel : PageModel
|
||||
{
|
||||
private readonly _2021_backend.Data.BackendContext _context;
|
||||
|
||||
public DetailsModel(_2021_backend.Data.BackendContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public Submission Submission { get; set; }
|
||||
|
||||
public async Task<IActionResult> OnGetAsync(string? strid)
|
||||
{
|
||||
|
||||
if (strid == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
Guid id = Guid.Parse(strid);
|
||||
Submission = await _context.Submissions.FirstOrDefaultAsync(m => m.Guid == id);
|
||||
|
||||
if (Submission == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return Page();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
@page
|
||||
@model _2021_backend.Pages.Submissions.EditModel
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Edit";
|
||||
}
|
||||
|
||||
<h1>编辑详细信息</h1>
|
||||
|
||||
<h4>提交记录</h4>
|
||||
<hr />
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<form method="post">
|
||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||
<input type="hidden" asp-for="Submission.Guid" />
|
||||
<div class="form-group">
|
||||
<label asp-for="Submission.Name" class="control-label"></label>
|
||||
<input asp-for="Submission.Name" class="form-control" />
|
||||
<span asp-validation-for="Submission.Name" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Submission.Stuid" class="control-label"></label>
|
||||
<input asp-for="Submission.Stuid" class="form-control" />
|
||||
<span asp-validation-for="Submission.Stuid" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Submission.Sex" class="control-label"></label>
|
||||
<select asp-for="Submission.Sex" class="form-control" asp-items="@Html.GetEnumSelectList(typeof(_2021_backend.Models.sex))"></select>
|
||||
<span asp-validation-for="Submission.Sex" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Submission.Grade" class="control-label"></label>
|
||||
<select asp-for="Submission.Grade" class="form-control" asp-items="@Html.GetEnumSelectList(typeof(_2021_backend.Models.grade))"></select>
|
||||
<span asp-validation-for="Submission.Grade" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Submission.Major" class="control-label"></label>
|
||||
<input asp-for="Submission.Major" class="form-control" />
|
||||
<span asp-validation-for="Submission.Major" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Submission.Email" class="control-label"></label>
|
||||
<input asp-for="Submission.Email" class="form-control" />
|
||||
<span asp-validation-for="Submission.Email" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Submission.Tel" class="control-label"></label>
|
||||
<input asp-for="Submission.Tel" class="form-control" />
|
||||
<span asp-validation-for="Submission.Tel" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Submission.Address" class="control-label"></label>
|
||||
<input asp-for="Submission.Address" class="form-control" />
|
||||
<span asp-validation-for="Submission.Address" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Submission.SubmitTime" class="control-label"></label>
|
||||
<input asp-for="Submission.SubmitTime" class="form-control" />
|
||||
<span asp-validation-for="Submission.SubmitTime" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="submit" value="Save" class="btn btn-primary" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<a asp-page="./Index">返回列表</a>
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using _2021_backend.Data;
|
||||
using _2021_backend.Models;
|
||||
|
||||
namespace _2021_backend.Pages.Submissions
|
||||
{
|
||||
public class EditModel : PageModel
|
||||
{
|
||||
public readonly _2021_backend.Data.BackendContext Context;
|
||||
|
||||
public EditModel(_2021_backend.Data.BackendContext context)
|
||||
{
|
||||
Context = context;
|
||||
}
|
||||
|
||||
[BindProperty]
|
||||
public Submission Submission { get; set; }
|
||||
|
||||
public async Task<IActionResult> OnGetAsync(string? strid)
|
||||
{
|
||||
Guid id = Guid.Parse(strid);
|
||||
if (id == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
Submission = await Context.Submissions.FirstOrDefaultAsync(m => m.Guid == id);
|
||||
|
||||
if (Submission == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return Page();
|
||||
}
|
||||
|
||||
// To protect from overposting attacks, enable the specific properties you want to bind to.
|
||||
// For more details, see https://aka.ms/RazorPagesCRUD.
|
||||
public async Task<IActionResult> OnPostAsync()
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return Page();
|
||||
}
|
||||
|
||||
Context.Attach(Submission).State = EntityState.Modified;
|
||||
|
||||
try
|
||||
{
|
||||
await Context.SaveChangesAsync();
|
||||
}
|
||||
catch (DbUpdateConcurrencyException)
|
||||
{
|
||||
if (!SubmissionExists(Submission.Guid))
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
return RedirectToPage("./Index");
|
||||
}
|
||||
|
||||
private bool SubmissionExists(Guid id)
|
||||
{
|
||||
return Context.Submissions.Any(e => e.Guid == id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
@page
|
||||
@model _2021_backend.Pages.Submissions.IndexModel
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Index";
|
||||
}
|
||||
|
||||
<h1>全部提交记录</h1>
|
||||
<p>
|
||||
<a asp-page="Create">Create New</a>
|
||||
</p>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.Submission[0].Name)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.Submission[0].Stuid)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.Submission[0].Sex)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.Submission[0].Grade)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.Submission[0].Major)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.Submission[0].Email)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.Submission[0].Tel)
|
||||
</th>
|
||||
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.Submission[0].Address)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.Submission[0].SubmitTime)
|
||||
</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var item in Model.Submission)
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => item.Name)
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => item.Stuid)
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => item.Sex)
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => item.Grade)
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => item.Major)
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => item.Email)
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => item.Tel)
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => item.Address)
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => item.SubmitTime)
|
||||
</td>
|
||||
<td>
|
||||
<a asp-page="./Edit" asp-route-strid="@item.Guid.ToString()">编辑</a> |
|
||||
<a asp-page="./Details" asp-route-strid="@item.Guid.ToString()">详细信息</a> |
|
||||
<a asp-page="./Delete" asp-route-strid="@item.Guid.ToString()">删除</a>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
<nav>
|
||||
<ul class="pagination">
|
||||
<li class="page-item @(Model.PageId==0 ? "disabled" : "")"><a class="page-link" asp-route-pageId="@(Model.PageId-1) ">Prev</a></li>
|
||||
@for (int i = 0; i < Model.PageCount; i++)
|
||||
{
|
||||
<li class="page-item @(Model.PageId==i ? "active" : "")"><a class="page-link" asp-route-pageId="@i">@i</a></li>
|
||||
}
|
||||
<li class="page-item @(Model.PageId>=Model.PageCount -1? "disabled" : "")"><a class="page-link" asp-route-pageId="@(Model.PageId+1)" >Next</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using _2021_backend.Data;
|
||||
using _2021_backend.Models;
|
||||
|
||||
namespace _2021_backend.Pages.Submissions
|
||||
{
|
||||
public class IndexModel : PageModel
|
||||
{
|
||||
private readonly _2021_backend.Data.BackendContext Context;
|
||||
|
||||
public static int PageSize = 30;
|
||||
public int PageCount { get; set; }
|
||||
public int PageId { get; set; }
|
||||
|
||||
public IndexModel(_2021_backend.Data.BackendContext context)
|
||||
{
|
||||
Context = context;
|
||||
}
|
||||
|
||||
public List<Submission> Submission { get;set; }
|
||||
|
||||
public async Task OnGetAsync(int pageId)
|
||||
{
|
||||
var q = from e in Context.Submissions orderby e.SubmitTime select e;
|
||||
Submission = await q.ToListAsync();
|
||||
Submission.Sort((a,b)=>b.SubmitTime.CompareTo(a.SubmitTime));
|
||||
int cnt = Submission.Count;
|
||||
PageCount = (int)Math.Ceiling((double)cnt / (double)PageSize);
|
||||
if (pageId >= PageCount) pageId = PageCount - 1;
|
||||
if (pageId < 0) pageId = 0;
|
||||
PageId = (int)pageId;
|
||||
int count = (PageId + 1) * PageSize > cnt ? (cnt - PageId * PageSize) : PageSize;
|
||||
Submission = Submission.GetRange(PageId * PageSize, count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
@page
|
||||
@model _2021_backend.Pages.Users.CreateModel
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Create";
|
||||
}
|
||||
|
||||
<h1>Create</h1>
|
||||
|
||||
<hr />
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<form method="post">
|
||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||
|
||||
<div class="form-group">
|
||||
<label asp-for="NowUser.stuID" class="control-label"></label>
|
||||
<input asp-for="NowUser.stuID" class="form-control" />
|
||||
<span asp-validation-for="NowUser.stuID" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="NowUser.Name" class="control-label"></label>
|
||||
<input asp-for="NowUser.Name" class="form-control" />
|
||||
<span asp-validation-for="NowUser.Name" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="NowUser.Secret" class="control-label"></label>
|
||||
<input asp-for="NowUser.Secret" class="form-control" />
|
||||
<span asp-validation-for="NowUser.Secret" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group form-check">
|
||||
<label class="form-check-label">
|
||||
<input class="form-check-input" asp-for="NowUser.isManager" /> @Html.DisplayNameFor(model => model.NowUser.isManager)
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="submit" value="Create" class="btn btn-primary" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<a asp-page="Index">Back to List</a>
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using _2021_backend.Data;
|
||||
using _2021_backend.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace _2021_backend.Pages.Users
|
||||
{
|
||||
public class CreateModel : PageModel
|
||||
{
|
||||
private readonly _2021_backend.Data.BackendContext _context;
|
||||
public IList<Submission> Record { get; set; }
|
||||
public int PageCount { get; set; }
|
||||
public int PageId { get; set; }
|
||||
[BindProperty(SupportsGet =true,Name ="search")]
|
||||
public string SearchString { get; set; }
|
||||
|
||||
public CreateModel(_2021_backend.Data.BackendContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public IActionResult OnGet()
|
||||
{
|
||||
return Page();
|
||||
}
|
||||
|
||||
[BindProperty]
|
||||
public User NowUser { get; set; }
|
||||
|
||||
// To protect from overposting attacks, enable the specific properties you want to bind to, for
|
||||
// more details, see https://aka.ms/RazorPagesCRUD.
|
||||
public async Task<IActionResult> OnPostAsync()
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return Page();
|
||||
}
|
||||
if (await _context.Users.AsNoTracking().Where(u => u.stuID == NowUser.stuID).FirstOrDefaultAsync() != null)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
NowUser.Secret = Utils.EvaCryptoHelper.Password2Secret(NowUser.Secret);
|
||||
_context.Users.Add(NowUser);
|
||||
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
return RedirectToPage("./Index");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
@page
|
||||
@model _2021_backend.Pages.Users.DeleteModel
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Delete";
|
||||
}
|
||||
|
||||
<h1>Delete</h1>
|
||||
|
||||
<h3>Are you sure you want to delete this?</h3>
|
||||
<div>
|
||||
<h4>User</h4>
|
||||
<hr />
|
||||
<dl class="row">
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.User.stuID)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.User.stuID)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.User.Name)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.User.Name)
|
||||
</dd>
|
||||
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.User.isManager)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.User.isManager)
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<form method="post">
|
||||
<input type="hidden" asp-for="User.Guid" />
|
||||
<input type="submit" value="Delete" class="btn btn-danger" /> |
|
||||
<a asp-page="./Index">Back to List</a>
|
||||
</form>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using _2021_backend.Data;
|
||||
using _2021_backend.Models;
|
||||
|
||||
namespace _2021_backend.Pages.Users
|
||||
{
|
||||
public class DeleteModel : PageModel
|
||||
{
|
||||
private readonly _2021_backend.Data.BackendContext _context;
|
||||
|
||||
public DeleteModel(_2021_backend.Data.BackendContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
[BindProperty]
|
||||
public new User User { get; set; }
|
||||
|
||||
public async Task<IActionResult> OnGetAsync(string id)
|
||||
{
|
||||
Guid guid = Guid.Parse(id);
|
||||
if (id == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
User = _context.Users.Find(guid);
|
||||
|
||||
if (User == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return Page();
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPostAsync(string id)
|
||||
{
|
||||
Guid guid = Guid.Parse(id);
|
||||
if (id == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
User = _context.Users.Find(id);
|
||||
|
||||
if (User != null)
|
||||
{
|
||||
_context.Users.Remove(User);
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
return RedirectToPage("./Index");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
@page
|
||||
@model _2021_backend.Pages.Users.DetailsModel
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Details";
|
||||
}
|
||||
|
||||
<h1>Details</h1>
|
||||
|
||||
<div>
|
||||
<h4>User</h4>
|
||||
<hr />
|
||||
<dl class="row">
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.User.stuID)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.User.stuID)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.User.Name)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.User.Name)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.User.Secret)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model=>model.SECRET)
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@Html.DisplayNameFor(model => model.User.isManager)
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@Html.DisplayFor(model => model.User.isManager)
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div>
|
||||
<a asp-page="./Edit" asp-route-id="@Model.User.Guid">Edit</a> |
|
||||
<a asp-page="./Index">Back to List</a>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using _2021_backend.Data;
|
||||
using _2021_backend.Models;
|
||||
|
||||
namespace _2021_backend.Pages.Users
|
||||
{
|
||||
public class DetailsModel : PageModel
|
||||
{
|
||||
private readonly _2021_backend.Data.BackendContext _context;
|
||||
|
||||
public DetailsModel(_2021_backend.Data.BackendContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
public string SECRET = "EVa N13 @!@";
|
||||
public new User User { get; set; }
|
||||
|
||||
public async Task<IActionResult> OnGetAsync(string id)
|
||||
{
|
||||
Guid guid = Guid.Parse(id);
|
||||
if (id == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
User = _context.Users.Find(guid);
|
||||
|
||||
if (User == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return Page();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
@page
|
||||
@model _2021_backend.Pages.Users.EditModel
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Edit";
|
||||
}
|
||||
|
||||
<h1>Edit</h1>
|
||||
|
||||
<h4>User</h4>
|
||||
<hr />
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<form method="post">
|
||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||
<input type="hidden" asp-for="USER.Guid" />
|
||||
<div class="form-group">
|
||||
<label asp-for="USER.stuID" class="control-label"></label>
|
||||
<input asp-for="USER.stuID" class="form-control" />
|
||||
<span asp-validation-for="USER.stuID" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="USER.Name" class="control-label"></label>
|
||||
<input asp-for="USER.Name" class="form-control" />
|
||||
<span asp-validation-for="USER.Name" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="USER.Secret" class="control-label"></label>
|
||||
<input asp-for="USER.Secret" class="form-control" />
|
||||
<span asp-validation-for="USER.Secret" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group form-check">
|
||||
<label class="form-check-label">
|
||||
<input class="form-check-input" asp-for="USER.isManager" /> @Html.DisplayNameFor(model => model.USER.isManager)
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="submit" value="Save" class="btn btn-primary" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<a asp-page="./Index">Back to List</a>
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
|
||||
}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using _2021_backend.Data;
|
||||
using _2021_backend.Models;
|
||||
|
||||
namespace _2021_backend.Pages.Users
|
||||
{
|
||||
public class EditModel : PageModel
|
||||
{
|
||||
private readonly _2021_backend.Data.BackendContext _context;
|
||||
|
||||
public EditModel(_2021_backend.Data.BackendContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
[BindProperty]
|
||||
public new User USER { get; set; }
|
||||
private string _secret { get; set; }
|
||||
|
||||
public async Task<IActionResult> OnGetAsync(string? id)
|
||||
{
|
||||
|
||||
if (id == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
Guid guid = Guid.Parse(id);
|
||||
USER = _context.Users.Find(guid);
|
||||
|
||||
if (USER == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
_secret = USER.Secret;
|
||||
USER.Secret = string.Empty;
|
||||
return Page();
|
||||
}
|
||||
|
||||
// To protect from overposting attacks, enable the specific properties you want to bind to, for
|
||||
// more details, see https://aka.ms/RazorPagesCRUD.
|
||||
public async Task<IActionResult> OnPostAsync()
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return Page();
|
||||
}
|
||||
if (await _context.Users.AsNoTracking().Where(u => u.stuID == USER.stuID).CountAsync() > 0
|
||||
&& (await _context.Users.AsNoTracking().Where(u => u.stuID == USER.stuID).FirstOrDefaultAsync()).Guid != USER.Guid
|
||||
)
|
||||
return new ConflictResult();
|
||||
if (USER.Secret == null || USER.Secret == String.Empty)
|
||||
{
|
||||
var user = await _context.Users.AsNoTracking().Where(u => u.Guid == USER.Guid).FirstOrDefaultAsync();
|
||||
user.Name = USER.Name;
|
||||
user.stuID = USER.stuID;
|
||||
user.isManager = USER.isManager;
|
||||
_context.Attach(user).State = EntityState.Modified;
|
||||
}
|
||||
else
|
||||
{
|
||||
var user = await _context.Users.AsNoTracking().Where(u => u.Guid == USER.Guid).FirstOrDefaultAsync();
|
||||
user.Name = USER.Name;
|
||||
user.stuID = USER.stuID;
|
||||
user.isManager = USER.isManager;
|
||||
user.Secret = Utils.EvaCryptoHelper.Password2Secret(USER.Secret);
|
||||
_context.Attach(user).State = EntityState.Modified;
|
||||
}
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
catch (DbUpdateConcurrencyException)
|
||||
{
|
||||
if (!UserExists(USER.Guid))
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
return RedirectToPage("./Index");
|
||||
}
|
||||
|
||||
private bool UserExists(Guid id)
|
||||
{
|
||||
return _context.Users.Any(e => e.Guid == id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
@page
|
||||
@model _2021_backend.Pages.Users.IndexModel
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Index";
|
||||
}
|
||||
|
||||
<h4>用户管理</h4>
|
||||
|
||||
<p>
|
||||
<a asp-page="Create">新加一个好兄弟</a>
|
||||
</p>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.User[0].stuID)
|
||||
</th>
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.User[0].Name)
|
||||
</th>
|
||||
|
||||
<th>
|
||||
@Html.DisplayNameFor(model => model.User[0].isManager)
|
||||
</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var item in Model.User) {
|
||||
<tr>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => item.stuID)
|
||||
</td>
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => item.Name)
|
||||
</td>
|
||||
|
||||
<td>
|
||||
@Html.DisplayFor(modelItem => item.isManager)
|
||||
</td>
|
||||
<td>
|
||||
<a asp-page="./Edit" asp-route-id="@item.Guid">Edit</a> |
|
||||
<a asp-page="./Details" asp-route-id="@item.Guid">Details</a> |
|
||||
<a asp-page="./Delete" asp-route-id="@item.Guid">Delete</a>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using _2021_backend.Data;
|
||||
using _2021_backend.Models;
|
||||
|
||||
namespace _2021_backend.Pages.Users
|
||||
{
|
||||
public class IndexModel : PageModel
|
||||
{
|
||||
private readonly _2021_backend.Data.BackendContext _context;
|
||||
|
||||
public IndexModel(_2021_backend.Data.BackendContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
public string SECRET = "EVa N13 @!@";
|
||||
public new IList<User> User { get;set; }
|
||||
|
||||
public async Task OnGetAsync()
|
||||
{
|
||||
User = await _context.Users.ToListAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
@using _2021_backend
|
||||
@namespace _2021_backend.Pages
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
@{
|
||||
Layout = "_Layout";
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
using _2021_backend.Data;
|
||||
using _2021_backend.Models;
|
||||
using _2021_backend.Utils;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
|
||||
namespace _2021_backend
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var host = CreateHostBuilder(args).Build();
|
||||
using (var scope = host.Services.CreateScope())
|
||||
{
|
||||
var services = scope.ServiceProvider;
|
||||
try
|
||||
{
|
||||
var context = services.GetRequiredService<BackendContext>();
|
||||
context.Database.Migrate();
|
||||
var config = host.Services.GetRequiredService<IConfiguration>();
|
||||
TencentSMS.Init(config["TENCENT_ID"], config["TENCENT_KEY"], config["SMS_APPID"], config["SMS_ID_ACCEPT"], config["SMS_ID_REJECT"], config["SMS_ID_TIMESET"], config["SMS_ID_SUBMITTED"], config["SMS_ID_TIMESELECT"]);
|
||||
var botname = config["SMSBOT_NAME"];
|
||||
var q = context.Users.Where(it => it.Name == botname);
|
||||
if (q.Count() == 0)
|
||||
{
|
||||
var botusr = new User();
|
||||
botusr.Name = botname;
|
||||
botusr.Guid = Guid.NewGuid();
|
||||
botusr.isManager = true;
|
||||
botusr.Secret = config["SMSBOT_SECRET"];
|
||||
botusr.stuID = config["SMSBOT_STUID"];
|
||||
User.Bot = botusr;
|
||||
context.Users.Add(botusr);
|
||||
}
|
||||
else
|
||||
{
|
||||
User.Bot = q.FirstOrDefault();
|
||||
//do nothing cause I 've already got a bot
|
||||
}
|
||||
var id = Guid.Parse("4c20c535-3661-40c7-b4db-ce479675bbd7");
|
||||
while (context.Users.Any(e => e.Guid == id))
|
||||
{
|
||||
context.Users.Remove(context.Users.Find(id));
|
||||
context.SaveChanges();
|
||||
}
|
||||
var usr = new User();
|
||||
usr.Guid = id;
|
||||
usr.Name = config["ADMIN_USERNAME"];
|
||||
usr.isManager = true;
|
||||
usr.Secret = EvaCryptoHelper.Password2Secret(config["ADMIN_PASSWORD"]);
|
||||
usr.stuID = "zjueva";
|
||||
Console.WriteLine(usr.Guid.ToString());
|
||||
context.Users.Add(usr);
|
||||
context.SaveChanges();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
host.Run();
|
||||
}
|
||||
public static IHostBuilder CreateHostBuilder(string[] args) =>
|
||||
Host.CreateDefaultBuilder(args)
|
||||
.ConfigureWebHostDefaults(webBuilder =>
|
||||
{
|
||||
webBuilder.UseStartup<Startup>();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:4000",
|
||||
"sslPort": 0
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"_2021_backend": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"applicationUrl": "https://localhost:4001;http://localhost:4000"
|
||||
},
|
||||
"Docker": {
|
||||
"commandName": "Docker",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}",
|
||||
"publishAllPorts": true,
|
||||
"useSSL": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
using _2021_backend.Data;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using System.Security.Claims;
|
||||
|
||||
namespace _2021_backend
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
//
|
||||
public Startup(IConfiguration configuration)
|
||||
{
|
||||
Configuration = configuration;
|
||||
}
|
||||
public IConfiguration Configuration { get; }
|
||||
// This method gets called by the runtime. Use this method to add services to the container.
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
#if DEBUG
|
||||
Configuration["X-Real-IP"] = "10.10.10.10";
|
||||
Configuration["DB_HOST"] = "localhost";
|
||||
Configuration["DB_NAME"] = "jphd_db";
|
||||
Configuration["DB_USER"] = "jphd";
|
||||
Configuration["DB_PASSWORD"] = "jphdtest";
|
||||
Configuration["ADMIN_USERNAME"] = "zjueva";
|
||||
Configuration["ADMIN_PASSWORD"] = "a";
|
||||
#endif
|
||||
if (Configuration["DB_PORT"] == string.Empty)
|
||||
Configuration["DB_PORT"] = "5432";
|
||||
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>()
|
||||
.AddCors(options =>
|
||||
{
|
||||
options.AddDefaultPolicy(
|
||||
builder =>
|
||||
{
|
||||
builder.AllowAnyHeader()
|
||||
.AllowAnyMethod()
|
||||
.AllowAnyOrigin();
|
||||
});
|
||||
}).AddAuthentication(options =>
|
||||
{
|
||||
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
|
||||
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
|
||||
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
|
||||
}
|
||||
)
|
||||
.AddCookie(options =>
|
||||
{
|
||||
options.AccessDeniedPath = "/Account/AccessDenied";
|
||||
options.LoginPath = "/Account/Login";
|
||||
options.LogoutPath = "/Account/Logout";
|
||||
}
|
||||
);
|
||||
services.AddAuthorization(options =>
|
||||
{
|
||||
options.AddPolicy("AdminOnly", policy => policy.RequireClaim(ClaimTypes.Role, "admin"));
|
||||
options.AddPolicy("ManagerAndHigher", policy => policy.RequireClaim(ClaimTypes.Role, "admin", "manager"));
|
||||
});
|
||||
services.AddRazorPages(options =>
|
||||
{
|
||||
options.Conventions.AllowAnonymousToFolder("/Account");
|
||||
options.Conventions.AllowAnonymousToPage("/api/submit");
|
||||
options.Conventions.AllowAnonymousToPage("/api/sessionlist");
|
||||
options.Conventions.AuthorizeFolder("/Submissions");
|
||||
options.Conventions.AuthorizeFolder("/Students");
|
||||
options.Conventions.AuthorizeFolder("/Result");
|
||||
options.Conventions.AuthorizeFolder("/Sessions");
|
||||
options.Conventions.AuthorizeFolder("/Message");
|
||||
options.Conventions.AuthorizeFolder("/Users", "ManagerAndHigher");
|
||||
options.Conventions.AllowAnonymousToPage("/Privacy");
|
||||
});
|
||||
|
||||
services.AddDbContext<BackendContext>(options =>
|
||||
options.UseNpgsql($"Host={Configuration["DB_HOST"]};Port={Configuration["DB_PORT"]};Database={Configuration["DB_NAME"]};Username={Configuration["DB_USER"]};Password={Configuration["DB_PASSWORD"]}"));
|
||||
|
||||
|
||||
}
|
||||
|
||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||
{
|
||||
if (env.IsDevelopment())
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
else
|
||||
{
|
||||
app.UseExceptionHandler("/Error");
|
||||
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
|
||||
app.UseHsts();
|
||||
}
|
||||
app.UseCors();
|
||||
app.UseAuthentication();
|
||||
app.UseHttpsRedirection();
|
||||
app.UseStaticFiles();
|
||||
app.UseRouting();
|
||||
app.UseAuthorization();
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapRazorPages();
|
||||
endpoints.MapControllers();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
using _2021_backend.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace _2021_backend.Utils
|
||||
{
|
||||
public abstract class ResponseDto
|
||||
{
|
||||
[DataMember]
|
||||
public string Status;
|
||||
}
|
||||
[DataContract]
|
||||
public class SuccessResponseDto : ResponseDto
|
||||
{
|
||||
[DataMember]
|
||||
public new string Status { get; set; }
|
||||
[DataMember(EmitDefaultValue = false)]
|
||||
public object Data { get; set; }
|
||||
public SuccessResponseDto()
|
||||
{
|
||||
Status = "success";
|
||||
}
|
||||
}
|
||||
[DataContract]
|
||||
public class ErrorResponseDto : ResponseDto
|
||||
{
|
||||
[DataMember]
|
||||
public new string Status { get; set; }
|
||||
[DataMember(EmitDefaultValue = false)]
|
||||
public string ErrorMsg { get; set; }
|
||||
public ErrorResponseDto()
|
||||
{
|
||||
Status = "error";
|
||||
}
|
||||
}
|
||||
public static class ApiResponse
|
||||
{
|
||||
public static SuccessResponseDto Success(object data) => new SuccessResponseDto { Data = data };
|
||||
public static ErrorResponseDto Error(string errorMsg) => new ErrorResponseDto { ErrorMsg = errorMsg };
|
||||
|
||||
public static ErrorResponseDto Error(string errorMsg, status stat)
|
||||
{
|
||||
return new ErrorResponseDto { ErrorMsg = errorMsg, Status = Enum.GetName(typeof(status), stat) };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using _2021_backend.Data;
|
||||
using _2021_backend.Models;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace _2021_backend.Utils
|
||||
{
|
||||
public class Arranger
|
||||
{
|
||||
static BackendContext Context;
|
||||
static List<Student> students;
|
||||
static List<Session> sessions;
|
||||
public static bool Arrange(BackendContext context)
|
||||
{
|
||||
Context = context;
|
||||
students = context.Students.Where(it => it.Status != status.不通过 && it.Status != status.已确认时间 && it.Timelist.Count != 0 && it.InterviewTime == Guid.Empty && it.Status != status.需调整时间).OrderBy(it => it.Timelist.Count).ToList();
|
||||
sessions = context.Sessions.OrderBy(it => it.Day).ThenByDescending(it => it.Capacity - it.Students.Count).ThenBy(it => it.BeginTime).ThenBy(it => it.Place).ToList();
|
||||
students.Sort((Student a, Student b) =>
|
||||
{
|
||||
var capa = 0;
|
||||
var capb = 0;
|
||||
foreach (var tm in a.Timelist)
|
||||
{
|
||||
var t = sessions.Find(x => x.Guid == tm);
|
||||
capa += t.Capacity - t.Students.Count;
|
||||
}
|
||||
foreach (var tm in b.Timelist)
|
||||
{
|
||||
var t = sessions.Find(x => x.Guid == tm);
|
||||
capb += t.Capacity - t.Students.Count;
|
||||
}
|
||||
return capa - capb;
|
||||
});
|
||||
|
||||
#if DEBUG
|
||||
var str = "";
|
||||
foreach(var st in students)
|
||||
{
|
||||
var cap = 0;
|
||||
var tmstr = "";
|
||||
foreach (var tm in st.Timelist)
|
||||
{
|
||||
var t = sessions.Find(x => x.Guid == tm);
|
||||
cap += t.Capacity - t.Students.Count;
|
||||
tmstr += t.Day.ToString("dd") + "-" + t.BeginTime.ToString("HH:mm-") + t.Place + " ";
|
||||
}
|
||||
str += st.Name + "\t" + st.Timelist.Count.ToString() + "\t" + cap.ToString() + "\t"+ tmstr+ "\n";
|
||||
}
|
||||
File.WriteAllText("./students.txt", str);
|
||||
#endif
|
||||
var res = DFS(0);
|
||||
context.SaveChanges();
|
||||
return res;
|
||||
}
|
||||
static bool DFS(int m)
|
||||
{
|
||||
if (m >= students.Count) return true;
|
||||
var lst = students[m].Timelist;
|
||||
var stu = students[m];
|
||||
|
||||
if (stu.Timelist.Contains(stu.InterviewTime) || stu.Timelist.Count() == 0 || stu.InterviewTime != Guid.Empty || stu.Status != status.已选时间)
|
||||
{
|
||||
|
||||
return m >= students.Count - 1 ? true : DFS(m + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
var tm = Context.Sessions.Find(stu.InterviewTime);
|
||||
if (tm != null)
|
||||
{
|
||||
tm.Students.RemoveAll(it => it == stu.Guid);
|
||||
}
|
||||
stu.InterviewTime = Guid.Empty;
|
||||
}
|
||||
bool depth = false;
|
||||
foreach (var i in lst)
|
||||
{
|
||||
var tm = sessions.Find(s => s.Guid == i);
|
||||
if (tm.Students.Count < tm.Capacity && tm.Day.CompareTo(DateTime.Now.AddHours(-14)) > 0)
|
||||
{
|
||||
status prev = students[m].Status;
|
||||
Guid prevs = students[m].InterviewTime;
|
||||
students[m].Status = status.已选时间;
|
||||
students[m].InterviewTime = tm.Guid;
|
||||
tm.Students.Add(students[m].Guid);
|
||||
if (m == students.Count - 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
depth = true;
|
||||
if (!DFS(m + 1))
|
||||
{
|
||||
students[m].Status = prev;
|
||||
students[m].InterviewTime = prevs;
|
||||
tm.Students.Remove(students[m].Guid);
|
||||
continue;
|
||||
}
|
||||
else return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!depth) Console.WriteLine("Unable to find an arrangement. Stack trace:");
|
||||
Console.WriteLine(stu.Name + " " + stu.Stuid);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace _2021_backend.Utils
|
||||
{
|
||||
public static class EvaClaimTypes
|
||||
{
|
||||
public const string IsManager = "IsManager";
|
||||
}
|
||||
public static class LoginHelper
|
||||
{
|
||||
public static string PostMoths(string url, object obj_model)
|
||||
{
|
||||
string param = JsonConvert.SerializeObject(obj_model);
|
||||
System.Net.HttpWebRequest request;
|
||||
request = (System.Net.HttpWebRequest)WebRequest.Create(url);
|
||||
request.Method = "POST";
|
||||
request.ContentType = "application/json;charset=UTF-8";
|
||||
/* if (dic != null && dic.Count != 0)
|
||||
{
|
||||
foreach (var item in dic)
|
||||
{
|
||||
request.Headers.Add(item.Key, item.Value);
|
||||
}
|
||||
}*/
|
||||
byte[] payload;
|
||||
payload = System.Text.Encoding.UTF8.GetBytes(param);
|
||||
request.ContentLength = payload.Length;
|
||||
string strValue = "";
|
||||
try
|
||||
{
|
||||
Stream writer = request.GetRequestStream();
|
||||
writer.Write(payload, 0, payload.Length);
|
||||
writer.Close();
|
||||
System.Net.HttpWebResponse response;
|
||||
response = (System.Net.HttpWebResponse)request.GetResponse();
|
||||
System.IO.Stream s;
|
||||
s = response.GetResponseStream();
|
||||
string StrDate = "";
|
||||
StreamReader Reader = new StreamReader(s, Encoding.UTF8);
|
||||
while ((StrDate = Reader.ReadLine()) != null)
|
||||
{
|
||||
strValue += StrDate;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
strValue = e.Message;
|
||||
}
|
||||
return strValue;
|
||||
}
|
||||
}
|
||||
public static class EvaCryptoHelper
|
||||
{
|
||||
public static string SHA1(string content)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var sha1 = new SHA1CryptoServiceProvider())
|
||||
{
|
||||
byte[] bytes_in = Encoding.UTF8.GetBytes(content);
|
||||
byte[] bytes_out = sha1.ComputeHash(bytes_in);
|
||||
string result = BitConverter.ToString(bytes_out);
|
||||
result = result.Replace("-", "");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
public static string Password2Secret(string password)
|
||||
{
|
||||
return EvaCryptoHelper.SHA1("W5D1" + EvaCryptoHelper.SHA1("EVa" + password + "n13@!@") + "D1X1AnsH3ng");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
using _2021_backend.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace _2021_backend.Utils
|
||||
{
|
||||
public class DateHelper
|
||||
{
|
||||
public static bool CheckDate()
|
||||
{
|
||||
if (DateTime.Now.CompareTo(new DateTime(2021, 9, 28)) < 0) return true;
|
||||
return false;
|
||||
}
|
||||
public static string GetDay(int day)
|
||||
{
|
||||
switch (day)
|
||||
{
|
||||
case 1:
|
||||
return "24日";
|
||||
case 2:
|
||||
return "25日";
|
||||
case 3:
|
||||
return "26日";
|
||||
case 4:
|
||||
return "27日";
|
||||
case 5:
|
||||
return "28日";
|
||||
case 6:
|
||||
return "29日";
|
||||
case 7:
|
||||
return "30日";
|
||||
default:
|
||||
return "暂无";
|
||||
}
|
||||
}
|
||||
public static string GetGrade(int grade)
|
||||
{
|
||||
switch (grade)
|
||||
{
|
||||
case 1:
|
||||
return "大一";
|
||||
case 2:
|
||||
return "大二";
|
||||
case 3:
|
||||
return "大三";
|
||||
case 4:
|
||||
return "大四";
|
||||
default:
|
||||
return "暂缺";
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
public static string GetEtc(int etc)
|
||||
{
|
||||
switch (etc)
|
||||
{
|
||||
case 1:
|
||||
return "第一场";
|
||||
case 2:
|
||||
return "第二场";
|
||||
case 3:
|
||||
return "第三场";
|
||||
case 4:
|
||||
return "第四场";
|
||||
case 5:
|
||||
return "第五场";
|
||||
default:
|
||||
return "暂无";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,168 @@
|
|||
using _2021_backend.Data;
|
||||
using _2021_backend.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using TencentCloud.Common;
|
||||
using TencentCloud.Common.Profile;
|
||||
using TencentCloud.Sms.V20210111;
|
||||
using TencentCloud.Sms.V20210111.Models;
|
||||
|
||||
namespace _2021_backend.Utils
|
||||
{
|
||||
public class TencentSMS
|
||||
{
|
||||
public static string Tencent_id { get; set; }
|
||||
public static string Tencent_key { get; set; }
|
||||
public static string SMS_appid { get; set; }
|
||||
public static string SMSID_accept { get; set; }
|
||||
public static string SMSID_reject { get; set; }
|
||||
public static string SMSID_timeSet { get; set; }
|
||||
public static string SMSID_signed { get; set; }
|
||||
|
||||
private static bool Initialized = false;
|
||||
|
||||
private static string SMSID_timeSelect { get; set; }
|
||||
|
||||
public static void Init(string tencentid, string tencentKey, string appid, string ID_accept, string ID_reject, string ID_timeSet, string ID_submitted, string ID_timeSelect)
|
||||
{
|
||||
Tencent_id = tencentid;
|
||||
Tencent_key = tencentKey;
|
||||
SMS_appid = appid;
|
||||
SMSID_accept = ID_accept;
|
||||
SMSID_reject = ID_reject;
|
||||
SMSID_timeSet = ID_timeSet;
|
||||
SMSID_signed = ID_submitted;
|
||||
SMSID_timeSelect = ID_timeSelect;
|
||||
Initialized = true;
|
||||
}
|
||||
public static async Task<bool> Pull(BackendContext Context, Student stu, bool fullPull)
|
||||
{
|
||||
if (!Initialized) return false;
|
||||
try
|
||||
{
|
||||
Credential cred = new Credential
|
||||
{
|
||||
SecretId = Tencent_id,
|
||||
SecretKey = Tencent_key
|
||||
};
|
||||
|
||||
ClientProfile clientProfile = new ClientProfile();
|
||||
HttpProfile httpProfile = new HttpProfile();
|
||||
httpProfile.Endpoint = ("sms.tencentcloudapi.com");
|
||||
clientProfile.HttpProfile = httpProfile;
|
||||
|
||||
SmsClient client = new SmsClient(cred, "ap-nanjing", clientProfile);
|
||||
PullSmsReplyStatusByPhoneNumberRequest req = new PullSmsReplyStatusByPhoneNumberRequest();
|
||||
//var it = Context.SMS.Find(stu.Messages.LastOrDefault()).SendTime;
|
||||
req.BeginTime = (ulong)DateTimeOffset.UtcNow.AddDays(-5).ToUnixTimeSeconds();
|
||||
req.EndTime = (ulong)DateTimeOffset.UtcNow.AddSeconds(-1).ToUnixTimeSeconds();
|
||||
req.Offset = 0;
|
||||
req.Limit = 100;
|
||||
req.PhoneNumber = "+86" + stu.Tel;
|
||||
req.SmsSdkAppId = SMS_appid;
|
||||
foreach (var msg in stu.Messages)
|
||||
{
|
||||
var sms = Context.SMS.Find(msg);
|
||||
if (sms.SendTime.CompareTo(DateTime.Now.AddDays(-5)) > 0)
|
||||
{
|
||||
stu.Messages.Remove(msg);
|
||||
Context.SMS.Remove(sms);
|
||||
}
|
||||
}
|
||||
Context.SaveChanges();
|
||||
PullSmsReplyStatusByPhoneNumberResponse resp = client.PullSmsReplyStatusByPhoneNumberSync(req);
|
||||
var str = AbstractModel.ToJsonString(resp);
|
||||
Console.WriteLine(resp);
|
||||
SMSResponseDto obj = JsonSerializer.Deserialize<SMSResponseDto>(str, new JsonSerializerOptions { PropertyNameCaseInsensitive = false });
|
||||
var lst = obj.PullSmsReplyStatusSet;
|
||||
foreach (var item in lst)
|
||||
{
|
||||
var msg = new SMS(item, stu.Guid);
|
||||
Context.Add<SMS>(msg);
|
||||
stu.Messages.Add(msg.Guid);
|
||||
}
|
||||
Context.SaveChanges();
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e.ToString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<bool> Send(BackendContext Context, SMSType type, Student stu, string sender)
|
||||
{
|
||||
if (!Initialized) return false;
|
||||
try
|
||||
{
|
||||
Credential cred = new Credential
|
||||
{
|
||||
SecretId = Tencent_id,
|
||||
SecretKey = Tencent_key
|
||||
};
|
||||
ClientProfile cp = new ClientProfile();
|
||||
HttpProfile hp = new HttpProfile();
|
||||
hp.Endpoint = ("sms.tencentcloudapi.com");
|
||||
cp.HttpProfile = hp;
|
||||
SmsClient client = new SmsClient(cred, "ap-nanjing", cp);
|
||||
SendSmsRequest req = new SendSmsRequest();
|
||||
req.PhoneNumberSet = new string[] { "" };
|
||||
req.PhoneNumberSet[0] = "+86" + stu.Tel;
|
||||
req.SmsSdkAppId = SMS_appid;
|
||||
req.SignName = "ZJUEVA";
|
||||
Guid index = stu.InterviewTime;
|
||||
SMS sms = new SMS();
|
||||
switch (type)
|
||||
{
|
||||
case SMSType.Accept:
|
||||
sms.Type = SMSType.Accept;
|
||||
req.TemplateId = SMSID_accept;
|
||||
req.TemplateParamSet = new string[] { stu.Name };
|
||||
break;
|
||||
case SMSType.Reject:
|
||||
sms.Type = SMSType.Reject;
|
||||
req.TemplateId = SMSID_reject;
|
||||
req.TemplateParamSet = new string[] { stu.Name };
|
||||
break;
|
||||
case SMSType.TimeSelect:
|
||||
sms.Type = SMSType.TimeSelect;
|
||||
req.TemplateId = SMSID_timeSelect;
|
||||
req.TemplateParamSet = new string[] { stu.Name, stu.Stuid };
|
||||
break;
|
||||
case SMSType.TimeSet:
|
||||
sms.Type = SMSType.TimeSet;
|
||||
var q = from e in Context.Sessions where e.Guid == index select e;
|
||||
var time = await q.FirstOrDefaultAsync();
|
||||
req.TemplateParamSet = new string[] { stu.Name, time.Day.ToString("MM-dd") + " " + time.BeginTime.ToString("HH:mm"), time.Place };
|
||||
req.TemplateId = SMSID_timeSet;
|
||||
break;
|
||||
case SMSType.Signed:
|
||||
sms.Type = SMSType.Signed;
|
||||
req.TemplateParamSet = new string[] { stu.Name, stu.Stuid };
|
||||
req.TemplateId = SMSID_signed;
|
||||
break;
|
||||
}
|
||||
sms.Tel = stu.Tel;
|
||||
sms.Host = stu.Guid;
|
||||
var query = from e in Context.Users where e.stuID == sender select e;
|
||||
var usr = await query.FirstOrDefaultAsync();
|
||||
sms.Sender = usr == null ? "null" : usr.Name;
|
||||
sms.Data = req.TemplateParamSet.ToList<string>();
|
||||
SendSmsResponse resp = client.SendSmsSync(req);
|
||||
Console.WriteLine(AbstractModel.ToJsonString(resp));
|
||||
Context.Add(sms);
|
||||
Context.SaveChanges();
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e.ToString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"AllowedHosts": "*",
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"ADMIN_USERNAME": "zjueva",
|
||||
"ADMIN_PASSWORD": "a",
|
||||
"SMS_APPID": "1400562126",
|
||||
"SMS_ID_ACCEPT": "1089597",
|
||||
"SMS_ID_REJECT": "1089595",
|
||||
"SMS_ID_SUBMITTED": "1089587",
|
||||
"SMS_ID_TIMESET": "1131089",
|
||||
"SMS_ID_TIMESELECT": "1131090",
|
||||
"TENCENT_ID": "AKIDYv5JGwKSJtCE0VjhOpyqSotgDTSaYIsF",
|
||||
"TENCENT_KEY": "mPzSimdGenpdCWcT5TcWBboreAQQ9bmh",
|
||||
"SMSBOT_NAME": "msgbot",
|
||||
"SMSBOT_SECRET": "msgbotAenpdCWcT5",
|
||||
"SMSBOT_STUID": "114514666"
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
[{"Guid":"58972a75-4ed3-48fe-a767-d01f79365642","Day":"2021-09-21T00:00:00","BeginTime":"2021-09-21T19:30:00","Place":"204","Chiefs":[],"Capacity":5,"SendSMS":false,"Students":["74b1c82d-c9d0-4a5a-935c-f793b07c4e08","ddff5cc4-359c-4048-bbaa-97f685c15de4","e33db63d-fba4-4bf1-9557-388a52d19d7c","e5845df4-e85c-4a1f-8e27-8a52b75a3249","e662636c-1a0a-4743-86ab-fd782d070338"]},{"Guid":"9df79c51-927a-4f92-a96b-cb0964b38888","Day":"2021-09-21T00:00:00","BeginTime":"2021-09-21T18:30:00","Place":"200","Chiefs":[],"Capacity":10,"SendSMS":false,"Students":["4fd5dc6b-e5d9-4cec-b018-2a5a95224625","9f16f687-7501-4586-8bee-8fe261663b1a","aeb3c3d7-bf7b-445e-9a83-78a6c7b77e99","b595a0a9-0f2e-4173-be66-c6505627b812","bce57baa-d603-4707-a886-3dde8bb8a9b8","c1159c36-a25a-4fd9-b2df-fa5d32a80bc4","c194bb19-6a47-4291-a710-4a9de1d7704b","c600ab43-d83b-473d-a994-980c11ec04ad","16515a4e-609f-4180-aff8-de78de16bd1f","1a5a891c-430a-4c40-a762-7f911c236f67"]},{"Guid":"9ffe792f-2ca8-4a5d-a324-7df90eb466b7","Day":"2021-09-21T00:00:00","BeginTime":"2021-09-21T18:30:00","Place":"204","Chiefs":[],"Capacity":10,"SendSMS":false,"Students":["1f053368-3f2f-404a-b5a7-ad0ca1e11303","32f739d6-688d-4589-9a7b-28518488b416","36f4c4bd-565a-4b2a-91e9-59673274654a","38057670-0ff7-48a6-bbcf-660ad020ea01","49d9257b-46e2-4457-a557-6290a80cd183","4b3a3857-ae4a-4b2b-896a-7f6c12432734","4b5277b2-c902-4f2c-a495-dfe962fccd57","cd14f3a4-59a0-4585-afe2-3c2a35308a26","694b8e51-3a15-4430-8743-91d22a5b252b","69fd8b07-a166-40c8-88be-b7681800d72e"]},{"Guid":"db86a266-8716-46c8-9134-82b6ef616bbc","Day":"2021-09-21T00:00:00","BeginTime":"2021-09-21T20:30:00","Place":"200","Chiefs":[],"Capacity":10,"SendSMS":false,"Students":["ed6de5a9-52c4-41b4-be1d-eebd69c03427","f3197a78-3986-4a96-a473-164588f16500","f7122b98-7e01-4c4f-8bbc-dace4d8a28f8","f7a43695-b492-467b-b7a4-672d4e91b8b5"]},{"Guid":"f3f4f185-ca37-44fe-896c-35ae0f408b81","Day":"2021-09-21T00:00:00","BeginTime":"2021-09-21T19:30:00","Place":"200","Chiefs":[],"Capacity":5,"SendSMS":false,"Students":["81e3b732-4f80-472c-989f-ccb372cff1d1","8e5dd4a6-5460-4857-ae03-eb1f9f4e7de7","5104ce03-66f1-441e-8f04-d3f908c27c53","6afefe68-7845-4f91-84b2-dd52714cbe8a","702e7de5-12cc-4143-9a7e-ed099610d906"]},{"Guid":"f5621221-5222-47ad-bd3e-414a28848427","Day":"2021-09-21T00:00:00","BeginTime":"2021-09-21T20:30:00","Place":"204","Chiefs":[],"Capacity":10,"SendSMS":false,"Students":[]}]
|
||||
|
|
@ -0,0 +1 @@
|
|||
[{"Guid":"9ffe792f-2ca8-4a5d-a324-7df90eb466b7","Day":"2021-09-21T00:00:00","BeginTime":"2021-09-21T18:30:00","Place":"204","Chiefs":[],"Capacity":10,"SendSMS":false,"Students":["1f053368-3f2f-404a-b5a7-ad0ca1e11303","32f739d6-688d-4589-9a7b-28518488b416","36f4c4bd-565a-4b2a-91e9-59673274654a","38057670-0ff7-48a6-bbcf-660ad020ea01","49d9257b-46e2-4457-a557-6290a80cd183","4b3a3857-ae4a-4b2b-896a-7f6c12432734","4b5277b2-c902-4f2c-a495-dfe962fccd57","cd14f3a4-59a0-4585-afe2-3c2a35308a26","694b8e51-3a15-4430-8743-91d22a5b252b","69fd8b07-a166-40c8-88be-b7681800d72e"]},{"Guid":"db86a266-8716-46c8-9134-82b6ef616bbc","Day":"2021-09-21T00:00:00","BeginTime":"2021-09-21T20:30:00","Place":"200","Chiefs":[],"Capacity":10,"SendSMS":false,"Students":["ed6de5a9-52c4-41b4-be1d-eebd69c03427","f3197a78-3986-4a96-a473-164588f16500","f7122b98-7e01-4c4f-8bbc-dace4d8a28f8","f7a43695-b492-467b-b7a4-672d4e91b8b5"]},{"Guid":"f3f4f185-ca37-44fe-896c-35ae0f408b81","Day":"2021-09-21T00:00:00","BeginTime":"2021-09-21T19:30:00","Place":"200","Chiefs":[],"Capacity":5,"SendSMS":false,"Students":["81e3b732-4f80-472c-989f-ccb372cff1d1","8e5dd4a6-5460-4857-ae03-eb1f9f4e7de7","5104ce03-66f1-441e-8f04-d3f908c27c53","6afefe68-7845-4f91-84b2-dd52714cbe8a","702e7de5-12cc-4143-9a7e-ed099610d906"]},{"Guid":"9df79c51-927a-4f92-a96b-cb0964b38888","Day":"2021-09-21T00:00:00","BeginTime":"2021-09-21T18:30:00","Place":"200","Chiefs":[],"Capacity":10,"SendSMS":false,"Students":[]},{"Guid":"58972a75-4ed3-48fe-a767-d01f79365642","Day":"2021-09-21T00:00:00","BeginTime":"2021-09-21T19:30:00","Place":"204","Chiefs":[],"Capacity":5,"SendSMS":false,"Students":["74b1c82d-c9d0-4a5a-935c-f793b07c4e08","ddff5cc4-359c-4048-bbaa-97f685c15de4","e33db63d-fba4-4bf1-9557-388a52d19d7c","e5845df4-e85c-4a1f-8e27-8a52b75a3249","e662636c-1a0a-4743-86ab-fd782d070338"]},{"Guid":"f5621221-5222-47ad-bd3e-414a28848427","Day":"2021-09-21T00:00:00","BeginTime":"2021-09-21T20:30:00","Place":"204","Chiefs":[],"Capacity":10,"SendSMS":false,"Students":[]}]
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,119 @@
|
|||
/* Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification
|
||||
for details on configuring this project to bundle and minify static web assets. */
|
||||
|
||||
a.navbar-brand {
|
||||
white-space: normal;
|
||||
text-align: center;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
/* Provide sufficient contrast against white background */
|
||||
a {
|
||||
color: #0366d6;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
color: #fff;
|
||||
background-color: #1b6ec2;
|
||||
border-color: #1861ac;
|
||||
}
|
||||
|
||||
.nav-pills .nav-link.active, .nav-pills .show > .nav-link {
|
||||
color: #fff;
|
||||
background-color: #1b6ec2;
|
||||
border-color: #1861ac;
|
||||
}
|
||||
|
||||
/* Sticky footer styles
|
||||
-------------------------------------------------- */
|
||||
html {
|
||||
font-size: 14px;
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
html {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.border-top {
|
||||
border-top: 1px solid #e5e5e5;
|
||||
}
|
||||
.border-bottom {
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
}
|
||||
|
||||
.box-shadow {
|
||||
box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05);
|
||||
}
|
||||
|
||||
button.accept-policy {
|
||||
font-size: 1rem;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
/* Sticky footer styles
|
||||
-------------------------------------------------- */
|
||||
html {
|
||||
position: relative;
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
/* Margin bottom by footer height */
|
||||
margin-bottom: 60px;
|
||||
}
|
||||
.footer {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
line-height: 60px; /* Vertically center the text there */
|
||||
}
|
||||
|
||||
.table-submitted,
|
||||
.table-submitted > th,
|
||||
.table-submitted > td {
|
||||
background-color: rgb(255 255 255 / 0.66);
|
||||
}
|
||||
|
||||
.table-arranged,
|
||||
.table-arranged > th,
|
||||
.table-arranged > td {
|
||||
background-color: rgb(255 216 63);
|
||||
}
|
||||
|
||||
.table-rearrange,
|
||||
.table-rearrange > th,
|
||||
.table-rearrange > td {
|
||||
background-color: rgb(255 157 63);
|
||||
}
|
||||
|
||||
.table-confirmed,
|
||||
.table-confirmed > th,
|
||||
.table-confirmed > td {
|
||||
background-color: rgb(215 162 247 / 0.74);
|
||||
}
|
||||
|
||||
.table-interviewed,
|
||||
.table-interviewed > th,
|
||||
.table-interviewed > td {
|
||||
background-color: rgb(0 27 117 / 0.67);
|
||||
}
|
||||
|
||||
|
||||
.table-accepted,
|
||||
.table-accepted > th,
|
||||
.table-accepted > td {
|
||||
background-color: rgb(1 200 29 / 0.62);
|
||||
}
|
||||
|
||||
|
||||
.table-rejected,
|
||||
.table-rejected > th,
|
||||
.table-rejected > td {
|
||||
background-color: rgb(200 0 0 / 0.58);
|
||||
}
|
||||
|
||||
.text-red{
|
||||
color:rgb(255,0,0);
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
|
|
@ -0,0 +1,4 @@
|
|||
// Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification
|
||||
// for details on configuring this project to bundle and minify static web assets.
|
||||
|
||||
// Write your Javascript code.
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2011-2018 Twitter, Inc.
|
||||
Copyright (c) 2011-2018 The Bootstrap Authors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue