Compare commits

..

18 Commits

Author SHA1 Message Date
Raymond Yang 42356d0f88 更改DB域名 2023-08-10 12:23:26 +08:00
Raymond Yang 9618374942 暫時移除前端,維持前後端分離 2023-07-11 11:39:18 +08:00
Raymond Yang 1dca536ab0 將前端整合進來 2023-07-10 12:08:58 +08:00
Raymond Yang 9614266453 修正開戰期間成員取得判斷 2023-07-10 12:04:55 +08:00
Raymond Yang dd2bbf46a6 拿掉print 2023-07-10 12:04:17 +08:00
Raymond Yang 97effcc442 清理import 2023-07-10 12:03:57 +08:00
ray650128 4131f03e42 加上updateTimer模組 2023-06-27 23:27:30 +08:00
Raymond Yang 4632b2cdc8 加上print date 2023-06-27 17:52:03 +08:00
Raymond Yang 947a791d87 加上shadowJar plugin 2023-06-27 17:03:48 +08:00
Raymond Yang 89cd1357f0 補上成員的刪除方法 2023-06-27 15:58:16 +08:00
Raymond Yang d3ae86b18d 修正CORS不允許delete 2023-06-27 15:56:08 +08:00
Raymond Yang 662aa4902d 修正成員put method 2023-06-27 15:54:28 +08:00
Raymond Yang 170d22273f 將MemberRecord的boss欄位設定成nullable 2023-06-27 13:51:27 +08:00
Raymond Yang 0c34bd36a1 關掉mongoDB的log 2023-06-27 13:50:35 +08:00
Raymond Yang 493ff96673 加入換日新增資料 2023-06-27 09:50:07 +08:00
ray650128 c6973a3618 加上更新功能及跨境請求 2023-06-26 23:31:38 +08:00
ray650128 525ae4d2b5 填表加上自動更新原有資料的功能 2023-06-26 21:25:58 +08:00
ray650128 85e0c18115 加入離開成員篩選 2023-06-26 21:11:46 +08:00
24 changed files with 1406 additions and 32 deletions
+17
View File
@@ -1,3 +1,5 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
val ktor_version: String by project
val kotlin_version: String by project
val logback_version: String by project
@@ -7,6 +9,7 @@ plugins {
kotlin("jvm") version "1.8.22"
id("io.ktor.plugin") version "2.3.1"
id("org.jetbrains.kotlin.plugin.serialization") version "1.8.22"
id("com.github.johnrengelman.shadow") version "7.1.2"
}
group = "com.ray650128.pcredive"
@@ -36,3 +39,17 @@ dependencies {
implementation("org.litote.kmongo:kmongo-id-serialization:$kmongo_version")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.1.0")
}
tasks.withType<KotlinCompile> {
kotlinOptions.jvmTarget = "1.8"
}
tasks.jar {
manifest {
attributes["Main-Class"] = "com.ray650128.bot.MainKt"
}
}
tasks.build {
dependsOn(tasks.shadowJar)
}
@@ -1,13 +1,21 @@
package com.ray650128.pcredive
import ch.qos.logback.classic.Level
import ch.qos.logback.classic.LoggerContext
import io.ktor.server.application.*
import com.ray650128.pcredive.plugins.*
import org.slf4j.LoggerFactory
fun main(args: Array<String>): Unit =
fun main(args: Array<String>) {
val loggerContext = LoggerFactory.getILoggerFactory() as LoggerContext
val rootLogger = loggerContext.getLogger("org.mongodb.driver")
rootLogger.level = Level.OFF
io.ktor.server.netty.EngineMain.main(args)
}
@Suppress("unused") // application.conf references the main function. This annotation prevents the IDE from marking it as unused.
fun Application.module() {
configureUpdateTimer()
configureHTTP()
configureSerialization()
configureMemberRouting()
@@ -9,18 +9,18 @@ import org.litote.kmongo.newId
data class MemberRecord(
@Contextual var _id: Id<MemberRecord> = newId(),
@Contextual var memberId: Id<Member>? = null,
var record1: Record = Record("未出"),
var record1c: Record = Record("未出"),
var record2: Record = Record("未出"),
var record2c: Record = Record("未出"),
var record3: Record = Record("未出"),
var record3c: Record = Record("未出"),
var record1: Record = Record(),
var record1c: Record = Record(),
var record2: Record = Record(),
var record2c: Record = Record(),
var record3: Record = Record(),
var record3c: Record = Record(),
var createdAt: Long? = null,
var updatedAt: Long? = null
)
@Serializable
data class Record(
var boss: String,
var boss: String? = null,
var damage: Int? = null
)
@@ -5,5 +5,5 @@ import kotlinx.serialization.Serializable
@Serializable
data class RecordData(
val member: Member,
var record: MemberRecord
var record: MemberRecord?
)
@@ -7,7 +7,7 @@ import org.litote.kmongo.*
import org.litote.kmongo.id.toId
object MemberRecordService {
private val client = KMongo.createClient("mongodb://ray650128:Zx650128!@www.ray650128.com:27017")
private val client = KMongo.createClient("mongodb://ray650128:Zx650128!@ray650128.com:27017")
private val database = client.getDatabase("pc_re_dive_clan_battle")
private val recordCollection = database.getCollection<MemberRecord>()
@@ -21,6 +21,11 @@ object MemberRecordService {
return recordCollection.findOne(MemberRecord::_id eq bsonId)
}
fun findByMemberIdBetweenDate(id: String, start: Long, end: Long): MemberRecord? {
val bsonId: Id<Member> = ObjectId(id).toId()
return recordCollection.findOne(MemberRecord::memberId eq bsonId, MemberRecord::createdAt gte start, MemberRecord::createdAt lt end)
}
fun findByTimeBetween(start: Long, end: Long): List<MemberRecord> {
return recordCollection.find(MemberRecord::createdAt gte start, MemberRecord::createdAt lt end).toList()
}
@@ -6,7 +6,7 @@ import org.litote.kmongo.*
import org.litote.kmongo.id.toId
object MemberService {
private val client = KMongo.createClient("mongodb://ray650128:Zx650128!@www.ray650128.com:27017")
private val client = KMongo.createClient("mongodb://ray650128:Zx650128!@ray650128.com:27017")
private val database = client.getDatabase("pc_re_dive_clan_battle")
private val memberCollection = database.getCollection<Member>()
@@ -3,15 +3,22 @@ package com.ray650128.pcredive.plugins
import io.ktor.http.*
import io.ktor.server.plugins.cors.routing.*
import io.ktor.server.application.*
import io.ktor.server.http.content.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import io.ktor.util.*
import java.io.File
fun Application.configureHTTP() {
install(CORS) {
allowMethod(HttpMethod.Options)
allowMethod(HttpMethod.Get)
allowMethod(HttpMethod.Put)
allowMethod(HttpMethod.Delete)
allowMethod(HttpMethod.Patch)
allowHeader(HttpHeaders.Authorization)
allowMethod(HttpMethod.Post)
allowHeader(HttpHeaders.AccessControlAllowOrigin)
allowHeader(HttpHeaders.Accept)
allowHeader(HttpHeaders.ContentType)
anyHost()
allowCredentials = true
allowNonSimpleContentTypes = true
@@ -21,8 +21,11 @@ import java.util.*
fun Application.configureMemberRecordRouting() {
routing {
options("{...}") {
call.respond(HttpStatusCode.OK)
}
route("/api") {
route("/record") {
route("/record") { // 查詢所有紀錄
get {
val calendar = Calendar.getInstance().apply {
timeInMillis = System.currentTimeMillis() - (5 * 60 * 60 * 1000) // 由於公連換日為每日早上5:00,因此減去時差
@@ -30,23 +33,43 @@ fun Application.configureMemberRecordRouting() {
val records = getData(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH))
call.respond(HttpStatusCode.OK, records)
}
post("/{id}") {
post("/{id}") { // 新增成員紀錄
val id = call.parameters.getOrFail<String>("id")
val record = call.receive<MemberRecord>()
val member = MemberService.findById(id) ?: run {
call.respond(HttpStatusCode.NotFound)
return@post
}
record.apply {
val now = Calendar.getInstance()
val startTime = getDayStartLong(now[Calendar.YEAR], now[Calendar.MONTH], now[Calendar.DAY_OF_MONTH])
val endTime = getDayEndLong(now[Calendar.YEAR], now[Calendar.MONTH], now[Calendar.DAY_OF_MONTH])
val existData = MemberRecordService.findByMemberIdBetweenDate(id, startTime, endTime) ?: run {
record.apply {
memberId = member._id
createdAt = System.currentTimeMillis()
updatedAt = System.currentTimeMillis()
}
MemberRecordService.create(record).let {
call.respond(HttpStatusCode.OK, record)
}
return@post
}
existData.apply {
memberId = member._id
createdAt = System.currentTimeMillis()
record1 = record.record1
record1c = record.record1c
record2 = record.record2
record2c = record.record2c
record3 = record.record3
record3c = record.record3c
updatedAt = System.currentTimeMillis()
}
MemberRecordService.create(record).let {
call.respond(HttpStatusCode.OK, record)
MemberRecordService.updateById(existData._id.toString(), existData).let {
call.respond(HttpStatusCode.OK, existData)
}
}
get("/{year}/{month}/{day}") {
get("/{year}/{month}/{day}") { // 取得特定日期
val year = call.parameters.getOrFail<Int>("year").toInt()
val month = call.parameters.getOrFail<Int>("month").toInt() - 1
val day = call.parameters.getOrFail<Int>("day").toInt()
@@ -86,25 +109,41 @@ fun Application.configureMemberRecordRouting() {
}
}
fun getData(year: Int, month: Int, day: Int): List<RecordData> {
fun getDayStartLong(year: Int, month: Int, day: Int): Long {
val calendar = Calendar.getInstance().apply {
set(Calendar.YEAR, year)
set(Calendar.MONTH, month)
set(Calendar.DAY_OF_MONTH, day)
}
val startTime = calendar.apply {
return calendar.apply {
set(Calendar.HOUR_OF_DAY, 5)
set(Calendar.MINUTE, 0)
set(Calendar.SECOND, 0)
set(Calendar.MILLISECOND, 0)
}.timeInMillis
val endTime = startTime + 86399000L
// Show a list of articles
}
fun getDayEndLong(year: Int, month: Int, day: Int): Long {
val startTime = getDayStartLong(year, month, day)
return startTime + 86399000L
}
fun getData(year: Int, month: Int, day: Int): List<RecordData> {
val startTime = getDayStartLong(year, month, day)
val endTime = getDayEndLong(year, month, day)
val records = ArrayList<RecordData>()
val memberList = MemberService.findAll()
memberList.forEach { member ->
if (member.leave && member.updatedAt!! < startTime) {
//println("成員離開 ${member.nickName}")
return@forEach
}
if (member.createAt!! > startTime) {
//println("成員不在當期開戰期間 ${member.nickName}")
return@forEach
}
records.add(
RecordData(member = member, MemberRecord())
RecordData(member = member, null)
)
}
val recordList = MemberRecordService.findByTimeBetween(startTime, endTime)
@@ -1,21 +1,20 @@
package com.ray650128.pcredive.plugins
import com.ray650128.pcredive.database.dto.toDto
import com.ray650128.pcredive.database.model.Member
import com.ray650128.pcredive.database.model.MemberRecord
import com.ray650128.pcredive.database.service.MemberService
import io.ktor.http.*
import io.ktor.serialization.kotlinx.json.*
import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.server.response.*
import io.ktor.server.application.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import io.ktor.server.util.*
import kotlinx.coroutines.coroutineScope
fun Application.configureMemberRouting() {
routing {
options("{...}") {
call.respond(HttpStatusCode.OK)
}
route("/api") {
route("/member") {
get {
@@ -55,11 +54,20 @@ fun Application.configureMemberRouting() {
nickName = member.nickName
discordID = member.discordID
uid = member.uid
leave = member.leave
updatedAt = System.currentTimeMillis()
}
MemberService.updateById(id, oldData)
call.respond(HttpStatusCode.OK, oldData)
}
delete("/{id}") {
val id = call.parameters.getOrFail<String>("id")
if (MemberService.deleteById(id)) {
call.respond(HttpStatusCode.OK)
} else {
call.respond(HttpStatusCode.NotFound)
}
}
}
}
}
@@ -0,0 +1,42 @@
package com.ray650128.pcredive.plugins
import com.ray650128.pcredive.database.model.MemberRecord
import com.ray650128.pcredive.database.model.Record
import com.ray650128.pcredive.database.service.MemberRecordService
import com.ray650128.pcredive.database.service.MemberService
import io.ktor.server.application.*
import java.util.*
fun Application.configureUpdateTimer() {
val date = Date()
val timer = Timer()
timer.schedule(object : TimerTask() {
override fun run() {
val c = Calendar.getInstance()
val hour = c[Calendar.HOUR_OF_DAY]
val minute = c[Calendar.MINUTE]
val second = c[Calendar.SECOND]
val day = c[Calendar.DAY_OF_MONTH]
val lastDay = c.getActualMaximum(Calendar.DAY_OF_MONTH)
//println("Time: $day, ${String.format("%2d:%2d:%2d", hour, minute, second)}")
if ((day in (lastDay - 5)..lastDay) && (hour == 5 && minute == 0 && second == 0)) {
val members = MemberService.findAll(false)
members.forEach { member ->
MemberRecordService.create(
MemberRecord(
memberId = member._id,
record1 = Record(""),
record1c = Record(""),
record2 = Record(""),
record2c = Record(""),
record3 = Record(""),
record3c = Record(""),
createdAt = System.currentTimeMillis(),
updatedAt = System.currentTimeMillis()
)
)
}
}
}
}, date, 1000L)
}
+175
View File
@@ -0,0 +1,175 @@
html {
background-image: url("../img/background.jpg");
}
table {
background-color: #ffffffbb;
border-style: solid;
border-width: 2px;
border-collapse: collapse;
width: 100%;
}
th, td {
padding: 1px 2px;
border: 1px solid #000;
}
hr {
border: 1px solid #2c6a99;
}
/* 未訪問超連結 */
a:link {
color: #000000;
}
/* 已訪問超連結 */
a:visited {
color: #000000;
}
/* 滑鼠移動到超連結上 */
a:hover {
color: #1070c4;
background-color: #ffffff;
}
/* 滑鼠點選時 */
a:active {
color: #0d5da3;
}
h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6, label {
font-family: 'Arial', system-ui;
margin-top: 0;
margin-bottom: 0;
margin-left: 0;
margin-right: 0;
}
.centerText {
font-family: 'Arial', system-ui;
text-align: center;
font-weight: bold;
}
p {
text-align: center;
font-weight: bold;
font-family: 'Arial', system-ui
}
input[type="text"], input[type="number"] {
width: 100%;
max-width: 100%;
padding: 10px;
font-size: 16px;
border-width: 1px;
border-color: #07407d;
background-color: #ffffffe0;
color: #000000;
box-sizing: border-box;
border-style: solid;
border-radius: 5px;
font-family: 'Arial', system-ui
}
input[type="text"], input[type="number"] {
outline:none;
}
input[type="date"] {
padding: 5px;
font-size: 16px;
border-width: 1px;
border-color: #07407d;
background-color: #ffffffe0;
color: #000000;
border-style: solid;
border-radius: 5px;
font-family: 'Arial', system-ui
}
input[type="date"] {
outline:none;
}
button {
display: inline-block;
text-align: center;
vertical-align: middle;
padding: 8px 20px;
border: 1px solid #07407d;
border-radius: 8px;
background: #4ab1ff;
background: -webkit-gradient(linear, left top, left bottom, from(#4ab1ff), to(#0d5da3));
background: -moz-linear-gradient(top, #4ab1ff, #0d5da3);
background: linear-gradient(to bottom, #4ab1ff, #0d5da3);
text-shadow: #591717 1px 1px 1px;
font-family: 'Arial', system-ui;
color: #ffffff;
text-decoration: none;
}
button:hover,
button:focus {
border: 1px solid #0b66c8;
background: #59d4ff;
background: -webkit-gradient(linear, left top, left bottom, from(#59d4ff), to(#1070c4));
background: -moz-linear-gradient(top, #59d4ff, #1070c4);
background: linear-gradient(to bottom, #59d4ff, #1070c4);
color: #ffffff;
text-decoration: none;
}
button:active {
background: #2c6a99;
background: -webkit-gradient(linear, left top, left bottom, from(#2c6a99), to(#0d5da3));
background: -moz-linear-gradient(top, #2c6a99, #0d5da3);
background: linear-gradient(to bottom, #2c6a99, #0d5da3);
}
.button_red {
display: inline-block;
text-align: center;
vertical-align: middle;
padding: 8px 20px;
border: 1px solid #7d0707;
border-radius: 8px;
background: #ff4a4a;
background: -webkit-gradient(linear, left top, left bottom, from(#ff4a4a), to(#a30d0d));
background: -moz-linear-gradient(top, #ff4a4a, #a30d0d);
background: linear-gradient(to bottom, #ff4a4a, #a30d0d);
text-shadow: #591717 1px 1px 1px;
font-family: 'Arial', system-ui;
color: #ffffff;
text-decoration: none;
}
.button_red:hover,
.button_red:focus {
border: 1px solid #c80b0b;
background: #ff5959;
background: -webkit-gradient(linear, left top, left bottom, from(#ff5959), to(#c41010));
background: -moz-linear-gradient(top, #ff5959, #c41010);
background: linear-gradient(to bottom, #ff5959, #c41010);
color: #ffffff;
text-decoration: none;
}
.button_red:active {
background: #992c2c;
background: -webkit-gradient(linear, left top, left bottom, from(#992c2c), to(#a30d0d));
background: -moz-linear-gradient(top, #992c2c, #a30d0d);
background: linear-gradient(to bottom, #992c2c, #a30d0d);
}
.center {
width: fit-content;
margin: 0 auto;
}
.autosize-text {
font-size: 5vw;
font-family: 'Arial', system-ui;
text-align: center;
font-weight: bold;
}
+146
View File
@@ -0,0 +1,146 @@
<!DOCTYPE html>
<html
lang="zh-TW"
xmlns="http://www.w3.org/1999/html"
xmlns="http://www.w3.org/1999/html"
>
<head>
<!-- Required meta tags -->
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>新增/修改紀錄</title>
<link rel="stylesheet" href="./css/style.css" />
</head>
<body>
<h1 class="autosize-text" id="my_title">新增/修改紀錄</h1>
<hr />
<h4><p>填寫方式:掉刀填0,正常出刀填X周-Y王。</p></h4>
<h4><p>傷害依照幹部規定要不要填,如不填可留空</p></h4>
<hr />
<form id="record-form">
<table>
<tr>
<td style="width: 15%">
<h5 class="centerText">第1刀<br />正刀</h5>
</td>
<td style="width: 25%">
<input type="text" id="knife1_boss" placeholder="x周-y王" />
</td>
<td style="width: 20%">
<h5 class="centerText">第1刀<br />正刀傷害</h5>
</td>
<td style="width: 40%">
<input
type="number"
id="knife1_damage"
placeholder="ex: 12000000"
/>
</td>
</tr>
<tr>
<td style="width: 15%">
<h5 class="centerText">第1刀<br />殘刀</h5>
</td>
<td style="width: 25%">
<input type="text" id="knife1c_boss" placeholder="x周-y王" />
</td>
<td style="width: 20%">
<h5 class="centerText">第1刀<br />殘刀傷害</h5>
</td>
<td style="width: 40%">
<input
type="number"
id="knife1c_damage"
placeholder="ex: 12000000"
/>
</td>
</tr>
</table>
<hr />
<table>
<tr>
<td style="width: 15%">
<h5 class="centerText">第2刀<br />正刀</h5>
</td>
<td style="width: 25%">
<input type="text" id="knife2_boss" placeholder="x周-y王" />
</td>
<td style="width: 20%">
<h5 class="centerText">第2刀<br />正刀傷害</h5>
</td>
<td style="width: 40%">
<input
type="number"
id="knife2_damage"
placeholder="ex: 12000000"
/>
</td>
</tr>
<tr>
<td style="width: 15%">
<h5 class="centerText">第2刀<br />殘刀</h5>
</td>
<td style="width: 25%">
<input type="text" id="knife2c_boss" placeholder="x周-y王" />
</td>
<td style="width: 20%">
<h5 class="centerText">第2刀<br />殘刀傷害</h5>
</td>
<td style="width: 40%">
<input
type="number"
id="knife2c_damage"
placeholder="ex: 12000000"
/>
</td>
</tr>
</table>
<hr />
<table>
<tr>
<td style="width: 15%">
<h5 class="centerText">第3刀<br />正刀</h5>
</td>
<td style="width: 25%">
<input type="text" id="knife3_boss" placeholder="x周-y王" />
</td>
<td style="width: 20%">
<h5 class="centerText">第3刀<br />正刀傷害</h5>
</td>
<td style="width: 40%">
<input
type="number"
id="knife3_damage"
placeholder="ex: 12000000"
/>
</td>
</tr>
<tr>
<td style="width: 15%">
<h5 class="centerText">第3刀<br />殘刀</h5>
</td>
<td style="width: 25%">
<input type="text" id="knife3c_boss" placeholder="x周-y王" />
</td>
<td style="width: 20%">
<h5 class="centerText">第3刀<br />殘刀傷害</h5>
</td>
<td style="width: 40%">
<input
type="number"
id="knife3c_damage"
placeholder="ex: 12000000"
/>
</td>
</tr>
</table>
<hr />
<p><button type="submit">送出</button></p>
</form>
<script src="https://cdn.jsdelivr.net/npm/axios@1.1.2/dist/axios.min.js"></script>
<script src="./js/edit.js"></script>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 218 KiB

+30
View File
@@ -0,0 +1,30 @@
<!DOCTYPE html>
<html lang="zh-TW" xmlns="http://www.w3.org/1999/html" xmlns="http://www.w3.org/1999/html">
<head>
<!-- Required meta tags -->
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>公主連結戰隊戰填表系統</title>
<link rel="stylesheet" href="./css/style.css">
</style>
</head>
<body id="body">
<h1 class="centerText">填表系統</h1>
<hr>
<!--p>
<a href="new.html">我要填表</a>
</p-->
<div class="center">
<label for="queryDate">日期篩選:</label>
<input type="date" id="queryDate">
</div>
<hr>
<script src="https://cdn.jsdelivr.net/npm/axios@1.1.2/dist/axios.min.js"></script>
<script src="./js/index.js"></script>
</body>
</html>
+149
View File
@@ -0,0 +1,149 @@
var paramValue = "";
var memberId = "";
var title = document.getElementById("my_title");
var knife1_boss = document.getElementById("knife1_boss");
var knife1_damage = document.getElementById("knife1_damage");
var knife1c_boss = document.getElementById("knife1c_boss");
var knife1c_damage = document.getElementById("knife1c_damage");
var knife2_boss = document.getElementById("knife2_boss");
var knife2_damage = document.getElementById("knife2_damage");
var knife2c_boss = document.getElementById("knife2c_boss");
var knife2c_damage = document.getElementById("knife2c_damage");
var knife3_boss = document.getElementById("knife3_boss");
var knife3_damage = document.getElementById("knife3_damage");
var knife3c_boss = document.getElementById("knife3c_boss");
var knife3c_damage = document.getElementById("knife3c_damage");
// 在頁面載入完成後,執行獲取參數的操作
window.onload = function () {
// 取得參數
paramValue = getParameterByName('id');
console.log(paramValue);
axios.get("./api/record/" + paramValue)
.then(function (response) {
// 在這裡處理回傳的資料
var options = response.data;
console.log(options);
memberId = options.member._id;
title.innerHTML = options.member.playerName + " 新增/修改紀錄";
knife1_boss.value = options.record1.boss;
knife1_damage.value = options.record1.damage ?? "";
knife1c_boss.value = options.record1c.boss;
knife1c_damage.value = options.record1c.damage ?? "";
knife2_boss.value = options.record2.boss;
knife2_damage.value = options.record2.damage ?? "";
knife2c_boss.value = options.record2c.boss;
knife2c_damage.value = options.record2c.damage ?? "";
knife3_boss.value = options.record3.boss;
knife3_damage.value = options.record3.damage ?? "";
knife3c_boss.value = options.record3c.boss;
knife3c_damage.value = options.record3c.damage ?? "";
})
.catch(function (error) {
// 處理錯誤
console.error(error);
});
};
document.addEventListener('resize', adjustTextSize);
document.getElementById("record-form").addEventListener("submit", function (event) {
event.preventDefault(); // 阻止表單預設提交行為
// 執行請求
fillRecord(
paramValue,
memberId,
knife1_boss.value,
knife1_damage.value,
knife1c_boss.value,
knife1c_damage.value,
knife2_boss.value,
knife2_damage.value,
knife2c_boss.value,
knife2c_damage.value,
knife3_boss.value,
knife3_damage.value,
knife3c_boss.value,
knife3c_damage.value
);
});
function adjustTextSize() {
var screenWidth = window.innerWidth;
var fontSize = screenWidth * 0.04;
title.fontSize = fontSize + 'px';
}
function getParameterByName(name) {
// 获取 URL 中的参数部分
var url = window.location.href;
// 对 URL 进行解析
var parsedUrl = new URL(url);
// 从解析后的 URL 中获取参数值
return parsedUrl.searchParams.get(name);
}
function fillRecord(
recordId,
memberId,
knife1_boss,
knife1_damage,
knife1c_boss,
knife1c_damage,
knife2_boss,
knife2_damage,
knife2c_boss,
knife2c_damage,
knife3_boss,
knife3_damage,
knife3c_boss,
knife3c_damage
) {
// 发送登录请求
axios.put("./api/record/" + recordId, {
memberId: memberId,
record1: {
boss: knife1_boss,
damage: parseInt(knife1_damage),
},
record1c: {
boss: knife1c_boss,
damage: parseInt(knife1c_damage),
},
record2: {
boss: knife2_boss,
damage: parseInt(knife2_damage),
},
record2c: {
boss: knife2c_boss,
damage: parseInt(knife2c_damage),
},
record3: {
boss: knife3_boss,
damage: parseInt(knife3_damage),
},
record3c: {
boss: knife3c_boss,
damage: parseInt(knife3c_damage),
}
})
.then(function (response) {
window.location.href = "./index.html";
})
.catch(function (error) {
const message = error.response.data.message;
alert("更新失敗");
//console.error('登入失敗:', error);
});
}
+146
View File
@@ -0,0 +1,146 @@
// 日期選擇
var dateInput = document.getElementById('queryDate');
dateInput.addEventListener('change', function () {
//console.log("change" + dateInput.value);
localStorage.setItem('temp_date', dateInput.value);
getDateOfRecords();
});
// 載入日期
if (localStorage.getItem('temp_date') !== null) {
dateInput.value = localStorage.getItem("temp_date");
} else {
var today = new Date();
var formattedDate = today.toISOString().split('T')[0];
dateInput.value = formattedDate;
}
let table = document.createElement("table");
let thead = document.createElement("thead");
let tbody = document.createElement("tbody");
generateTable();
getDateOfRecords();
setInterval(getDateOfRecords, 2000);
function generateTable() {
table.appendChild(thead);
table.appendChild(tbody);
// Adding the entire table to the body tag
document.getElementById("body").appendChild(table);
// Creating and adding data to first row of the table
let row_1 = document.createElement("tr");
let heading_1 = document.createElement("th");
heading_1.setAttribute('style', 'width: 40%;')
let heading_2 = document.createElement("th");
heading_2.setAttribute('style', 'width: 10%;')
let heading_3 = document.createElement("th");
heading_3.setAttribute('style', 'width: 10%;')
let heading_4 = document.createElement("th");
heading_4.setAttribute('style', 'width: 10%;')
let heading_5 = document.createElement("th");
heading_5.setAttribute('style', 'width: 10%;')
let heading_6 = document.createElement("th");
heading_6.setAttribute('style', 'width: 10%;')
let heading_7 = document.createElement("th");
heading_7.setAttribute('style', 'width: 10%;')
let heading_1_text = document.createElement("h5");
heading_1_text.innerHTML = "成員名稱";
let heading_2_text = document.createElement("h5");
heading_2_text.innerHTML = "1<br>正刀";
let heading_3_text = document.createElement("h5");
heading_3_text.innerHTML = "2<br>正刀";
let heading_4_text = document.createElement("h5");
heading_4_text.innerHTML = "3<br>正刀";
let heading_5_text = document.createElement("h5");
heading_5_text.innerHTML = "1<br>殘刀";
let heading_6_text = document.createElement("h5");
heading_6_text.innerHTML = "2<br>殘刀";
let heading_7_text = document.createElement("h5");
heading_7_text.innerHTML = "3<br>殘刀";
heading_1.appendChild(heading_1_text);
heading_2.appendChild(heading_2_text);
heading_3.appendChild(heading_3_text);
heading_4.appendChild(heading_4_text);
heading_5.appendChild(heading_5_text);
heading_6.appendChild(heading_6_text);
heading_7.appendChild(heading_7_text);
row_1.appendChild(heading_1);
row_1.appendChild(heading_2);
row_1.appendChild(heading_3);
row_1.appendChild(heading_4);
row_1.appendChild(heading_5);
row_1.appendChild(heading_6);
row_1.appendChild(heading_7);
thead.appendChild(row_1);
}
// 取得刀表
function getDateOfRecords() {
var dateSplit = dateInput.value.split("-");
console.log(dateSplit);
// 取得刀表
axios.get("./api/record/" + dateSplit[0] + "/" + dateSplit[1] + "/" + dateSplit[2], {
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
})
.then(function (response) {
const data = response.data;
//console.log(data);
// 清除原有的資料列
while (tbody.firstChild) {
tbody.removeChild(tbody.firstChild);
}
for (let i = 0; i < data.length; i++) {
// 建立新的資料列
let row_2 = document.createElement("tr");
let row_2_data_1 = document.createElement("td");
let row_2_data_2 = document.createElement("td");
let row_2_data_3 = document.createElement("td");
let row_2_data_4 = document.createElement("td");
let row_2_data_5 = document.createElement("td");
let row_2_data_6 = document.createElement("td");
let row_2_data_7 = document.createElement("td");
const item = data[i];
if (item.record !== null) {
row_2_data_1.innerHTML = "<h5 class=\"centerText\"><a href=\"edit.html?id=" + item.record._id + "\">" + item.member.playerName + "</a></h5>";
row_2_data_2.innerHTML = "<h5 class=\"centerText\">" + item.record.record1.boss + "</h5>";
row_2_data_3.innerHTML = "<h5 class=\"centerText\">" + item.record.record2.boss + "</h5>";
row_2_data_4.innerHTML = "<h5 class=\"centerText\">" + item.record.record3.boss + "</h5>";
row_2_data_5.innerHTML = "<h5 class=\"centerText\">" + item.record.record1c.boss + "</h5>";
row_2_data_6.innerHTML = "<h5 class=\"centerText\">" + item.record.record2c.boss + "</h5>";
row_2_data_7.innerHTML = "<h5 class=\"centerText\">" + item.record.record3c.boss + "</h5>";
} else {
row_2_data_1.innerHTML = "<h5 class=\"centerText\">" + item.member.playerName + "</h5>";
row_2_data_2.innerHTML = "<h5 class=\"centerText\">---</h5>";
row_2_data_3.innerHTML = "<h5 class=\"centerText\">---</h5>";
row_2_data_4.innerHTML = "<h5 class=\"centerText\">---</h5>";
row_2_data_5.innerHTML = "<h5 class=\"centerText\">---</h5>";
row_2_data_6.innerHTML = "<h5 class=\"centerText\">---</h5>";
row_2_data_7.innerHTML = "<h5 class=\"centerText\">---</h5>";
}
row_2.appendChild(row_2_data_1);
row_2.appendChild(row_2_data_2);
row_2.appendChild(row_2_data_3);
row_2.appendChild(row_2_data_4);
row_2.appendChild(row_2_data_5);
row_2.appendChild(row_2_data_6);
row_2.appendChild(row_2_data_7);
tbody.appendChild(row_2);
}
})
.catch(function (error) {
console.error('資料取得失敗:', error);
});
}
+114
View File
@@ -0,0 +1,114 @@
document
.getElementById("record-form")
.addEventListener("submit", function (event) {
event.preventDefault(); // 阻止表單預設提交行為
// 假設你有一個下拉式選單的 HTML 元素
var selectElement = document.getElementById("member_select");
var knife1_boss = document.getElementById("knife1_boss").value;
var knife1_damage = document.getElementById("knife1_damage").value;
var knife1c_boss = document.getElementById("knife1c_boss").value;
var knife1c_damage = document.getElementById("knife1c_damage").value;
var knife2_boss = document.getElementById("knife2_boss").value;
var knife2_damage = document.getElementById("knife2_damage").value;
var knife2c_boss = document.getElementById("knife2c_boss").value;
var knife2c_damage = document.getElementById("knife2c_damage").value;
var knife3_boss = document.getElementById("knife3_boss").value;
var knife3_damage = document.getElementById("knife3_damage").value;
var knife3c_boss = document.getElementById("knife3c_boss").value;
var knife3c_damage = document.getElementById("knife3c_damage").value;
// 執行請求
fillRecord(
selectElement.value,
knife1_boss,
knife1_damage,
knife1c_boss,
knife1c_damage,
knife2_boss,
knife2_damage,
knife2c_boss,
knife2c_damage,
knife3_boss,
knife3_damage,
knife3c_boss,
knife3c_damage
);
});
axios
.get("./api/member/not_leave")
.then(function (response) {
// 在這裡處理回傳的資料
var options = response.data;
// 假設你有一個下拉式選單的 HTML 元素
var selectElement = document.getElementById("member_select");
// 將資料加入到下拉式選單中
options.forEach(function (option) {
var optionElement = document.createElement("option");
optionElement.value = option._id;
optionElement.textContent = option.playerName;
selectElement.appendChild(optionElement);
});
})
.catch(function (error) {
// 處理錯誤
console.error(error);
});
function fillRecord(
memberId,
knife1_boss,
knife1_damage,
knife1c_boss,
knife1c_damage,
knife2_boss,
knife2_damage,
knife2c_boss,
knife2c_damage,
knife3_boss,
knife3_damage,
knife3c_boss,
knife3c_damage
) {
// 发送登录请求
axios.post("./api/record/" + memberId, {
record1: {
boss: knife1_boss,
damage: parseInt(knife1_damage),
},
record1c: {
boss: knife1c_boss,
damage: parseInt(knife1c_damage),
},
record2: {
boss: knife2_boss,
damage: parseInt(knife2_damage),
},
record2c: {
boss: knife2c_boss,
damage: parseInt(knife2c_damage),
},
record3: {
boss: knife3_boss,
damage: parseInt(knife3_damage),
},
record3c: {
boss: knife3c_boss,
damage: parseInt(knife3c_damage),
}
})
.then(function (response) {
window.location.href = "./index.html";
})
.catch(function (error) {
const message = error.response.data.message;
alert("新增失敗");
//console.error('登入失敗:', error);
});
}
+82
View File
@@ -0,0 +1,82 @@
<!DOCTYPE html>
<html
lang="zh-TW"
xmlns="http://www.w3.org/1999/html"
xmlns="http://www.w3.org/1999/html"
>
<head>
<!-- Required meta tags -->
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>修改成員</title>
<link rel="stylesheet" href="../css/style.css" />
</head>
<body>
<h1 class="centerText">修改成員</h1>
<hr />
<form id="member-form">
<table>
<tr>
<td style="width: 30%"><h4>成員名稱</h4></td>
<td style="width: 70%">
<input
type="text"
id="nick_name"
placeholder="請輸入成員 Discord 名稱"
/>
</td>
</tr>
<tr>
<td><h4>遊戲角色名稱</h4></td>
<td>
<input
type="text"
id="player_name"
placeholder="請輸入遊戲主角名稱"
/>
</td>
</tr>
<tr>
<td><h4>遊戲UID</h4></td>
<td>
<input type="text" id="game_uid" placeholder="請輸入遊戲U ID" />
</td>
</tr>
<tr>
<td><h4>DC ID</h4></td>
<td>
<input
type="text"
id="discord_id"
placeholder="請輸入 Discord user ID"
/>
</td>
</tr>
<tr>
<td><h4>是否離開戰隊</h4></td>
<td>
<input type="radio" id="leave_true" name="is_leave" value="true" />
<label for="leave_true"></label>
<input
type="radio"
id="leave_false"
name="is_leave"
value="false"
/>
<label for="leave_true"></label>
</td>
</tr>
</table>
<hr />
<p>
<button id="submit" type="button">更新</button>
<button class="button_red" id="delete" type="button">刪除</button>
</p>
</form>
<script src="https://cdn.jsdelivr.net/npm/axios@1.1.2/dist/axios.min.js"></script>
<script src="./js/edit.js"></script>
</body>
</html>
+25
View File
@@ -0,0 +1,25 @@
<!DOCTYPE html>
<html lang="zh-TW" xmlns="http://www.w3.org/1999/html" xmlns="http://www.w3.org/1999/html">
<head>
<!-- Required meta tags -->
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>公主連結戰隊戰填表系統 - 成員管理</title>
<link rel="stylesheet" href="../css/style.css">
</style>
</head>
<body id="body">
<h1 class="centerText">成員管理</h1>
<hr>
<div class="center">
<h4><a href="./new.html">新增成員</a></h4>
</div>
<hr>
<script src="https://cdn.jsdelivr.net/npm/axios@1.1.2/dist/axios.min.js"></script>
<script src="./js/index.js"></script>
</body>
</html>
+99
View File
@@ -0,0 +1,99 @@
var paramValue = "";
var memberId = "";
var nickName = document.getElementById("nick_name");
var playerName = document.getElementById("player_name");
var gameUid = document.getElementById("game_uid");
var discordId = document.getElementById("discord_id");
// 在頁面載入完成後,執行獲取參數的操作
window.onload = function () {
// 取得參數
paramValue = getParameterByName('id');
console.log(paramValue);
axios.get("../api/member/" + paramValue)
.then(function (response) {
// 在這裡處理回傳的資料
var options = response.data;
console.log(options);
nickName.value = options.nickName;
playerName.value = options.playerName;
gameUid.value = options.uid;
discordId.value = options.discordID;
if (options.leave) {
document.getElementById("leave_true").checked = true;
} else {
document.getElementById("leave_false").checked = true;
}
})
.catch(function (error) {
// 處理錯誤
console.error(error);
});
};
document.getElementById("submit").addEventListener("click", function (event) {
event.preventDefault(); // 阻止表單預設提交行為
// 執行請求
updateMember(paramValue, nickName.value, playerName.value, gameUid.value, discordId.value);
});
document.getElementById("delete").addEventListener("click", function (event) {
event.preventDefault(); // 阻止表單預設提交行為
// 執行請求
deleteMember(paramValue);
});
function getParameterByName(name) {
// 获取 URL 中的参数部分
var url = window.location.href;
// 对 URL 进行解析
var parsedUrl = new URL(url);
// 从解析后的 URL 中获取参数值
return parsedUrl.searchParams.get(name);
}
function updateMember(memberId, nickName, playerName, gameUid, discordId) {
var selected = document.querySelector('input[name="is_leave"]:checked')
console.log(selected.value);
var isLeave = false;
if (selected) {
if (selected.value == "true") {
isLeave = true;
} else {
isLeave = false;
}
}
// 发送登录请求
axios.put("../api/member/" + memberId, {
playerName: playerName,
nickName: nickName,
discordID: discordId,
uid: gameUid,
leave: isLeave
})
.then(function (response) {
window.location.href = "../index.html";
})
.catch(function (error) {
//const message = error.response.data.message;
alert("更新失敗");
//console.error('登入失敗:', error);
});
}
function deleteMember(memberId) {
axios.delete("../api/member/" + memberId)
.then(function (response) {
window.location.href = "./index.html";
})
.catch(function (error) {
//const message = error.response.data.message;
alert("刪除失敗");
//console.error('登入失敗:', error);
});
}
+78
View File
@@ -0,0 +1,78 @@
var selectedDate = document.getElementById("queryDate");
let table = document.createElement("table");
let thead = document.createElement("thead");
let tbody = document.createElement("tbody");
table.appendChild(thead);
table.appendChild(tbody);
// Adding the entire table to the body tag
document.getElementById("body").appendChild(table);
// Creating and adding data to first row of the table
let row_1 = document.createElement("tr");
/*let heading_1 = document.createElement("th");
heading_1.innerHTML = "<h4>成員名稱</h4>";*/
let heading_2 = document.createElement("th");
heading_2.innerHTML = "<h4>角色暱稱</h4>";
heading_2.setAttribute('style', 'width: 54%;')
let heading_3 = document.createElement("th");
heading_3.innerHTML = "<h4>角色UID</h4>";
heading_3.setAttribute('style', 'width: 34%;')
/*let heading_4 = document.createElement("th");
heading_4.innerHTML = "<h4>DC ID</h4>";*/
let heading_5 = document.createElement("th");
heading_5.innerHTML = "<h4>離開</h4>";
heading_5.setAttribute('style', 'width: 12%;')
//row_1.appendChild(heading_1);
row_1.appendChild(heading_2);
row_1.appendChild(heading_3);
//row_1.appendChild(heading_4);
row_1.appendChild(heading_5);
thead.appendChild(row_1);
// 取得刀表
axios.get("../api/member", {
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
})
.then(function (response) {
const data = response.data;
console.log(data);
for (let i = 0; i < data.length; i++) {
// Creating and adding data to second row of the table
let row_2 = document.createElement("tr");
//let row_2_data_1 = document.createElement("td");
let row_2_data_2 = document.createElement("td");
let row_2_data_3 = document.createElement("td");
//let row_2_data_4 = document.createElement("td");
let row_2_data_5 = document.createElement("td");
const item = data[i];
//row_2_data_1.innerHTML = "<a href=\"edit.html?id=" + item._id + "\">" + item.nickName + "</a>";
row_2_data_2.innerHTML = "<h4><a href=\"edit.html?id=" + item._id + "\">" + item.playerName + "</a></h4>";
row_2_data_3.innerHTML = "<h4>" + item.uid + "</h4>";
//row_2_data_4.innerHTML = item.discordID;
if (item.leave) {
row_2_data_5.innerHTML = "<h4>O</h4>";
} else {
row_2_data_5.innerHTML = "<h4>X</h4>";
}
//row_2.appendChild(row_2_data_1);
row_2.appendChild(row_2_data_2);
row_2.appendChild(row_2_data_3);
//row_2.appendChild(row_2_data_4);
row_2.appendChild(row_2_data_5);
tbody.appendChild(row_2);
}
})
.catch(function (error) {
//const message = error.response.data.message;
//alert("資料取得失敗");
console.error('資料取得失敗:', error);
});
+31
View File
@@ -0,0 +1,31 @@
document
.getElementById("member-form")
.addEventListener("submit", function (event) {
event.preventDefault(); // 阻止表單預設提交行為
var nickName = document.getElementById("nick_name");
var playerName = document.getElementById("player_name");
var gameUid = document.getElementById("game_uid");
var discordId = document.getElementById("discord_id");
// 執行請求
newMember(nickName.value, playerName.value, gameUid.value, discordId.value);
});
function newMember(nickName, playerName, gameUid, discordId) {
// 发送登录请求
axios.post("../api/member", {
playerName: playerName,
nickName: nickName,
discordID: discordId,
uid: gameUid
})
.then(function (response) {
window.location.href = "../index.html";
})
.catch(function (error) {
const message = error.response.data.message;
alert("新增失敗");
//console.error('登入失敗:', error);
});
}
+65
View File
@@ -0,0 +1,65 @@
<!DOCTYPE html>
<html
lang="zh-TW"
xmlns="http://www.w3.org/1999/html"
xmlns="http://www.w3.org/1999/html"
>
<head>
<!-- Required meta tags -->
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>新增成員</title>
<link rel="stylesheet" href="../css/style.css" />
</head>
<body id="body">
<h1 class="centerText">新增成員</h1>
<hr />
<form id="member-form">
<table>
<tr>
<td style="width: 30%"><h4>成員名稱</h4></td>
<td style="width: 70%">
<input
type="text"
id="nick_name"
placeholder="請輸入成員 Discord 名稱"
/>
</td>
</tr>
<tr>
<td><h4>遊戲角色名稱</h4></td>
<td>
<input
type="text"
id="player_name"
placeholder="請輸入遊戲主角名稱"
/>
</td>
</tr>
<tr>
<td><h4>遊戲UID</h4></td>
<td>
<input type="text" id="game_uid" placeholder="請輸入遊戲U ID" />
</td>
</tr>
<tr>
<td><h4>DC ID</h4></td>
<td>
<input
type="text"
id="discord_id"
placeholder="請輸入 Discord user ID"
/>
</td>
</tr>
</table>
<hr />
<p><button type="submit">送出</button></p>
</form>
<script src="https://cdn.jsdelivr.net/npm/axios@1.1.2/dist/axios.min.js"></script>
<script src="./js/new.js"></script>
</body>
</html>
+108
View File
@@ -0,0 +1,108 @@
<!DOCTYPE html>
<html
lang="zh-TW"
xmlns="http://www.w3.org/1999/html"
xmlns="http://www.w3.org/1999/html"
>
<head>
<!-- Required meta tags -->
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>新增紀錄</title>
<link rel="stylesheet" href="./css/style.css" />
</head>
<body id="body">
<h1 class="centerText">新增紀錄</h1>
<hr />
<h4>
填寫方式:掉刀填0,正常出刀填X周-Y王。傷害依照幹部規定要不要填,如不填可留空
</h4>
<hr />
<form id="record-form">
<table>
<tr>
<td>請選擇你的名字</td>
<td>
<select id="member_select"></select>
</td>
</tr>
</table>
<hr />
<table>
<tr>
<td>第1刀正刀</td>
<td>
<input type="text" id="knife1_boss" placeholder="x周-y王" />
</td>
<td>第1刀正刀傷害</td>
<td>
<input type="text" id="knife1_damage" placeholder="ex: 12000000" />
</td>
</tr>
<tr>
<td>第1刀殘刀</td>
<td>
<input type="text" id="knife1c_boss" placeholder="x周-y王" />
</td>
<td>第1刀殘刀傷害</td>
<td>
<input type="text" id="knife1c_damage" placeholder="ex: 12000000" />
</td>
</tr>
</table>
<hr />
<table>
<tr>
<td>第2刀正刀</td>
<td>
<input type="text" id="knife2_boss" placeholder="x周-y王" />
</td>
<td>第2刀正刀傷害</td>
<td>
<input type="text" id="knife2_damage" placeholder="ex: 12000000" />
</td>
</tr>
<tr>
<td>第2刀殘刀</td>
<td>
<input type="text" id="knife2c_boss" placeholder="x周-y王" />
</td>
<td>第2刀殘刀傷害</td>
<td>
<input type="text" id="knife2c_damage" placeholder="ex: 12000000" />
</td>
</tr>
</table>
<hr />
<table>
<tr>
<td>第3刀正刀</td>
<td>
<input type="text" id="knife3_boss" placeholder="x周-y王" />
</td>
<td>第3刀正刀傷害</td>
<td>
<input type="text" id="knife3_damage" placeholder="ex: 12000000" />
</td>
</tr>
<tr>
<td>第3刀殘刀</td>
<td>
<input type="text" id="knife3c_boss" placeholder="x周-y王" />
</td>
<td>第3刀殘刀傷害</td>
<td>
<input type="text" id="knife3c_damage" placeholder="ex: 12000000" />
</td>
</tr>
</table>
<hr />
<p><button type="submit">送出</button></p>
</form>
<script src="https://cdn.jsdelivr.net/npm/axios@1.1.2/dist/axios.min.js"></script>
<script src="./js/new.js"></script>
</body>
</html>