zdg #152

Merged
zhengdegang merged 2 commits from zdg into main 2024-08-23 10:45:01 +08:00
4 changed files with 120 additions and 26 deletions
Showing only changes of commit c1f81a8e5c - Show all commits

View File

@ -169,12 +169,12 @@ export class ImChat {
logout() { logout() {
if (!this.timChat) return if (!this.timChat) return
return this.timChat.TIMLogout().then(res => { return this.timChat.TIMLogout().then(res => {
console.log('登出成功', res) this.setConsole('%cim-chat: logout', '登出成功')
this.status.isLogin = false this.status.isLogin = false
this.timChat.TIMUninit() // 反初始化 this.timChat.TIMUninit() // 反初始化
return res return res
}).catch(error => { }).catch(error => {
console.log('登出失败', error) this.setConsole('%cim-chat: logout', '登出失败', error)
return error return error
}) })
} }

View File

@ -77,7 +77,7 @@ import { getSmarttalkPage, getPrepareById } from '@/api/file'
import SetHomework from '@/views/prepare/container/set-homework.vue' import SetHomework from '@/views/prepare/container/set-homework.vue'
import FileImage from '@/components/file-image/index.vue' import FileImage from '@/components/file-image/index.vue'
import { useGetHomework } from '@/hooks/useGetHomework' import { useGetHomework } from '@/hooks/useGetHomework'
import { ipcMsgSend, ipcMsgInvoke } from '@/utils/tool' import { ipcMsgSend, ipcMsgSend2, ipcMsgInvoke } from '@/utils/tool'
import { useToolState } from '@/store/modules/tool' import { useToolState } from '@/store/modules/tool'
import { asyncLocalFile } from '@/utils/talkFile' import { asyncLocalFile } from '@/utils/talkFile'
import Lesson from './lesson.vue'; import Lesson from './lesson.vue';
@ -113,6 +113,7 @@ const sendHomework = (row) => {
const closeHomework = async() => { const closeHomework = async() => {
ipcMsgSend('tool-sphere:set:ignore', true) ipcMsgSend('tool-sphere:set:ignore', true)
// im-(app|) // im-(app|)
console.log('发送im消息-推送作业(app|平板)', curRow.value.id)
await ipcMsgInvoke('im-chat:msg', curRow.value.id, MsgEnum.HEADS.MSG_0016) await ipcMsgInvoke('im-chat:msg', curRow.value.id, MsgEnum.HEADS.MSG_0016)
setDialog.value = false setDialog.value = false
} }

View File

@ -1,9 +1,15 @@
<template> <template>
<div v-if="props.test"> <div v-if="props.test">
<el-button type="primary" @click="trigger">点赞</el-button> <el-button type="primary" @click="trigger" v-tap:trigger="">点赞</el-button>
<el-button type="primary" @click="trigger(1, '学生A')">疑惑</el-button> <el-button type="primary" @click="trigger(2, '学生A')" v-tap:trigger="[2,'学生A']">疑惑</el-button>
</div> </div>
<div ref="warpRef" class="c-warp"> <!-- 温度计-模式 -->
<div v-if="props.type == 2" class="c-anim">
<div class="item like" :style="`height:${wtData.like*5}px;`"></div>
<div class="item doubt" :style="`height:${wtData.doubt*5}px;`"></div>
</div>
<!-- (默认)弹幕-模式 -->
<div v-else ref="warpRef" class="c-warp">
<template v-for="(item, index) in iconCache.list"> <template v-for="(item, index) in iconCache.list">
<slot> <slot>
<el-icon v-if="props.def"><Star /></el-icon> <el-icon v-if="props.def"><Star /></el-icon>
@ -19,29 +25,46 @@
</slot> </slot>
</template> </template>
</div> </div>
</template> </template>
<script setup> <script setup>
// - // -
import { ref, nextTick, useSlots, reactive } from 'vue' import { ref, nextTick, useSlots, reactive } from 'vue'
import {Star} from '@element-plus/icons-vue' import {Star} from '@element-plus/icons-vue'
const warpRef = ref(null) const warpRef = ref(null)
const props = defineProps({ test: Boolean, def: Boolean })
const slots = useSlots() // const slots = useSlots() //
let iconCache = reactive({list:[]}) //
const isSlot = !!Object.keys(slots).length // 使 const isSlot = !!Object.keys(slots).length // 使
// === type 1 def === const props = defineProps({
test: Boolean, // -
def: Boolean, // 使
type: String, // 1- 2-
tback: Number, // -退
tsleep: Number, // -退
})
let iconCache = reactive({list:[]}) //
let wtData = reactive({ // -
like: 0, doubt: 0,
timeout: {like: null, doubt: null}, // -
interval: {like: null, doubt: null}, // -
})
// === type 1: 2: ===
const trigger = async (type, name) => { const trigger = async (type, name) => {
if (typeof type == 'string') { name = type; type = 1 } // if (typeof type == 'string') { name = type; type = 1 } //
iconCache.list.push({ if (props.type == 2) { // -
name, weatherglassModel(type)
icon: isSlot||props.def ? '' : getRandomIcon(type) // } else { // -
}) iconCache.list.push({
nextTick(() => { name,
const el = warpRef.value.lastElementChild // icon: isSlot||props.def ? '' : getRandomIcon(type) //
const tipEl = el.querySelector('.tip') // })
// console.log(el) nextTick(() => {
animInit(el, tipEl, type) const el = warpRef.value.lastElementChild //
}) const tipEl = el.querySelector('.tip') //
// console.log(el)
animInit(el, tipEl, type)
})
}
} }
// //
const animInit = (el, tipEl, type) => { const animInit = (el, tipEl, type) => {
@ -95,7 +118,31 @@ const animInit = (el, tipEl, type) => {
} }
amFn() // amFn() //
} }
// - 1: 2:
const weatherglassModel = async(type) => {
const field = type == 2 ? 'doubt' : 'like'
wtData[field]++
autoReduce(type)
}
// -
const autoReduce = type => {
const field = type == 2 ? 'doubt' : 'like'
const reduceFn = () => { // : 1s
wtData.interval[field] = setInterval(() => {
wtData[field]--
// -
if (wtData[field] <= 0) {
clearInterval(wtData.interval[field])
wtData[field] = 0
}
}, (props.tback||100))
}
if (!!wtData.timeout[field]) clearInterval(wtData.timeout[field]) //
if (!!wtData.interval[field]) clearInterval(wtData.interval[field]) //
wtData.timeout[field] = setTimeout(() => {
reduceFn()
}, (props.tsleep||20) * 1000)
}
// - // -
const setStatic = (el, type, val, end) => el.style[type] = val + (end || '') const setStatic = (el, type, val, end) => el.style[type] = val + (end || '')
// //
@ -107,7 +154,7 @@ const resetIconCache = () => {
const getRandomIcon = (type) => { const getRandomIcon = (type) => {
let iconArr = [] let iconArr = []
switch (type) { switch (type) {
case 1: // icon- case 2: // icon-
iconArr = ['yiwen', 'a-yiwen', 'yihuo', 'yiwen-01'] iconArr = ['yiwen', 'a-yiwen', 'yihuo', 'yiwen-01']
break break
default: default:
@ -132,11 +179,28 @@ const getRandomBool = () => Math.random() > 0.5
const toNumber = (v, pos = 2) => Number(v.toFixed(pos)) const toNumber = (v, pos = 2) => Number(v.toFixed(pos))
// //
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)) const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
// -
const vTap = {
mounted(el, binding) {
const instance = binding.instance
const fn = binding.arg
const args = binding.value||[]
if (!fn) return
let cleId = null
el.addEventListener('mousedown', () => {
cleId = setInterval(() => {instance[fn](...args)}, 10);
})
el.addEventListener('mouseup', () => {
!!cleId && clearInterval(cleId)
})
}
}
// //
defineExpose({ trigger }) defineExpose({ trigger })
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
// -
.c-warp { .c-warp {
position: fixed; position: fixed;
right: 0; right: 0;
@ -179,4 +243,31 @@ defineExpose({ trigger })
} }
} }
} }
// -
.c-anim {
position: fixed;
// height: 90vh;
// border: 1px solid;
inset: auto auto 3em 1em;
display: flex;
gap: 10px;
align-items: flex-end;
.item{
flex: 1;
border-radius: 3px;
min-width: 15px;
// height: 500px;
&.like{
background-image: linear-gradient(to top, #fef0f0, #f56c6c);
// animation: striped-flow 5s linear infinite;
}
&.doubt{
background-image: linear-gradient(to top, #fdf6ec, #e6a23c);
}
}
}
@keyframes striped-flow {
0%{background-position: 0 500px;}
100%{background-position: 0 0;}
}
</style> </style>

View File

@ -7,7 +7,7 @@
<side-vue v-ignore @ignore-mounted="sideMouse" @change="sideChange"></side-vue> <side-vue v-ignore @ignore-mounted="sideMouse" @change="sideChange"></side-vue>
<!-- 点赞组件 --> <!-- 点赞组件 -->
<upvote-vue ref="upvoteRef"></upvote-vue> <upvote-vue ref="upvoteRef" type="2"></upvote-vue>
<!-- im-chat 聊天组件 --> <!-- im-chat 聊天组件 -->
<im-chat ref="imChatRef" @change="chatChange" /> <im-chat ref="imChatRef" @change="chatChange" />
@ -67,7 +67,8 @@ const classObj = reactive({ // 课程相关
data: {} // data: {} //
}) })
const msgIds = [] // id const msgIds = [] // id
const btnList = [ // const electron = window.electron // electron
const btnList = [ //
{ label: '选择', value: 'select', icon: 'icon-mouse' }, { label: '选择', value: 'select', icon: 'icon-mouse' },
{ label: '画笔', value: 'brush', icon: 'icon-huabi' }, { label: '画笔', value: 'brush', icon: 'icon-huabi' },
{ label: '板擦', value: 'erase', icon: 'icon-xiangpica' }, { label: '板擦', value: 'erase', icon: 'icon-xiangpica' },
@ -78,9 +79,10 @@ const btnList = [ // 工具栏按钮列表
] ]
// === === // === ===
onMounted(async() => { onMounted(async() => {
getClassInfo() // ex3 if (!electron) return //
getClassInfo() // ex3
setTimeout(() => { setTimeout(() => {
resetStatus() // - resetStatus() // -
}, 200); }, 200);
}) })
@ -130,7 +132,7 @@ const chatChange = (type, data, ...args) => {
case MsgEnum.HEADS.MSG_0002: // case MsgEnum.HEADS.MSG_0002: //
// console.log(':', data) // console.log(':', data)
if(msgIds.includes(msgId)) return // - if(msgIds.includes(msgId)) return // -
upvoteRef.value.trigger(data.name) // | upvoteRef.value.trigger(head, data.name) // |
if (msgIds.length >= 100) msgIds.shift() // if (msgIds.length >= 100) msgIds.shift() //
msgIds.push(msgId) // msgIds.push(msgId) //
break break