support searching players when applying textures
This commit is contained in:
parent
9e792b9c3a
commit
cf6f1aa547
@ -5,21 +5,25 @@
|
|||||||
:title="$t('user.closet.use-as.title')"
|
:title="$t('user.closet.use-as.title')"
|
||||||
:ok-button-text="$t('general.submit')"
|
:ok-button-text="$t('general.submit')"
|
||||||
flex-footer
|
flex-footer
|
||||||
center
|
|
||||||
>
|
>
|
||||||
<template v-if="players.length !== 0">
|
<template v-if="players.length !== 0">
|
||||||
<div v-for="player in players" :key="player.pid" class="player-item">
|
<div class="form-group">
|
||||||
<label class="model-label" :for="player.pid">
|
|
||||||
<input
|
<input
|
||||||
v-model="selected"
|
v-model="search"
|
||||||
type="radio"
|
type="text"
|
||||||
name="player"
|
class="form-control"
|
||||||
:value="player.pid"
|
:placeholder="$t('user.typeToSearch')"
|
||||||
>
|
>
|
||||||
<img :src="avatarUrl(player)" width="35" height="35">
|
|
||||||
<span>{{ player.name }}</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
|
<button
|
||||||
|
v-for="player in filteredPlayers"
|
||||||
|
:key="player.pid"
|
||||||
|
class="btn btn-block btn-outline-info text-left"
|
||||||
|
@click="submit(player.pid)"
|
||||||
|
>
|
||||||
|
<img :src="avatarUrl(player)" width="45" height="45">
|
||||||
|
<span>{{ player.name }}</span>
|
||||||
|
</button>
|
||||||
</template>
|
</template>
|
||||||
<p v-else v-t="'user.closet.use-as.empty'" />
|
<p v-else v-t="'user.closet.use-as.empty'" />
|
||||||
<template #footer>
|
<template #footer>
|
||||||
@ -31,8 +35,8 @@
|
|||||||
class="btn btn-default"
|
class="btn btn-default"
|
||||||
href="#"
|
href="#"
|
||||||
/>
|
/>
|
||||||
<button class="btn btn-primary" data-test="submit" @click="submit">
|
<button class="btn btn-default" data-dismiss="modal">
|
||||||
{{ $t('general.submit') }}
|
{{ $t('general.cancel') }}
|
||||||
</button>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
</modal>
|
</modal>
|
||||||
@ -59,26 +63,29 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
players: [],
|
players: [],
|
||||||
selected: 0,
|
search: '',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
filteredPlayers() {
|
||||||
|
return this.players.filter(player => player.name.includes(this.search))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.fetchList()
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async fetchList() {
|
async fetchList() {
|
||||||
this.players = (await this.$http.get('/user/player/list')).data
|
this.players = (await this.$http.get('/user/player/list')).data
|
||||||
},
|
},
|
||||||
async submit() {
|
async submit(selected) {
|
||||||
if (!this.selected) {
|
|
||||||
toast.info(this.$t('user.emptySelectedPlayer'))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.skin && !this.cape) {
|
if (!this.skin && !this.cape) {
|
||||||
toast.info(this.$t('user.emptySelectedTexture'))
|
toast.info(this.$t('user.emptySelectedTexture'))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const { code, message } = await this.$http.post(
|
const { code, message } = await this.$http.post(
|
||||||
`/user/player/set/${this.selected}`,
|
`/user/player/set/${selected}`,
|
||||||
{
|
{
|
||||||
skin: this.skin || undefined,
|
skin: this.skin || undefined,
|
||||||
cape: this.cape || undefined,
|
cape: this.cape || undefined,
|
||||||
@ -92,13 +99,8 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
avatarUrl(player) {
|
avatarUrl(player) {
|
||||||
return `${blessing.base_url}/avatar/${player.tid_skin}?3d&size=35`
|
return `${blessing.base_url}/avatar/${player.tid_skin}?3d&size=45`
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="stylus">
|
|
||||||
.player-item:not(:nth-child(1))
|
|
||||||
margin-top 10px
|
|
||||||
</style>
|
|
||||||
|
@ -8,16 +8,13 @@ import ApplyToPlayerDialog from '@/components/ApplyToPlayerDialog.vue'
|
|||||||
jest.mock('@/scripts/notify')
|
jest.mock('@/scripts/notify')
|
||||||
|
|
||||||
test('submit applying texture', async () => {
|
test('submit applying texture', async () => {
|
||||||
Vue.prototype.$http.get.mockResolvedValue({ data: [{ pid: 1 }] })
|
Vue.prototype.$http.get.mockResolvedValue({ data: [{ pid: 1, name: 'a' }] })
|
||||||
Vue.prototype.$http.post.mockResolvedValueOnce({ code: 1 })
|
Vue.prototype.$http.post.mockResolvedValueOnce({ code: 1 })
|
||||||
.mockResolvedValue({ code: 0, message: 'ok' })
|
.mockResolvedValue({ code: 0, message: 'ok' })
|
||||||
const wrapper = mount(ApplyToPlayerDialog)
|
const wrapper = mount(ApplyToPlayerDialog)
|
||||||
const button = wrapper.find('[data-test=submit]')
|
await flushPromises()
|
||||||
|
const button = wrapper.find('.btn-outline-info')
|
||||||
|
|
||||||
button.trigger('click')
|
|
||||||
expect(toast.info).toBeCalledWith('user.emptySelectedPlayer')
|
|
||||||
|
|
||||||
wrapper.setData({ selected: 1 })
|
|
||||||
button.trigger('click')
|
button.trigger('click')
|
||||||
expect(toast.info).toBeCalledWith('user.emptySelectedTexture')
|
expect(toast.info).toBeCalledWith('user.emptySelectedTexture')
|
||||||
|
|
||||||
@ -48,5 +45,17 @@ test('compute avatar URL', () => {
|
|||||||
// eslint-disable-next-line camelcase
|
// eslint-disable-next-line camelcase
|
||||||
const wrapper = mount<Vue & { avatarUrl(player: { tid_skin: number }): string }>(ApplyToPlayerDialog)
|
const wrapper = mount<Vue & { avatarUrl(player: { tid_skin: number }): string }>(ApplyToPlayerDialog)
|
||||||
const { avatarUrl } = wrapper.vm
|
const { avatarUrl } = wrapper.vm
|
||||||
expect(avatarUrl({ tid_skin: 1 })).toBe('/avatar/1?3d&size=35')
|
expect(avatarUrl({ tid_skin: 1 })).toBe('/avatar/1?3d&size=45')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('search players', async () => {
|
||||||
|
Vue.prototype.$http.get.mockResolvedValue({ data: [{ pid: 1, name: 'abc' }] })
|
||||||
|
const wrapper = mount(ApplyToPlayerDialog)
|
||||||
|
await flushPromises()
|
||||||
|
|
||||||
|
wrapper.find('input').setValue('e')
|
||||||
|
expect(wrapper.find('.btn-outline-info').exists()).toBeFalse()
|
||||||
|
|
||||||
|
wrapper.find('input').setValue('b')
|
||||||
|
expect(wrapper.find('.btn-outline-info').exists()).toBeTrue()
|
||||||
})
|
})
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
- Added login with 3rd-party services. (GitHub and Microsoft Live are supported currently.)
|
- Added login with 3rd-party services. (GitHub and Microsoft Live are supported currently.)
|
||||||
- Added support of character "§" for player name. (Under CJK mode.)
|
- Added support of character "§" for player name. (Under CJK mode.)
|
||||||
- New password hash algorithm: Argon2i.
|
- New password hash algorithm: Argon2i.
|
||||||
|
- Support searching players when applying textures.
|
||||||
|
|
||||||
## Tweaked
|
## Tweaked
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
- 第三方登录(目前仅支持 GitHub 和 Microsoft Live)
|
- 第三方登录(目前仅支持 GitHub 和 Microsoft Live)
|
||||||
- 角色名支持字符「§」(需开启「CJK」模式)
|
- 角色名支持字符「§」(需开启「CJK」模式)
|
||||||
- 新的密码哈希算法:Argon2i
|
- 新的密码哈希算法:Argon2i
|
||||||
|
- 将材质应用到角色时可进行搜索
|
||||||
|
|
||||||
## 调整
|
## 调整
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user