Files
tk-mini-program-PC/src/components/mineSubComponent/PKmessage.vue
pengxiaolong 9c82553013 优化代码
2025-08-20 22:11:41 +08:00

977 lines
26 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<!-- PK信息 -->
<div class="pk-message">
<el-splitter>
<el-splitter-panel>
<div class="demo-panel">
<div
class="anchor-library-list"
style="overflow: auto"
v-infinite-scroll="load"
>
<div class="anchor-library-card" v-for="(item, index) in list" :key="index">
<div class="card-content">
<div class="card-avatar">
<img
:src="item.anchorIcon"
style="width: 100%; height: 100%; border-radius: 100px"
alt=""
/>
</div>
<div class="personalInformation">
<div class="name">{{ item.anchorId }}</div>
<div class="GenderAndCountry">
<div
class="Gender"
:style="{
background: item.sex == 1 ? '#59D8DB' : '#F3876F',
}"
>
{{ item.sex == 1 ? "男" : "女" }}
</div>
<div class="Country">{{ item.country }}</div>
<div class="goldbox">
<img
class="gold-icon"
src="https://vv-1317974657.cos.ap-shanghai.myqcloud.com/util/gold.png"
alt=""
/>
<div class="gold">
金币
<div class="gold-num">{{ item.coin }}K</div>
</div>
</div>
<div class="goldbox">
<img
class="gold-icon"
src="https://vv-1317974657.cos.ap-shanghai.myqcloud.com/util/session.png"
alt=""
/>
<div class="gold">
场次
<div class="gold-num">{{ item.pkNumber }}</div>
</div>
</div>
</div>
<div class="time">
PK时间:{{ TimestamptolocalTime(item.pkTime * 1000) }}
</div>
</div>
<div class="card-Operation">
<div class="modify" @click="topPosition(item)">
<!-- 置顶 -->
<img
v-if="item.isPin == false"
class="delete-icon"
src="@/assets/topPosition.png"
alt=""
/>
<img
v-if="item.isPin == true"
class="delete-icon"
src="@/assets/unpinned.png"
alt=""
/>
</div>
<!-- 修改 -->
<div class="modify" @click="modify(item)">
<img class="modify-icon" src="@/assets/Editor.png" alt="" />
</div>
<!-- 删除 -->
<div class="delete" @click="deletePKInfo(item)">
<img class="modify-icon" src="@/assets/Delete.png" alt="" />
</div>
</div>
</div>
</div>
</div>
</div>
</el-splitter-panel>
<el-splitter-panel size="25%" :resizable="false" collapsible>
<!-- 添加或修改主播 -->
<div class="demo-panel">
<div class="add-anchor-library">
<div class="title">
<img class="titleimg" src="@/assets/embellish.png" alt="" />
<div v-if="!modifyDialogstate">发布新PK</div>
<div v-if="modifyDialogstate">修改PK信息</div>
<img class="titleimg" src="@/assets/embellish.png" alt="" />
</div>
<div class="add-anchor-library-content">
<div class="input-name">
<!-- 主播名称 -->
<el-input
class="input-name-input"
v-model="anchorName"
size="large"
placeholder="请输入主播名称"
@blur="handleChange()"
/>
<div class="myanchor">
<div class="myanchor-btn" @click="myAnchorDialogVisible = true">
选择我的主播
</div>
</div>
</div>
<div class="country">
<!-- 国家 -->
<el-select-v2
v-model="countryvalue"
filterable
:options="country"
placeholder="请选择国家"
size="large"
style="vertical-align: middle"
class="select"
/>
</div>
<div class="gender">
<!-- 性别 -->
<el-select-v2
v-model="gendervalue"
filterable
:options="genderOptions"
size="large"
placeholder="请选择性别"
style="vertical-align: middle"
class="select"
/>
</div>
<div class="timeselect">
<el-date-picker
v-model="timevalue"
type="datetime"
placeholder="选择PK时间"
size="large"
style="width: 100%; height: 100%"
format="YYYY/MM/DD hh:mm"
value-format="x"
/>
</div>
<div class="Gold-sessions">
<div class="Goldcoinbox-right">
<div class="Goldcoinbox-text">金币数单位为K</div>
<el-input-number v-model="goldvalue" controls-position="right" />
</div>
<div class="Goldcoinbox-right">
<div class="Goldcoinbox-text">场次</div>
<el-input-number v-model="sessionnum" controls-position="right" />
</div>
</div>
<div class="remark">
<!-- 备注 -->
<textarea
v-model="remark"
class="textarea"
style="width: 100%; height: 100%"
maxlength="50"
placeholder="请输入备注(选填)"
/>
</div>
<div class="Confirm" @click="Confirm()">确认</div>
<div class="Reset" @click="Reset()">重置</div>
<div class="Reset" v-if="modifyDialogstate" @click="cancel()">取消</div>
</div>
</div>
</div>
</el-splitter-panel>
</el-splitter>
</div>
<!-- 确认删除弹窗 -->
<el-dialog
center
class="center-dialog"
v-model="centerDialogVisible"
title="提示"
width="200"
align-center
>
<span>确认删除该条主播PK信息</span>
<template #footer>
<div class="dialog-footer">
<el-button @click="centerDialogVisible = false">取消</el-button>
<el-button type="primary" @click="deleteAnchor()"> 确认 </el-button>
</div>
</template>
</el-dialog>
<!-- 选择我的主播弹窗 -->
<el-dialog align-center center v-model="myAnchorDialogVisible" title="选择我的主播库主播" width="800">
<div class="myanchor-content">
<div class="myanchor-list">
<div
class="anchor-library-card"
v-for="(item, index) in anchorLibrary"
:key="index"
@click="selectStreamerLibrary(item)"
>
<div class="card-content" :style="{ backgroundImage: item == selectAnchor ? '' : '',background: item == selectAnchor ? '#FFFBFA' : '',border: item == selectAnchor ? '1px solid #F4D0C9' : ''}">
<div class="card-avatar">
<img
style="width: 100%; height: 100%; border-radius: 100px"
:src="item.headerIcon"
alt=""
/>
</div>
<div class="personalInformation">
<div class="name">{{ item.anchorId }}</div>
<div class="GenderAndCountry">
<div
class="Gender"
:style="{
background: item.gender == 1 ? '#59D8DB' : '#F3876F',
}"
>
{{ item.gender == 1 ? "男" : "女" }}
</div>
<div class="Country">{{ item.country }}</div>
</div>
</div>
</div>
</div>
</div>
<div class="myanchor-dialog-btn">
<div class="Reset" @click="myAnchorDialogVisible = false">取消</div>
<div class="Confirm" @click="myAnchorDialogConfirm()">确认</div>
</div>
</div>
</el-dialog>
<!-- 置顶弹窗 -->
<el-dialog align-center center v-model="topPositionstate" title="置顶" width="800">
<div class="topPosition-content">
<div class="topPosition-content-title">
置顶后该用户将在首页置顶并在指定时长内享有置顶特权置顶时长
不足1小时系统将按1小时计算积分扣除请选择置顶时长
</div>
<div class="topPosition-input">
<el-select-v2
v-model="topPositionvalue"
:options="topPositionOptions"
placeholder="请选择置顶时长"
style="width: 100%"
size="large"
filterable
/>
</div>
<div class="myanchor-dialog-btn">
<div class="Reset" @click="topPositionstate = false">取消</div>
<div class="Confirm" @click="topPositionstateConfirm()">确认</div>
</div>
</div>
</el-dialog>
<!-- 取消置顶弹窗 -->
<el-dialog center v-model="cancelTopPositionstate" title="取消置顶" width="700" align-center>
<div class="cancelTopPosition">
<div class="cancelTopPosition-content">
您确定要取消置顶吗?取消置顶后该用户将不再享有置顶特权但仍可继续参与
PK挑战若置顶时长不足1小时系统将按1小时计算积分扣除取消后按实际使用时长比例返还剩余积分是否确认执行此操作?
</div>
<div class="myanchor-dialog-btn">
<div class="Reset" @click="cancelTopPositionstate = false">取消</div>
<div class="Confirm" @click="cancelTopPositionstateConfirm()">确认</div>
</div>
</div>
</el-dialog>
</template>
<script setup>
import {
ref, // 响应式基础
watch, // 侦听器
onMounted, // 组件挂载完成后执行
onUpdated, // 组件更新后执行
onUnmounted, // 组件销毁前执行
} from "vue";
import {
getPkInfo,
getAnchorAvatar,
releasePkInfo,
editPkInfo,
delPkInfo,
topPkInfo,
cancelTopPkInfo,
getAnchorList,
} from "@/api/account";
import { TimestamptolocalTime } from "@/utils/timeConversion.js";
import { getCountryNamesArray } from "../../utils/countryUtil";
import { ElLoading } from "element-plus";
import { ElMessage } from "element-plus";
import { setStorage, getStorage, getPromiseStorage } from "@/utils/storage.js";
const country = ref([]);
country.value = getCountryNamesArray(); //国家条目
const genderOptions = [
{ value: 1, label: "男" },
{ value: 2, label: "女" },
]; // 性别选项
const user = ref(null); // 用户信息
const gendervalue = ref(null); // 性别值
const countryvalue = ref(null); //国家
const anchorName = ref(null); // 主播名称
const AnchorProfilePicture = ref(""); // 主播头像
const timevalue = ref(null); // PK时间
const goldvalue = ref(null); // 金币数
const sessionnum = ref(null); // 场次
const remark = ref(null); // 备注
const list = ref([]); // PK信息列表
const page = ref(0); // 页码
const centerDialogVisible = ref(false); // 确认删除弹窗
const modifyDialogstate = ref(false); // 修改弹窗
const modifyDialogstateID = ref(null); // 修改弹窗ID
const myAnchorDialogVisible = ref(false); // 选择我的主播弹窗
const anchorLibrary = ref([]); // 我的主播库
const selectAnchor = ref(null); //选中的主播信息
const topPositionstate = ref(false); // 置顶弹窗
const cancelTopPositionstate = ref(false); // 取消置顶弹窗
const topPositiondata = ref(null); // 置顶or取消置顶数据
const topPositionvalue = ref(null); // 置顶时长
const topPositionOptions = ref([]); // 置顶时长选项
// 选择我的主播
function selectStreamerLibrary(item) {
selectAnchor.value = item;
}
function myAnchorDialogConfirm() {
AnchorProfilePicture.value = selectAnchor.value.headerIcon.split("/").pop();
anchorName.value = selectAnchor.value.anchorId;
gendervalue.value = selectAnchor.value.gender;
countryvalue.value = selectAnchor.value.country;
myAnchorDialogVisible.value = false;
}
//获取我的主播库数据
function getMyAnchorLibrary() {
getAnchorList({ id: user.value.id }).then((res) => {
console.log("anchorLibrary", res);
anchorLibrary.value = res;
});
}
// 置顶or取消置顶
function topPosition(item) {
if (item.isPin == false) {
topPositionstate.value = true;
const currentTime = Math.floor(Date.now() / 1000);
topPositionOptions.value = generateTimeOptions(currentTime, item.pkTime);
} else {
cancelTopPositionstate.value = true;
}
topPositiondata.value = item;
}
// 确认置顶
function topPositionstateConfirm() {
if (topPositionvalue.value == 0) {
topPositionstate.value = false;
return;
}
topPkInfo({
articleId: topPositiondata.value.id,
pinExpireTime: topPositionvalue.value,
}).then((res) => {
ElMessage.success("置顶成功");
topPositionstate.value = false;
list.value = [];
page.value = 0;
PKInfo();
});
}
// 确认取消置顶
function cancelTopPositionstateConfirm() {
cancelTopPkInfo({articleId: topPositiondata.value.id}).then((res) => {
ElMessage.success(res);
cancelTopPositionstate.value = false;
list.value = [];
page.value = 0;
PKInfo();
});
}
//计算置顶时长
function generateTimeOptions(currentTimestamp, targetTimestamp) {
const timeDiff = targetTimestamp - currentTimestamp;
// 时间差小于0说明已过期
if (timeDiff <= 0) return [{ value: 0, label: "已过期" }];
const hours = Math.ceil(timeDiff / 3600);
const options = Array.from({ length: hours }, (_, i) => {
const hour = i + 1;
return {
value: currentTimestamp + hour * 3600,
label: `${hour}个小时`,
};
});
return options;
}
//修改
function modify(item) {
if (modifyDialogstate.value) {
cancel();
return;
}
modifyDialogstateID.value = item.id;
modifyDialogstate.value = true;
countryvalue.value = item.country;
gendervalue.value = item.sex;
anchorName.value = item.anchorId;
AnchorProfilePicture.value = item.anchorIcon.split("/").pop();
timevalue.value = item.pkTime * 1000;
goldvalue.value = item.coin;
sessionnum.value = item.pkNumber;
remark.value = item.remark;
}
// 取消修改
function cancel() {
modifyDialogstateID.value = null;
modifyDialogstate.value = false;
countryvalue.value = null;
gendervalue.value = null;
anchorName.value = null;
AnchorProfilePicture.value = null;
timevalue.value = null;
goldvalue.value = null;
sessionnum.value = null;
remark.value = null;
}
// 删除
const deletePKInfodata = ref(null);
function deletePKInfo(item) {
deletePKInfodata.value = item;
centerDialogVisible.value = true;
}
// 确认删除
function deleteAnchor() {
centerDialogVisible.value = false;
delPkInfo({
id: deletePKInfodata.value.id,
}).then((res) => {
ElMessage.success("删除成功");
list.value = [];
page.value = 0;
PKInfo();
});
}
// 确认发布
function Confirm() {
const currentTime = Date.now();
if (anchorName.value == null || anchorName.value == "") {
ElMessage.error("请输入主播名称");
return;
}
if (gendervalue.value == null || gendervalue.value == "") {
ElMessage.error("请选择性别");
return;
}
if (timevalue.value == null || timevalue.value == "") {
ElMessage.error("请选择PK时间");
return;
}
if (currentTime > timevalue.value) {
ElMessage.error("PK时间不能早于当前时间");
return;
}
if (countryvalue.value == null || countryvalue.value == "") {
ElMessage.error("请选择国家");
return;
}
if (goldvalue.value == null || goldvalue.value == "") {
ElMessage.error("请输入金币数");
return;
}
if (sessionnum.value == null || sessionnum.value == "") {
ElMessage.error("请输入场次");
return;
}
const loading = ElLoading.service({
lock: true,
text: "发布中....",
background: "rgba(0, 0, 0, 0.7)",
});
if (modifyDialogstate.value) {
editPkInfo({
id: modifyDialogstateID.value,
anchorId: anchorName.value,
pkTime: timevalue.value / 1000,
sex: gendervalue.value,
country: countryvalue.value,
coin: goldvalue.value,
remark: remark.value,
status: 0,
senderId: user.value.id,
anchorIcon: AnchorProfilePicture.value,
pkNumber: sessionnum.value,
}).then((res) => {
loading.close();
ElMessage.success("修改成功");
list.value = [];
page.value = 0;
PKInfo();
cancel();
});
} else {
releasePkInfo({
anchorId: anchorName.value,
pkTime: timevalue.value / 1000,
sex: gendervalue.value,
country: countryvalue.value,
coin: goldvalue.value,
remark: remark.value,
status: 0,
senderId: user.value.id,
anchorIcon: AnchorProfilePicture.value,
pkNumber: sessionnum.value,
})
.then((res) => {
loading.close();
ElMessage.success("发布成功");
list.value = [];
page.value = 0;
PKInfo();
Reset();
})
.catch((err) => {
loading.close();
console.log(err);
});
}
}
// 重置
function Reset() {
anchorName.value = null;
gendervalue.value = null;
timevalue.value = null;
goldvalue.value = null;
sessionnum.value = null;
remark.value = null;
countryvalue.value = null;
}
//输入框失去焦点
function handleChange() {
if (anchorName.value == null || anchorName.value == "") {
ElMessage.error("请输入主播名称");
return;
}
const loading = ElLoading.service({
lock: true,
text: "查询主播中....",
background: "rgba(0, 0, 0, 0.7)",
});
getAnchorAvatar({ name: anchorName.value })
.then((res) => {
loading.close();
AnchorProfilePicture.value = res;
ElMessage.success("查询成功");
})
.catch((err) => {
loading.close();
});
}
// 加载更多
function load() {
page.value++;
PKInfo();
}
//PK信息列表
function PKInfo() {
getPkInfo({
userId: user.value.id,
page: page.value,
size: 10,
}).then((res) => {
console.log("list", res);
list.value.push(...res);
});
}
// 组件挂载完成后执行
onMounted(() => {
getPromiseStorage("user")
.then((res) => {
user.value = res;
PKInfo();
getMyAnchorLibrary();
})
.catch((err) => {
console.log(err);
});
});
onUpdated(() => {
// 组件更新后执行
});
onUnmounted(() => {
// 组件销毁前执行
});
const refname = ref(""); //
watch(refname, async (newQuestion, oldQuestion) => {
// 变化后执行
});
</script>
<style scoped lang="less">
.pk-message {
width: 100%;
height: 100%;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.demo-panel {
width: 100%;
height: 100%;
}
.anchor-library-list {
width: 100%;
height: 100%;
}
.anchor-library-card {
width: 100%;
height: 150px;
margin-bottom: 15px;
margin-top: 15px;
display: flex;
justify-content: center;
align-items: center;
}
.card-content {
width: 90%;
height: 100%;
border-radius: 10px;
background-image: url(@/assets/PKbackground.png);
background-size: 100% 100%;
transition: all 0.4s ease;
display: flex;
align-items: center;
}
.card-content:hover {
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.3);
transform: scale(1.08);
opacity: 0.8;
}
.card-avatar {
width: 100px;
height: 100px;
border-radius: 50%;
background-color: #ffffff;
margin-left: 20px;
}
.personalInformation {
width: calc(100% - 340px);
height: 100px;
margin-left: 20px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.name {
font-size: 20px;
font-weight: bold;
color: #333333;
}
.GenderAndCountry {
display: flex;
align-items: center;
}
.Gender {
font-size: 16px;
color: #ffffff;
border-radius: 50px;
padding: 5px 20px 5px 20px;
margin-right: 20px;
line-height: 100%;
}
.Country {
font-size: 16px;
color: #03aba8;
border-radius: 50px;
background-color: #e4f9f9;
padding: 2px 20px 2px 20px;
}
.goldbox {
margin-left: 20px;
display: flex;
align-items: center;
}
.gold-icon {
width: 20px;
height: 20px;
margin-right: 5px;
}
.gold {
color: @Prompt-text-color;
font-size: 16px;
display: flex;
align-items: center;
}
.gold-num {
font-size: 16px;
color: @font-color;
font-weight: bold;
}
.time {
font-size: 14px;
color: @Prompt-text-color;
}
.card-Operation {
width: 200px;
height: 100px;
margin-left: 20px;
margin-right: 20px;
display: flex;
align-items: center;
justify-content: space-around;
}
.modify-icon {
width: 30px;
height: 30px;
transition: all 0.4s ease;
}
.modify-icon:hover {
transform: scale(1.3);
}
.modify-icon:active {
transition: all 0.1s ease;
transform: scale(0.95) !important;
}
.delete-icon {
width: 20px;
height: 28px;
transition: all 0.4s ease;
}
.delete-icon:hover {
transform: scale(1.3);
}
.delete-icon:active {
transition: all 0.1s ease;
transform: scale(0.95) !important;
}
.add-anchor-library {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
}
.title {
width: 80%;
height: 70px;
font-size: 24px;
font-weight: bold;
color: #333333;
text-align: center;
line-height: 70px;
display: flex;
align-items: center;
justify-content: space-evenly;
}
.titleimg {
width: 44px;
height: 30px;
}
.add-anchor-library-content {
width: 100%;
height: calc(100% - 70px);
display: flex;
flex-direction: column;
align-items: center;
}
.input-name {
width: 90%;
height: 50px;
margin-top: 20px;
display: flex;
}
.input-name-input {
width: 70%;
height: 40px;
}
.myanchor {
width: 30%;
height: 40px;
display: flex;
justify-content: center;
align-items: center;
}
.myanchor-btn {
width: 90%;
height: 40px;
border-radius: 2px;
font-size: 12px;
background-image: linear-gradient(to top, #4fcacd, #5fdbde);
text-align: center;
line-height: 40px;
transition: all 0.4s ease;
color: #ffffff;
}
.myanchor-btn:hover {
transform: scale(1.03);
}
.myanchor-btn:active {
transition: all 0.1s ease;
transform: scale(0.95) !important;
}
.country {
width: 90%;
height: 50px;
margin-top: 20px;
}
.gender {
width: 90%;
height: 50px;
margin-top: 20px;
}
.select {
width: 100%;
}
.timeselect {
width: 90%;
height: 40px;
margin-top: 20px;
}
.Gold-sessions {
width: 90%;
height: 50px;
margin-top: 20px;
display: flex;
justify-content: space-between;
align-items: center;
}
.Goldcoinbox-right {
display: flex;
flex-direction: column;
}
.Goldcoinbox-text {
font-size: 12px;
color: @Prompt-text-color;
}
.remark {
margin-top: 30px;
width: 98%;
height: 100px;
display: flex;
align-items: center;
justify-content: center;
// margin-top: 10px;
}
.textarea {
width: 90%;
height: 90%;
max-height: 90%;
border: 1px solid #4fcacd;
border-radius: 10px;
outline: none;
overflow: hidden;
background-color: #ff000000;
font-size: 16px;
margin-left: 5px;
margin-right: 5px;
color: #000000;
letter-spacing: 1px;
resize: none;
}
.Confirm {
width: 400px;
height: 50px;
margin-top: 40px;
text-align: center;
line-height: 50px;
background-image: linear-gradient(to top, #4fcacd, #5fdbde);
color: #ffffff;
font-size: 22px;
transition: all 0.4s ease;
border-radius: 25px;
}
.Confirm:active {
transition: all 0.1s ease;
transform: scale(0.95) !important;
}
.Confirm:hover {
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.3);
transform: scale(1.05);
opacity: 0.8;
}
.Reset {
width: 400px;
height: 50px;
margin-top: 30px;
text-align: center;
line-height: 50px;
background-image: linear-gradient(to top, #e4ffff, #ffffff);
border: 1px solid #4fcacd;
color: #03aba8;
font-size: 22px;
transition: all 0.4s ease;
border-radius: 25px;
}
.Reset:hover {
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.3);
transform: scale(1.05);
opacity: 0.8;
}
.Reset:active {
transition: all 0.1s ease;
transform: scale(0.95) !important;
}
.myanchor-content {
width: 100%;
height: 600px;
}
.myanchor-list {
width: 100%;
height: 500px;
background-color: #e0f4f1;
border-radius: 16px;
border: 1px solid #4fcacd;
overflow: auto;
}
.myanchor-list::-webkit-scrollbar {
display: none;
}
.myanchor-dialog-btn {
width: 100%;
height: 100px;
display: flex;
justify-content: space-around;
align-items: center;
}
.topPosition-content {
width: 100%;
height: 500px;
display: flex;
align-items: center;
flex-direction: column;
}
.topPosition-content-title {
width: 80%;
height: 100px;
margin-top: 50px;
color: #999999;
font-size: 24px;
}
.topPosition-input {
width: 80%;
margin-top: 70px;
margin-bottom: 70px;
}
.cancelTopPosition{
width: 100%;
height: 400px;
display: flex;
flex-direction: column;
align-items: center;
}
.cancelTopPosition-content{
width: 80%;
color: #999999;
font-size: 24px;
height: 300px;
}
</style>