Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
T
tabulator-another-web
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
MyCard
tabulator-another-web
Commits
5072a08a
Commit
5072a08a
authored
Jun 03, 2025
by
xiaoye
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix
parent
371604ae
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
510 additions
and
465 deletions
+510
-465
index.html
index.html
+1
-1
src/pages/main.vue
src/pages/main.vue
+29
-463
src/pages/tabulator.vue
src/pages/tabulator.vue
+473
-0
src/style/transition.scss
src/style/transition.scss
+7
-1
No files found.
index.html
View file @
5072a08a
<!DOCTYPE html>
<!DOCTYPE html>
<html
lang=
"
en
"
>
<html
lang=
"
zh-CN
"
>
<head>
<head>
<meta
charset=
"UTF-8"
/>
<meta
charset=
"UTF-8"
/>
<script>
<script>
...
...
src/pages/main.vue
View file @
5072a08a
<
template
>
<
template
>
<view
id =
'page'
>
<transition
name =
'move_right_slow'
>
<view
id =
'really'
class =
'click head'
>
<view
v-show =
'loading'
id =
'background'
>
<view>
<view
id =
'pic'
></view>
<button
:style =
"size.width > size.height ?
{ width: '30%' } : {}"
class = 'button'
@click = 'page.show.drawer()'
>
<uni-icons
:type =
"page.menu ? page.drawer ? 'left' : 'search' : page.drawer ? 'left' : 'info'"
></uni-icons>
</button>
</view>
<view>
</view>
<view>
</view>
<view>
</view>
<uni-list>
<uni-list-chat
:avatar-circle =
true
:title =
'Mycard.username'
:note =
'Mycard.email'
:clickable =
true
:avatar =
'Mycard.avatar'
@
click =
'page.show.user()'
>
<uni-icons
:type =
"page.user ? 'right' : 'left'"
></uni-icons>
</uni-list-chat>
</uni-list>
</view>
<view
class =
'click head'
><uni-list><uni-list-chat></uni-list-chat></uni-list></view>
<Pics
:style =
"
{
'--maxsize' : `${size.width > size.height ? size.width / 2 : size.width / 1.2}px`,
'--minsize' : `${size.width / 2}px`,
'--height' : `${size.width > size.height ? 10 : 25}%`,
}"
>
</Pics>
<transition
name =
'move_right'
>
<uni-card
class =
'click'
id =
'user'
v-show =
'page.user'
:title =
'Mycard.username'
:sub-title =
'Mycard.email'
:thumbnail =
'Mycard.avatar'
:style =
"
{ '--size' : `${size.width > size.height ? size.width / 2 : size.width / 1.2}px` }"
>
<view
v-show =
'Mycard.id >= 0'
><h2>
{{
Mycard
.
id
}}
</h2></view>
<hr
v-show =
'Mycard.id >= 0'
>
<view
v-show =
'Mycard.id >= 0'
class =
'user'
@
click =
'page.show.api()'
><span>
api_key
</span></view>
<hr
v-show =
'Mycard.id >= 0'
>
<view
v-show =
'Mycard.id >= 0'
class =
'user'
@
click =
'page.show.create()'
><span>
新建比赛
</span></view>
<hr
v-show =
'Mycard.id >= 0'
>
<view
class =
'user'
@
click =
'() =>
{
Mycard.id >= 0 ? Mycard.logout() : Mycard.login();
}'
>
<span>
{{
Mycard
.
id
>=
0
?
'
退出登陆
'
:
'
登陆
'
}}
</span></view>
</uni-card>
</transition>
<transition
name =
'move_left'
>
<Searcher
class =
'click'
id =
'drawer'
v-show =
'page.drawer && page.menu && !(page.create || page.apikey)'
title =
'搜索'
:style =
"
{ '--size' : `${size.width > size.height ? size.width / 4 : size.width / 2}px` }"
>
</Searcher>
</transition>
<transition
name =
'move_left'
>
<Setting
class =
'click'
id =
'drawer'
v-show =
'page.drawer && page.tournament && !(page.create || page.apikey)'
title =
'比赛设置'
:style =
"
{ '--size' : `${size.width > size.height ? size.width / 4 : size.width / 2}px` }"
>
</Setting>
</transition>
<transition
name =
'move_left'
>
<Create
class =
'click'
id =
'drawer'
v-show =
'page.drawer && page.create'
title =
'比赛创建'
:style =
"
{ '--size' : `${size.width > size.height ? size.width / 4 : size.width / 2}px` }"
>
</Create>
</transition>
<transition
name =
'move_left'
>
<API
class =
'click'
id =
'drawer'
v-show =
'page.drawer && page.apikey'
title =
'我的api密钥'
:style =
"
{ '--size' : `${size.width > size.height ? size.width / 4 : size.width / 2}px` }"
>
</API>
</transition>
<br>
<transition
name =
'switch'
>
<view
id =
'body'
:style =
"
{ '--size' : `${size.width > size.height ? size.width / 2 : size.width}px` }"
>
<transition
name =
'switch'
>
<uni-list
v-show =
'search.result.total > 0 && page.menu'
>
<uni-list-item
id =
'list'
v-for =
'(i, v) in search.result.tournaments'
:title =
'i.name'
:note =
'search.rule.note.get(i.rule)'
:rightText =
'`$
{i.createdAt.toLocaleDateString()}\n${i.count}`'
:clickable = true
@click = 'page.show.tournament(v)'
>
</uni-list-item>
</uni-list>
</transition>
<transition
name =
'switch'
>
<uni-pagination
:current =
'search.info.pageCount'
v-model =
'search.info.pageCount'
pageSize =
20
:total =
'search.result.total'
v-show =
'page.menu'
@
change =
'search.on()'
>
</uni-pagination>
</transition>
<transition
name =
'switch'
>
<PageTournament
v-if =
'page.tournament'
/>
</transition>
</view>
</view>
</transition>
</transition>
<
/view
>
<
Tabulator/
>
</
template
>
</
template
>
<
script
setup
lang =
'ts'
>
<
script
setup
lang =
'ts'
>
import
{
ref
,
reactive
,
onMounted
,
onUnmounted
,
onBeforeMount
,
watch
}
from
'
vue
'
;
import
{
ref
,
reactive
,
onMounted
,
onUnmounted
,
onBeforeMount
,
watch
}
from
'
vue
'
;
import
{
TournamentFindObject
,
TournamentCreateObject
,
ruleSettings
,
UserObject
}
from
'
../script/type.ts
'
;
import
Tabulator
from
'
./tabulator.vue
'
;
import
Uniapp
from
'
../script/uniapp.ts
'
;
let
loading
=
ref
(
true
);
import
{
Tabulator
,
User
}
from
'
../script/post.ts
'
;
onMounted
(
async
()
=>
{
import
Tournament
from
'
../script/tournament.ts
'
;
import
Mycard
from
'
../script/mycard.ts
'
;
import
emitter
from
'
../script/emitter.ts
'
import
Const
from
'
../script/const.ts
'
import
PageTournament
from
'
./tournament.vue
'
;
import
Create
from
'
./drawer/creator.vue
'
;
import
Pics
from
'
./pics.vue
'
;
import
Setting
from
'
./drawer/setting.vue
'
;
import
Searcher
from
'
./drawer/searcher.vue
'
;
import
API
from
'
./drawer/api.vue
'
;
let
page
=
reactive
({
user
:
false
,
drawer
:
false
,
menu
:
true
,
tournament
:
false
,
create
:
false
,
apikey
:
false
,
show
:
{
user
:
()
:
void
=>
{
page
.
user
=
!
page
.
user
;
},
drawer
:
()
:
void
=>
{
page
.
drawer
=
!
page
.
drawer
;
if
(
!
page
.
drawer
&&
page
.
create
)
page
.
create
=
false
;
if
(
!
page
.
drawer
&&
page
.
apikey
)
page
.
apikey
=
false
;
if
(
!
page
.
drawer
&&
page
.
tournament
)
tournament
.
init
(
tournament
.
this
as
Tournament
);
},
tournament
:
async
(
v
:
number
=
0
):
Promise
<
void
>
=>
{
page
.
menu
=
false
;
await
(
new
Promise
(
resolve
=>
setTimeout
(
resolve
,
500
)));
page
.
tournament
=
true
;
const
url
=
window
.
location
.
href
.
split
(
'
/?
'
);
window
.
location
.
replace
(
`
${
url
[
0
].
replace
(
/
\/?
$/
,
''
)}
/tournament/
${
search
.
result
.
tournaments
[
v
].
id
}${
url
[
1
]
?
`/?
${
url
[
1
]}
`
:
''
}
`
);
},
menu
:
async
():
Promise
<
void
>
=>
{
page
.
tournament
=
false
;
tournament
.
clear
();
await
search
.
on
();
await
(
new
Promise
(
resolve
=>
setTimeout
(
resolve
,
500
)));
page
.
menu
=
true
;
},
create
:
async
():
Promise
<
void
>
=>
{
if
(
page
.
drawer
)
{
page
.
show
.
drawer
();
await
(
new
Promise
(
resolve
=>
setTimeout
(
resolve
,
500
)));
}
page
.
create
=
true
;
page
.
show
.
drawer
();
},
api
:
async
():
Promise
<
void
>
=>
{
if
(
page
.
drawer
)
{
page
.
show
.
drawer
();
await
(
new
Promise
(
resolve
=>
setTimeout
(
resolve
,
500
)));
await
(
new
Promise
(
resolve
=>
setTimeout
(
resolve
,
500
)));
}
loading
.
value
=
false
;
page
.
apikey
=
true
;
page
.
show
.
drawer
();
},
clear
:
(
e
)
:
void
=>
{
let
element
=
e
.
target
;
let
chk
=
false
;
let
inPage
=
false
;
let
uniElement
=
false
;
while
(
element
)
{
if
([
'
head
'
,
'
user
'
,
'
drawer
'
].
includes
(
element
.
id
)
||
element
.
classList
.
contains
(
'
click
'
))
chk
=
true
;
if
(
element
.
id
==
'
page
'
)
inPage
=
true
;
if
(
typeof
element
.
className
==
'
string
'
&&
element
.
className
.
includes
(
'
uni
'
))
uniElement
=
true
;
element
=
element
.
parentElement
;
}
if
(
chk
||
(
!
inPage
&&
uniElement
))
return
undefined
;
if
(
page
.
user
)
page
.
show
.
user
();
if
(
page
.
drawer
)
page
.
show
.
drawer
();
}
}
});
let
search
=
reactive
({
id
:
''
,
creator
:
''
,
date
:
[]
as
Array
<
string
>
,
rule
:
{
range
:
[
{
value
:
'
'
,
text
:
'
全部
'
},
{
value
:
'
SingleElimination
'
,
text
:
'
单淘
'
},
{
value
:
'
Swiss
'
,
text
:
'
瑞士轮
'
}
],
note
:
new
Map
([
[
'
SingleElimination
'
,
'
单淘
'
],
[
'
Swiss
'
,
'
瑞士轮
'
]
])
as
Map
<
string
,
string
>
},
visibility
:
{
range
:
[
{
value
:
'
'
,
text
:
'
全部
'
},
{
value
:
'
Public
'
,
text
:
'
公开
'
},
{
value
:
'
Internal
'
,
text
:
'
仅登陆可见
'
},
{
value
:
'
Private
'
,
text
:
'
私密
'
}
]
},
status
:
{
range
:
[
{
value
:
'
'
,
text
:
'
全部
'
},
{
value
:
'
Ready
'
,
text
:
'
准备中
'
},
{
value
:
'
Running
'
,
text
:
'
进行中
'
},
{
value
:
'
Finished
'
,
text
:
'
已结束
'
}
]
},
info
:
{
pageCount
:
1
,
id
:
0
,
creator
:
0
,
before
:
undefined
,
after
:
undefined
,
name
:
''
,
rule
:
''
,
visibility
:
''
,
status
:
''
}
as
TournamentFindObject
,
result
:
{
total
:
0
,
tournaments
:
[]
as
Array
<
Tournament
>
},
on
:
async
(
Data
:
TournamentFindObject
=
search
.
info
)
:
Promise
<
void
>
=>
{
page
.
drawer
=
false
;
if
(
search
.
result
.
total
>
0
)
{
search
.
result
.
total
=
0
;
}
const
result
=
await
Tabulator
.
Tournament
.
FindALL
(
Mycard
.
token
,
Data
);
search
.
result
.
total
=
result
.
total
;
search
.
result
.
tournaments
=
result
.
tournaments
;
},
mine
:
()
=>
{
search
.
creator
=
Mycard
.
id
>=
0
?
Mycard
.
id
.
toString
()
:
''
;
}
});
let
tournament
=
reactive
({
this
:
undefined
as
undefined
|
Tournament
,
name
:
''
,
description
:
''
,
visibility
:
{
select
:
''
,
range
:
[
{
value
:
'
Public
'
,
text
:
'
公开
'
},
{
value
:
'
Internal
'
,
text
:
'
仅登陆可见
'
},
{
value
:
'
Private
'
,
text
:
'
私密
'
}
]
},
rule
:
{
select
:
''
,
range
:
[
{
value
:
'
SingleElimination
'
,
text
:
'
单淘
'
},
{
value
:
'
Swiss
'
,
text
:
'
瑞士轮
'
}
],
settings
:
{
}
as
ruleSettings
},
hasThirdPlaceMatch
:
{
select
:
(
e
)
=>
{
tournament
.
rule
.
settings
.
hasThirdPlaceMatch
=
e
.
detail
.
value
.
length
>
0
}
},
collaborator
:
''
,
collaborators
:
[]
as
Array
<
UserObject
>
,
init
:
async
(
t
:
Tournament
)
:
Promise
<
void
>
=>
{
if
(
!
t
)
return
;
tournament
.
this
=
t
;
tournament
.
name
=
t
.
name
;
tournament
.
description
=
t
.
description
;
tournament
.
visibility
.
select
=
t
.
visibility
;
tournament
.
rule
.
select
=
t
.
rule
;
tournament
.
rule
.
settings
=
Object
.
assign
({},
t
.
ruleSettings
);
let
collaborators
:
Array
<
UserObject
>
=
[];
for
(
const
id
of
t
.
collaborators
)
{
const
i
=
tournament
.
collaborators
.
find
(
i
=>
i
.
id
==
id
)
??
await
User
.
Find
.
Id
(
id
);
if
(
i
)
collaborators
.
push
(
i
);
}
tournament
.
collaborators
=
collaborators
;
},
clear
:
()
:
void
=>
{
tournament
.
this
=
undefined
;
tournament
.
name
=
''
;
tournament
.
description
=
''
;
tournament
.
visibility
.
select
=
''
;
tournament
.
rule
.
select
=
''
;
tournament
.
rule
.
settings
=
{}
as
ruleSettings
;
tournament
.
collaborators
=
[];
},
update
:
()
:
void
=>
{
if
(
tournament
.
visibility
.
select
==
''
)
// @ts-ignore
tournament
.
visibility
.
select
=
tournament
.
this
.
visibility
;
const
collaborators
=
tournament
.
collaborators
.
map
(
user
=>
user
.
id
);
emitter
.
emit
(
Const
.
updateTournament
,
{
name
:
tournament
.
name
,
description
:
tournament
.
description
,
visibility
:
tournament
.
visibility
.
select
,
collaborators
:
collaborators
,
// PS:这里接口暂时不通
// rule : tournament.rule.select,
// ruleSettings : tournament.rule.settings
}
as
TournamentCreateObject
);
},
remove
:
(
v
:
number
)
:
void
=>
{
tournament
.
collaborators
.
splice
(
v
,
1
);
},
add
:
async
()
:
Promise
<
void
>
=>
{
try
{
if
(
tournament
.
collaborators
.
findIndex
(
i
=>
i
.
username
==
tournament
.
collaborator
)
>=
0
)
throw
new
Error
(
'
协作者已存在
'
);
const
i
=
await
User
.
Find
.
Name
(
tournament
.
collaborator
);
if
(
!
i
)
throw
new
Error
(
'
未搜索到此用户
'
);
if
(
tournament
.
this
?.
creator
==
i
.
id
)
throw
new
Error
(
'
协作者不可以是比赛创建者
'
);
tournament
.
collaborators
.
push
(
i
);
}
catch
(
error
)
{
uni
.
showModal
({
title
:
'
添加失败
'
,
content
:
error
.
message
,
showCancel
:
false
});
}
finally
{
tournament
.
collaborator
=
''
;
}
},
operatorChk
:
()
:
boolean
=>
{
if
(
!
tournament
.
this
)
return
true
return
!
(
Mycard
.
id
>=
0
&&
(
Mycard
.
id
==
tournament
.
this
?.
creator
||
tournament
.
this
?.
collaborators
.
includes
(
Mycard
.
id
)))
}
});
const
creator
=
{
off
:
async
()
:
Promise
<
void
>
=>
{
page
.
show
.
drawer
();
if
(
page
.
tournament
)
page
.
show
.
menu
();
search
.
mine
();
await
search
.
on
();
}
};
let
size
=
reactive
({
width
:
0
,
height
:
0
,
get
:
()
=>
{
// @ts-ignore
size
.
width
=
uni
.
getSystemInfoSync
().
windowWidth
;
size
.
height
=
uni
.
getSystemInfoSync
().
windowHeight
;
}
});
onBeforeMount
(()
:
void
=>
{
Uniapp
.
chkScreen
(
size
.
get
);
document
.
addEventListener
(
"
click
"
,
page
.
show
.
clear
);
emitter
.
on
(
Const
.
tournamentInfo
,
page
.
show
.
drawer
);
// @ts-ignore
emitter
.
on
(
Const
.
tournamentReload
,
tournament
.
init
);
emitter
.
on
(
Const
.
createOff
,
creator
.
off
);
const
url
=
window
.
location
.
pathname
.
match
(
/
\/
tournament
\/([^\/]
+
)(?=\/
|$
)
/
);
if
(
url
&&
!
isNaN
(
parseInt
(
url
[
1
])))
{
page
.
menu
=
false
;
page
.
tournament
=
true
;
}
else
{
if
(
window
.
location
.
pathname
.
length
>
1
)
window
.
location
.
replace
(
window
.
location
.
href
.
replace
(
window
.
location
.
pathname
,
''
))
else
{
search
.
mine
();
search
.
on
();
}
}
});
onMounted
(()
=>
{
emitter
.
emit
(
Const
.
settingInit
,
tournament
);
emitter
.
emit
(
Const
.
searcherInit
,
search
);
});
});
onUnmounted
(()
=>
{
document
.
removeEventListener
(
"
click
"
,
page
.
show
.
clear
);
emitter
.
off
(
Const
.
tournamentInfo
,
page
.
show
.
drawer
);
// @ts-ignore
emitter
.
off
(
Const
.
tournamentReload
,
tournament
.
init
);
emitter
.
off
(
Const
.
createOff
,
creator
.
off
);
});
watch
(()
=>
{
return
search
.
date
;
},
()
=>
{
const
toDate
=
()
=>
{
search
.
info
.
after
=
new
Date
(
search
.
date
[
0
]);
search
.
info
.
before
=
new
Date
(
`
${
search
.
date
[
1
]}
T23:59:59.999`
);
};
const
toUndefined
=
()
=>
{
search
.
info
.
after
=
undefined
;
search
.
info
.
before
=
undefined
;
};
search
.
date
.
length
>
0
?
toDate
()
:
toUndefined
();
});
watch
(()
=>
{
return
search
.
id
;
},
()
=>
{
search
.
info
.
id
=
search
.
id
==
''
?
0
:
parseInt
(
search
.
id
);
});
watch
(()
=>
{
return
search
.
creator
;
},
()
=>
{
search
.
info
.
creator
=
search
.
creator
==
''
?
0
:
parseInt
(
search
.
creator
);
});
</
script
>
</
script
>
<
style
scoped
lang =
'scss'
>
<
style
scoped
lang =
'scss'
>
@import
'../style/page.scss'
;
@import
'../style/transition.scss'
;
@import
'../style/transition.scss'
;
#background
{
position
:
fixed
;
background
:
linear-gradient
(
45deg
,
rgb
(
0
,
162
,
255
)
,
rgb
(
0
,
72
,
255
));
width
:
100vw
;
height
:
100vh
;
z-index
:
2
;
#pic
{
// background-image: url("./static/pic.png");
width
:
100%
;
height
:
100%
;
background-size
:
contain
;
background-repeat
:
no-repeat
;
background-position
:
center
;
}
}
.Tabulator
{
position
:
fixed
;
z-index
:
1
;
}
</
style
>
</
style
>
\ No newline at end of file
src/pages/tabulator.vue
0 → 100644
View file @
5072a08a
<
template
>
<view
id =
'page'
>
<view
id =
'really'
class =
'click head'
>
<view>
<button
:style =
"size.width > size.height ?
{ width: '30%' } : {}"
class = 'button'
@click = 'page.show.drawer()'
>
<uni-icons
:type =
"page.menu ? page.drawer ? 'left' : 'search' : page.drawer ? 'left' : 'info'"
></uni-icons>
</button>
</view>
<view>
</view>
<view>
</view>
<view>
</view>
<uni-list>
<uni-list-chat
:avatar-circle =
true
:title =
'Mycard.username'
:note =
'Mycard.email'
:clickable =
true
:avatar =
'Mycard.avatar'
@
click =
'page.show.user()'
>
<uni-icons
:type =
"page.user ? 'right' : 'left'"
></uni-icons>
</uni-list-chat>
</uni-list>
</view>
<view
class =
'click head'
><uni-list><uni-list-chat></uni-list-chat></uni-list></view>
<Pics
:style =
"
{
'--maxsize' : `${size.width > size.height ? size.width / 2 : size.width / 1.2}px`,
'--minsize' : `${size.width / 2}px`,
'--height' : `${size.width > size.height ? 10 : 25}%`,
}"
>
</Pics>
<transition
name =
'move_right'
>
<uni-card
class =
'click'
id =
'user'
v-show =
'page.user'
:title =
'Mycard.username'
:sub-title =
'Mycard.email'
:thumbnail =
'Mycard.avatar'
:style =
"
{ '--size' : `${size.width > size.height ? size.width / 2 : size.width / 1.2}px` }"
>
<view
v-show =
'Mycard.id >= 0'
><h2>
{{
Mycard
.
id
}}
</h2></view>
<hr
v-show =
'Mycard.id >= 0'
>
<view
v-show =
'Mycard.id >= 0'
class =
'user'
@
click =
'page.show.api()'
><span>
api_key
</span></view>
<hr
v-show =
'Mycard.id >= 0'
>
<view
v-show =
'Mycard.id >= 0'
class =
'user'
@
click =
'page.show.create()'
><span>
新建比赛
</span></view>
<hr
v-show =
'Mycard.id >= 0'
>
<view
class =
'user'
@
click =
'() =>
{
Mycard.id >= 0 ? Mycard.logout() : Mycard.login();
}'
>
<span>
{{
Mycard
.
id
>=
0
?
'
退出登陆
'
:
'
登陆
'
}}
</span></view>
</uni-card>
</transition>
<transition
name =
'move_left'
>
<Searcher
class =
'click'
id =
'drawer'
v-show =
'page.drawer && page.menu && !(page.create || page.apikey)'
title =
'搜索'
:style =
"
{ '--size' : `${size.width > size.height ? size.width / 4 : size.width / 2}px` }"
>
</Searcher>
</transition>
<transition
name =
'move_left'
>
<Setting
class =
'click'
id =
'drawer'
v-show =
'page.drawer && page.tournament && !(page.create || page.apikey)'
title =
'比赛设置'
:style =
"
{ '--size' : `${size.width > size.height ? size.width / 4 : size.width / 2}px` }"
>
</Setting>
</transition>
<transition
name =
'move_left'
>
<Create
class =
'click'
id =
'drawer'
v-show =
'page.drawer && page.create'
title =
'比赛创建'
:style =
"
{ '--size' : `${size.width > size.height ? size.width / 4 : size.width / 2}px` }"
>
</Create>
</transition>
<transition
name =
'move_left'
>
<API
class =
'click'
id =
'drawer'
v-show =
'page.drawer && page.apikey'
title =
'我的api密钥'
:style =
"
{ '--size' : `${size.width > size.height ? size.width / 4 : size.width / 2}px` }"
>
</API>
</transition>
<br>
<transition
name =
'switch'
>
<view
id =
'body'
:style =
"
{ '--size' : `${size.width > size.height ? size.width / 2 : size.width}px` }"
>
<transition
name =
'switch'
>
<uni-list
v-show =
'search.result.total > 0 && page.menu'
>
<uni-list-item
id =
'list'
v-for =
'(i, v) in search.result.tournaments'
:title =
'i.name'
:note =
'search.rule.note.get(i.rule)'
:rightText =
'`$
{i.createdAt.toLocaleDateString()}\n${i.count}`'
:clickable = true
@click = 'page.show.tournament(v)'
>
</uni-list-item>
</uni-list>
</transition>
<transition
name =
'switch'
>
<uni-pagination
:current =
'search.info.pageCount'
v-model =
'search.info.pageCount'
pageSize =
20
:total =
'search.result.total'
v-show =
'page.menu'
@
change =
'search.on()'
>
</uni-pagination>
</transition>
<transition
name =
'switch'
>
<PageTournament
v-if =
'page.tournament'
/>
</transition>
</view>
</transition>
</view>
</
template
>
<
script
setup
lang =
'ts'
>
import
{
ref
,
reactive
,
onMounted
,
onUnmounted
,
onBeforeMount
,
watch
}
from
'
vue
'
;
import
{
TournamentFindObject
,
TournamentCreateObject
,
ruleSettings
,
UserObject
}
from
'
../script/type.ts
'
;
import
Uniapp
from
'
../script/uniapp.ts
'
;
import
{
Tabulator
,
User
}
from
'
../script/post.ts
'
;
import
Tournament
from
'
../script/tournament.ts
'
;
import
Mycard
from
'
../script/mycard.ts
'
;
import
emitter
from
'
../script/emitter.ts
'
import
Const
from
'
../script/const.ts
'
import
PageTournament
from
'
./tournament.vue
'
;
import
Create
from
'
./drawer/creator.vue
'
;
import
Pics
from
'
./pics.vue
'
;
import
Setting
from
'
./drawer/setting.vue
'
;
import
Searcher
from
'
./drawer/searcher.vue
'
;
import
API
from
'
./drawer/api.vue
'
;
let
page
=
reactive
({
user
:
false
,
drawer
:
false
,
menu
:
true
,
tournament
:
false
,
create
:
false
,
apikey
:
false
,
show
:
{
user
:
()
:
void
=>
{
page
.
user
=
!
page
.
user
;
},
drawer
:
()
:
void
=>
{
page
.
drawer
=
!
page
.
drawer
;
if
(
!
page
.
drawer
&&
page
.
create
)
page
.
create
=
false
;
if
(
!
page
.
drawer
&&
page
.
apikey
)
page
.
apikey
=
false
;
if
(
!
page
.
drawer
&&
page
.
tournament
)
tournament
.
init
(
tournament
.
this
as
Tournament
);
},
tournament
:
async
(
v
:
number
=
0
):
Promise
<
void
>
=>
{
page
.
menu
=
false
;
await
(
new
Promise
(
resolve
=>
setTimeout
(
resolve
,
500
)));
page
.
tournament
=
true
;
const
url
=
window
.
location
.
href
.
split
(
'
/?
'
);
window
.
location
.
replace
(
`
${
url
[
0
].
replace
(
/
\/?
$/
,
''
)}
/tournament/
${
search
.
result
.
tournaments
[
v
].
id
}${
url
[
1
]
?
`/?
${
url
[
1
]}
`
:
''
}
`
);
},
menu
:
async
():
Promise
<
void
>
=>
{
page
.
tournament
=
false
;
tournament
.
clear
();
await
search
.
on
();
await
(
new
Promise
(
resolve
=>
setTimeout
(
resolve
,
500
)));
page
.
menu
=
true
;
},
create
:
async
():
Promise
<
void
>
=>
{
if
(
page
.
drawer
)
{
page
.
show
.
drawer
();
await
(
new
Promise
(
resolve
=>
setTimeout
(
resolve
,
500
)));
}
page
.
create
=
true
;
page
.
show
.
drawer
();
},
api
:
async
():
Promise
<
void
>
=>
{
if
(
page
.
drawer
)
{
page
.
show
.
drawer
();
await
(
new
Promise
(
resolve
=>
setTimeout
(
resolve
,
500
)));
}
page
.
apikey
=
true
;
page
.
show
.
drawer
();
},
clear
:
(
e
)
:
void
=>
{
let
element
=
e
.
target
;
let
chk
=
false
;
let
inPage
=
false
;
let
uniElement
=
false
;
while
(
element
)
{
if
([
'
head
'
,
'
user
'
,
'
drawer
'
].
includes
(
element
.
id
)
||
element
.
classList
.
contains
(
'
click
'
))
chk
=
true
;
if
(
element
.
id
==
'
page
'
)
inPage
=
true
;
if
(
typeof
element
.
className
==
'
string
'
&&
element
.
className
.
includes
(
'
uni
'
))
uniElement
=
true
;
element
=
element
.
parentElement
;
}
if
(
chk
||
(
!
inPage
&&
uniElement
))
return
undefined
;
if
(
page
.
user
)
page
.
show
.
user
();
if
(
page
.
drawer
)
page
.
show
.
drawer
();
}
}
});
let
search
=
reactive
({
id
:
''
,
creator
:
''
,
date
:
[]
as
Array
<
string
>
,
rule
:
{
range
:
[
{
value
:
'
'
,
text
:
'
全部
'
},
{
value
:
'
SingleElimination
'
,
text
:
'
单淘
'
},
{
value
:
'
Swiss
'
,
text
:
'
瑞士轮
'
}
],
note
:
new
Map
([
[
'
SingleElimination
'
,
'
单淘
'
],
[
'
Swiss
'
,
'
瑞士轮
'
]
])
as
Map
<
string
,
string
>
},
visibility
:
{
range
:
[
{
value
:
'
'
,
text
:
'
全部
'
},
{
value
:
'
Public
'
,
text
:
'
公开
'
},
{
value
:
'
Internal
'
,
text
:
'
仅登陆可见
'
},
{
value
:
'
Private
'
,
text
:
'
私密
'
}
]
},
status
:
{
range
:
[
{
value
:
'
'
,
text
:
'
全部
'
},
{
value
:
'
Ready
'
,
text
:
'
准备中
'
},
{
value
:
'
Running
'
,
text
:
'
进行中
'
},
{
value
:
'
Finished
'
,
text
:
'
已结束
'
}
]
},
info
:
{
pageCount
:
1
,
id
:
0
,
creator
:
0
,
before
:
undefined
,
after
:
undefined
,
name
:
''
,
rule
:
''
,
visibility
:
''
,
status
:
''
}
as
TournamentFindObject
,
result
:
{
total
:
0
,
tournaments
:
[]
as
Array
<
Tournament
>
},
on
:
async
(
Data
:
TournamentFindObject
=
search
.
info
)
:
Promise
<
void
>
=>
{
page
.
drawer
=
false
;
if
(
search
.
result
.
total
>
0
)
{
search
.
result
.
total
=
0
;
}
const
result
=
await
Tabulator
.
Tournament
.
FindALL
(
Mycard
.
token
,
Data
);
search
.
result
.
total
=
result
.
total
;
search
.
result
.
tournaments
=
result
.
tournaments
;
},
mine
:
()
=>
{
search
.
creator
=
Mycard
.
id
>=
0
?
Mycard
.
id
.
toString
()
:
''
;
}
});
let
tournament
=
reactive
({
this
:
undefined
as
undefined
|
Tournament
,
name
:
''
,
description
:
''
,
visibility
:
{
select
:
''
,
range
:
[
{
value
:
'
Public
'
,
text
:
'
公开
'
},
{
value
:
'
Internal
'
,
text
:
'
仅登陆可见
'
},
{
value
:
'
Private
'
,
text
:
'
私密
'
}
]
},
rule
:
{
select
:
''
,
range
:
[
{
value
:
'
SingleElimination
'
,
text
:
'
单淘
'
},
{
value
:
'
Swiss
'
,
text
:
'
瑞士轮
'
}
],
settings
:
{
}
as
ruleSettings
},
hasThirdPlaceMatch
:
{
select
:
(
e
)
=>
{
tournament
.
rule
.
settings
.
hasThirdPlaceMatch
=
e
.
detail
.
value
.
length
>
0
}
},
collaborator
:
''
,
collaborators
:
[]
as
Array
<
UserObject
>
,
init
:
async
(
t
:
Tournament
)
:
Promise
<
void
>
=>
{
if
(
!
t
)
return
;
tournament
.
this
=
t
;
tournament
.
name
=
t
.
name
;
tournament
.
description
=
t
.
description
;
tournament
.
visibility
.
select
=
t
.
visibility
;
tournament
.
rule
.
select
=
t
.
rule
;
tournament
.
rule
.
settings
=
Object
.
assign
({},
t
.
ruleSettings
);
let
collaborators
:
Array
<
UserObject
>
=
[];
for
(
const
id
of
t
.
collaborators
)
{
const
i
=
tournament
.
collaborators
.
find
(
i
=>
i
.
id
==
id
)
??
await
User
.
Find
.
Id
(
id
);
if
(
i
)
collaborators
.
push
(
i
);
}
tournament
.
collaborators
=
collaborators
;
},
clear
:
()
:
void
=>
{
tournament
.
this
=
undefined
;
tournament
.
name
=
''
;
tournament
.
description
=
''
;
tournament
.
visibility
.
select
=
''
;
tournament
.
rule
.
select
=
''
;
tournament
.
rule
.
settings
=
{}
as
ruleSettings
;
tournament
.
collaborators
=
[];
},
update
:
()
:
void
=>
{
if
(
tournament
.
visibility
.
select
==
''
)
// @ts-ignore
tournament
.
visibility
.
select
=
tournament
.
this
.
visibility
;
const
collaborators
=
tournament
.
collaborators
.
map
(
user
=>
user
.
id
);
emitter
.
emit
(
Const
.
updateTournament
,
{
name
:
tournament
.
name
,
description
:
tournament
.
description
,
visibility
:
tournament
.
visibility
.
select
,
collaborators
:
collaborators
,
// PS:这里接口暂时不通
// rule : tournament.rule.select,
// ruleSettings : tournament.rule.settings
}
as
TournamentCreateObject
);
},
remove
:
(
v
:
number
)
:
void
=>
{
tournament
.
collaborators
.
splice
(
v
,
1
);
},
add
:
async
()
:
Promise
<
void
>
=>
{
try
{
if
(
tournament
.
collaborators
.
findIndex
(
i
=>
i
.
username
==
tournament
.
collaborator
)
>=
0
)
throw
new
Error
(
'
协作者已存在
'
);
const
i
=
await
User
.
Find
.
Name
(
tournament
.
collaborator
);
if
(
!
i
)
throw
new
Error
(
'
未搜索到此用户
'
);
if
(
tournament
.
this
?.
creator
==
i
.
id
)
throw
new
Error
(
'
协作者不可以是比赛创建者
'
);
tournament
.
collaborators
.
push
(
i
);
}
catch
(
error
)
{
uni
.
showModal
({
title
:
'
添加失败
'
,
content
:
error
.
message
,
showCancel
:
false
});
}
finally
{
tournament
.
collaborator
=
''
;
}
},
operatorChk
:
()
:
boolean
=>
{
if
(
!
tournament
.
this
)
return
true
return
!
(
Mycard
.
id
>=
0
&&
(
Mycard
.
id
==
tournament
.
this
?.
creator
||
tournament
.
this
?.
collaborators
.
includes
(
Mycard
.
id
)))
}
});
const
creator
=
{
off
:
async
()
:
Promise
<
void
>
=>
{
page
.
show
.
drawer
();
if
(
page
.
tournament
)
page
.
show
.
menu
();
search
.
mine
();
await
search
.
on
();
}
};
let
size
=
reactive
({
width
:
0
,
height
:
0
,
get
:
()
=>
{
// @ts-ignore
size
.
width
=
uni
.
getSystemInfoSync
().
windowWidth
;
size
.
height
=
uni
.
getSystemInfoSync
().
windowHeight
;
}
});
onBeforeMount
(()
:
void
=>
{
Uniapp
.
chkScreen
(
size
.
get
);
document
.
addEventListener
(
"
click
"
,
page
.
show
.
clear
);
emitter
.
on
(
Const
.
tournamentInfo
,
page
.
show
.
drawer
);
// @ts-ignore
emitter
.
on
(
Const
.
tournamentReload
,
tournament
.
init
);
emitter
.
on
(
Const
.
createOff
,
creator
.
off
);
const
url
=
window
.
location
.
pathname
.
match
(
/
\/
tournament
\/([^\/]
+
)(?=\/
|$
)
/
);
if
(
url
&&
!
isNaN
(
parseInt
(
url
[
1
])))
{
page
.
menu
=
false
;
page
.
tournament
=
true
;
}
else
{
if
(
window
.
location
.
pathname
.
length
>
1
)
window
.
location
.
replace
(
window
.
location
.
href
.
replace
(
window
.
location
.
pathname
,
''
))
else
{
search
.
mine
();
search
.
on
();
}
}
});
onMounted
(()
=>
{
emitter
.
emit
(
Const
.
settingInit
,
tournament
);
emitter
.
emit
(
Const
.
searcherInit
,
search
);
});
onUnmounted
(()
=>
{
document
.
removeEventListener
(
"
click
"
,
page
.
show
.
clear
);
emitter
.
off
(
Const
.
tournamentInfo
,
page
.
show
.
drawer
);
// @ts-ignore
emitter
.
off
(
Const
.
tournamentReload
,
tournament
.
init
);
emitter
.
off
(
Const
.
createOff
,
creator
.
off
);
});
watch
(()
=>
{
return
search
.
date
;
},
()
=>
{
const
toDate
=
()
=>
{
search
.
info
.
after
=
new
Date
(
search
.
date
[
0
]);
search
.
info
.
before
=
new
Date
(
`
${
search
.
date
[
1
]}
T23:59:59.999`
);
};
const
toUndefined
=
()
=>
{
search
.
info
.
after
=
undefined
;
search
.
info
.
before
=
undefined
;
};
search
.
date
.
length
>
0
?
toDate
()
:
toUndefined
();
});
watch
(()
=>
{
return
search
.
id
;
},
()
=>
{
search
.
info
.
id
=
search
.
id
==
''
?
0
:
parseInt
(
search
.
id
);
});
watch
(()
=>
{
return
search
.
creator
;
},
()
=>
{
search
.
info
.
creator
=
search
.
creator
==
''
?
0
:
parseInt
(
search
.
creator
);
});
</
script
>
<
style
scoped
lang =
'scss'
>
@import
'../style/page.scss'
;
@import
'../style/transition.scss'
;
</
style
>
\ No newline at end of file
src/style/transition.scss
View file @
5072a08a
...
@@ -32,7 +32,7 @@
...
@@ -32,7 +32,7 @@
}
}
}
}
.move_right
{
.move_right
,
.move_right_slow
{
&
-enter-active
,
&
-enter-active
,
&
-leave-active
{
&
-leave-active
{
transition
:
transform
0
.5s
ease
;
transition
:
transform
0
.5s
ease
;
...
@@ -49,6 +49,12 @@
...
@@ -49,6 +49,12 @@
}
}
}
}
.move_right_slow
{
&
-leave-active
{
transition
:
transform
2s
ease
;
}
}
.move_up
{
.move_up
{
&
-enter-active
,
&
-enter-active
,
&
-leave-active
{
&
-leave-active
{
...
...
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