Commit c0ea6e29 authored by sunxiwei's avatar sunxiwei

第一版

parent b491f20b
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>比赛管理</title>
<style>
html,body,#app{
height: 100%;
}
</style>
</head>
<body>
<div id="app"></div>
<script type="module" src="src/game_manage.js"></script>
</body>
</html>
......@@ -14,7 +14,7 @@
</head>
<body>
<div id="app"></div>
<div id="app" style="background-color: #F9F9F9;"></div>
<script type="module" src="src/home.js"></script>
</body>
......
......@@ -14,7 +14,7 @@
</head>
<body>
<div id="app"></div>
<div id="app" style="background-color: #F9F9F9;"></div>
<script type="module" src="src/main.js"></script>
</body>
......
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>南高乒乓球俱乐部</title>
<style>
html,body,#app{
height: 100%;
}
</style>
</head>
<body>
<div id="app" style="background-color: #F9F9F9;"></div>
<script type="module" src="src/manage.js"></script>
</body>
</html>
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>比赛列表</title>
<style>
html,body,#app{
height: 100%;
}
</style>
</head>
<body>
<div id="app"></div>
<script type="module" src="src/my_recentgames.js"></script>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>过往赛季</title>
<style>
html,body,#app{
height: 100%;
}
</style>
</head>
<body>
<div id="app"></div>
<script type="module" src="src/past_seasons.js"></script>
</body>
</html>
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>球员审核</title>
<style>
html,body,#app{
height: 100%;
}
</style>
</head>
<body>
<div id="app"></div>
<script type="module" src="src/player_audit.js"></script>
</body>
</html>
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>球员管理</title>
<style>
html,body,#app{
height: 100%;
}
</style>
</head>
<body>
<div id="app"></div>
<script type="module" src="src/player_manage.js"></script>
</body>
</html>
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>积分榜单</title>
<style>
html,body,#app{
height: 100%;
}
</style>
</head>
<body>
<div id="app"></div>
<script type="module" src="src/score_ranking.js"></script>
</body>
</html>
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>赛季管理</title>
<style>
html,body,#app{
height: 100%;
}
</style>
</head>
<body>
<div id="app"></div>
<script type="module" src="src/season_manage.js"></script>
</body>
</html>
......@@ -2,8 +2,8 @@
<v-app>
<!-- {{ filteredMatches }} -->
<v-container>
<v-data-table class="overflow-auto " :headers="headers" :items="filteredMatches" item-key="id"
:search="search.value" :items-per-page="10">
<v-data-table :loading="loading" class="overflow-auto " :headers="headers" :items="filteredMatches" item-key="id"
:search="search" :items-per-page="10">
<template v-slot:top>
<v-toolbar flat>
<v-toolbar-title>比赛</v-toolbar-title>
......@@ -24,11 +24,11 @@
</template>
<template v-slot:item.actions="{ item }">
<div style="width:45px"> <v-icon v-if="!item.shenhe" small color="green" @click="opendialog(item, 'approve')"
<div style="width:45px"> <v-icon small color="green" @click="opendialog(item, 'approve')"
style="padding-right: 20px;">mdi-check</v-icon>
<v-icon v-if="!item.shenhe" small color="red" @click="opendialog(item, 'reject')"
<v-icon small color="red" @click="opendialog(item, 'reject')"
style="padding-left: 20px;">mdi-close</v-icon>
<div v-if="item.shenhe" variant="text">已审核</div>
<!-- <div v-if="item.shenhe" variant="text">已审核</div> -->
</div>
</template>
......@@ -44,7 +44,7 @@
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="indigo" text="取消" @click="dialog = false"></v-btn>
<v-btn color="indigo" text="确定" @click="confirmAction"></v-btn>
<v-btn color="indigo" :loading="confirmLoading" text="确定" @click="confirmAction"></v-btn>
</v-card-actions>
</v-card>
</v-dialog>
......@@ -70,6 +70,8 @@ const shenhetitle = ref(null);
const shenhetext = ref(null);
const dialog = ref(false);
const verify = ref(true);
const loading = ref(false);
const confirmLoading = ref(false);
function info(title, text) {
cardtitle.value = title;
......@@ -78,9 +80,11 @@ function info(title, text) {
}
function refresh() {
loading.value = true;
axios.get('/api/lauchedGames',)
.then(function (response) {
const data = response.data;
matches.value.length = 0;
for (var i = 0; i < data.Games.length; i++) {
var match = {
id: data.Games[i].id,
......@@ -89,7 +93,7 @@ function refresh() {
awayTeam: data.Games[i].player2_real_name,
homeScore: data.Games[i].score1,
awayScore: data.Games[i].score2,
shenhe: false,
// shenhe: false,
}
matches.value[i] = match;
}
......@@ -97,6 +101,7 @@ function refresh() {
.catch(function (error) {
console.log(error);
})
loading.value = false;
}
refresh();
......@@ -133,9 +138,10 @@ function opendialog(game, type) {
}
function confirmAction() {
confirmLoading.value = true;
if (actiontype.value === 'approve') {
verify.value = true;
selectedMatch.value.shenhe = true;
// selectedMatch.value.shenhe = true;
axios.post('/api/confirmGame', {
game_id: selectedMatch.value.id,
confirm: verify.value,
......@@ -145,6 +151,7 @@ function confirmAction() {
if (data.status === "SUCCESS") {
console.log('success');
}
refresh();
})
.catch(function (error) {
console.log(error);
......@@ -152,7 +159,7 @@ function confirmAction() {
}
else if (actiontype.value === 'reject') {
verify.value = false;
selectedMatch.value.shenhe = true;
// selectedMatch.value.shenhe = true;
axios.post('/api/confirmGame', {
game_id: selectedMatch.value.id,
confirm: verify.value,
......@@ -162,11 +169,14 @@ function confirmAction() {
if (data.status === "SUCCESS") {
console.log('success');
}
refresh();
})
.catch(function (error) {
console.log(error);
})
}
confirmLoading.value = false;
dialog.value = false;
}
</script>
\ No newline at end of file
......@@ -2,7 +2,7 @@
<div class="text-h4 headline">
比赛管理
</div>
<v-card class="game-info-card">
<v-card class="game-info-card" v-if="exist_season">
<v-container>
<!-- <v-card-title color="indigo">
提交比赛
......@@ -80,9 +80,17 @@
</v-dialog>
<div>
<v-card class="mx-auto my-2" href="/lauched_games.html" width="95%" rel="noopener" target="_blank" title="已提交比赛"
<v-card v-if="exist_season" class="mx-auto my-2" href="/lauched_games.html" width="95%" rel="noopener" target="_blank" title="已提交比赛"
append-icon="mdi-chevron-right"></v-card>
<v-card class="mx-auto my-2" href="/audit_games.html" width="95%" rel="noopener" target="_blank" title="待审核比赛"
<v-card v-if="exist_season" class="mx-auto my-2" href="/audit_games.html" width="95%" rel="noopener" target="_blank" title="待审核比赛">
<template v-slot:append>
<v-icon v-if="unaudit_number === 0">mdi-chevron-right</v-icon>
<v-badge v-if="unaudit_number !== 0" color="error" :content="unaudit_number" inline></v-badge>
</template>
</v-card>
<v-card v-if="exist_season" class="mx-auto my-2" href="/score_ranking.html" width="95%" rel="noopener" target="_blank" title="球员积分榜单"
append-icon="mdi-chevron-right"></v-card>
<v-card class="mx-auto my-2" href="/my_recentgames.html" width="95%" rel="noopener" target="_blank" title="比赛列表"
append-icon="mdi-chevron-right"></v-card>
</div>
......@@ -106,6 +114,8 @@ const id = ref(null);
const form = ref(null);
const form1 = ref(null);
const form2 = ref(null);
const unaudit_number = ref(0);
const exist_season = ref(false);
var s1;
var s2;
var p1_id;
......@@ -152,9 +162,14 @@ watch(score2, (newVal, oldVal) => {
}
});
axios.get('/api/players')
axios.get('/api/players',{
params:{
lim: 1000,
}
})
.then(function (response) {
const data = response.data;
exist_season.value = data.ExistSeason;
for (var i = 0; i < data.Players.length; i++) {
arr.value[i] = data.Players[i].player_id.toString() + '-' + data.Players[i].player_real_name;
}
......@@ -163,6 +178,15 @@ axios.get('/api/players')
console.log(error);
})
axios.get('/api/lauchedGames',)
.then(function (response) {
const data1 = response.data;
unaudit_number.value = data1.Games.length;
})
.catch(function (error) {
console.log(error);
})
function submit() {
loading.value = true;
p1_id = parseInt(player1.value);
......@@ -184,9 +208,8 @@ function submit() {
game_date: selectedDate.value.toLocaleDateString(),
})
.then(function (response) {
const data = response.data;
console.log(data)
if (data.status == 'SUCCESS') {
const data2 = response.data;
if (data2.status == 'SUCCESS') {
info('提交成功!', "");
}
})
......@@ -220,7 +243,5 @@ function info(title, text) {
margin-left: 5%;
margin-top: 5%;
margin-bottom: 2%;
}
</style>
\ No newline at end of file
<template>
<v-card style="height: 200px;width: 95%;margin: auto;">
<v-card class="relative1" style="height: 200px;" elevation="5">
<v-carousel :show-arrows="false" style="height: 100%;width: 100%;" cycle interval="2000" hide-delimiter-background>
<v-carousel-item v-for="(img, i) in imgs" :key="i" cover>
<img :src="img.src" class="tupian">
</v-carousel-item>
</v-carousel>
</v-card>
<div class="relative1">
<h class="text-h6">近期比赛</h>
<h class="text-h6 float-right">更多</h>
<v-divider thickness="3px"></v-divider>
<v-card class="card1">
<div class="text-subtitle-1" style="height: 33px;" v-for="(item, index) in items" :key="index">
<div class="float-left">
{{ item.date }}
</div>
<div class="float-left zhibiao1" style="width: 20%;">
{{ item.homeTeam }}
</div>
<div class="float-left zhibiao2">
{{ item.homeScore }}
</div>
<div class="float-left">
<div class="relative1" v-if="my_info.season_play != -2">
<v-card class="card1" elevation="5">
<template v-slot:prepend>
<v-icon size="25px">mdi-tournament</v-icon>
</template>
<template v-slot:title>
<div class="text-h6">{{ my_info.season_name }}赛季</div>
</template>
<template v-slot:subtitle>
<div>已有{{ my_info.players_number }}人加入</div>
</template>
<template v-slot:default>
<v-list v-if="my_info.season_play == 1">
<v-list-item>
<div class="d-flex justify-space-between align-center game-item" style="margin-top: -5px;">
<div>
<v-avatar size="48px"><img :src="my_info.player_profile_file" class="img2"></v-avatar>
</div>
<div class="my-realname-text">{{ my_info.player_real_name }}</div>
<div class="winrate-text">{{ my_info.winrate }}%</div>
<div class="games-text">{{ my_info.total_games }}</div>
<div class="point-text">{{ my_info.score }}</div>
<div class="group-text">{{ my_info.group }}</div>
</div>
</v-list-item>
</v-list>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn v-if="my_info.season_play == -1" :loading="season_loading" prepend-icon="mdi-plus-box" color="indigo" variant="text" text="加入赛季"
@click="season_join"></v-btn>
<v-btn v-if="my_info.season_play == 0" :disabled="true" prepend-icon="mdi-help-circle" color="green"
variant="text" text="待审核"></v-btn>
<v-btn v-if="my_info.season_play == 1" :disabled="true" prepend-icon="mdi-check-circle" color="green"
variant="text" text="已加入"></v-btn>
</v-card-actions>
</template>
</v-card>
</div>
<div class="relative1" v-if="my_info.season_play != -2">
<v-card class="card1" elevation="5">
<template v-slot:prepend>
<v-icon size="25px">mdi-trophy</v-icon>
</template>
<template v-slot:title>
<div class="text-h6">近期比赛</div>
</template>
<v-list>
<v-list-item v-for="(item, index) in items" :key="index" :value="item" @click="getGameInfo(item.id)">
<template v-slot:default>
<div class="d-flex justify-space-between align-center game-item">
<div>
<v-avatar size="48px"><img :src="item.homeTeam_avatar" class="img2"></v-avatar>
</div>
<div class="name-score">
<div class="score-text">{{ item.homeScore }}</div>
<div class="name-text">{{ item.homeTeam }}</div>
</div>
<div>
:
</div>
<div class="float-left zhibiao2">
{{ item.awayScore }}
<div class="name-score">
<div class="score-text">{{ item.awayScore }}</div>
<div class="name-text">{{ item.awayTeam }}</div>
</div>
<div class="float-left zhibiao1" style="width: 20%;">
{{ item.awayTeam }}
<div>
<v-avatar size="48px"><img :src="item.awayTeam_avatar" class="img2"></v-avatar>
</div>
<div class="float-right">
<v-icon>mdi-chevron-right</v-icon>
<div>
<!-- <div>{{ item.year }}</div> -->
<div class="game-date-text">{{ item.date }}</div>
</div>
<br>
<v-icon>mdi-chevron-right</v-icon>
</div>
</template>
</v-list-item>
</v-list>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="indigo" variant="text" href="/my_recentgames.html" text="更多"></v-btn>
</v-card-actions>
</v-card>
</div>
<div class="relative1">
<h class="text-h6">队员榜单</h>
<h class="text-h6 float-right">更多</h>
<v-divider thickness="3px"></v-divider>
<div class="relative1" v-if="my_info.season_play != -2">
<!-- <h class="text-h6">队员榜单</h>
<v-divider thickness="3px"></v-divider> -->
<v-card class="card1">
<!-- 1组 -->
<!-- <div style="text-align: center;">A组</div> -->
<v-card class="card1" elevation="5">
<template v-slot:prepend>
<v-icon size="25px">mdi-podium</v-icon>
</template>
<template v-slot:title>
<div class="text-h6">队员榜单</div>
</template>
<div class="text-subtitle-1" style="height: 33px;" v-for="(thing, index) in things" :key="index">
<div class="float-left zhibiao5">
{{ thing.number }}. {{ thing.realname }}
<v-chip-group v-model="group_select" selected-class="text-indigo" mandatory style="margin-left: 10px;">
<v-chip v-for="group in groups" :key="group" :text="group" :value="group"></v-chip>
</v-chip-group>
<v-window v-model="group_select">
<v-window-item :key="1" :value="'A组'">
<v-list>
<v-list-item v-for="(group_1, index) in group1" :key="index" :value="group_1"
@click="goto_space(group_1.id)">
<template v-slot:default>
<div class="d-flex justify-space-between align-center game-item">
<div>
<v-avatar size="48px"><img :src="group_1.avatar" class="img2"></v-avatar>
</div>
<div class="realname-text">{{ group_1.realname }}</div>
<div class="winrate-text">{{ group_1.winrate }}%</div>
<div class="games-text">{{ group_1.games }}</div>
<div class="point-text">{{ group_1.point }}</div>
<v-icon>mdi-chevron-right</v-icon>
</div>
<div class="float-left zhibiao3">
{{ thing.level }}
</template>
</v-list-item>
</v-list>
</v-window-item>
<v-window-item :key="2" :value="'B组'">
<v-list>
<v-list-item v-for="(group_2, index) in group2" :key="index" :value="group_2"
@click="goto_space(group_2.id)">
<template v-slot:default>
<div class="d-flex justify-space-between align-center game-item">
<div>
<v-avatar size="48px"><img :src="group_2.avatar" class="img2"></v-avatar>
</div>
<div class="float-left zhibiao4">
{{ thing.point }}
<div class="realname-text">{{ group_2.realname }}</div>
<div class="winrate-text">{{ group_2.winrate }}%</div>
<div class="games-text">{{ group_2.games }}</div>
<div class="point-text">{{ group_2.point }}</div>
<v-icon>mdi-chevron-right</v-icon>
</div>
</template>
</v-list-item>
</v-list>
</v-window-item>
<v-window-item :key="3" :value="'C组'">
<v-list>
<v-list-item v-for="(group_3, index) in group3" :key="index" :value="group_3"
@click="goto_space(group_3.id)">
<template v-slot:default>
<div class="d-flex justify-space-between align-center game-item">
<div>
<v-avatar size="48px"><img :src="group_3.avatar" class="img2"></v-avatar>
</div>
<div class="float-right" style="line-height: 32px;">
<div class="realname-text">{{ group_3.realname }}</div>
<div class="winrate-text">{{ group_3.winrate }}%</div>
<div class="name-score">{{ group_3.games }}</div>
<div class="date-text">{{ group_3.point }}</div>
<v-icon>mdi-chevron-right</v-icon>
</div>
<br>
</template>
</v-list-item>
</v-list>
</v-window-item>
</v-window>
</v-card>
</div>
<v-dialog v-model="dialog1" width="auto">
<v-card width="300px">
<v-card-title>
{{ cardtitle }}
</v-card-title>
<v-card-text>
{{ cardtext }}
</v-card-text>
<template v-slot:actions>
<v-btn class="ms-auto" variant="text" color="indigo" text="确定" @click="dialog1 = false"></v-btn>
</template>
</v-card>
</v-dialog>
<v-dialog v-model="game_dialog" width="auto">
<v-card width="300px">
<template v-slot:prepend>
<v-icon size="25px">mdi-trophy</v-icon>
</template>
<template v-slot:title>
<div class="text-h6">比赛详情</div>
</template>
<template v-slot:subtitle>
<div>{{ game_detail.game_date }}</div>
</template>
<template v-slot:default>
<div class="d-flex justify-space-between align-center gamedetail-item">
<div>
<v-avatar size="48px"><img :src="game_detail.player1_profile_file" class="img2"></v-avatar>
</div>
<div class="name-score">
<div class="score-text">{{ game_detail.score1 }}</div>
<div class="name-text">{{ game_detail.player1_real_name }}</div>
</div>
<div>
:
</div>
<div class="name-score">
<div class="score-text">{{ game_detail.score2 }}</div>
<div class="name-text">{{ game_detail.player2_real_name }}</div>
</div>
<div>
<v-avatar size="48px"><img :src="game_detail.player2_profile_file" class="img2"></v-avatar>
</div>
</div>
<div class="d-flex justify-space-between align-center gamedetail-item">
<div class="name-score">
<div class="text-h6">发起:</div>
</div>
<div>{{ game_detail.laucher_real_name }}</div>
<div class="name-text">{{ game_detail.lauch_date }}</div>
</div>
<div class="d-flex justify-space-between align-center gamedetail-item">
<div class="name-score">
<div class="text-h6">审核:</div>
</div>
<div>{{ game_detail.confirmer_real_name }}</div>
<div class="name-text">{{ game_detail.confirm_date }}</div>
</div>
</template>
<template v-slot:actions>
<v-btn class="ms-auto" variant="text" color="indigo" text="确定" @click="game_dialog = false"></v-btn>
</template>
</v-card>
</v-dialog>
</template>
</template>
<script setup>
import { ref } from 'vue';
......@@ -86,19 +259,107 @@ const imgs = reactive([
]
);
const items = ref(new Array());
const things = ref(new Array());
const group1 = ref(new Array());
const group2 = ref(new Array());
const group3 = ref(new Array());
const players = ref(new Array());
const groups = ref(['A组', 'B组', 'C组']);
const group_select = ref('A组');
const my_info = ref({
season_id: 0,
season_name: '',
players_number: 0,
score: 0,
group: 0,
player_real_name: '',
player_profile_file: '',
winrate: 0,
total_games: 0,
season_play: -1,
});
const game_detail = ref({
game_date: "",
player1_real_name: "",
player1_profile_file: "",
score1: 0,
player2_real_name: "",
player2_profile_file: "",
score2: 0,
laucher_real_name: "",
laucher_profile_file: "",
lauch_date: "",
confirmer_real_name: "",
confirmer_profile_file: "",
confirm_date: "",
game_type: 0,
});
const game_dialog = ref(false);
const season_loading = ref(false);
function formatDate(date) {
var d = new Date(date),
month = '0' + (d.getMonth() + 1),
day = '' + d.getDate();
// year = d.getFullYear();
return [month + '/' + day].join(''); // 返回形如 MM/DD 的字符串
}
function formatYear(date) {
var d = new Date(date),
// month = '0' + (d.getMonth() + 1);
// day = '' + d.getDate();
year = d.getFullYear();
axios.get('/api/games',)
return [year].join(''); // 返回形如 MM/DD 的字符串
}
function refresh() {
axios.get('/api/mySeasonInfo',)
.then(function (response) {
const data4 = response.data;
my_info.value.season_play = data4.Season_Play;
my_info.value.season_name = data4.Current_season.season_name;
my_info.value.players_number = data4.Current_season.players_number;
my_info.value.score = data4.SeasonInfo.score;
my_info.value.group = data4.SeasonInfo.group;
my_info.value.player_real_name = data4.SeasonInfo.player_real_name;
my_info.value.player_profile_file = data4.SeasonInfo.player_profile_file;
my_info.value.winrate = data4.SeasonInfo.winrate;
my_info.value.total_games = data4.SeasonInfo.total_games;
if (my_info.value.group == 1) {
my_info.value.group = 'A组'
}
if (my_info.value.group == 2) {
my_info.value.group = 'B组'
}
if (my_info.value.group == 3) {
my_info.value.group = 'C组'
}
})
.catch(function (error) {
console.log(error);
})
axios.get('/api/games',)
.then(function (response) {
const data2 = response.data;
for (var i = 0; i < data2.Games.length; i++) {
var length1 = 4;
if (length1 > data2.Games.length) {
length1 = data2.Games.length
}
items.value.length = 0;
for (var i = 0; i < length1; i++) {
var item = {
id: data2.Games[i].id,
date: data2.Games[i].game_date,
year: formatYear(data2.Games[i].game_date),
date: formatDate(data2.Games[i].game_date),
homeTeam: data2.Games[i].player1_real_name,
awayTeam: data2.Games[i].player2_real_name,
homeScore: data2.Games[i].score1,
awayScore: data2.Games[i].score2,
homeTeam_avatar: data2.Games[i].player1_profile_file,
awayTeam_avatar: data2.Games[i].player2_profile_file,
}
items.value[i] = item;
}
......@@ -107,20 +368,157 @@ axios.get('/api/games',)
console.log(error);
})
axios.get("/api/players",)
.then(function(response){
const data3=response.data;
for (var i = 0; i < data3.Players.length; i++) {
var thing = {
number: i+1,
realname: data3.Players[i].player_real_name,
level: data3.Players[i].group,
point: data3.Players[i].score,
axios.get("/api/player_ranking",)
.then(function (response) {
const data3 = response.data;
var length2 = 5;
var length3 = 5;
var length4 = 5;
if (length2 > data3.Group_1.length) {
length2 = data3.Group_1.length
}
if (length3 > data3.Group_2.length) {
length3 = data3.Group_2.length
}
if (length4 > data3.Group_3.length) {
length4 = data3.Group_3.length
}
for (var i = 0; i < length2; i++) {
var group_1 = {
number: i + 1,
id: data3.Group_1[i].player_id,
realname: data3.Group_1[i].player_real_name,
games: data3.Group_1[i].total_games,
point: data3.Group_1[i].score,
winrate: data3.Group_1[i].winrate,
avatar: data3.Group_1[i].player_profile_file
}
things.value[i] = thing;
group1.value[i] = group_1;
}
for (var j = 0; j < length3; j++) {
var group_2 = {
number: j + 1,
id: data3.Group_2[j].player_id,
realname: data3.Group_2[j].player_real_name,
games: data3.Group_2[j].total_games,
point: data3.Group_2[j].score,
winrate: data3.Group_2[j].winrate,
avatar: data3.Group_2[j].player_profile_file
}
group2.value[j] = group_2;
}
for (var k = 0; k < length4; k++) {
var group_3 = {
number: k + 1,
id: data3.Group_3[k].player_id,
realname: data3.Group_3[k].player_real_name,
games: data3.Group_3[k].total_games,
point: data3.Group_3[k].score,
winrate: data3.Group_3[k].winrate,
avatar: data3.Group_3[k].player_profile_file
}
group3.value[k] = group_3;
}
})
.catch(function (error) {
console.log(error);
})
axios.get("/api/players",)
.then(function (response) {
const data1 = response.data;
var length5 = 5;
if (length5 > data1.Players.length) {
length5 = data1.Players.length
}
for (var i = 0; i < length5; i++) {
var player = {
number: i + 1,
realname: data1.Players[i].player_real_name,
games: data1.Players[i].total_games,
point: data1.Players[i].score,
winrate: data1.Players[i].winrate,
player_id: data1.Players[i].player_id,
}
players.value[i] = player;
}
})
.catch(function (error) {
console.log(error);
})
}
refresh();
const cardtitle = ref(null);
const cardtext = ref(null);
const dialog1 = ref(false);
function info(title, text) {
cardtitle.value = title;
cardtext.value = text;
dialog1.value = true;
}
function season_join() {
season_loading.value = true;
axios.post('/api/mySeasonJoin')
.then(function (response) {
const data5 = response.data;
if (data5.status === "FAILED") {
info("加入失败!", "");
}
refresh();
})
.catch(function (error) {
console.log(error);
})
season_loading.value = false;
}
function getGameInfo(game_id) {
axios.get('/api/gameDetail', {
params: {
game_id: game_id,
}
})
.then(function (response) {
const data6 = response.data;
if (data6.status === "SUCCESS") {
game_detail.value.game_date = data6.game_date;
game_detail.value.confirmer_profile_file = data6.confirmer_profile_file;
game_detail.value.confirmer_real_name = data6.confirmer_real_name;
game_detail.value.laucher_profile_file = data6.laucher_profile_file;
game_detail.value.laucher_real_name = data6.laucher_real_name;
game_detail.value.player1_profile_file = data6.player1_profile_file;
game_detail.value.player1_real_name = data6.player1_real_name;
game_detail.value.player2_profile_file = data6.player2_profile_file;
game_detail.value.player2_real_name = data6.player2_real_name;
game_detail.value.score1 = data6.score1;
game_detail.value.score2 = data6.score2;
game_detail.value.game_type = data6.game_type;
game_detail.value.confirm_date = data6.confirm_date;
game_detail.value.lauch_date = data6.lauch_date;
}
})
.then(game_dialog.value = true)
.catch(function (error) {
console.log(error);
})
}
function goto_space(my_id) {
window.location.href = '/space.html?myid=' + my_id;
// axios.get('/api/myRecentGames?myid=' + myid)
// .then(function () {
// window.location.href = "/space.html";
// console.log(myid);
// }
// )
// .catch(function (error) {
// console.log(error);
// })
}
</script>
......@@ -145,25 +543,105 @@ axios.get("/api/players",)
.zhibiao1 {
text-align: center;
/* line-height: 33px; */
}
.zhibiao2 {
width: 10%;
.game-item {
height: 70px;
width: 100%;
/* padding: 20px; */
}
.gamedetail-item {
height: 70px;
width: 100%;
padding-left: 20px;
padding-right: 20px;
}
.name-score {
width: 20%;
text-align: center;
margin-left: 5px;
margin-right: 5px;
/* line-height: 33px; */
}
.score-text {
font-size: large;
font-weight: bold;
}
.name-text {
font-size: small;
color: grey;
text-align: center;
}
.realname-text {
font-size: large;
font-weight: bold;
width: 72px;
text-align: center;
}
.winrate-text {
font-family: 'Times New Roman';
width: 40px;
text-align: center;
}
.games-text {
font-family: 'Times New Roman';
text-align: center;
}
.point-text {
font-family: 'Times New Roman';
text-align: center;
}
.group-text {
font-family: 'Times New Roman';
text-align: center;
}
.my-realname-text {
font-size: large;
font-weight: bold;
text-align: center;
}
.game-date-text {
width: 60px;
font-size: small;
color: grey;
text-align: center;
padding-left: 7px;
padding-right: 7px;
}
.zhibiao3 {
width: 20%;
text-align: center;
/* line-height: 33px; */
}
.zhibiao4 {
width: 20%;
width: 15%;
/* line-height: 33px; */
/* text-align: center; */
}
.zhibiao5 {
width: 75px;
/* line-height: 33px; */
/* text-align: center; */
}
.img2 {
object-fit: cover;
width: 100%;
height: 100%;
}
</style>
\ No newline at end of file
......@@ -66,6 +66,15 @@ const isValid = ref(false);
const realname1 = ref(false);
const loading = ref(false);
const cardtitle = ref(null);
const cardtext = ref(null);
const dialog = ref(false);
function info(title, text) {
cardtitle.value = title;
cardtext.value = text;
dialog.value = true;
}
function login() {
loading.value = true;
axios.post('/api/login', {
......@@ -77,9 +86,9 @@ function login() {
// console.log(data.is_member);
// console.log(data.is_member == 0);
if (data.status == 'SUCCESS') {
if (data.status === 'SUCCESS') {
if (data.is_su) {
// window.location.href = '/main.html';
window.location.href = '/main.html';
// console.log("su");
}
else if (data.is_member) {
......@@ -89,10 +98,16 @@ function login() {
else if (!data.is_member) {
// console.log("not member");
// console.log(realname1);
window.location.href = '/main.html';
// window.location.href = '/main.html';
realname1.value = true;
}
}
else if(data.status === 'USER_NOT_EXIST'){
info('用户不存在!');
}
else if(data.status === 'AUTHENTICATION_FAILED'){
info('密码错误!');
}
})
.catch(function (error) {
console.log(error);
......@@ -114,13 +129,4 @@ function submit() {
loading.value = false;
}
const cardtitle = ref(null);
const cardtext = ref(null);
const dialog = ref(false);
function info(title, text) {
cardtitle.value = title;
cardtext.value = text;
dialog.value = true;
}
</script>
\ No newline at end of file
<template>
<v-card
class="ma-6"
>
<v-list density="comfortable">
<v-list-subheader>快捷审核</v-list-subheader>
<v-list-item
color="primary"
href="/user_audit.html"
height="60px"
appendIcon = "mdi-chevron-right"
>
<v-list-item-title class="text-h6">用户入会审核</v-list-item-title>
</v-list-item>
<v-list-item
color="primary"
href="/player_audit.html"
height="60px"
appendIcon = "mdi-chevron-right"
>
<v-list-item-title class="text-h6">球员加入赛季审核</v-list-item-title>
</v-list-item>
<v-divider></v-divider>
<v-list-subheader>赛季管理</v-list-subheader>
<v-list-item
color="primary"
href="/season_manage.html"
height="60px"
appendIcon = "mdi-chevron-right"
>
<v-list-item-title class="text-h6">开启/关闭赛季</v-list-item-title>
</v-list-item>
<v-list-item
color="primary"
href="/player_manage.html"
height="60px"
appendIcon = "mdi-chevron-right"
>
<v-list-item-title class="text-h6">球员信息维护</v-list-item-title>
</v-list-item>
<v-divider></v-divider>
<v-list-subheader>基础数据维护</v-list-subheader>
<v-list-item
color="primary"
href="/user_manage.html"
height="60px"
appendIcon = "mdi-chevron-right"
>
<v-list-item-title class="text-h6">用户管理</v-list-item-title>
</v-list-item>
<v-list-item
color="primary"
href="/game_manage.html"
height="60px"
appendIcon = "mdi-chevron-right"
>
<v-list-item-title class="text-h6">比赛管理</v-list-item-title>
</v-list-item>
</v-list>
</v-card>
<!-- <div class="text-h4 headline">
快捷审核
</div>
<v-card class="mx-auto my-2" href="/user_audit.html" width="95%" rel="noopener" target="_blank" title="用户入会审核"
append-icon="mdi-chevron-right"></v-card>
<v-card class="mx-auto my-2" href="/player_audit.html" width="95%" rel="noopener" target="_blank" title="球员加入赛季审核"
append-icon="mdi-chevron-right"></v-card>
<div class="text-h4 headline">
赛季管理
</div>
<v-card class="mx-auto my-2" href="/season_manage.html" width="95%" rel="noopener" target="_blank" title="开启/关闭赛季"
append-icon="mdi-chevron-right"></v-card>
<v-card class="mx-auto my-2" href="/player_manage.html" width="95%" rel="noopener" target="_blank" title="球员信息维护"
append-icon="mdi-chevron-right"></v-card>
<div class="text-h4 headline">
基础数据维护
</div>
<v-card class="mx-auto my-2" href="/user_manage.html" width="95%" rel="noopener" target="_blank" title="用户管理"
append-icon="mdi-chevron-right"></v-card>
<v-card class="mx-auto my-2" href="/game_manage.html" width="95%" rel="noopener" target="_blank" title="比赛管理"
append-icon="mdi-chevron-right"></v-card> -->
</template>
<style>
.title-size {
margin-left: 5%;
margin-top: 10%;
margin-bottom: 2%;
}
</style>
\ No newline at end of file
<template>
<div class="background" @click="dialog2 = true">
<div class="background">
<img v-if="pre_background_image" :src="pre_background_image" class="img1" alt="上传背景图">
<div v-if="!pre_background_image">点击头像处上传背景图</div>
<!-- <v-overlay activator="parent" /> -->
......@@ -7,7 +7,7 @@
<!-- <v-overlay activator=".img1" /> -->
<!-- <v-container class="relative"> -->
<div class="yuanjiao">
<div class="relative">
<div class="d-flex justify-start align-stretch relative ">
<!-- 头像 -->
<v-menu rounded>
<template v-slot:activator="{ props }">
......@@ -18,7 +18,7 @@
</v-avatar>
</v-btn>
</template>
<v-card>
<v-card v-if="players_id === 0">
<v-card-text>
<div class="mx-auto text-center">
<v-avatar size="50px">
......@@ -44,56 +44,77 @@
</v-card-text>
</v-card>
</v-menu>
<div class="float-left">
<div class="text-h6 user float-left">
<div class="flex-1-0">
<div class="d-flex justify-start align-center user-info-box">
<div class="text-h6 user">
{{ username }}
</div>
<div class="text-subtitle-1 user float-left" style="color:red;">
<!-- <div class="text-subtitle-1 user float-left" style="color:red;">
{{ level }}级
</div>
<div class="text-subtitle-1 user float-left">
</div> -->
<div class="text-subtitle-1 user">
{{ group }}组
</div>
<div class="text-subtitle-1 user">
{{ total_game }}场
</div>
</div>
<div class="float-left">
<div class="text-subtitle-1 user1 float-left">
<div class="d-flex justify-start align-center">
<div class="text-subtitle-1 user1">
积分:{{ score }}
</div>
<div class="text-subtitle-1 user1 float-left">
<div class="text-subtitle-1 user1">
胜率:{{ winrate }}%
</div>
</div>
</div>
<div class="relative2">
<h class="text-h6">最近比赛</h>
<h class="text-h6 float-right">更多</h>
<v-divider thickness="3px"></v-divider>
<v-card class="card1">
<div class="text-subtitle-1" style="height: 33px;" v-for="(item, index) in items" :key="index">
<div class="float-left">
{{ item.date }}
</div>
<div class="float-left zhibiao1" style="width: 20%;">
{{ item.homeTeam }}
<div class="game-relative" v-if="exist_season">
<v-card class="game-card" elevation="5">
<template v-slot:prepend>
<v-icon size="25px">mdi-trophy</v-icon>
</template>
<template v-slot:title>
<div class="text-h6">最近比赛</div>
</template>
<v-list>
<v-list-item v-for="(item, index) in items" :key="index" :value="item" @click="myGameDeail(item.id)">
<template v-slot:default>
<div class="d-flex justify-space-between align-center game-card-item">
<div>
<v-avatar size="48px"><img :src="item.homeTeam_avatar" class="img2"></v-avatar>
</div>
<div class="float-left zhibiao2">
{{ item.homeScore }}
<div class="game-name-score">
<div class="game-score-text">{{ item.homeScore }}</div>
<div class="game-name-text">{{ item.homeTeam }}</div>
</div>
<div class="float-left">
<div>
:
</div>
<div class="float-left zhibiao2">
{{ item.awayScore }}
<div class="game-name-score">
<div class="game-score-text">{{ item.awayScore }}</div>
<div class="game-name-text">{{ item.awayTeam }}</div>
</div>
<div class="float-left zhibiao1" style="width: 20%;">
{{ item.awayTeam }}
<div>
<v-avatar size="48px"><img :src="item.awayTeam_avatar" class="img2"></v-avatar>
</div>
<div class="float-right">
<v-icon>mdi-chevron-right</v-icon>
<div>
<!-- <div>{{ item.year }}</div> -->
<div class="game-date-text">{{ item.date }}</div>
</div>
<br>
<!-- <v-divider :thickness="2"></v-divider> -->
<v-icon>mdi-chevron-right</v-icon>
</div>
</template>
</v-list-item>
</v-list>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="indigo" variant="text" @click="button1" text="更多"></v-btn>
</v-card-actions>
</v-card>
</div>
</div>
......@@ -104,13 +125,13 @@
头像上传
</v-card-text>
<v-card-text>
<v-file-input accept="image/*" id="avatarInput" label="上传头像" prepend-icon="mdi-camera"
<v-file-input show-size accept="image/*" id="avatarInput" label="上传头像" prepend-icon="mdi-camera"
variant="solo"></v-file-input>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="indigo" text="取消" @click="dialog1 = false"></v-btn>
<v-btn color="indigo" text="确认上传" @click="setAvatar"></v-btn>
<v-btn color="indigo" text="上传" :loading="avatarLoading" @click="setAvatar"></v-btn>
</v-card-actions>
</v-card>
</v-dialog>
......@@ -126,8 +147,8 @@
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="indigo" text="取消" @click="dialog1 = false"></v-btn>
<v-btn color="indigo" text="上传" @click="setBackground"></v-btn>
<v-btn color="indigo" text="取消" @click="dialog2 = false"></v-btn>
<v-btn color="indigo" text="上传" :loading="backgroundLoading" @click="setBackground"></v-btn>
</v-card-actions>
</v-card>
</v-dialog>
......@@ -148,7 +169,7 @@
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="indigo" text="取消" @click="dialog3 = false"></v-btn>
<v-btn color="indigo" text="修改" @click="setUserinform"></v-btn>
<v-btn color="indigo" text="修改" :loading="informLoading" @click="setUserinform"></v-btn>
</v-card-actions>
</v-card>
</v-dialog>
......@@ -166,7 +187,58 @@
</template>
</v-card>
</v-dialog>
<!-- </v-container> -->
<v-dialog v-model="mygame_dialog" width="auto">
<v-card width="300px">
<template v-slot:prepend>
<v-icon size="25px">mdi-trophy</v-icon>
</template>
<template v-slot:title>
<div class="text-h6">比赛详情</div>
</template>
<template v-slot:subtitle>
<div>{{ mygame_detail.game_date }}</div>
</template>
<template v-slot:default>
<div class="d-flex justify-space-between align-center gameDetail-item">
<div>
<v-avatar size="48px"><img :src="mygame_detail.player1_profile_file" class="img2"></v-avatar>
</div>
<div class="game-name-score">
<div class="game-score-text">{{ mygame_detail.score1 }}</div>
<div class="game-name-text">{{ mygame_detail.player1_real_name }}</div>
</div>
<div>
:
</div>
<div class="game-name-score">
<div class="game-score-text">{{ mygame_detail.score2 }}</div>
<div class="game-name-text">{{ mygame_detail.player2_real_name }}</div>
</div>
<div>
<v-avatar size="48px"><img :src="mygame_detail.player2_profile_file" class="img2"></v-avatar>
</div>
</div>
<div class="d-flex justify-space-between align-center gameDetail-item">
<div class="game-name-score">
<div class="text-h6">发起:</div>
</div>
<div>{{ mygame_detail.laucher_real_name }}</div>
<div class="game-name-text">{{ mygame_detail.lauch_date }}</div>
</div>
<div class="d-flex justify-space-between align-center gameDetail-item">
<div class="game-name-score">
<div class="text-h6">审核:</div>
</div>
<div>{{ mygame_detail.confirmer_real_name }}</div>
<div class="game-name-text">{{ mygame_detail.confirm_date }}</div>
</div>
</template>
<template v-slot:actions>
<v-btn class="ms-auto" variant="text" color="indigo" text="确定" @click="mygame_dialog = false"></v-btn>
</template>
</v-card>
</v-dialog>
</template>
<script setup>
......@@ -181,7 +253,7 @@ const username = ref('XXX');
const username1 = ref(null);
const score = ref(0);
const group = ref(null);
const level = ref("A");
//const level = ref("A");
const items = ref(new Array());
const dialog = ref(false);
const dialog1 = ref(false);
......@@ -190,6 +262,7 @@ const dialog3 = ref(false);
const pre_avatar_image = ref('');
const pre_background_image = ref('');
var my_id = 0;
const total_game = ref(0);
const winrate = ref(null);
const cardtitle = ref(null);
const cardtext = ref(null);
......@@ -204,12 +277,56 @@ const rules = reactive({
username: v => !!v || '姓名不能为空',
confirmpassword: v => v === password.value || '密码不匹配',
});
const mygame_detail = ref({
game_date: "",
player1_real_name: "",
player1_profile_file: "",
score1: 0,
player2_real_name: "",
player2_profile_file: "",
score2: 0,
laucher_real_name: "",
laucher_profile_file: "",
lauch_date: "",
confirmer_real_name: "",
confirmer_profile_file: "",
confirm_date: "",
game_type: 0,
});
const mygame_dialog = ref(false);
const exist_season = ref(false);
const avatarLoading = ref(false);
const backgroundLoading = ref(false);
const informLoading = ref(false);
var my_idstr = window.location.search;
var players_id = 0;
if (my_idstr) {
players_id = extractNumbers(my_idstr)[0];
}
function extractNumbers(str) {
const pattern = /\d+/g;
const matches = str.match(pattern);
return matches ? matches.map(Number) : [];
}
axios.get('/api/currentUser',)
function formatDate(date) {
var d = new Date(date),
month = '0' + (d.getMonth() + 1),
day = '' + d.getDate();
// year = d.getFullYear();
return [month + '/' + day].join(''); // 返回形如 MM/DD 的字符串
}
function refresh() {
axios.get('/api/currentUser',)
.then(function (response) {
const data1 = response.data;
if (data1.status === "SUCCESS") {
my_id = data1.user_id;
if (players_id === my_id || players_id === 0) {
username.value = data1.username;
pre_avatar_image.value = data1.profile_file;
pre_background_image.value = data1.background_file;
......@@ -220,43 +337,135 @@ axios.get('/api/currentUser',)
})
.then(function (response) {
const data4 = response.data;
exist_season.value = data4.ExistSeason;
if (data4.status === "SUCCESS") {
total_game.value = data4.Players[0].total_games;
score.value = data4.Players[0].score;
group.value = data4.Players[0].group;
winrate.value = data4.Players[0].winrate;
if (group.value == 1) {
group.value = 'A';
}
else if (group.value == 2) {
group.value = 'B';
}
else if (group.value == 3) {
group.value = 'C';
}
}
})
.catch(function (error) {
console.log(error);
})
axios.get('/api/games', {
params: {
myid: my_id,
}
})
.then(function (response) {
const data2 = response.data;
var length1 = 5;
if (length1 > data2.Games.length) {
length1 = data2.Games.length
}
items.value.length = 0;
for (var i = 0; i < length1; i++) {
var item = {
id: data2.Games[i].id,
date: formatDate(data2.Games[i].game_date),
homeTeam: data2.Games[i].player1_real_name,
awayTeam: data2.Games[i].player2_real_name,
homeScore: data2.Games[i].score1,
awayScore: data2.Games[i].score2,
homeTeam_avatar: data2.Games[i].player1_profile_file,
awayTeam_avatar: data2.Games[i].player2_profile_file,
}
items.value[i] = item;
}
})
.catch(function (error) {
console.log(error);
})
axios.get('/api/games',)
}
else if (players_id !== my_id) {
axios.get('/api/players', {
params: {
player_id: players_id
}
})
.then(function (response) {
const data4 = response.data;
exist_season.value = data4.ExistSeason;
if (data4.status === "SUCCESS") {
total_game.value = data4.Players[0].total_games;
username.value = data4.Players[0].player_real_name;
pre_avatar_image.value = data4.Players[0].player_profile_file;
pre_background_image.value = data4.Players[0].player_background_file;
score.value = data4.Players[0].score;
group.value = data4.Players[0].group;
winrate.value = data4.Players[0].winrate;
if (group.value == 1) {
group.value = 'A';
}
else if (group.value == 2) {
group.value = 'B';
}
else if (group.value == 3) {
group.value = 'C';
}
}
})
.catch(function (error) {
console.log(error);
})
axios.get('/api/games', {
params: {
myid: players_id,
}
})
.then(function (response) {
const data2 = response.data;
let j = 0;
for (var i = 0; i < data2.Games.length; i++) {
if (data2.Games[i].player1_id === my_id || data2.Games[i].player2_id === my_id) {
var length1 = 5;
if (length1 > data2.Games.length) {
length1 = data2.Games.length
}
items.value.length = 0;
for (var i = 0; i < length1; i++) {
var item = {
id: data2.Games[i].id,
date: data2.Games[i].game_date,
date: formatDate(data2.Games[i].game_date),
homeTeam: data2.Games[i].player1_real_name,
awayTeam: data2.Games[i].player2_real_name,
homeScore: data2.Games[i].score1,
awayScore: data2.Games[i].score2,
homeTeam_avatar: data2.Games[i].player1_profile_file,
awayTeam_avatar: data2.Games[i].player2_profile_file,
}
items.value[j] = item;
j++;
items.value[i] = item;
}
})
.catch(function (error) {
console.log(error);
})
}
}
})
.catch(function (error) {
console.log(error);
})
}
refresh();
function button1() {
if (players_id !== 0) {
window.location.href = '/my_recentgames.html?myid=' + players_id;
}
else {
window.location.href = '/my_recentgames.html?myid=' + my_id;
}
}
function info(title, text) {
cardtitle.value = title;
......@@ -265,7 +474,7 @@ function info(title, text) {
}
function setUserinform() {
// loading.value = true;
informLoading.value = true;
var user = { user_name: username1.value, user_password: password.value }
if (user.user_name !== null || user.user_password !== null) {
axios.post('/api/setUserinform',
......@@ -275,6 +484,7 @@ function setUserinform() {
const data = response.data;
if (data.status == 'SUCCESS') {
info('修改成功!', "");
username.value = user.user_name;
}
else if (data.status == 'FAILED') {
info('用户名已存在!', "");
......@@ -288,10 +498,11 @@ function setUserinform() {
username1.value = null;
password.value = null;
confirmpassword.value = null;
// loading.value = false;
informLoading.value = false;
}
function setAvatar() {
avatarLoading.value = true;
const fileInput = document.querySelector('#avatarInput');
const file = fileInput.files[0];
......@@ -304,15 +515,21 @@ function setAvatar() {
'Content-Type': 'multipart/form-data'
}
}).then(response => {
info("上传成功", "");
refresh();
console.log('上传成功', response.data);
pre_avatar_image.value = response.data.new_avatar_path;
}).catch(error => {
info("头像需小于10MB", "");
console.error('上传失败', error);
});
avatarLoading.value = false;
dialog1.value = false;
}
function setBackground() {
backgroundLoading.value = true;
const background_fileInput = document.querySelector('#backgroundInput');
const background_file = background_fileInput.files[0];
......@@ -328,9 +545,43 @@ function setBackground() {
console.log('上传成功', response.data);
pre_background_image.value = response.data.new_background_path;
}).catch(error => {
info("背景需小于10MB", "");
console.error('上传失败', error);
});
backgroundLoading.value = false;
dialog2.value = false;
refresh();
}
function myGameDeail(my_gameid) {
axios.get('/api/gameDetail', {
params: {
game_id: my_gameid,
}
})
.then(function (response) {
const data6 = response.data;
if (data6.status === "SUCCESS") {
mygame_detail.value.game_date = data6.game_date;
mygame_detail.value.confirmer_profile_file = data6.confirmer_profile_file;
mygame_detail.value.confirmer_real_name = data6.confirmer_real_name;
mygame_detail.value.laucher_profile_file = data6.laucher_profile_file;
mygame_detail.value.laucher_real_name = data6.laucher_real_name;
mygame_detail.value.player1_profile_file = data6.player1_profile_file;
mygame_detail.value.player1_real_name = data6.player1_real_name;
mygame_detail.value.player2_profile_file = data6.player2_profile_file;
mygame_detail.value.player2_real_name = data6.player2_real_name;
mygame_detail.value.score1 = data6.score1;
mygame_detail.value.score2 = data6.score2;
mygame_detail.value.game_type = data6.game_type;
mygame_detail.value.confirm_date = data6.confirm_date;
mygame_detail.value.lauch_date = data6.lauch_date;
}
})
.then(mygame_dialog.value = true)
.catch(function (error) {
console.log(error);
})
}
</script>
......@@ -341,14 +592,14 @@ function setBackground() {
width: 100%;
height: 100px;
position: relative;
z-index: -1;
z-index: 1;
}
.img1 {
object-fit: cover;
width: 100%;
height: 100%;
z-index: -1;
z-index: 1;
}
.yuanjiao {
......@@ -357,7 +608,7 @@ function setBackground() {
position: relative;
top: -6px;
z-index: 10;
background-color: white;
background-color: #F9F9F9;
}
.img2 {
......@@ -366,6 +617,14 @@ function setBackground() {
height: 100%;
}
.game-relative {
position: relative;
top: -22px;
width: 95%;
margin: auto;
margin-top: 10px;
}
.relative {
position: relative;
top: -22px;
......@@ -376,16 +635,20 @@ function setBackground() {
.user {
position: relative;
top: 22px;
height: 32px;
margin-left: 20px;
line-height: 32px;
font-family: "Times New Roman", "宋体";
}
.user-info-box {
margin-top: 22px;
}
.user1 {
position: relative;
top: 22px;
margin-left: 20px;
line-height: 22px;
font-family: "Times New Roman", "宋体";
......@@ -408,10 +671,51 @@ function setBackground() {
margin-right: 20px;
}
.card1 {
.game-card {
margin-top: 4px;
}
.game-card-item {
height: 70px;
width: 100%;
/* padding: 20px; */
}
.game-name-score {
width: 20%;
text-align: center;
margin-left: 5px;
margin-right: 5px;
/* line-height: 33px; */
}
.game-score-text {
font-size: large;
font-weight: bold;
}
.game-name-text {
font-size: small;
color: grey;
text-align: center;
}
.gameDetail-item {
height: 70px;
width: 100%;
padding-left: 20px;
padding-right: 20px;
}
.game-date-text {
width: 60px;
font-size: small;
color: grey;
text-align: center;
padding-left: 7px;
padding-right: 7px;
}
.zhibiao1 {
text-align: center;
}
......
......@@ -8,7 +8,7 @@
import { registerPlugins } from '@/plugins'
// Components
import App from './home.vue'
import App from './game_manage.vue'
// Composables
import { createApp } from 'vue'
......
<template>
<v-app>
<v-data-table-server :headers="headers" v-model:items-per-page="itemsPerPage" :items="games" item-key="id"
:search="search" :items-length="totalGames" @update:options="loadGames" :loading="loading">
<template v-slot:top>
<v-toolbar flat>
<v-toolbar-title>比赛管理</v-toolbar-title>
<v-divider class="mx-3" inset vertical></v-divider>
<v-spacer></v-spacer>
<v-text-field v-model="search" append-icon="mdi-magnify" label="搜索" single-line
hide-details></v-text-field>
</v-toolbar>
</template>
<template v-slot:item.game_id="{ item }">
<p v-if="item.game_id" style="width:50px">{{ item.game_id }}</p>
</template>
<template v-slot:item.season_name="{ item }">
<p v-if="item.season_name" style="width:50px">{{ item.season_name }}</p>
</template>
<template v-slot:item.game_date="{ item }">
<p v-if="item.game_date" style="width:50px">{{ item.game_date }}</p>
</template>
<template v-slot:item.player1_real_name="{ item }">
<p v-if="item.player1_real_name" style="width:50px">{{ item.player1_real_name }}</p>
</template>
<template v-slot:item.score1="{ item }">
<p style="width:50px">{{ item.score1 }}</p>
</template>
<template v-slot:item.player2_real_name="{ item }">
<p v-if="item.player2_real_name" style="width:50px">{{ item.player2_real_name }}</p>
</template>
<template v-slot:item.score2="{ item }">
<p style="width:50px">{{ item.score2 }}</p>
</template>
<template v-slot:item.actions="{ item }">
<v-icon @click="editGame(item)" style="width:50px">mdi-pencil</v-icon>
</template>
</v-data-table-server>
</v-app>
<v-dialog v-model="dialog" width="auto">
<v-card width="300px">
<v-card-title>
{{ selectGame.season_name }}赛季
</v-card-title>
<v-card-text>
<v-form ref="form" v-model="isValid">
<v-row no-gutters>
<v-col>
<v-autocomplete variant="underlined" v-model="player1" label="姓名"
:rules="[rules.player_not_none, rules.player1]" :items="arr"></v-autocomplete>
</v-col>
<v-col cols="2" align-self="center">
<div style="text-align: center;">VS</div>
</v-col>
<v-col>
<v-autocomplete variant="underlined" v-model="player2" label="姓名"
:rules="[rules.player_not_none, rules.player2]" :items="arr"></v-autocomplete>
</v-col>
</v-row>
<v-row no-gutters>
<v-col align-self="center">
<v-select variant="underlined" v-model="score1" label="得分"
:rules="[rules.score_not_none, rules.score1]"
:items="['0', '1', '2', '3', '4', '5']"></v-select>
</v-col>
<v-col cols="2" align-self="center">
<div class="text-h6" style="text-align: center;">:</div>
</v-col>
<v-col align-self="center">
<v-select variant="underlined" v-model="score2" label="得分"
:rules="[rules.score_not_none, rules.score2]"
:items="['0', '1', '2', '3', '4', '5']"></v-select>
</v-col>
</v-row>
<v-btn block @click="date_dialog = true" class="text-none mb-4" color="indigo" size="large"
variant="outlined">
<template v-slot:default>
选择比赛日期:{{ selectedDate.toLocaleDateString() }}
</template>
</v-btn>
</v-form>
</v-card-text>
<template v-slot:actions>
<v-btn :disabled="!isValid" :loading="gameLoading" class="ms-auto" variant="flat" color="indigo" text="确定"
@click="changeGame"></v-btn>
</template>
</v-card>
</v-dialog>
<v-dialog v-model="date_dialog" width="auto">
<v-card>
<v-locale-provider locale="zhHans">
<v-date-picker v-model="selectedDate" header="日期" title="选择比赛日期" color="indigo"
width="100%"></v-date-picker>
</v-locale-provider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn variant="flat" text="确定" color="indigo" @click="date_dialog = false"></v-btn>
</v-card-actions>
</v-card>
</v-dialog>
<v-dialog v-model="dialog1" width="auto">
<v-card width="300px">
<v-card-title>
{{ cardtitle }}
</v-card-title>
<v-card-text>
{{ cardtext }}
</v-card-text>
<template v-slot:actions>
<v-btn class="ms-auto" variant="flat" color="indigo" text="确认" @click="dialog = false"></v-btn>
</template>
</v-card>
</v-dialog>
</template>
<script setup>
import { ref } from 'vue';
import { reactive } from 'vue';
// import { computed } from 'vue';
import axios from 'axios';
import { watch } from 'vue';
const search = ref('');
// const actions_text = ref('');
const headers = reactive([
{ title: 'ID', key: 'game_id' },
{ title: '赛季', key: 'season_name' },
{ title: '日期', key: 'game_date' },
{ title: '球员1', key: 'player1_real_name' },
{ title: '得分', key: 'score1' },
{ title: '球员2', key: 'player2_real_name' },
{ title: '得分', key: 'score2' },
{ title: '编辑', key: 'actions' },
]);
const rules = reactive({
email: v => !!(v || '').match(/@/) || 'Please enter a valid email',
length: len => v => (v || '').length >= len || `Invalid character length, required ${len}`,
usrname: v => !!v || '用户名不能为空',
realname: v => !!v || '姓名不能为空',
password: v => !!v || '密码不能为空',
su: v => !!v || '管理员不能为空',
member: v => !!v || '会员不能为空',
player_not_none: v => !!v || '姓名不能为空',
player1: v => v != player2.value || '姓名不能相同',
player2: v => v != player1.value || '姓名不能相同',
score_not_none: v => !!v || '得分不能为空',
score1: v => v != score2.value || '得分不能相同',
score2: v => v != score1.value || '得分不能相同',
// password: v => !!(v || '').match(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*(_|[^\w])).+$/) ||
// 'Password must contain an upper case letter, a numeric character, and a special character',
required: v => !!v || 'This field is required',
});
const isValid = ref(false);
const itemsPerPage = ref(5);
const totalGames = ref(0);
const loading = ref(true);
const gameLoading = ref(false);
const form = ref(null);
const player1 = ref(null);
const player2 = ref(null);
const score1 = ref(null);
const score2 = ref(null);
const arr = ref(new Array());
const date_dialog = ref(false);
const games = ref(new Array());
const selectedDate = ref(new Date());
const dialog = ref(false);
const selectGame = ref({
game_id: 0,
game_date: '',
player1_id: 0,
player1_real_name: '',
score1: 0,
player2_id: 0,
player2_real_name: '',
score2: 0,
season_name: '',
});
const cardtitle = ref(null);
const cardtext = ref(null);
const dialog1 = ref(false);
function info(title, text) {
cardtitle.value = title;
cardtext.value = text;
dialog1.value = true;
}
function loadGames({ page, itemsPerPage }) {
axios.get('/api/getGames',{
params:{
pages: page,
lim: itemsPerPage,
}
})
.then(function (response) {
loading.value =true;
const data = response.data;
games.value.length = 0;
totalGames.value = data.totalGames;
for (var i = 0; i < data.Games.length; i++) {
var game = {
game_id: data.Games[i].game_id,
season_name: data.Games[i].season_name,
game_date: data.Games[i].game_date,
player1_id: data.Games[i].player1_id,
player1_real_name: data.Games[i].player1_real_name,
score1: data.Games[i].score1,
player2_id: data.Games[i].player2_id,
player2_real_name: data.Games[i].player2_real_name,
score2: data.Games[i].score2,
}
games.value[i] = game;
}
loading.value =false;
})
.catch(function (error) {
console.log(error);
})
}
// refresh();
// 监听 player1 的变化,并更新 player2 的验证规则
watch(player1, (newVal, oldVal) => {
if (newVal !== oldVal) {
form.value.validate(); // 触发表单验证
}
});
watch(player2, (newVal, oldVal) => {
if (newVal !== oldVal) {
form.value.validate(); // 触发表单验证
}
});
watch(score1, (newVal, oldVal) => {
if (newVal !== oldVal) {
form.value.validate(); // 触发表单验证
}
});
watch(score2, (newVal, oldVal) => {
if (newVal !== oldVal) {
form.value.validate(); // 触发表单验证
}
});
function editGame(item) {
dialog.value = true;
selectGame.value = item;
selectedDate.value = new Date(selectGame.value.game_date);
player1.value = selectGame.value.player1_id + '-' + selectGame.value.player1_real_name;
player2.value = selectGame.value.player2_id + '-' + selectGame.value.player2_real_name;
score1.value = String(selectGame.value.score1);
score2.value = String(selectGame.value.score2);
axios.get('/api/players')
.then(function (response) {
const data2 = response.data;
for (var i = 0; i < data2.Players.length; i++) {
arr.value[i] = data2.Players[i].player_id.toString() + '-' + data2.Players[i].player_real_name;
}
})
.catch(function (error) {
console.log(error);
})
}
function changeGame() {
gameLoading.value = true;
selectGame.value.player1_id = parseInt(player1.value);
selectGame.value.player2_id = parseInt(player2.value);
selectGame.value.score1 = parseInt(score1.value);
selectGame.value.score2 = parseInt(score2.value);
selectGame.value.game_date = selectedDate.value.toLocaleDateString();
axios.post('/api/gameManage', selectGame.value)
.then(function (response) {
const data1 = response.data;
if (data1.status === "FAILED") {
info("修改失败!", "");
}
dialog.value = false;
refresh();
})
gameLoading.value = false;
}
</script>
\ No newline at end of file
<!-- <script setup>
import Dialog from './components/dialog.vue';
import { ref } from 'vue';
const count = ref(0)
const info = ref(0)
function testclick() {
count.value++
info.value=count.value
}
</script>
<template>
<v-app>
<v-main>
<Dialog class="dialog" ></Dialog>
<v-btn @click="testclick">
</v-btn>
<div>{{ info }}</div>
</v-main>
</v-app>
</template>
-->
<script setup>
// import { ref } from 'vue';
// const tab = ref(null)
// const text = ref('Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.')
// export default {
// data () {
// return {
// tab: null,
// text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.',
// }
// },
// }
</script>
<template>
<!-- <div>发起比赛</div> -->
</template>
<style>
.main-card{
height: 100%;
width: 100%;
}
.tabs{
width: 100%;
position: fixed;
bottom: 0;
}
</style>
\ No newline at end of file
<!-- <script setup>
import Dialog from './components/dialog.vue';
import { ref } from 'vue';
const count = ref(0)
const info = ref(0)
function testclick() {
count.value++
info.value=count.value
}
</script>
<template>
<v-app>
<v-main>
<Dialog class="dialog" ></Dialog>
<v-btn @click="testclick">
</v-btn>
<div>{{ info }}</div>
</v-main>
</v-app>
</template>
-->
<script setup>
// import { ref } from 'vue';
// const tab = ref(null)
// const text = ref('Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.')
// export default {
// data () {
// return {
// tab: null,
// text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.',
// }
// },
// }
</script>
<template>
<!-- <div>首页</div> -->
</template>
<style>
.main-card{
height: 100%;
width: 100%;
}
.tabs{
width: 100%;
position: fixed;
bottom: 0;
}
</style>
\ No newline at end of file
<template>
<v-app>
<v-data-table :headers="headers" :items="filteredMatches" item-key="id" :search="search.value"
:items-per-page="10">
<v-data-table-server :headers="headers" :items="filteredMatches" item-key="id" :search="search"
v-model:items-per-page="itemsPerPage" @update:options="loadGames" :items-length="totalGames"
:loading="loading">
<template v-slot:top>
<v-toolbar flat>
<v-toolbar-title>比赛</v-toolbar-title>
......@@ -12,7 +13,7 @@
</v-toolbar>
</template>
<template v-slot:item.date="{ item }">
<p style="width:60px" >{{ item.date }}</p>
<p style="width:60px">{{ item.date }}</p>
</template>
<template v-slot:item.name="{ item }">
<p style="width:120px">{{ item.username }} VS {{ item.opponentname }}</p>
......@@ -23,9 +24,10 @@
<template v-slot:item.verified="{ item }">
<div style="width:80px"><v-icon v-if="item.verified === 'WAITING'" color="blue">mdi-help-circle</v-icon>
<v-icon v-else-if="item.verified === 'PASSED'" color="green">mdi-check-circle</v-icon>
<v-icon v-else-if="item.verified === 'REJECT'" color="red">mdi-close-circle</v-icon></div>
<v-icon v-else-if="item.verified === 'REJECT'" color="red">mdi-close-circle</v-icon>
</div>
</template>
</v-data-table>
</v-data-table-server>
</v-app>
</template>
......@@ -44,6 +46,9 @@ const headers = reactive([
{ title: '审核状态', key: 'verified' },
]);
const matches = ref(new Array());
const loading = ref(true);
const totalGames = ref(0);
const itemsPerPage = ref(5);
// matches = [
// { id: 1, username: '张三', opponentname: '零', userScore: 3, opponentScore: 2, verified: "PASSED" },
// ];
......@@ -58,24 +63,37 @@ const filteredMatches = computed(() => {
);
})
axios.get('/api/myLauchedGames',)
.then(function(response){
function loadGames({ page, itemsPerPage }) {
axios.get('/api/myLauchedGames',{
params:{
pages: page,
lim: itemsPerPage,
}
})
.then(function (response) {
loading.value = true;
const data = response.data;
for(var i = 0; i < data.Games.length; i++){
totalGames.value = data.totalGames;
matches.value.length = 0;
for (var i = 0; i < data.Games.length; i++) {
// matches.value[i].id = i+1;
var match = {
id:data.Games[i].id,
date:data.Games[i].game_date,
username:data.Games[i].player1_real_name,
opponentname:data.Games[i].player2_real_name,
userScore:data.Games[i].score1,
opponentScore:data.Games[i].score2,
verified:data.Games[i].status,
id: data.Games[i].id,
date: data.Games[i].game_date,
username: data.Games[i].player1_real_name,
opponentname: data.Games[i].player2_real_name,
userScore: data.Games[i].score1,
opponentScore: data.Games[i].score2,
verified: data.Games[i].status,
}
matches.value[i] = match;
}
loading.value = false;
})
.catch(function (error) {
console.log(error);
})
}
</script>
\ No newline at end of file
<template>
<div class="h-screen w-auto">
<v-window v-model="tab" class="h-screen w-auto bottom-navigation">
<div class="w-auto">
<v-window v-model="tab" class="h-screen w-auto">
<v-window-item :key="1" :value="'tab-1'" class="h-screen w-100 bottom-navigation">
<Home></Home>
</v-window-item>
......@@ -10,17 +10,23 @@
<v-window-item :key="3" :value="'tab-3'" class="h-screen w-100 bottom-navigation">
<Space></Space>
</v-window-item>
<v-window-item :key="4" :value="'tab-4'" class="h-screen w-100 bottom-navigation">
<Manage></Manage>
</v-window-item>
</v-window>
<v-layout class="overflow-visible" style="height: 56px;">
<v-layout class="tabs">
<v-bottom-navigation v-model="tab" color="indigo" align-tabs="center" stacked grow class="tabs">
<v-bottom-navigation v-model="tab" color="indigo" align-tabs="center" stacked grow>
<v-btn value="tab-1">
<v-icon>mdi-home</v-icon>
首页
</v-btn>
<v-btn value="tab-2">
<v-badge color="error" dot v-if="unaudit_number !== 0">
<v-icon>mdi-table-tennis</v-icon>
</v-badge>
<v-icon v-if="unaudit_number === 0">mdi-table-tennis</v-icon>
比赛
</v-btn>
......@@ -28,6 +34,11 @@
<v-icon>mdi-account</v-icon>
我的
</v-btn>
<v-btn v-if="is_su" value="tab-4">
<v-icon>mdi-account-cog</v-icon>
管理
</v-btn>
</v-bottom-navigation>
</v-layout>
......@@ -39,8 +50,31 @@ import { ref } from 'vue';
import Gamemanage from './components/gamemanage.vue';
import Space from './components/space.vue';
import Home from './components/home.vue';
import Manage from './components/manage.vue';
import axios from 'axios';
const tab = ref(null);
const is_su = ref(false);
const unaudit_number = ref(0);
axios.get('/api/currentUser')
.then(function (response) {
const data = response.data;
is_su.value = data.is_su;
})
.catch(function (error) {
console.log(error);
})
axios.get('/api/lauchedGames',)
.then(function (response) {
const data1 = response.data;
unaudit_number.value = data1.Games.length;
})
.catch(function (error) {
console.log(error);
})
const tab = ref(null)
</script>
<style>
......@@ -49,12 +83,15 @@ const tab = ref(null)
position: fixed;
bottom: 0;
z-index: 100;
height: 56px;
}
.bottom-navigation {
overflow-y: auto;
padding-bottom: 57px;
padding-bottom: 70px;
box-sizing: border-box;
}
/*.main-card{
height: 100%;
width: 100%;
......
/**
* main.js
*
* Bootstraps Vuetify and other plugins then mounts the App`
*/
// Plugins
import { registerPlugins } from '@/plugins'
// Components
import App from './my_recentgames.vue'
// Composables
import { createApp } from 'vue'
const app = createApp(App)
registerPlugins(app)
app.mount('#app')
<template>
<v-app>
<v-data-table-server :headers="headers" v-model:items-per-page="itemsPerPage" :items="filteredMatches"
item-key="id" :search="search" :items-length="totalGames" @update:options="loadGames" :loading="loading">
<template v-slot:top>
<v-toolbar flat>
<v-toolbar-title>比赛列表</v-toolbar-title>
<v-divider class="mx-3" inset vertical></v-divider>
<v-spacer></v-spacer>
<v-text-field v-model="search" append-icon="mdi-magnify" label="搜索" single-line
hide-details></v-text-field>
</v-toolbar>
<v-form v-model="isValid">
<div class="d-flex justify-space-around align-center">
<div>
<v-autocomplete :rules="[rules.season_not_none]" style="width: 150px;" variant="underlined" v-model="selectSeason"
:items="arr" label="选择赛季"></v-autocomplete>
</div>
<div>
<v-btn :disabled="!isValid" @click="getSeasonInfo" color="indigo" style="width: 80px;" text="确定"></v-btn>
</div>
</div>
</v-form>
</template>
<template v-slot:item.date="{ item }">
<p style="width:60px">{{ item.date }}</p>
</template>
<template v-slot:item.name="{ item }">
<p style="width:120px">{{ item.homeTeam }} VS {{ item.awayTeam }}</p>
</template>
<template v-slot:item.score="{ item }">
<p style="width:30px">{{ item.homeScore }} - {{ item.awayScore }}</p>
</template>
</v-data-table-server>
</v-app>
</template>
<script setup>
import { ref } from 'vue';
import { reactive } from 'vue';
import { computed } from 'vue';
import axios from 'axios';
const search = ref('');
var my_idstr = window.location.search;
const my_id = extractNumbers(my_idstr)[0];
const itemsPerPage = ref(5);
const totalGames = ref(0);
const loading = ref(true);
const selectSeason = ref(null);
const arr = ref(new Array());
const isValid = ref(false);
const headers = reactive([
{ title: '日期', key: 'date', sortable: false },
{ title: '比赛', key: 'name', sortable: false },
{ title: '比分', key: 'score', sortable: false },
]);
const matches = ref(new Array());
// matches = [
// { id: 1, username: '张三', opponentname: '零', userScore: 3, opponentScore: 2, verified: "PASSED" },
// ];
function extractNumbers(str) {
const pattern = /\d+/g;
const matches = str.match(pattern);
return matches ? matches.map(Number) : [];
}
const filteredMatches = computed(() => {
// return matches.value
return matches.value.filter(match =>
match.homeTeam.includes(search.value) ||
match.awayTeam.includes(search.value) ||
match.homeScore === parseInt(search.value) ||
match.awayScore === parseInt(search.value) ||
match.date.includes(search.value)
);
})
const rules = reactive({
email: v => !!(v || '').match(/@/) || 'Please enter a valid email',
length: len => v => (v || '').length >= len || `Invalid character length, required ${len}`,
season_not_none: v => !!v || '赛季不能为空',
});
axios.get('/api/seasonInfo')
.then(function (response) {
const data = response.data;
if (data.selectSeason.season_id !== -1) {
selectSeason.value = data.selectSeason.season_id.toString() + '-' + data.selectSeason.season_name;
}
for (var i = 0; i < data.Seasons.length; i++) {
arr.value[i] = data.Seasons[i].season_id.toString() + '-' + data.Seasons[i].season_name;
}
})
.catch(function (error) {
console.log(error);
})
function getSeasonInfo() {
loadGames({ page: 1, itemsPerPage: itemsPerPage.value });
}
function loadGames({ page, itemsPerPage }) {
loading.value = true;
if (selectSeason.value !== null) {
axios.get('/api/games', {
params: {
pages: page,
lim: itemsPerPage,
myid: my_id,
season_id: parseInt(selectSeason.value),
}
})
.then(function (response) {
const data2 = response.data;
matches.value.length = 0;
totalGames.value = data2.totalGames;
for (var i = 0; i < data2.Games.length; i++) {
var match = {
id: data2.Games[i].id,
date: data2.Games[i].game_date,
homeTeam: data2.Games[i].player1_real_name,
awayTeam: data2.Games[i].player2_real_name,
homeScore: data2.Games[i].score1,
awayScore: data2.Games[i].score2,
}
matches.value[i] = match;
}
loading.value = false
})
.catch(function (error) {
console.log(error);
})
}
else {
axios.get('/api/games', {
params: {
pages: page,
lim: itemsPerPage,
myid: my_id,
}
})
.then(function (response) {
const data2 = response.data;
matches.value.length = 0;
totalGames.value = data2.totalGames;
for (var i = 0; i < data2.Games.length; i++) {
var match = {
id: data2.Games[i].id,
date: data2.Games[i].game_date,
homeTeam: data2.Games[i].player1_real_name,
awayTeam: data2.Games[i].player2_real_name,
homeScore: data2.Games[i].score1,
awayScore: data2.Games[i].score2,
}
matches.value[i] = match;
}
loading.value = false
})
.catch(function (error) {
console.log(error);
})
}
}
// axios.get('/api/myLauchedGames',)
// .then(function(response){
// const data = response.data;
// for(var i = 0; i < data.Games.length; i++){
// // matches.value[i].id = i+1;
// var match = {
// id:data.Games[i].id,
// date:data.Games[i].game_date,
// username:data.Games[i].player1_real_name,
// opponentname:data.Games[i].player2_real_name,
// userScore:data.Games[i].score1,
// opponentScore:data.Games[i].score2,
// verified:data.Games[i].status,
// }
// matches.value[i] = match;
// }
// })
// .catch(function (error) {
// console.log(error);
// })
</script>
\ No newline at end of file
/**
* main.js
*
* Bootstraps Vuetify and other plugins then mounts the App`
*/
// Plugins
import { registerPlugins } from '@/plugins'
// Components
import App from './past_seasons.vue'
// Composables
import { createApp } from 'vue'
const app = createApp(App)
registerPlugins(app)
app.mount('#app')
<template>
<v-app>
<v-data-table-server :headers="headers" v-model:items-per-page="itemsPerPage" :items="filteredMatches"
item-key="id" :search="search" :items-length="totalGames" @update:options="loadGames" :loading="loading">
<template v-slot:top>
<v-toolbar flat>
<v-toolbar-title>过往赛季</v-toolbar-title>
<v-divider class="mx-3" inset vertical></v-divider>
<v-spacer></v-spacer>
<v-text-field v-model="search" append-icon="mdi-magnify" label="搜索" single-line
hide-details></v-text-field>
</v-toolbar>
<div class="d-flex justify-space-around align-center" style="height: 60px;">
<div>
<v-autocomplete style="width: 150px;" variant="underlined" v-model="selectSeason" :items="arr"
label="选择赛季"></v-autocomplete>
</div>
<div>
<v-btn color="indigo" style="width: 80px;" text="确定"></v-btn>
</div>
</div>
</template>
<template v-slot:item.date="{ item }">
<p style="width:60px">{{ item.date }}</p>
</template>
<template v-slot:item.name="{ item }">
<p style="width:120px">{{ item.homeTeam }} VS {{ item.awayTeam }}</p>
</template>
<template v-slot:item.score="{ item }">
<p style="width:30px">{{ item.homeScore }} - {{ item.awayScore }}</p>
</template>
</v-data-table-server>
</v-app>
</template>
<script setup>
import { ref } from 'vue';
import { reactive } from 'vue';
import { computed } from 'vue';
import axios from 'axios';
const search = ref('');
const itemsPerPage = ref(5);
const totalGames = ref(0);
const loading = ref(true);
const selectSeason = ref(null);
const arr = ref(new Array());
const headers = reactive([
{ title: '日期', key: 'date', sortable: false },
{ title: '比赛', key: 'name', sortable: false },
{ title: '比分', key: 'score', sortable: false },
]);
const matches = ref(new Array());
const filteredMatches = computed(() => {
// return matches.value
return matches.value.filter(match =>
match.homeTeam.includes(search.value) ||
match.awayTeam.includes(search.value) ||
match.homeScore === parseInt(search.value) ||
match.awayScore === parseInt(search.value) ||
match.date.includes(search.value)
);
})
axios.get('/api/seasonInfo')
.then(function (response) {
const data = response.data;
for (var i = 0; i < data.Seasons.length; i++) {
arr.value[i] = data.Seasons[i].season_id.toString() + '-' + data.Seasons[i].season_name;
}
})
.catch(function (error) {
console.log(error);
})
function getSeasonInfo(){
}
function loadGames({ page, itemsPerPage }) {
loading.value = true;
axios.get('/api/games', {
params: {
pages: page,
lim: itemsPerPage,
}
})
.then(function (response) {
const data2 = response.data;
matches.value.length = 0;
totalGames.value = data2.totalGames;
for (var i = 0; i < data2.Games.length; i++) {
var match = {
id: data2.Games[i].id,
date: data2.Games[i].game_date,
homeTeam: data2.Games[i].player1_real_name,
awayTeam: data2.Games[i].player2_real_name,
homeScore: data2.Games[i].score1,
awayScore: data2.Games[i].score2,
}
matches.value[i] = match;
}
loading.value = false
})
.catch(function (error) {
console.log(error);
})
}
</script>
\ No newline at end of file
/**
* main.js
*
* Bootstraps Vuetify and other plugins then mounts the App`
*/
// Plugins
import { registerPlugins } from '@/plugins'
// Components
import App from './player_audit.vue'
// Composables
import { createApp } from 'vue'
const app = createApp(App)
registerPlugins(app)
app.mount('#app')
<template>
<v-app>
<v-data-table :loading="loading" :headers="headers" :items="players" item-key="id" :search="search" :items-per-page="5">
<template v-slot:top>
<v-toolbar flat>
<v-toolbar-title>球员审核</v-toolbar-title>
<v-divider class="mx-3" inset vertical></v-divider>
<v-spacer></v-spacer>
<v-text-field v-model="search" append-icon="mdi-magnify" label="搜索" single-line
hide-details></v-text-field>
</v-toolbar>
</template>
<template v-slot:item.player_id="{ item }">
<p v-if="item.player_id" style="width:50px">{{ item.player_id }}</p>
</template>
<template v-slot:item.player_real_name="{ item }">
<p v-if="item.player_real_name" style="width:50px">{{ item.player_real_name }}</p>
</template>
<template v-slot:item.actions="{ item }">
<v-icon @click="editPlayer(item)" style="width:50px">mdi-pencil</v-icon>
</template>
</v-data-table>
</v-app>
<v-dialog v-model="dialog" width="auto">
<v-card width="300px">
<v-card-title>
审核球员信息
</v-card-title>
<v-card-text>
<v-form v-model="isValid">
<p variant="filled" style="margin-bottom: 20px;">姓名:{{ selectPlayer.player_real_name }}</p>
<v-select v-model="selectPlayer.group" :rules="[rules.group]" :items="['A组', 'B组', 'C组']"
variant="filled" color="indigo" label="分组"></v-select>
</v-form>
</v-card-text>
<template v-slot:actions>
<v-btn :disabled="!isValid" :loading="playerLoading" class="ms-auto" variant="flat" color="indigo" text="确定" @click="changePlayer"></v-btn>
</template>
</v-card>
</v-dialog>
<v-dialog v-model="dialog1" width="auto">
<v-card width="300px">
<v-card-title>
{{ cardtitle }}
</v-card-title>
<v-card-text>
{{ cardtext }}
</v-card-text>
<template v-slot:actions>
<v-btn class="ms-auto" variant="flat" color="indigo" text="确认" @click="dialog = false"></v-btn>
</template>
</v-card>
</v-dialog>
</template>
<script setup>
import { ref } from 'vue';
import { reactive } from 'vue';
// import { computed } from 'vue';
import axios from 'axios';
const search = ref('');
// const actions_text = ref('');
const headers = reactive([
{ title: 'ID', key: 'player_id' },
{ title: '姓名', key: 'player_real_name' },
{ title: '编辑', key: 'actions' },
]);
const rules = reactive({
email: v => !!(v || '').match(/@/) || 'Please enter a valid email',
length: len => v => (v || '').length >= len || `Invalid character length, required ${len}`,
usrname: v => !!v || '用户名不能为空',
realname: v => !!v || '姓名不能为空',
confirmpassword: v => v === password.value || '密码不匹配',
password: v => !!v || '密码不能为空',
su: v => !!v || '管理员不能为空',
member: v => !!v || '会员不能为空',
group: v => !!v || '分组不能为空',
// password: v => !!(v || '').match(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*(_|[^\w])).+$/) ||
// 'Password must contain an upper case letter, a numeric character, and a special character',
required: v => !!v || 'This field is required',
});
const isValid = ref(false);
const loading = ref(true);
const playerLoading = ref(false);
const players = ref(new Array());
const dialog = ref(false);
const selectPlayer = ref({
player_id: 0,
player_real_name: '',
group: '',
group_number: 0,
});
const cardtitle = ref(null);
const cardtext = ref(null);
const dialog1 = ref(false);
function info(title, text) {
cardtitle.value = title;
cardtext.value = text;
dialog1.value = true;
}
function refresh() {
loading.value = true;
axios.get('/api/getPlayers')
.then(function (response) {
const data = response.data;
players.value.length = 0;
for (var i = 0; i < data.unaudited_season_playersInfo.length; i++) {
const player = ref({
player_id: data.unaudited_season_playersInfo[i].player_id,
player_real_name: data.unaudited_season_playersInfo[i].player_real_name,
})
players.value[i] = player;
}
})
.catch(function (error) {
console.log(error);
})
loading.value = false;
}
refresh();
function editPlayer(item) {
dialog.value = true;
selectPlayer.value = item;
}
function changePlayer() {
playerLoading.value = true;
if (selectPlayer.value.group === 'A组'){
selectPlayer.value.group_number = 1;
}
if (selectPlayer.value.group === 'B组'){
selectPlayer.value.group_number = 2;
}
if (selectPlayer.value.group === 'C组'){
selectPlayer.value.group_number = 3;
}
axios.post('/api/playerAudit', selectPlayer.value)
.then(function (response) {
const data1 = response.data;
if (data1.status === "FAILED") {
info("修改失败!", "");
}
dialog.value = false;
refresh();
})
.catch(function (error) {
console.log(error);
})
playerLoading.value = false;
}
</script>
\ No newline at end of file
/**
* main.js
*
* Bootstraps Vuetify and other plugins then mounts the App`
*/
// Plugins
import { registerPlugins } from '@/plugins'
// Components
import App from './player_manage.vue'
// Composables
import { createApp } from 'vue'
const app = createApp(App)
registerPlugins(app)
app.mount('#app')
<template>
<v-app>
<v-data-table :loading="loading" :headers="headers" :items="players" item-key="id" :search="search" :items-per-page="5">
<template v-slot:top>
<v-toolbar flat>
<v-toolbar-title>球员管理</v-toolbar-title>
<v-divider class="mx-3" inset vertical></v-divider>
<v-spacer></v-spacer>
<v-text-field v-model="search" append-icon="mdi-magnify" label="搜索" single-line
hide-details></v-text-field>
</v-toolbar>
</template>
<template v-slot:item.player_id="{ item }">
<p v-if="item.player_id" style="width:50px">{{ item.player_id }}</p>
</template>
<template v-slot:item.player_real_name="{ item }">
<p v-if="item.player_real_name" style="width:50px">{{ item.player_real_name }}</p>
</template>
<template v-slot:item.group="{ item }">
<p v-if="item.group" style="width:50px">{{ item.group }}</p>
</template>
<template v-slot:item.score="{ item }">
<p style="width:50px">{{ item.score }}</p>
</template>
<template v-slot:item.total_games="{ item }">
<p style="width:50px">{{ item.total_games }}</p>
</template>
<template v-slot:item.winrate="{ item }">
<p style="width:50px">{{ item.winrate }}%</p>
</template>
<template v-slot:item.actions="{ item }">
<v-icon @click="editPlayer(item)" style="width:50px">mdi-pencil</v-icon>
</template>
</v-data-table>
</v-app>
<v-dialog v-model="dialog" width="auto">
<v-card width="300px">
<v-card-title>
编辑用户信息
</v-card-title>
<v-card-text>
<v-form v-model="isValid">
<p variant="filled" style="margin-bottom: 20px;">姓名:{{ selectPlayer.player_real_name }}</p>
<v-select v-model="selectPlayer.group" :rules="[rules.group]" variant="filled" :items="['A组', 'B组', 'C组']"
color="indigo" label="分组"></v-select>
<v-text-field type="number" v-model="selectPlayer.score" :rules="[rules.score_not_none ,rules.score]" variant="filled"
color="indigo" label="积分"></v-text-field>
<v-text-field type="number" v-model="selectPlayer.total_games" :rules="[rules.totalgames_not_none,rules.totalgames]"
variant="filled" color="indigo" label="场次"></v-text-field>
</v-form>
</v-card-text>
<template v-slot:actions>
<v-btn :disabled="!isValid" :loading="PlayerLoading" class="ms-auto" variant="flat" color="indigo" text="修改" @click="changePlayer"></v-btn>
</template>
</v-card>
</v-dialog>
<v-dialog v-model="dialog1" width="auto">
<v-card width="300px">
<v-card-title>
{{ cardtitle }}
</v-card-title>
<v-card-text>
{{ cardtext }}
</v-card-text>
<template v-slot:actions>
<v-btn class="ms-auto" variant="flat" color="indigo" text="确认" @click="dialog = false"></v-btn>
</template>
</v-card>
</v-dialog>
</template>
<script setup>
import { ref } from 'vue';
import { reactive } from 'vue';
// import { computed } from 'vue';
import axios from 'axios';
const search = ref('');
// const actions_text = ref('');
const headers = reactive([
{ title: 'ID', key: 'player_id' },
{ title: '姓名', key: 'player_real_name' },
{ title: '分组', key: 'group' },
{ title: '积分', key: 'score' },
{ title: '场次', key: 'total_games' },
{ title: '胜率', key: 'winrate' },
{ title: '编辑', key: 'actions' },
]);
const rules = reactive({
email: v => !!(v || '').match(/@/) || 'Please enter a valid email',
length: len => v => (v || '').length >= len || `Invalid character length, required ${len}`,
// score: v => !!v || '积分不能为空',
// totalgames: v => !!v || '场次不能为空',
group: v => !!v || '分组不能为空',
score_not_none: v => /^[0-9]\d*$/.test(v) || '积分应为非负整数',
totalgames_not_none: v => /^[0-9]\d*$/.test(v) || '场次应为非负整数',
score: v => (Number(v) <= selectPlayer.value.total_games)|| '积分应小于等于场次',
totalgames: v => (Number(v) >= selectPlayer.value.score)|| '场次应大于等于积分',
// password: v => !!v || '密码不能为空',
// su: v => !!v || '管理员不能为空',
// member: v => !!v || '会员不能为空',
// password: v => !!(v || '').match(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*(_|[^\w])).+$/) ||
// 'Password must contain an upper case letter, a numeric character, and a special character',
required: v => !!v || 'This field is required',
});
const isValid = ref(false);
const PlayerLoading = ref(false);
const loading = ref(true);
const players = ref(new Array());
const dialog = ref(false);
const selectPlayer = ref({
player_id: 0,
player_real_name: '',
score: 0,
group: '',
group_number: 0,
total_games: 0,
winrate: 0,
});
const cardtitle = ref(null);
const cardtext = ref(null);
const dialog1 = ref(false);
function info(title, text) {
cardtitle.value = title;
cardtext.value = text;
dialog1.value = true;
}
function refresh() {
loading.value = true;
axios.get('/api/getPlayers')
.then(function (response) {
const data = response.data;
players.value.length = 0;
for (var i = 0; i < data.season_playersInfo.length; i++) {
const player = ref({
player_id: data.season_playersInfo[i].player_id,
player_real_name: data.season_playersInfo[i].player_real_name,
group_number: data.season_playersInfo[i].group,
score: data.season_playersInfo[i].score,
total_games: data.season_playersInfo[i].total_games,
winrate: data.season_playersInfo[i].winrate,
group: '',
})
if (player.value.group_number === 1){
player.value.group = 'A组'
}
if (player.value.group_number === 2){
player.value.group = 'B组'
}
if (player.value.group_number === 3){
player.value.group = 'C组'
}
players.value[i] = player;
}
})
.catch(function (error) {
console.log(error);
})
loading.value = false;
}
refresh();
function editPlayer(item) {
dialog.value = true;
selectPlayer.value = item;
}
function changePlayer() {
PlayerLoading.value = true;
if (selectPlayer.value.group === 'A组'){
selectPlayer.value.group_number = 1
}
if (selectPlayer.value.group === 'B组'){
selectPlayer.value.group_number = 2
}
if (selectPlayer.value.group === 'C组'){
selectPlayer.value.group_number = 3
}
selectPlayer.value.score = Number(selectPlayer.value.score)
selectPlayer.value.total_games = Number(selectPlayer.value.total_games)
axios.post('/api/playerManage', selectPlayer.value)
.then(function (response) {
const data1 = response.data;
if (data1.status === "FAILED") {
info("修改失败!", "");
}
dialog.value = false;
refresh();
})
.catch(function (error) {
console.log(error);
})
PlayerLoading.value = false;
}
</script>
\ No newline at end of file
/**
* main.js
*
* Bootstraps Vuetify and other plugins then mounts the App`
*/
// Plugins
import { registerPlugins } from '@/plugins'
// Components
import App from './score_ranking.vue'
// Composables
import { createApp } from 'vue'
const app = createApp(App)
registerPlugins(app)
app.mount('#app')
<template>
<div class="score-card">
<v-card v-if="players.length" elevation="5">
<template v-slot:prepend>
<v-icon size="25px">mdi-medal</v-icon>
</template>
<template v-slot:title>
<div class="text-h6">积分榜单</div>
</template>
<v-infinite-scroll mode="manual" @load="load">
<v-list>
<v-list-item v-for="(player, index) in players" :key="index" :value="players"
@click="goto_space(player.player_id)">
<template v-slot:default>
<div class="d-flex justify-space-between align-center game-item">
<div>
<v-avatar size="48px"><img :src="player.avatar" class="avatar-img"></v-avatar>
</div>
<div class="realname-text">{{ player.realname }}</div>
<div class="winrate-text">{{ player.winrate }}%</div>
<div class="name-score">{{ player.games }}</div>
<div class="date-text">{{ player.point }}</div>
<v-icon>mdi-chevron-right</v-icon>
</div>
</template>
</v-list-item>
</v-list>
</v-infinite-scroll>
</v-card>
</div>
</template>
<script setup>
import { ref } from 'vue';
// import { reactive } from 'vue';
// import { computed } from 'vue';
import axios from 'axios';
const players = ref(new Array());
const pages = ref(1);
function refresh() {
axios.get("/api/players", {
params: {
pages: pages.value,
}
})
.then(function (response) {
const data1 = response.data;
// players.value.length = 0;
for (var i = 0; i < data1.Players.length; i++) {
var player = {
number: i + 1,
player_id: data1.Players[i].player_id,
realname: data1.Players[i].player_real_name,
games: data1.Players[i].total_games,
point: data1.Players[i].score,
winrate: data1.Players[i].winrate,
avatar: data1.Players[i].player_profile_file,
}
players.value.push(player);
}
})
.catch(function (error) {
console.log(error);
})
}
refresh();
function goto_space(my_id) {
window.location.href = '/space.html?myid=' + my_id;
}
async function api() {
pages.value += 1;
refresh();
return players.value
}
async function load({ done }) {
const res = await api();
// console.log(res)
// players.value.push(res);
done('ok')
done('empty')
}
</script>
<style>
.score-card {
/* margin-top: 10px; */
margin: auto;
/* margin-top: 10px; */
padding-top: 10px;
width: 95%;
}
.avatar-img {
object-fit: cover;
width: 100%;
height: 100%;
}
.date-text {
font-size: small;
color: grey;
text-align: center;
padding-left: 7px;
padding-right: 7px;
}
.realname-text {
font-size: large;
font-weight: bold;
width: 72px;
text-align: center;
}
.winrate-text {
font-family: 'Times New Roman';
width: 40px;
text-align: center;
}
.name-score {
width: 20%;
text-align: center;
margin-left: 5px;
margin-right: 5px;
/* line-height: 33px; */
}
</style>
\ No newline at end of file
/**
* main.js
*
* Bootstraps Vuetify and other plugins then mounts the App`
*/
// Plugins
import { registerPlugins } from '@/plugins'
// Components
import App from './season_manage.vue'
// Composables
import { createApp } from 'vue'
const app = createApp(App)
registerPlugins(app)
app.mount('#app')
<template>
<v-app>
<v-data-table :loading="loading" :headers="headers" :items="seasons" item-key="id" :search="search" :items-per-page="5">
<template v-slot:top>
<v-toolbar flat>
<v-toolbar-title>赛季管理</v-toolbar-title>
<v-divider class="mx-3" inset vertical></v-divider>
<v-spacer></v-spacer>
<v-text-field v-model="search" append-icon="mdi-magnify" label="搜索" single-line
hide-details></v-text-field>
</v-toolbar>
</template>
<template v-slot:item.season_id="{ item }">
<p v-if="item.season_id" style="width:50px">{{ item.season_id }}</p>
</template>
<template v-slot:item.season_name="{ item }">
<p v-if="item.season_name" style="width:50px">{{ item.season_name }}</p>
</template>
<template v-slot:item.start_date="{ item }">
<p v-if="item.start_date" style="width:50px">{{ formatDate(item.start_date) }}</p>
</template>
<template v-slot:item.end_date="{ item }">
<p v-if="item.end_date" style="width:50px">{{ formatDate(item.end_date) }}</p>
</template>
<template v-slot:item.season_enable="{ item }">
<p v-if="item.season_enable" style="width:50px">{{ item.season_enable }}</p>
</template>
<template v-slot:item.actions="{ item }">
<v-btn v-if="item.season_enable" :loading="endLoading" @click="season_end(item)" style="width:50px" variant="text"
color="indigo" text="结束赛季"></v-btn>
<v-btn v-if="!item.season_enable" :loading="restartLoading" @click="season_restart(item)" style="width:50px" variant="text"
color="indigo" text="重启赛季"></v-btn>
</template>
</v-data-table>
<div><v-btn style="width: 100px;" class="float-right" variant="text" color="indigo"
prepend-icon="mdi-scoreboard" @click="dialog = true" text="开启赛季"></v-btn></div>
</v-app>
<v-dialog v-model="dialog" width="auto">
<v-card width="300px">
<v-card-title>
开启赛季
</v-card-title>
<v-card-text>
<v-form v-model="isValid">
<v-text-field v-model="new_season_name" variant="filled" color="indigo" label="赛季名" :rules="[rules.season]"></v-text-field>
<v-btn block @click="date_dialog = true" class="text-none mb-4" color="indigo" size="large"
variant="outlined">
<template v-slot:default>
选择赛季开始日期:{{ selectedDate.toLocaleDateString() }}
</template>
</v-btn>
</v-form>
</v-card-text>
<template v-slot:actions>
<v-btn :disabled="!isValid" :loading="startLoading" class="ms-auto" variant="flat" color="indigo" text="确定" @click="season_start"></v-btn>
</template>
</v-card>
</v-dialog>
<v-dialog v-model="date_dialog" width="auto">
<v-card>
<v-locale-provider locale="zhHans">
<v-date-picker v-model="selectedDate" header="日期" title="选择赛季开始日期" color="indigo"
width="100%"></v-date-picker>
</v-locale-provider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn variant="flat" text="确定" color="indigo" @click="date_dialog = false"></v-btn>
</v-card-actions>
</v-card>
</v-dialog>
<v-dialog v-model="dialog1" width="auto">
<v-card width="300px">
<v-card-title>
{{ cardtitle }}
</v-card-title>
<v-card-text>
{{ cardtext }}
</v-card-text>
<template v-slot:actions>
<v-btn class="ms-auto" variant="flat" color="indigo" text="确认" @click="dialog = false"></v-btn>
</template>
</v-card>
</v-dialog>
</template>
<script setup>
import { ref } from 'vue';
import { reactive } from 'vue';
import axios from 'axios';
const search = ref('');
// const actions_text = ref('');
const headers = reactive([
{ title: 'ID', key: 'season_id' },
{ title: '赛季', key: 'season_name' },
{ title: '开始日期', key: 'start_date' },
{ title: '结束时间', key: 'end_date' },
{ title: '进行中', key: 'season_enable' },
// { title: '管理员', key: 'is_su' },
{ title: '操作', key: 'actions' },
]);
const rules = reactive({
email: v => !!(v || '').match(/@/) || 'Please enter a valid email',
length: len => v => (v || '').length >= len || `Invalid character length, required ${len}`,
usrname: v => !!v || '用户名不能为空',
realname: v => !!v || '姓名不能为空',
confirmpassword: v => v === password.value || '密码不匹配',
password: v => !!v || '密码不能为空',
su: v => !!v || '管理员不能为空',
member: v => !!v || '会员不能为空',
season: v => !!v || '赛季名不能为空',
// password: v => !!(v || '').match(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*(_|[^\w])).+$/) ||
// 'Password must contain an upper case letter, a numeric character, and a special character',
required: v => !!v || 'This field is required',
});
const isValid = ref(false);
const seasons = ref(new Array());
const dialog = ref(false);
const new_season_name = ref('');
const selectedDate = ref(new Date());
const date_dialog = ref(false);
const loading = ref(true);
const endLoading = ref(false);
const restartLoading = ref(false);
const startLoading = ref(false);
const cardtitle = ref(null);
const cardtext = ref(null);
const dialog1 = ref(false);
function info(title, text) {
cardtitle.value = title;
cardtext.value = text;
dialog1.value = true;
}
function formatDate(date) {
var d = new Date(date),
month = '0' + (d.getMonth() + 1),
day = '' + d.getDate(),
year = d.getFullYear();
return [year + '/' + month + '/' + day].join(''); // 返回形如 MM/DD 的字符串
}
function refresh() {
loading.value = true;
axios.get('/api/seasonInfo')
.then(function (response) {
const data = response.data;
seasons.value.length = 0;
for (var i = 0; i < data.Seasons.length; i++) {
const season = ref({
season_id: data.Seasons[i].season_id,
season_name: data.Seasons[i].season_name,
start_date: data.Seasons[i].start_date,
end_date: data.Seasons[i].end_date,
season_enable: data.Seasons[i].season_enable,
// user_is_su: data.Seasons[i].is_su,
})
seasons.value[i] = season;
}
})
.catch(function (error) {
console.log(error);
})
loading.value = false;
}
refresh();
function season_end(endSeason) {
endLoading.value = true;
axios.post('/api/seasonManage', {
season_id: endSeason.season_id,
condition_singal: 1,
})
.then(function (response) {
const data1 = response.data;
if (data1.status === "FAILED") {
info("结束失败!", "");
}
refresh();
})
.catch(function (error) {
console.log(error);
})
endLoading.value = false;
}
function season_restart(restartSeason) {
restartLoading.value = true;
axios.post('/api/seasonManage', {
season_id: restartSeason.season_id,
condition_singal: -1,
})
.then(function (response) {
const data1 = response.data;
if (data1.status === "FAILED") {
info("重启失败!", "");
}
refresh();
})
.catch(function (error) {
console.log(error);
})
restartLoading.value = false;
}
function season_start() {
startLoading.value = true;
axios.post('/api/seasonManage', {
season_name: new_season_name.value,
start_date: selectedDate.value.toLocaleDateString(),
condition_singal: 0,
})
.then(function (response) {
const data1 = response.data;
if (data1.status === "FAILED") {
info("开启失败!", "");
}
refresh();
dialog.value = false;
})
.catch(function (error) {
console.log(error);
})
startLoading.value = false;
}
</script>
\ No newline at end of file
......@@ -30,6 +30,7 @@ function testclick() {
-->
<script setup>
import Space from './components/space.vue';
// import { ref } from 'vue';
// const tab = ref(null)
// const text = ref('Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.')
......@@ -43,20 +44,10 @@ function testclick() {
// }
</script>
<template>
<!-- <div>个人空间</div> -->
<Space></Space>
</template>
<style>
.main-card{
height: 100%;
width: 100%;
}
.tabs{
width: 100%;
position: fixed;
bottom: 0;
}
</style>
\ No newline at end of file
......@@ -8,7 +8,7 @@
import { registerPlugins } from '@/plugins'
// Components
import App from './gamemanage.vue'
import App from './user_audit.vue'
// Composables
import { createApp } from 'vue'
......
<template>
<v-app>
<v-data-table :loading="loading"item-value="return-object" return-object="true" v-model="selected" show-select :headers="headers"
:items="users" item-key="id" :search="search" :items-per-page="5">
<template v-slot:top>
<v-toolbar flat>
<v-toolbar-title>用户审核</v-toolbar-title>
<v-divider class="mx-3" inset vertical></v-divider>
<v-spacer></v-spacer>
<v-text-field v-model="search" append-icon="mdi-magnify" label="搜索" single-line
hide-details></v-text-field>
</v-toolbar>
</template>
<template v-slot:item.username="{ item }">
<p v-if="item.username" style="width:50px">{{ item.username }}</p>
</template>
<template v-slot:item.realname="{ item }">
<p v-if="item.realname" style="width:50px">{{ item.realname }}</p>
</template>
</v-data-table>
<div><v-btn style="width: 100px;" class="float-right" variant="text" color="indigo"
prepend-icon="mdi-check-circle" :loading="memberLoading" @click="setMember" text="审核通过"></v-btn></div>
</v-app>
<v-dialog v-model="dialog" width="auto">
<v-card width="300px">
<v-card-title>
{{ cardtitle }}
</v-card-title>
<v-card-text>
{{ cardtext }}
</v-card-text>
<template v-slot:actions>
<v-btn class="ms-auto" variant="flat" color="indigo" text="确认" @click="dialog = false"></v-btn>
</template>
</v-card>
</v-dialog>
</template>
<script setup>
import { ref } from 'vue';
import { reactive } from 'vue';
// import { computed } from 'vue';
import axios from 'axios';
const search = ref('');
// const actions_text = ref('');
const headers = reactive([
{ title: '用户名', key: 'username' },
{ title: '姓名', key: 'realname' },
// { title: '审核', key: 'actions' },
]);
const users = ref(new Array());
const selected = ref([]);
const loading = ref(true);
const memberLoading = ref(false);
const cardtitle = ref(null);
const cardtext = ref(null);
const dialog = ref(false);
function info(title, text) {
cardtitle.value = title;
cardtext.value = text;
dialog.value = true;
}
function refresh(){
loading.value = true;
axios.get('/api/getUser')
.then(function (response) {
const data = response.data;
users.value.length = 0;
// users.splice()
for (var i = 0; i < data.Unauidted_users.length; i++) {
const user = ref({
usr_id: data.Unauidted_users[i].user_id,
username: data.Unauidted_users[i].username,
realname: data.Unauidted_users[i].real_name,
is_member: false,
})
users.value[i] = user;
}
})
.catch(function (error) {
console.log(error);
})
loading.value = false;
}
refresh();
function setMember() {
memberLoading.value = true;
for (var j =0; j < selected.value.length; j++){
selected.value[j].is_member = true;
}
axios.post('/api/setMembers', selected.value)
.then(function(response) {
const data1 =response.data;
if (data1.status === "SUCCESS"){
info("审核成功!");
}
if (data1.status === "FAILED"){
info("未审核用户!");
}
refresh();
})
// .then(refresh())
.catch(function(error){
console.log(error);
})
memberLoading.value = false;
}
</script>
\ No newline at end of file
/**
* main.js
*
* Bootstraps Vuetify and other plugins then mounts the App`
*/
// Plugins
import { registerPlugins } from '@/plugins'
// Components
import App from './user_manage.vue'
// Composables
import { createApp } from 'vue'
const app = createApp(App)
registerPlugins(app)
app.mount('#app')
<template>
<v-app>
<v-data-table :loading="loading" :headers="headers" :items="users" item-key="id" :search="search" :items-per-page="5">
<template v-slot:top>
<v-toolbar flat>
<v-toolbar-title>用户管理</v-toolbar-title>
<v-divider class="mx-3" inset vertical></v-divider>
<v-spacer></v-spacer>
<v-text-field v-model="search" append-icon="mdi-magnify" label="搜索" single-line
hide-details></v-text-field>
</v-toolbar>
</template>
<template v-slot:item.userid="{ item }">
<p v-if="item.user_id" style="width:50px">{{ item.user_id }}</p>
</template>
<template v-slot:item.username="{ item }">
<p v-if="item.user_name" style="width:50px">{{ item.user_name }}</p>
</template>
<template v-slot:item.realname="{ item }">
<p v-if="item.user_realname" style="width:50px">{{ item.user_realname }}</p>
</template>
<template v-slot:item.password="{ item }">
<p v-if="item.user_password" style="width:50px">{{ item.user_password }}</p>
</template>
<template v-slot:item.is_member="{ item }">
<p v-if="item.user_is_member" style="width:50px">{{ item.user_is_member }}</p>
</template>
<template v-slot:item.is_su="{ item }">
<p v-if="item.user_is_su" style="width:50px">{{ item.user_is_su }}</p>
</template>
<template v-slot:item.actions="{ item }">
<v-icon @click="editUser(item)" style="width:50px">mdi-pencil</v-icon>
</template>
</v-data-table>
</v-app>
<v-dialog v-model="dialog" width="auto">
<v-card width="300px">
<v-card-title>
编辑用户信息
</v-card-title>
<v-card-text>
<v-form v-model="isValid">
<v-text-field v-model="selectUser.user_name" :rules="[rules.usrname]" variant="filled"
color="indigo" label="用户名"></v-text-field>
<v-text-field v-model="selectUser.user_realname" :rules="[rules.usrname]" variant="filled"
color="indigo" label="姓名"></v-text-field>
<v-text-field v-model="selectUser.user_password" :rules="[rules.password]" variant="filled"
color="indigo" label="密码"></v-text-field>
<v-select v-model="selectUser.is_member" :rules="[rules.su]" :items="['是', '否']"
variant="filled" color="indigo" label="会员"></v-select>
<v-select v-model="selectUser.is_su" :rules="[rules.member]" :items="['是', '否']"
variant="filled" color="indigo" label="管理员"></v-select>
</v-form>
</v-card-text>
<template v-slot:actions>
<v-btn :disabled="!isValid" :loading="userLoading" class="ms-auto" variant="flat" color="indigo" text="修改" @click="changeUser"></v-btn>
</template>
</v-card>
</v-dialog>
<v-dialog v-model="dialog1" width="auto">
<v-card width="300px">
<v-card-title>
{{ cardtitle }}
</v-card-title>
<v-card-text>
{{ cardtext }}
</v-card-text>
<template v-slot:actions>
<v-btn class="ms-auto" variant="flat" color="indigo" text="确认" @click="dialog = false"></v-btn>
</template>
</v-card>
</v-dialog>
</template>
<script setup>
import { ref } from 'vue';
import { reactive } from 'vue';
// import { computed } from 'vue';
import axios from 'axios';
const search = ref('');
// const actions_text = ref('');
const headers = reactive([
{ title: 'ID', key: 'userid' },
{ title: '用户名', key: 'username' },
{ title: '姓名', key: 'realname' },
{ title: '密码', key: 'password' },
{ title: '会员', key: 'is_member' },
{ title: '管理员', key: 'is_su' },
{ title: '编辑', key: 'actions' },
]);
const rules = reactive({
email: v => !!(v || '').match(/@/) || 'Please enter a valid email',
length: len => v => (v || '').length >= len || `Invalid character length, required ${len}`,
usrname: v => !!v || '用户名不能为空',
realname: v => !!v || '姓名不能为空',
confirmpassword: v => v === password.value || '密码不匹配',
password: v => !!v || '密码不能为空',
su: v => !!v || '管理员不能为空',
member: v => !!v || '会员不能为空',
// password: v => !!(v || '').match(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*(_|[^\w])).+$/) ||
// 'Password must contain an upper case letter, a numeric character, and a special character',
required: v => !!v || 'This field is required',
});
const isValid = ref(false);
const loading = ref(true);
const userLoading = ref(false);
const users = ref(new Array());
const dialog = ref(false);
const selectUser = ref({
user_id: 0,
user_name: '',
user_realname: '',
user_password: '',
user_is_member: false,
user_is_su: false,
is_member: '',
is_su: '',
});
const cardtitle = ref(null);
const cardtext = ref(null);
const dialog1 = ref(false);
function info(title, text) {
cardtitle.value = title;
cardtext.value = text;
dialog1.value = true;
}
function refresh() {
loading.value = true;
axios.get('/api/getUser')
.then(function (response) {
const data = response.data;
users.value.length = 0;
for (var i = 0; i < data.Users.length; i++) {
const user = ref({
user_id: data.Users[i].user_id,
user_name: data.Users[i].username,
user_realname: data.Users[i].real_name,
user_password: data.Users[i].password,
user_is_member: data.Users[i].is_member,
user_is_su: data.Users[i].is_su,
is_member: '',
is_su: '',
})
if (user.value.user_is_member){
user.value.is_member = '是'
}
if (!user.value.user_is_member){
user.value.is_member = '否'
}
if (user.value.user_is_su){
user.value.is_su = '是'
}
if (!user.value.user_is_su){
user.value.is_su = '否'
}
users.value[i] = user;
}
})
.catch(function (error) {
console.log(error);
})
loading.value = false;
}
refresh();
function editUser(item) {
dialog.value = true;
selectUser.value = item;
}
function changeUser() {
userLoading.value = true;
if (selectUser.value.is_member === '是'){
selectUser.value.user_is_member = true
}
if (selectUser.value.is_member === '否'){
selectUser.value.user_is_member = false
}
if (selectUser.value.is_su === '是'){
selectUser.value.user_is_su = true
}
if (selectUser.value.is_su === '否'){
selectUser.value.user_is_su = false
}
axios.post('/api/userManage', selectUser.value)
.then(function (response) {
const data1 = response.data;
if (data1.status === "FAILED") {
info("修改失败!", "");
}
dialog.value = false;
refresh();
})
.catch(function (error) {
console.log(error);
})
userLoading.value = false;
}
</script>
\ No newline at end of file
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>用户审核</title>
<style>
html,body,#app{
height: 100%;
}
</style>
</head>
<body>
<div id="app"></div>
<script type="module" src="src/user_audit.js"></script>
</body>
</html>
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>用户管理</title>
<style>
html,body,#app{
height: 100%;
}
</style>
</head>
<body>
<div id="app"></div>
<script type="module" src="src/user_manage.js"></script>
</body>
</html>
......@@ -52,11 +52,21 @@ export default defineConfig({
rollupOptions: {
input: {
index: resolve(__dirname, 'index.html'),
home: resolve(__dirname, 'home.html'),
// home: resolve(__dirname, 'home.html'),
space: resolve(__dirname, 'space.html'),
main: resolve(__dirname, 'main.html'),
lauched_games: resolve(__dirname, 'lauched_games.html'),
audit_games: resolve(__dirname, 'audit_games.html'),
my_recentgames: resolve(__dirname, 'my_recentgames.html'),
score_ranking: resolve(__dirname, 'score_ranking.html'),
// manage: resolve(__dirname, 'manage.html'),
user_audit: resolve(__dirname, 'user_audit.html'),
user_manage: resolve(__dirname, 'user_manage.html'),
season_manage: resolve(__dirname, 'season_manage.html'),
player_audit: resolve(__dirname, 'player_audit.html'),
player_manage: resolve(__dirname, 'player_manage.html'),
game_manage: resolve(__dirname, 'game_manage.html'),
past_seasons: resolve(__dirname, 'past_seasons.html'),
}
},
},
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment