chore: v3.0.0-4030620241128001

main
刘东阳 3 months ago
parent 4dff64e8b1
commit 48961be22b

@ -52,9 +52,12 @@
"@dcloudio/uni-quickapp-webview": "3.0.0-4030620241128001",
"@dcloudio/uni-ui": "^1.5.7",
"@hyoga/uni-socket.io": "^3.0.4",
"axios": "^1.9.0",
"axios-adapter-uniapp": "^0.1.4",
"dayjs": "^1.11.13",
"moment": "^2.30.1",
"pinia": "^3.0.2",
"uuid": "^11.1.0",
"vue": "^3.4.21",
"vue-i18n": "^9.1.9",
"vue-router": "^4.5.1"

@ -1,10 +1,438 @@
<script setup lang="ts">
import { ref } from 'vue'
</script>
<template>
<view>签到</view>
<view class="checkin-container">
<!-- 累计时间显示 -->
<view>
<span>{{qdttitle}}</span>
</view>
<view v-if="finish==='no'">
<div class="time-display">
<span>累计时间</span>
<span>{{ formattedTime }}</span>
</div>
<div v-if="selecttype === '普通签到'">
<!-- 立即签到按钮 -->
<button
v-if="totalTime > 0 "
@click="handleCheckIn"
class="checkin-button"
>
立即签到
</button>
</div>
<div v-if="selecttype === '伪签到'">
<!-- 立即签到按钮 -->
<button
v-if="totalTime > 0 "
@click="handleCheckIn"
class="checkin-button"
>
立即签到
</button>
</div>
<div v-if="selecttype === '密码签到'">
<div class="password-checkin">
<p>请输入签到密码</p>
<input type="password" v-model="password" placeholder="密码" />
<button @click="handlePasswordCheckIn"></button>
<div v-if="passwordCheckInResult" :class="['checkin-result', passwordCheckInResult === '签到成功' ? 'success' : 'error']">
{{ passwordCheckInResult }}
</div>
</div>
</div>
<div v-if="selecttype === '二维码签到'">
<div class="scan-checkin">
<p>请扫描二维码进行签到</p>
<button @click="onDecode" class="scan-button">开始扫码</button>
</div>
</div>
</view>
<!-- 不可签到状态 -->
<div v-if="totalTime <= 0 && checkInResult !== '签到成功'" class="checkin-result">
不可签到
</div>
<view v-if="finish==='finish'">
<!-- 签到成功提示 -->
<div v-if="selecttype!=='伪签到'" class="checkin-result">
{{ checkInResult }}
</div>
<div v-if="selecttype==='伪签到'" class="checkin-result">
请诚信学习
</div>
<div v-if="checkInResult === '签到成功'" class="checkin-result-time">
{{qidndaotime}}
</div>
</view>
</view>
</template>
<script setup lang="ts">
import { ref, onMounted, onUnmounted, computed } from 'vue';
import {onLoad} from "@dcloudio/uni-app";
import moment from "moment";
//
const selecttype = ref('扫描签到');
const initialTime = 10; // 60
const totalTime = ref(initialTime);
const intervalId = ref<number | null>(null); //
const uid=ref('123')
const qdttitle=ref('')
//
const formattedTime = computed(() => {
const minutes = Math.floor(totalTime.value / 60);
const seconds = totalTime.value % 60;
return `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
});
const password = ref(''); //
const passwordCheckInResult = ref(''); //
const endtime=ref('')
const finish=ref('no')
const qidndaotime=ref('')
const checkInResult = ref('');
const handlePasswordCheckIn = () => {
//
const correctPassword = '123456'; //
if (totalTime.value > 0) {
uni.request({
url: 'http://localhost:3400/apistu/qdstuinclass_password',
method: 'POST',
data: { // GET `data` `params` :ml-citation{ref="8" data="citationList"}
uuid: uid.value,
kch:'202413501',
kctime:'n8z1A1',
xuehao: '202413501062',
output:'no',
password:password.value,
time:moment().format('YYYY-MM-DD HH:mm:ss')
},
success: (res) => { /* ... */
if(res.data.stats==="ok") {
console.log(res.data);
passwordCheckInResult.value = '签到成功';
stopTimer(); //
}else{
uni.showModal({
title: '提示',
content: '签到密码错误',
});
}
}
});
}
else {
passwordCheckInResult.value = '签到时间已结束';
}
};
onLoad((options) => {
console.log('load', options)
if(options) {
console.log('options:', options.uuid)
uni.request({
url: 'http://localhost:3400/apistu/getinclassactivestu_ex',
method: 'GET',
data: { // GET `data` `params` :ml-citation{ref="8" data="citationList"}
uuid: options.uuid,
xuehao:'202413501062'
},
success: (res) => { /* ... */
console.log(res.data)
if(res.data.length>0) {
qidndaotime.value = res.data[0].time;
checkInResult.value = '签到成功';
finish.value = 'finish'
}
}
});
uid.value=options.uuid
uni.request({
url: 'http://localhost:3400/apistu/getinclassactive',
method: 'GET',
data: { // GET `data` `params` :ml-citation{ref="8" data="citationList"}
uuid: options.uuid
},
success: (res) => { /* ... */
console.log(res.data)
let infor=JSON.parse(res.data.infor)
console.log(infor.endtime)
endtime.value = infor.endtime
qdttitle.value=infor.title
selecttype.value=infor.lxA
}
});
}
})
//
const startTimer = () => {
intervalId.value = setInterval(() => {
if (totalTime.value > 0) {
totalTime.value=moment(endtime.value).diff(moment(),'seconds')
} else {
stopTimer();
}
}, 1000);
};
//
const stopTimer = () => {
if (intervalId.value !== null) {
clearInterval(intervalId.value);
intervalId.value = null;
}
};
//
const handleCheckIn = () => {
if (totalTime.value > 0) {
//
checkInResult.value = '签到成功';
stopTimer(); //
uni.request({
url: 'http://localhost:3400/apistu/qdstuinclass',
method: 'POST',
data: { // GET `data` `params` :ml-citation{ref="8" data="citationList"}
uuid: uid.value,
kch:'202413501',
kctime:'n8z1A1',
xuehao: '202413501062',
output:'no',
time:moment().format('YYYY-MM-DD HH:mm:ss')
},
success: (res) => { /* ... */
finish.value='finish'
checkInResult.value = '签到成功';
}
});
} else {
checkInResult.value = '已过签到时间';
}
};
//
const onDecode = () => {
uni.scanCode({
success: (res) => {
console.log('扫码结果:', res.result);
if (totalTime.value > 0) {
console.log(1245)
if(JSON.parse(res.result).qduuid){
uni.request({
url: 'http://localhost:3400/apistu/qdstuinclass_qrcode1',
method: 'POST',
data: { // GET `data` `params` :ml-citation{ref="8" data="citationList"}
uuid: uid.value,
kch:'202413501',
kctime:'n8z1A1',
xuehao: '202413501062',
output:'no',
qduuid:JSON.parse(res.result).qduuid,
time:moment().format('YYYY-MM-DD HH:mm:ss')
},
success: (res_2) => { /* ... */
if(res_2.data.stats==="ok") {
console.log(res.data);
passwordCheckInResult.value = '签到成功';
uni.$emit('finish', uid.value)
stopTimer(); //
}else{
uni.showModal({
title: '提示',
content: '签到密码错误',
});
}
}
});
}
checkInResult.value = '签到成功';
stopTimer();
} else {
checkInResult.value = '已过签到时间';
}
},
fail: (err) => {
console.error('扫码失败:', err);
}
});
};
//
onMounted(() => {
startTimer();
});
//
onUnmounted(() => {
stopTimer();
});
</script>
<style scoped>
</style>
.checkin-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh; /* 使容器高度为视口高度 */
padding: 20px;
background-color: #f9f9f9;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
.time-display {
text-align: center;
margin-bottom: 20px;
font-size: 14px; /* 缩小“累计时间”文本的字体大小 */
color: #333;
}
.time-display span:first-child {
display: block;
font-size: 14px;
color: #666;
margin-bottom: 5px;
}
.time-display span:last-child {
font-size: 36px;
color: #333;
}
.checkin-button {
background-color: #ff4d4f;
color: white;
border: none;
border-radius: 50%;
width: 150px; /* 进一步增大按钮尺寸 */
height: 150px;
font-size: 24px; /* 增大按钮内文字的字体大小 */
transition: background-color 0.3s;
display: flex;
align-items: center;
justify-content: center;
margin: 20px 0; /* 调整按钮与上下元素的间距 */
}
.checkin-button:hover {
background-color: #e53935;
}
.checkin-result {
margin-top: 20px;
font-size: 18px;
color: green;
font-weight: bold;
}
.password-checkin {
text-align: center;
margin-bottom: 20px;
}
.password-checkin p {
font-size: 18px;
color: #333;
margin-bottom: 10px;
}
.password-checkin input {
padding: 10px;
margin-bottom: 10px;
border: 1px solid #ccc;
border-radius: 4px;
width: 200px;
text-align: center;
}
.password-checkin button {
background-color: #ff4d4f;
color: white;
border: none;
border-radius: 50px;
width: 150px;
height: 40px;
font-size: 16px;
transition: background-color 0.3s;
}
.password-checkin button:hover {
background-color: #e53935;
}
.checkin-result {
margin-top: 20px;
font-size: 18px;
margin-left: 10px;
font-weight: bold;
}
.checkin-result.success {
color: green;
}
.checkin-result-time {
margin-top: 20px;
font-size: 12px;
font-weight: bold;
color: #7f8fa6;
}
.checkin-result-time.success {
color: green;
}
.checkin-result.error {
color: red;
}
.scan-checkin {
text-align: center;
margin-bottom: 20px;
}
.scan-checkin p {
font-size: 18px;
color: #333;
margin-bottom: 10px;
}
.scan-button {
background-color: #4CAF50; /* 绿色背景 */
color: white;
border: none;
border-radius: 50px; /* 圆角按钮 */
padding: 12px 24px;
font-size: 16px;
font-weight: bold;
width: 80%;
max-width: 300px;
margin: 10px auto;
display: block;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); /* 阴影增加质感 */
transition: background-color 0.3s ease, transform 0.2s ease;
}
.scan-button:hover {
background-color: #45a049;
transform: translateY(-2px); /* 微动效果 */
}
.scan-button:active {
transform: scale(0.98); /* 按下缩小一点 */
}
</style>

@ -1,10 +1,318 @@
<script setup lang="ts">
import { ref } from 'vue'
</script>
<template>
<view>讨论</view>
<view class="discussion">
<!-- 教师区域 -->
<view v-if="content.length > 0">
<view v-for="item in content" :key="item.tid">
<!-- 用户信息 -->
<view class="user-info">
<image class="avatar" :src="item.avatar"></image>
<view class="user-details">
<text class="username">{{ item.username }}</text><br>
<text class="timestamp">{{ item.timestamp }} 回复:{{ reply }} 阅读:{{ reading }}</text>
</view>
</view>
<!-- 标题 -->
<view class="title">
<text>{{ item.title }}</text>
</view>
<!-- 内容 -->
<view class="content">
<view v-for="(item_xiang,index) in item.contentlist">
<view v-if="item_xiang.leixing==='video'">
<view>
<video :src="item_xiang.sp"></video>
</view>
</view>
<view v-if="item_xiang.leixing==='wb'">
<view>
<text>{{item_xiang.wb}}</text>
</view>
</view>
<view v-if="item_xiang.leixing==='pic'">
<view>
<image :src="item_xiang.pic" mode="aspectFit" />
</view>
</view>
</view>
</view>
</view>
</view>
<!-- 评论区 -->
<view class="comments">
<view v-for="comment in comments" :key="comment.id" class="comment">
<image class="avatar" :src="comment.avatar"></image>
<view class="comment-details">
<text class="username">{{ comment.author }}</text><br>
<text class="timestamp">{{ moment(comment.fabutime).format("MM-DD HH:mm") }}</text><br>
<text class="comment-content">{{ comment.neirong }}</text>
</view>
</view>
</view>
<!-- 发表评论 -->
<view class="comment-input">
<button class="add-comment-btn">+</button>
<input v-model="newCommentContent" placeholder="写下你的评论..."/>
<button @click="submitComment" class="submit-button">发表</button>
</view>
</view>
</template>
<script setup lang="ts">
import { computed, ref } from 'vue'
import {onLoad} from "@dcloudio/uni-app";
import uuidv4 from "../../utile/uuid/uuidv4";
import moment from "moment";
//
const content = ref([
{
tid: 0,
username: '白雪芹',
avatar: '/static/course-image/Avatar.png',
timestamp: '04-25 11:46',
title: '思考题',
content: '简述视频中的两起民事纠纷过程回答1、为什么案例1中的被告需承担民事责任、受到民事制裁2、为什么案例1中的被告不构成“高空抛物罪”3、案例2中的被告为什么无需担责请找到《中华人民共和国民法典》的具体条文规定分析讨论法院的判决是否合理。',
contentlist:[]
}
])
const comments = ref([])
const reply = computed(() => comments.value.length)
const reading = ref(1)
const uid=ref('12')
const finish=ref('no')
//
onLoad((options) => {
console.log('load', options)
if(options) {
console.log('options:', options.uuid)
uid.value=options.uuid
uni.request({
url: 'http://localhost:3400/api/selectcommit',
method: 'GET',
data: { // GET `data` `params` :ml-citation{ref="8" data="citationList"}
xuhao: options.uuid
},
success: (res) => { /* ... */
console.log(res.data)
comments.value=res.data
}
});
uni.request({
url: 'http://localhost:3400/apistu/getinclassactive',
method: 'GET',
data: { // GET `data` `params` :ml-citation{ref="8" data="citationList"}
uuid: options.uuid
},
success: (res) => { /* ... */
console.log(res.data)
let infor=JSON.parse(res.data.infor)
console.log(infor)
content.value[0].contentlist = infor.taolonglist
content.value[0].title=infor.title
content.value[0].username=res.data.teacher
content.value[0].timestamp=moment(res.data.time).format("MM-DD HH:mm")
}
});
}
})
const loadedComments = () => {
//
const saved = uni.getStorageSync('discussion_comments')
return saved || [
{
id: 1,
username: '王中铎',
avatar: '/static/course-image/Avatar.png',
timestamp: '04-25 11:54',
content: '1.根据《中华人民共和国民法典》第1254条规定禁止从建筑物中抛掷物和2.高空抛物罪的犯罪主体一般要求是年满十六周岁、具备刑事责任能力的自然人。如果小孩未满十六周岁,或者属于限制刑事责任能力人,可能无法构成..'
}
]
}
//
const newCommentContent = ref('')
//
const submitComment = async () => {
const text = newCommentContent.value.trim()
if (!text) return
uni.request({
url: 'http://localhost:3400/apistu/inclassfabutaolong',
method: 'POST',
data: { // GET `data` `params` :ml-citation{ref="8" data="citationList"}
uuid: uid.value,
content: text,
xuehao: '202413501062'
},
success: (res) => { /* ... */
}
});
const newComment = {
id: Date.now(),
author: '刘东阳',
avatar: '/static/course-image/Avatar.png',
fabutime: formatTime(new Date()),
neirong: text
}
uni.request({
url: 'http://localhost:3400/api/fabucommit',
method: 'POST',
data: { // GET `data` `params` :ml-citation{ref="8" data="citationList"}
dislikes: [],
author: "刘东阳",
uuid: "A1",
likes: [],
filelist: [],
neirong: text,
fabutime: moment().format(),
xuehao: "202413501062",
xuhao: uid.value//
},
success: (res) => { /* ... */
}
});
uni.$emit('finish', uid.value)
comments.value.unshift(newComment)
newCommentContent.value = ''
//
uni.setStorageSync('discussion_comments', comments.value)
}
//
const formatTime = (date: Date): string => {
const month = (date.getMonth() + 1).toString().padStart(2, '0')
const day = date.getDate().toString().padStart(2, '0')
const hours = date.getHours().toString().padStart(2, '0')
const minutes = date.getMinutes().toString().padStart(2, '0')
return `${month}-${day} ${hours}:${minutes}`
}
</script>
<style scoped>
</style>
.discussion {
padding: 20px;
}
.user-info {
display: flex;
align-items: center;
margin-bottom: 10px;
}
.avatar {
width: 35px;
height: 35px;
border-radius: 50%;
margin-right: 10rpx;
}
.user-details .username {
font-weight: bold;
}
.user-details .timestamp {
color: #888;
font-size: 12px;
}
.title {
font-size: 21px;
margin: 20px 0;
}
.content {
margin-bottom: 20px;
padding-bottom: 30rpx;
border-bottom: #d0cece solid;
}
.paragraph {
display: block;
text-indent: 2em;
}
.comments {
margin-top: 20px;
}
.comment {
display: flex;
align-items: flex-start;
margin-bottom: 10px;
padding-bottom: 10px;
border-bottom: #eeeeee solid;
}
.comment-details {
flex: 1;
margin-left: 10px;
}
.comment-details .username {
font-weight: bold;
}
.comment-details .timestamp {
color: #888;
font-size: 12px;
}
.comment-content {
margin-top: 5px;
}
.comment-input {
position: fixed;/* 固定定位 */
bottom: 0;
left: 0;
right: 0;
display: flex;
align-items: center;
padding: 10px;
background-color: #f9f9f9;
border-top: 1rpx solid #ddd;
z-index: 10;
}
.add-comment-btn {
background-color: transparent;
border: none;
font-size: 20px;
color: #007AFF;
margin-right: 10px;
}
.input-box {
flex: 1;
height: 30px;
padding: 0 10px;
font-size: 14px;
border: 1px solid #ccc;
border-radius: 6px;
}
.submit-button {
background-color: #007AFF;
color: white;
font-size: 14px;
padding: 5px 15px;
border-radius: 5px;
margin-left: 10px;
}
</style>

@ -16,8 +16,8 @@
</view>
</view>
<view v-else-if="item.lx == 'activity'">
<view class="activity-item" :style="{ backgroundColor: !finish.includes(item.id) ? item.color : '#666' }">
<view class="content" :style="{ backgroundColor: !finish.includes(item.id) ? item.color : '#666' }">
<view class="activity-item" :style="{ backgroundColor:item.finish!=='finish' ? item.color : '#666' }" @click="()=>enterinclassactive(item)">
<view class="content" :style="{ backgroundColor: item.finish!=='finish' ? item.color : '#666' }">
<view class="title">{{ item.showname }}</view>
<view class="subtitle">{{ item.title }}</view>
</view>
@ -25,7 +25,7 @@
</view>
<view class="footer">
<text class="time">{{ moment(item.time).fromNow() }}</text>
<text class="status">{{ finish.includes(item.id) ? '已完成' : '' }}</text>
<text class="status">{{ item.finish==="finish" ? item.finishwb : '' }}</text>
</view>
</view>
<view v-else-if="item.lx == 'notice'">
@ -65,7 +65,7 @@ import uvDivider from '@/pages/shangke/fgx.vue';
const kctivityAndPPT = ref([
{ id: 0, lx: 'notice', wb: '上课了' },
{ lx: 'ppt', id: 1, name: 'PPT展示1', src: '/static/course-image/ppt1.png', time: '2025-05-06T19:54:43+08:00' },
{ lx: 'activity', id: 2, name: '课堂活动1', lxA: '讨论', color: 'green', showname: '课程讨论', title: '历史为什么选择了中国共产党', time: '2025-05-06T19:54:43+08:00' }
{ lx: 'activity', id: '181346ab-e4ca-4110-b92e-cca0fbea99c1', name: '课堂活动1', lxA: '讨论', color: 'green', showname: '课程讨论', title: '历史为什么选择了中国共产党', time: '2025-05-06T19:54:43+08:00' }
])
const finish = ref([1])
const currentPage = ref(1)
@ -74,12 +74,31 @@ const currentPage = ref(1)
let socket
moment.locale('zh-cn');
//
const handleRefresh = (newId) => {
let index=kctivityAndPPT.value.findIndex(item => item.id === newId);
if(index!==-1){
kctivityAndPPT.value[index].finish="finish"
}
}
onLoad((options) => {
console.log('load', options)
console.log(kctivityAndPPT.value)
socket = null;
if (options) {
uni.request({
url: 'http://localhost:3400/apistu/getskxiang',
method: 'GET',
data: { // GET `data` `params` :ml-citation{ref="8" data="citationList"}
teacherid:'202413501',
kch:'n8z1A1',
xuehao:'202413501062'
},
success: (res) => { /* ... */
kctivityAndPPT.value = res.data
console.log(res.data)
}
});
socket = io('ws://localhost:3400', {
transports: ['websocket'],
auth: {
@ -103,6 +122,7 @@ onLoad((options) => {
})
}
//
uni.$on('finish', handleRefresh)
socket.on('connect', () => console.log('Socket 已连接'))
socket.on('server', (data) => {
console.log(data)
@ -127,6 +147,17 @@ const handleMessage = (data) => {
console.log('处理消息:', data)
}
const enterinclassactive=(item)=>{
if(item.lxA == '讨论'){
uni.navigateTo({
url: '/pages/discussion/discussion?uuid=' +item.id
});
}else if(item.lxA=='签到'){
uni.navigateTo({
url: '/pages/checkin/checkin?uuid=' +item.id
});
}
}
//
const sendData = () => {
if (socket) {

@ -0,0 +1,201 @@
<template>
<view class="container">
<!-- 页面内容 -->
<h3 >
上课
</h3>
<view v-if="kctivityAndPPT.length > 0">
<H4>课堂活动与 PPT 列表</H4>
<ul >
<li v-for="item in kctivityAndPPT" :key="item.id">
展示:课程活动
<view v-if="item.lx=='ppt'">
<view class="content" >
<image
:src="item.src"
mode="aspectFit"
/>
</view>
<view class="footer">
<text class="time">{{moment(item.time).fromNow()}}</text>
<text class="status">已完成</text>
</view>
</view>
<view v-else-if="item.lx=='activity'">
<view class="activity-item" :style="{backgroundColor: !finish.includes(item.id) ?item.color:'#666'}">
<view class="content" :style="{backgroundColor:!finish.includes(item.id) ?item.color:'#666'}">
<view class="title">{{ item.showname }}</view>
<view class="subtitle">{{ item.title }}</view>
</view>
<image class="icon" src="/src/static/student-course/course-active.png" mode="aspectFit"></image>
</view>
<view class="footer">
<text class="time">{{moment(item.time).fromNow()}}</text>
<text class="status">{{finish.includes(item.id)?'已完成':''}}</text>
</view>
<!-- <view :style="{backgroundColor:item.color,width:'90vw',height:'70px'}">
<view :style="{fontSize:'30px'}">
<text :style="{color:'white'}">{{item.name}}</text>
</view>
<view :style="{fontSize:'15px'}">
<text :style="{color:'white'}">{{item.title}}</text>
</view>
</view> -->
</view>
<view v-else-if="item.lx=='notice'">
<view class="notice-view">
<text >{{item.wb}}</text>
</view>
</view>
</li>
</ul>
</view>
<view v-else>
<p>暂无课堂活动或 PPT 数据</p>
</view>
</view>
</template>
<script setup>
import { onMounted, onUnmounted } from 'vue'
import moment from "moment/min/moment-with-locales";
import io from '@hyoga/uni-socket.io'
import { ref } from 'vue'
import {onLoad} from "@dcloudio/uni-app";
// 课堂活动and PPT
const kctivityAndPPT = ref([{id:0,lx:'notice',wb:'上课了'},
{lx:'ppt',id:1,name:'PPT展示1',src:'https://img11.360buyimg.com/n1/s720x720_jfs/t1/303510/33/1806/82651/6815a7a6F2e5d77b6/08d231a86927b0ce.jpg',time:'2025-05-06T19:54:43+08:00'},
{lx :'activity',id:2,name:'课堂活动1',lxA:'讨论',color:'green',showname:'课程讨论',title:'历史为什么选择了中国共产党',time:'2025-05-06T19:54:43+08:00'}
])
const finish=ref([1])
// 定义 socket 变量
let socket
moment.locale('zh-cn');
// 初始化连接
onLoad((options) => {
console.log('load',options)
console.log(kctivityAndPPT.value)
socket = null;
if(options) {
socket= io('ws://localhost:3400', {
transports: ['websocket'],
auth: {
xuehao: "202413501062",
sf: "stu",
kch: options.kch,
kctime: options.kctime,
k_id: options.uuid,
}
})
}else {
socket= io('ws://localhost:3400', {
transports: ['websocket'],
auth: {
xuehao: "202413501062",
sf: "stu",
kch: "nokch",
kctime: "nokctime",
k_id: "nouuid",
}
})
}
// 监听事件
socket.on('connect', () => console.log('Socket 已连接'))
socket.on('server', (data) => {
console.log(data)
})
socket.on('activeandppt', (data) => {
kctivityAndPPT.value.unshift(data)
})
socket.on('message', (data) => handleMessage(data))
})
// 断开连接并移除监听
onUnmounted(() => {
if (socket) {
socket.off('message')
socket.disconnect()
}
})
// 处理消息的方法
const handleMessage = (data) => {
// 处理消息逻辑
console.log('处理消息:', data)
}
// 发送数据的方法
const sendData = () => {
if (socket) {
socket.emit('chat', { text: 'Hello' })
}
}
</script>
<style scoped>
.container {
padding: 20rpx;
}
.classactivetitle {
font-size: 32rpx;
}
.activity-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px;
border: 1px solid #080808;
background-color: #c5c3c3;
width: 90vw;
}
.content{
flex: 1;
display: flex;
flex-direction: column;
background-color: #fff;
padding: 10px;
}
.icon {
width: 50px;
height: 50px;
}
.title {
font-size: 18px;
color: white;
}
.subtitle {
font-size: 14px;
color: white;
}
.footer {
display: flex;
justify-content: space-between;
margin-top: 10px;
}
.time {
font-size: 12px;
color: #666;
}
.status {
font-size: 12px;
color: #666;
}
.notice-view {
color:white;
display: flex;
background-color: #666;
align-items: center;
}
</style>

@ -0,0 +1 @@
export default /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;

@ -0,0 +1,14 @@
export default function rng(): Promise<Uint8Array> {
return new Promise((resolve) => {
wx.getRandomValues({
length: 16,
success: res => {
resolve(new Uint8Array(res.randomValues));
},
fail: () => {
throw new Error("Failed to get random values");
}
})
});
}

@ -0,0 +1,57 @@
import validate from './validate.js';
/**
* Convert array of 16 byte values to UUID string format of the form:
* XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
*/
const byteToHex: string[] = [];
for (let i = 0; i < 256; ++i) {
byteToHex.push((i + 0x100).toString(16).slice(1));
}
export function unsafeStringify(arr: Uint8Array, offset: number = 0) {
// Note: Be careful editing this code! It's been tuned for performance
// and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434
//
// Note to future-self: No, you can't remove the `toLowerCase()` call.
// REF: https://github.com/uuidjs/uuid/pull/677#issuecomment-1757351351
return (
byteToHex[arr[offset + 0]] +
byteToHex[arr[offset + 1]] +
byteToHex[arr[offset + 2]] +
byteToHex[arr[offset + 3]] +
'-' +
byteToHex[arr[offset + 4]] +
byteToHex[arr[offset + 5]] +
'-' +
byteToHex[arr[offset + 6]] +
byteToHex[arr[offset + 7]] +
'-' +
byteToHex[arr[offset + 8]] +
byteToHex[arr[offset + 9]] +
'-' +
byteToHex[arr[offset + 10]] +
byteToHex[arr[offset + 11]] +
byteToHex[arr[offset + 12]] +
byteToHex[arr[offset + 13]] +
byteToHex[arr[offset + 14]] +
byteToHex[arr[offset + 15]]
).toLowerCase();
}
function stringify(arr: Uint8Array, offset: number = 0) {
const uuid = unsafeStringify(arr, offset);
// Consistency check for valid UUID. If this throws, it's likely due to one
// of the following:
// - One or more input array values don't map to a hex octet (leading to
// "undefined" in the uuid)
// - Invalid input values for the RFC `version` or `variant` fields
if (!validate(uuid)) {
throw TypeError('Stringified UUID is invalid');
}
return uuid;
}
export default stringify;

@ -0,0 +1,28 @@
import rng from './rng.js';
import { unsafeStringify } from './stringify.js';
async function uuidv4(random: undefined | Uint8Array = undefined,
buf: undefined | Uint8Array = undefined,
offset: number = 0): Promise<string | Uint8Array> {
const rnds = random || await rng();
// Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
rnds[6] = (rnds[6] & 0x0f) | 0x40;
rnds[8] = (rnds[8] & 0x3f) | 0x80;
// Copy bytes to buffer, if provided
if (buf) {
offset = offset || 0;
for (let i = 0; i < 16; ++i) {
buf[offset + i] = rnds[i];
}
return buf;
}
return unsafeStringify(rnds);
}
export default uuidv4;

@ -0,0 +1,7 @@
import REGEX from './regex.js';
function validate(uuid: string) {
return typeof uuid === 'string' && REGEX.test(uuid);
}
export default validate;
Loading…
Cancel
Save