<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>