@@ -1,4 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { h, onMounted, reactive, ref, watch } from "vue"
|
||||||
|
import { useRouter } from "vue-router"
|
||||||
import { NButton } from "naive-ui"
|
import { NButton } from "naive-ui"
|
||||||
import { getRank } from "oj/api"
|
import { getRank } from "oj/api"
|
||||||
import Pagination from "shared/components/Pagination.vue"
|
import Pagination from "shared/components/Pagination.vue"
|
||||||
@@ -12,9 +14,13 @@ const submissionCount = ref(0)
|
|||||||
const contestCount = ref(0)
|
const contestCount = ref(0)
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const message = useMessage()
|
|
||||||
const showModal = ref(false)
|
const showModal = ref(false)
|
||||||
const luckyGuy = ref("")
|
const luckyGuy = ref("")
|
||||||
|
const isRolling = ref(false)
|
||||||
|
const rollingNames = ref<string[]>([])
|
||||||
|
const pulseKey = ref(0)
|
||||||
|
let rollingTimer: ReturnType<typeof setInterval> | null = null
|
||||||
|
let rollingStopper: ReturnType<typeof setTimeout> | null = null
|
||||||
const data = ref<Rank[]>([])
|
const data = ref<Rank[]>([])
|
||||||
const total = ref(0)
|
const total = ref(0)
|
||||||
const query = reactive({
|
const query = reactive({
|
||||||
@@ -71,19 +77,50 @@ async function listRanks() {
|
|||||||
total.value = res.data.total
|
total.value = res.data.total
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function stopRolling() {
|
||||||
|
if (rollingTimer) {
|
||||||
|
clearInterval(rollingTimer)
|
||||||
|
rollingTimer = null
|
||||||
|
}
|
||||||
|
if (rollingStopper) {
|
||||||
|
clearTimeout(rollingStopper)
|
||||||
|
rollingStopper = null
|
||||||
|
}
|
||||||
|
isRolling.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
function startRolling(finalName: string) {
|
||||||
|
stopRolling()
|
||||||
|
if (!rollingNames.value.length) return
|
||||||
|
isRolling.value = true
|
||||||
|
const interval = 80
|
||||||
|
const duration = 2000
|
||||||
|
let index = 0
|
||||||
|
rollingTimer = setInterval(() => {
|
||||||
|
luckyGuy.value = rollingNames.value[index % rollingNames.value.length]
|
||||||
|
index += 1
|
||||||
|
}, interval)
|
||||||
|
rollingStopper = setTimeout(() => {
|
||||||
|
stopRolling()
|
||||||
|
luckyGuy.value = finalName
|
||||||
|
pulseKey.value += 1
|
||||||
|
}, duration)
|
||||||
|
}
|
||||||
|
|
||||||
async function getRandom() {
|
async function getRandom() {
|
||||||
const res = await randomUser10(query.classroom)
|
const res = await randomUser10(query.classroom)
|
||||||
const name = res.data[res.data.length - 1]
|
const names = (res.data as string[]).map(
|
||||||
luckyGuy.value = name.split(query.classroom)[1]
|
(name) => name.split(query.classroom)[1],
|
||||||
|
)
|
||||||
|
rollingNames.value = names
|
||||||
|
const finalName = names[names.length - 1]
|
||||||
|
startRolling(finalName)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getRandomModal() {
|
async function getRandomModal() {
|
||||||
try {
|
|
||||||
await getRandom()
|
|
||||||
showModal.value = true
|
showModal.value = true
|
||||||
} catch (error) {
|
stopRolling()
|
||||||
message.error("没有学生")
|
luckyGuy.value = ""
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(() => query.page, listRanks)
|
watch(() => query.page, listRanks)
|
||||||
@@ -107,7 +144,10 @@ watch(
|
|||||||
)
|
)
|
||||||
|
|
||||||
watch(showModal, (v) => {
|
watch(showModal, (v) => {
|
||||||
if (!v) luckyGuy.value = ""
|
if (!v) {
|
||||||
|
stopRolling()
|
||||||
|
luckyGuy.value = ""
|
||||||
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -160,8 +200,10 @@ watch(showModal, (v) => {
|
|||||||
style="width: 400px"
|
style="width: 400px"
|
||||||
>
|
>
|
||||||
<n-flex vertical justify="center" align="center">
|
<n-flex vertical justify="center" align="center">
|
||||||
<n-h1 class="lucky">{{ luckyGuy }}</n-h1>
|
<n-h1 :key="pulseKey" class="lucky pulse">{{ luckyGuy }}</n-h1>
|
||||||
<n-button block @click="getRandom">再来一次</n-button>
|
<n-button block :disabled="isRolling" @click="getRandom">
|
||||||
|
{{ luckyGuy ? "再来一次" : "开始抽签" }}
|
||||||
|
</n-button>
|
||||||
</n-flex>
|
</n-flex>
|
||||||
</n-modal>
|
</n-modal>
|
||||||
</template>
|
</template>
|
||||||
@@ -183,4 +225,20 @@ watch(showModal, (v) => {
|
|||||||
.lucky {
|
.lucky {
|
||||||
height: 48px;
|
height: 48px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pulse {
|
||||||
|
animation: lucky-pulse 0.6s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes lucky-pulse {
|
||||||
|
0% {
|
||||||
|
transform: scale(0.9);
|
||||||
|
}
|
||||||
|
60% {
|
||||||
|
transform: scale(1.18);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -198,7 +198,8 @@ const classColumns: DataTableColumn<ClassRank>[] = [
|
|||||||
{
|
{
|
||||||
title: "班级",
|
title: "班级",
|
||||||
key: "class_name",
|
key: "class_name",
|
||||||
render: (row) => `${row.class_name.slice(0, 2)}计算机${row.class_name.slice(2)}班`,
|
render: (row) =>
|
||||||
|
`${row.class_name.slice(0, 2)}计算机${row.class_name.slice(2)}班`,
|
||||||
width: 200,
|
width: 200,
|
||||||
titleAlign: "center",
|
titleAlign: "center",
|
||||||
align: "center",
|
align: "center",
|
||||||
|
|||||||
@@ -289,6 +289,6 @@ function handleMenuSelect(key: string) {
|
|||||||
.title {
|
.title {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
margin: 0 20px;
|
margin: 0 16px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user