Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
F
fc-minigame
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
陈冲
fc-minigame
Commits
3bf97d48
Commit
3bf97d48
authored
Jun 16, 2026
by
陈冲
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix: 已上榜的玩家不显示在大屏
parent
2ce3787b
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
93 additions
and
74 deletions
+93
-74
game.rs
backend/src/db/models/game.rs
+39
-0
socket_io.rs
backend/src/protocols/socket_io.rs
+0
-0
utils.ts
frontend-h5/src/commons/utils.ts
+6
-41
useGameSocket.ts
frontend-h5/src/composables/useGameSocket.ts
+12
-12
Game.vue
frontend-h5/src/pages/game1/Game.vue
+10
-4
PlayingView.vue
frontend-h5/src/pages/game1/views/PlayingView.vue
+3
-2
Game.vue
frontend-h5/src/pages/game2/Game.vue
+1
-1
Game3.vue
frontend-h5/src/pages/game3/Game3.vue
+2
-1
Game4.vue
frontend-h5/src/pages/game4/Game4.vue
+1
-1
Game5.vue
frontend-h5/src/pages/game5/Game5.vue
+1
-1
Game.vue
frontend-h5/src/pages/game6/Game.vue
+16
-9
LoadingView.vue
frontend-h5/src/pages/game6/views/LoadingView.vue
+1
-1
PlayingView.vue
frontend-h5/src/pages/game6/views/PlayingView.vue
+1
-1
No files found.
backend/src/db/models/game.rs
View file @
3bf97d48
...
...
@@ -60,4 +60,43 @@ impl Game {
}
}
}
pub
async
fn
get_rank
(
wechat_id
:
&
str
)
->
i32
{
let
Some
(
_
)
=
&
config
.db
else
{
println!
(
"没有配置数据库, get_rank return 0;"
);
return
0
;
};
let
res
=
crate
::
db
::
db_query
(
r
#
"SELECT COUNT(1) AS rank_count FROM tb_game WHERE wechat_id = ?
AND game_rank <= 10"
#
,
vec!
[
json!
(
&
wechat_id
)],
)
.await
;
match
res
{
Ok
(
res
)
=>
res
.first
()
.and_then
(|
row
|
row
.get
(
"rank_count"
))
.and_then
(|
value
|
value
.as_i64
()
.or_else
(||
value
.as_u64
()
.map
(|
v
|
v
as
i64
)))
.unwrap_or
(
0
)
as
i32
,
Err
(
err
)
=>
{
// dbg!(&err);
// let log = Log {
// id: 0,
// msg: err,
// params: json!({
// "wechat_id": self.wechat_id,
// "nickname": self.nickname,
// "avatar": self.avatar,
// "item_num": self.item_num,
// "game_rank":self.game_rank,
// "score": self.score,
// }),
// create_date: None,
// };
// log.insert().await;
0
}
}
}
}
backend/src/protocols/socket_io.rs
View file @
3bf97d48
This diff is collapsed.
Click to expand it.
frontend-h5/src/commons/utils.ts
View file @
3bf97d48
...
...
@@ -326,11 +326,11 @@ export function $read_socket_storge(): any | null {
export
function
$getWechat
():
any
|
null
{
const
q
=
$query
([
'token'
,
'nickname'
,
'avatar'
]);
if
(
q
&&
q
.
length
==
3
)
{
const
q
=
$query
([
'token'
,
'nickname'
,
'avatar'
,
'userno'
]);
if
(
q
&&
q
.
length
==
4
)
{
return
{
token
:
SHA256
(
q
[
0
]).
toString
(),
//原token很长,这里压缩下,压缩后不能还原,最后提交成绩时要提交原始token
token_origin
:
q
[
0
],
token
:
q
[
3
],
//玩家的唯一码,不用做压缩
token_origin
:
q
[
0
],
//这个token要提交给api.guocai365.org.cn做验证
nickname
:
q
[
1
],
avatar
:
q
[
2
],
};
...
...
@@ -349,47 +349,12 @@ export function $getWechat(): any | null {
return
null
;
}
export
async
function
postJson
(
token
:
string
,
index
:
number
)
{
const
url
=
"https://api.guocai365.org.cn/adminapi/offline_clearance/score/list"
;
let
arr
=
[
''
,
'JGQF'
,
'JBJF'
,
'MSYF'
,
'CMYF'
,
'QCNF'
,
'FYDT'
];
try
{
const
resp
=
await
fetch
(
url
,
{
method
:
"POST"
,
headers
:
{
"Authorization"
:
`Bearer
${
token
}
`
,
"Content-Type"
:
"application/json"
,
},
body
:
JSON
.
stringify
({
activity_id
:
1
,
game_code
:
arr
[
index
],
page
:
1
,
pageSize
:
20
,
}),
});
const
text
=
await
resp
.
text
();
if
(
!
resp
.
ok
)
{
console
.
error
(
"请求失败:"
,
resp
.
status
,
text
);
return
;
}
// 如果返回的是 JSON
const
data
=
JSON
.
parse
(
text
);
console
.
log
(
"响应:"
,
data
);
}
catch
(
err
)
{
console
.
error
(
"请求异常:"
,
err
);
}
}
export
async
function
postScreenGameScore
(
token
:
string
,
gameCode
:
string
,
score
:
number
)
{
export
async
function
postScreenGameScore
(
gameCode
:
string
,
score
:
number
)
{
try
{
const
resp
=
await
fetch
(
'https://api.guocai365.org.cn/api/offline_clearance/user/screen_game_score'
,
{
method
:
'POST'
,
headers
:
{
Authorization
:
toke
n
,
Authorization
:
$getWechat
()?.
token_origi
n
,
'Content-Type'
:
'application/json'
,
},
body
:
JSON
.
stringify
({
...
...
frontend-h5/src/composables/useGameSocket.ts
View file @
3bf97d48
...
...
@@ -55,6 +55,7 @@ export function sendGameMessage(cmd: string, data: any = {}) {
return
sendSocketMessage
(
cmd
,
data
)
}
export
const
userJoinStatus
=
ref
(
false
)
export
const
userTop10RankStatus
=
ref
(
false
)
export
function
useGameSocket
(
options
:
GameSocketOptions
)
{
const
router
=
useRouter
()
...
...
@@ -96,7 +97,7 @@ export function useGameSocket(options: GameSocketOptions) {
// router.replace('/loading').then(() => { });
return
;
}
if
(
evt
==
'submit_score_save'
)
{
if
(
evt
==
'submit_score_save
_result
'
)
{
//提交分数的情况下有问题的情况下,只重试3次
if
(
resubmitcount
>=
3
)
{
return
;
...
...
@@ -111,12 +112,6 @@ export function useGameSocket(options: GameSocketOptions) {
return
;
}
if
(
state
===
0
)
{
// alert(msg)
$toast
(
msg
)
return
}
switch
(
evt
)
{
case
'room_create_result'
:
{
// if (`game${data}` == options.gameId) {
...
...
@@ -133,10 +128,12 @@ export function useGameSocket(options: GameSocketOptions) {
// break
}
case
'room_join_result'
:
{
if
(
data
!=
options
.
gameId
)
{
if
(
data
.
gameId
!=
options
.
gameId
)
{
// debugger
return
;
}
//是否上过前十榜
userTop10RankStatus
.
value
=
data
.
alreadyTopRanked
$toast
(
'您已进入游戏房间'
)
userJoinStatus
.
value
=
true
break
...
...
@@ -163,10 +160,12 @@ export function useGameSocket(options: GameSocketOptions) {
break
}
case
'submit_score_save_result'
:
{
const
submittedScore
=
options
.
onScoreSubmitted
?.(
true
,
data
)
const
token
=
$getWechat
()?.
token_origin
if
(
token
&&
submittedScore
&&
Number
.
isFinite
(
submittedScore
.
score
))
{
void
postScreenGameScore
(
token
,
submittedScore
.
code
,
submittedScore
.
score
)
if
(
!
userTop10RankStatus
)
{
const
submittedScore
=
options
.
onScoreSubmitted
?.(
true
,
data
)
const
token_origin
=
$getWechat
()?.
token_origin
if
(
token_origin
&&
submittedScore
&&
Number
.
isFinite
(
submittedScore
.
score
))
{
void
postScreenGameScore
(
submittedScore
.
code
,
submittedScore
.
score
)
}
}
break
}
...
...
@@ -199,6 +198,7 @@ export function useGameSocket(options: GameSocketOptions) {
return
{
socket
,
userJoinStatus
,
userTop10RankStatus
,
offSocketMessage
}
}
frontend-h5/src/pages/game1/Game.vue
View file @
3bf97d48
...
...
@@ -2,7 +2,7 @@
import
{
onBeforeUnmount
,
onMounted
,
ref
,
watch
}
from
'vue'
import
{
cssAssetUrl
}
from
'@/commons/assets.ts'
import
MobileStage
from
'@/components/MobileStage.vue'
import
{
useGameSocket
,
sendGameMessage
,
userJoinStatus
,
joinSharedRoom
}
from
'@/composables/useGameSocket'
import
{
useGameSocket
,
sendGameMessage
,
userJoinStatus
,
userTop10RankStatus
,
joinSharedRoom
}
from
'@/composables/useGameSocket'
import
LoadingView
from
'./views/LoadingView.vue'
import
PlayingView
from
'./views/PlayingView.vue'
import
ScoreView
from
'./views/ScoreView.vue'
...
...
@@ -69,7 +69,7 @@ function submitScore(save: boolean = false) {
//wechat 原始token
sendGameMessage
(
'submit_score_save'
,
{
score
:
tick
.
value
,
wechat
:
wechat
.
token
_origin
,
wechat
:
wechat
.
token
,
item_num
:
1
,
nickname
:
wechat
.
nickname
,
avatar
:
wechat
.
avatar
,
...
...
@@ -143,7 +143,13 @@ function showScoreView() {
showGameRule
.
value
=
false
;
stopGameCountdown
()
setDivDescVisible
(
false
)
currentView
.
value
=
'score'
if
(
userTop10RankStatus
.
value
){
currentView
.
value
=
'loading'
userJoinStatus
.
value
=
false
;
$toast
(
'一人只能上榜领奖一次,您的福利已到手,把机会留给其他玩家吧'
,
30000
)
}
else
{
currentView
.
value
=
'score'
}
}
const
touchHandler
=
()
=>
{
...
...
@@ -290,7 +296,7 @@ const showGameRuleHandler = () => {
@
touchGameRule=
"showGameRuleHandler"
/>
<PlayingView
v-else-if=
"currentView === 'playing'"
:image-urls=
"imageUrls"
:tick=
"tick"
:rank=
"rank"
:current-gu-frame=
"currentGuFrame"
:countdown-interval=
"countdownInterval"
:is-div-desc-visible=
"isDivDescVisible"
@
touch=
"touchHandler"
/>
@
touch=
"touchHandler"
:userTop10RankStatus=
"userTop10RankStatus"
/>
<ScoreView
v-else
:image-urls=
"imageUrls"
:rank=
"rank"
:tick=
"tick"
/>
</MobileStage>
<div
v-else
style=
"text-align: center; width: 100vw; height: 100vh; line-height: 30; font-size: 20px;"
>
...
...
frontend-h5/src/pages/game1/views/PlayingView.vue
View file @
3bf97d48
...
...
@@ -5,7 +5,8 @@ defineProps<{
isDivDescVisible
:
boolean
tick
:
number
rank
:
number
currentGuFrame
:
number
currentGuFrame
:
number
,
userTop10RankStatus
:
boolean
,
}
>
()
defineEmits
<
{
...
...
@@ -25,7 +26,7 @@ defineEmits<{
<div
class=
"play-content"
>
<div>
当前击鼓积分
</div>
<div>
{{
tick
}}
</div>
<div>
当前排名:
第
<label>
{{
rank
}}
</label>
名
</div>
<div
v-if=
"!userTop10RankStatus"
>
当前排名:
第
<label>
{{
rank
}}
</label>
名
</div>
</div>
<div
class=
"bg-bottom"
></div>
<div
class=
"play-gu"
:style=
"
{ backgroundPosition: `-${currentGuFrame * 400}px 0` }" @click="$emit('touch')">
</div>
...
...
frontend-h5/src/pages/game2/Game.vue
View file @
3bf97d48
...
...
@@ -94,7 +94,7 @@ function submitScore(save: boolean = false, currentTick = score.value) {
//wechat 原始token
sendGameMessage
(
'submit_score_save'
,
{
score
:
currentTick
,
wechat
:
wechat
.
token
_origin
,
wechat
:
wechat
.
token
,
item_num
:
2
,
nickname
:
wechat
.
nickname
,
avatar
:
wechat
.
avatar
,
...
...
frontend-h5/src/pages/game3/Game3.vue
View file @
3bf97d48
...
...
@@ -108,7 +108,7 @@ function submitScore(save: boolean = false, currentTick = score.value) {
}
sendGameMessage
(
'submit_score_save'
,
{
score
:
currentTick
,
wechat
:
wechat
.
token
_origin
,
wechat
:
wechat
.
token
,
item_num
:
3
,
nickname
:
wechat
.
nickname
,
avatar
:
wechat
.
avatar
,
...
...
@@ -244,6 +244,7 @@ if (wechat) {
rank
.
value
=
nextRank
}
}
return
{
code
:
'MSYF'
,
score
:
score
.
value
}
},
onRescoreSubmitted
:
(
_recount
)
=>
{
submitScore
(
true
);
...
...
frontend-h5/src/pages/game4/Game4.vue
View file @
3bf97d48
...
...
@@ -89,7 +89,7 @@ function submitScore(save: boolean = false) {
// wechat 原始token
sendGameMessage
(
"submit_score_save"
,
{
score
:
tick
.
value
,
wechat
:
wechat
.
token
_origin
,
wechat
:
wechat
.
token
,
item_num
:
4
,
nickname
:
wechat
.
nickname
,
avatar
:
wechat
.
avatar
,
...
...
frontend-h5/src/pages/game5/Game5.vue
View file @
3bf97d48
...
...
@@ -136,7 +136,7 @@ function submitScore(save: boolean = false) {
//wechat 原始token
const
data
=
{
score
:
tick
.
value
,
wechat
:
wechat
.
token
_origin
,
wechat
:
wechat
.
token
,
item_num
:
1
,
nickname
:
wechat
.
nickname
,
avatar
:
wechat
.
avatar
,
...
...
frontend-h5/src/pages/game6/Game.vue
View file @
3bf97d48
...
...
@@ -2,7 +2,7 @@
import
{
computed
,
onBeforeUnmount
,
onMounted
,
ref
}
from
'vue'
import
{
cssAssetUrl
}
from
'@/commons/assets.ts'
import
MobileStage
from
'@/components/MobileStage.vue'
import
{
useGameSocket
,
sendGameMessage
,
userJoinStatus
,
joinSharedRoom
}
from
'@/composables/useGameSocket'
import
{
useGameSocket
,
sendGameMessage
,
userJoinStatus
,
userTop10RankStatus
,
joinSharedRoom
}
from
'@/composables/useGameSocket'
import
LoadingView
from
'./views/LoadingView.vue'
import
PlayingView
from
'./views/PlayingView.vue'
import
{
$format_str
,
$getWechat
,
$toast
}
from
'@/commons/utils.ts'
...
...
@@ -101,7 +101,7 @@ function submitScore(save: boolean = false, currentTick = score.value) {
//wechat 原始token
sendGameMessage
(
'submit_score_save'
,
{
score
:
currentTick
,
wechat
:
wechat
.
token
_origin
,
wechat
:
wechat
.
token
,
item_num
:
6
,
nickname
:
wechat
.
nickname
,
avatar
:
wechat
.
avatar
,
...
...
@@ -123,9 +123,16 @@ function startGameCountdown(seconds = 60) {
if
(
countdownInterval
.
value
<=
0
)
{
countdownInterval
.
value
=
0
gameCountdownTimer
=
undefined
setDivDescVisible
(
false
)
submitScore
(
true
)
showGameOverRank
()
currentView
.
value
=
'loading'
if
(
userTop10RankStatus
.
value
)
{
userJoinStatus
.
value
=
false
;
showGameRank
.
value
=
false
;
$toast
(
'一人只能上榜领奖一次,您的福利已到手,把机会留给其他玩家吧'
,
30000
)
}
else
{
setDivDescVisible
(
false
)
submitScore
(
true
)
showGameOverRank
()
}
return
}
...
...
@@ -343,7 +350,7 @@ const rankCloseHandler = () => {
<div
class=
"col-2"
>
<div
class=
"avatar"
:style=
"item.avatar ?
{ backgroundImage: `url(${item.avatar})` } : {}">
</div>
<div>
{{
$format_str
(
item
.
nickname
,
12
)
}}
</div>
<div>
{{
$format_str
(
item
.
nickname
,
12
)
}}
</div>
</div>
<div
class=
"col-3"
>
{{
item
.
score
}}
</div>
</div>
...
...
@@ -358,12 +365,12 @@ const rankCloseHandler = () => {
</div>
</div>
<div
class=
"img-close"
@
click=
"rankCloseHandler"
></div>
</div>
</div>
</
template
>
<LoadingView
v-if=
"currentView === 'loading'"
:image-urls=
"imageUrls"
:user-join-status=
"userJoinStatus"
@
touchGameRule=
"showGameRuleHandler"
/>
<PlayingView
v-else
:image-urls=
"imageUrls"
:tick=
"score"
:rank=
"rank"
:countdown-interval=
"countdownInterval"
:is-div-desc-visible=
"isDivDescVisible"
@
touch=
"touchHandler"
/>
:is-div-desc-visible=
"isDivDescVisible"
@
touch=
"touchHandler"
:userTop10RankStatus=
"userTop10RankStatus"
/>
</MobileStage>
<div
v-else
style=
"text-align: center; width: 100vw; height: 100vh; line-height: 30; font-size: 20px;"
>
请使用微信扫码进入游戏
...
...
@@ -399,7 +406,7 @@ const rankCloseHandler = () => {
width
:
57px
;
height
:
57px
;
background
:
v-bind
(
'imageUrls.close'
)
center
/
cover
no-repeat
;
transform
:
translateX
(
-50%
)
scale
(
1.5
);
transform
:
translateX
(
-50%
)
scale
(
1.5
);
position
:
absolute
;
top
:
-73px
;
left
:
100%
;
...
...
frontend-h5/src/pages/game6/views/LoadingView.vue
View file @
3bf97d48
...
...
@@ -4,7 +4,7 @@ import { onMounted, ref } from 'vue';
defineProps
<
{
imageUrls
:
Record
<
string
,
string
>
userJoinStatus
:
boolean
userJoinStatus
:
boolean
,
}
>
();
const
nickname
=
ref
(
''
);
const
avatar
=
ref
(
''
);
...
...
frontend-h5/src/pages/game6/views/PlayingView.vue
View file @
3bf97d48
...
...
@@ -7,7 +7,7 @@ defineProps<{
isDivDescVisible
:
boolean
tick
:
number
rank
:
number
// currentGu: string
userTop10RankStatus
:
boolean
}
>
()
const
emit
=
defineEmits
<
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment