263 lines
6.2 KiB
Vue
263 lines
6.2 KiB
Vue
<template>
|
|
<div class="forever-mc">
|
|
<loading v-if="doFetching" :show-on="doFetching" />
|
|
<template v-else>
|
|
<markdown-view :content="computedBindTips" />
|
|
<t-table
|
|
class="table"
|
|
row-key="id"
|
|
:data="playerList"
|
|
:columns="columns"
|
|
>
|
|
<template #lastLoginAt="{ row }">
|
|
<span v-text="Time.toDateTime(row.lastLoginAt)"></span>
|
|
</template>
|
|
<template #action="{ row }">
|
|
<icon
|
|
class="cur-pointer"
|
|
name="FAIL"
|
|
fill="RED"
|
|
@click="doDelete(row.id)"
|
|
v-popup="`解除绑定`"
|
|
/>
|
|
</template>
|
|
</t-table>
|
|
<t-form class="bind-form" :disabled="computedBoundMax">
|
|
<p
|
|
v-if="computedBoundMax"
|
|
class="bound-max-tips red"
|
|
v-text="`已达到最大绑定数量:${maxBind}`"
|
|
></p>
|
|
<t-form-item label="添加绑定" name="name">
|
|
<t-input class="short" v-model="newBind" placeholder="请输入玩家昵称" />
|
|
<template #statusIcon>
|
|
<t-button
|
|
class="submit"
|
|
theme="success"
|
|
:disabled="doSubmittingBind || computedBoundMax"
|
|
@click="doSubmitBind"
|
|
>提交</t-button>
|
|
</template>
|
|
</t-form-item>
|
|
</t-form>
|
|
</template>
|
|
</div>
|
|
<t-dialog
|
|
class="unbind-confirm-dialog"
|
|
v-model:visible="visibleUnbindConfirmDialog"
|
|
attach="body"
|
|
:close-btn="false"
|
|
header="注意: "
|
|
>
|
|
<template #body>
|
|
<markdown-view :content="computedUnbindTips" />
|
|
</template>
|
|
<template #footer>
|
|
<div class="footer">
|
|
<t-button
|
|
class="submit"
|
|
theme="default"
|
|
@click="doSubmitUnbind"
|
|
:loading="doSubmittingUnbind"
|
|
:disabled="doSubmittingUnbind || delayConfirm"
|
|
:content="confirmBtnText"
|
|
/>
|
|
<t-button
|
|
@click="visibleUnbindConfirmDialog = false"
|
|
:disabled="doSubmittingUnbind"
|
|
content="取消"
|
|
/>
|
|
</div>
|
|
</template>
|
|
</t-dialog>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import {
|
|
CommonAPI,
|
|
Icon,
|
|
Loading,
|
|
MarkdownView,
|
|
SettingKey,
|
|
SettingMapper,
|
|
TemplateBizType,
|
|
Time,
|
|
Toolkit
|
|
} from "timi-web";
|
|
import MinecraftAPI from "@/api/MinecraftAPI.ts";
|
|
import { useVisitUserStore } from "@/store/visitUser.ts";
|
|
import { MinecraftPlayer } from "@/types/MinecraftPlayer.ts";
|
|
import { MessagePlugin } from "tdesign-vue-next";
|
|
|
|
defineOptions({
|
|
name: "ForeverMC"
|
|
});
|
|
|
|
const visitUserStore = useVisitUserStore();
|
|
|
|
const columns = computed(() => [
|
|
{
|
|
title: "昵称",
|
|
colKey: "name",
|
|
width: "40%"
|
|
},
|
|
{
|
|
title: "上次登录",
|
|
colKey: "lastLoginAt",
|
|
align: "center"
|
|
},
|
|
{
|
|
align: "right",
|
|
width: "3rem",
|
|
colKey: "id",
|
|
cell: "action"
|
|
}
|
|
]);
|
|
|
|
const tipsBind = ref();
|
|
const tipsUnbind = ref();
|
|
const computedBindTips = computed(() => {
|
|
if (tipsBind.value) {
|
|
return Toolkit.format(tipsBind.value, {
|
|
maxBind: SettingMapper.getValue(SettingKey.FMC_MAX_BIND)
|
|
});
|
|
}
|
|
return "";
|
|
});
|
|
onMounted(() => {
|
|
Toolkit.async(async () => {
|
|
tipsBind.value = await CommonAPI.getTemplate(TemplateBizType.FOREVER_MC, "PLAYER_BIND");
|
|
tipsUnbind.value = await CommonAPI.getTemplate(TemplateBizType.FOREVER_MC, "PLAYER_UNBIND");
|
|
});
|
|
});
|
|
|
|
const playerList = ref<MinecraftPlayer[]>([]);
|
|
const doFetching = ref<boolean>(false);
|
|
async function doFetch() {
|
|
if (!doFetching.value) {
|
|
doFetching.value = true;
|
|
playerList.value.length = 0;
|
|
playerList.value.push(...(await MinecraftAPI.list()));
|
|
}
|
|
doFetching.value = false;
|
|
}
|
|
watch(() => visitUserStore.visitUserView, doFetch);
|
|
onMounted(() => Toolkit.async(async () => await doFetch()));
|
|
|
|
const newBind = ref();
|
|
const maxBind = SettingMapper.getValueRef(SettingKey.FMC_MAX_BIND);
|
|
const doSubmittingBind = ref<boolean>(false);
|
|
async function doSubmitBind() {
|
|
doSubmittingBind.value = true;
|
|
await Toolkit.sleep(1E3);
|
|
MinecraftAPI.bind(newBind.value).then(async () => {
|
|
await MessagePlugin.success("添加绑定成功");
|
|
await doFetch();
|
|
newBind.value = "";
|
|
doSubmittingBind.value = false;
|
|
}).catch(async (msg: string) => {
|
|
await MessagePlugin.error(msg);
|
|
doSubmittingBind.value = false;
|
|
});
|
|
}
|
|
|
|
const doSubmittingUnbind = ref<boolean>(false);
|
|
const visibleUnbindConfirmDialog = ref<boolean>(false);
|
|
const unbindId = ref<number>();
|
|
const delayConfirm = ref<boolean>(false);
|
|
const delaySeconds = ref<number>(8);
|
|
const delayTimer = ref();
|
|
watch(visibleUnbindConfirmDialog, () => delayConfirm.value = visibleUnbindConfirmDialog.value);
|
|
watch(delayConfirm, () => {
|
|
if (delayTimer.value) {
|
|
clearInterval(delayTimer.value);
|
|
}
|
|
delaySeconds.value = 8;
|
|
delayTimer.value = setInterval(() => {
|
|
delaySeconds.value--;
|
|
if (delaySeconds.value === 0) {
|
|
delayConfirm.value = false;
|
|
clearInterval(delayTimer.value);
|
|
}
|
|
}, 1E3);
|
|
});
|
|
const computedBoundMax = computed(() => SettingMapper.getValue(SettingKey.FMC_MAX_BIND) as any as number <= playerList.value.length);
|
|
const computedUnbindTips = computed(() => {
|
|
if (unbindId.value) {
|
|
return Toolkit.format(tipsUnbind.value, {
|
|
name: playerList.value.find(i => i.id === unbindId.value)?.name
|
|
});
|
|
}
|
|
return "";
|
|
});
|
|
const confirmBtnText = computed(() => {
|
|
if (delayConfirm.value) {
|
|
return `确认 (${delaySeconds.value})`;
|
|
}
|
|
if (doSubmittingUnbind.value) {
|
|
return "正在保存..";
|
|
}
|
|
return "确认";
|
|
});
|
|
async function doSubmitUnbind() {
|
|
if (unbindId.value) {
|
|
doSubmittingUnbind.value = true;
|
|
|
|
await Toolkit.sleep(1E3);
|
|
MinecraftAPI.unbind(unbindId.value).then(async () => {
|
|
await MessagePlugin.success("解除绑定成功");
|
|
await doFetch();
|
|
visibleUnbindConfirmDialog.value = doSubmittingUnbind.value = false;
|
|
}).catch(async (msg: string) => {
|
|
await MessagePlugin.error(msg);
|
|
visibleUnbindConfirmDialog.value = doSubmittingUnbind.value = false;
|
|
});
|
|
}
|
|
}
|
|
async function doDelete(id: number) {
|
|
unbindId.value = id;
|
|
visibleUnbindConfirmDialog.value = true;
|
|
}
|
|
</script>
|
|
|
|
<style lang="less" scoped>
|
|
.forever-mc {
|
|
padding: 2rem 4rem;
|
|
display: flex;
|
|
transition: padding 500ms var(--tui-bezier);
|
|
align-items: center;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
|
|
.table {
|
|
max-width: 26rem;
|
|
margin-top: 2rem;
|
|
}
|
|
|
|
.bind-form {
|
|
margin: 1rem 0;
|
|
|
|
.bound-max-tips {
|
|
text-align: center;
|
|
}
|
|
|
|
.submit {
|
|
width: 4rem;
|
|
display: block;
|
|
}
|
|
}
|
|
}
|
|
|
|
@media screen and (max-width: 720px) {
|
|
.forever-mc {
|
|
padding: 2rem;
|
|
transition: padding 500ms var(--tui-bezier);
|
|
}
|
|
}
|
|
|
|
:global(.update-confirm-dialog .footer) {
|
|
display: flex;
|
|
justify-content: center;
|
|
}
|
|
</style>
|