mirror of
https://github.com/Megghy/vtsuru.live.git
synced 2025-12-07 02:46:55 +08:00
nothing
This commit is contained in:
@@ -1,65 +0,0 @@
|
||||
<template>
|
||||
<div class="hello">
|
||||
<h1>{{ msg }}</h1>
|
||||
<p>
|
||||
For a guide and recipes on how to configure / customize this project,<br />
|
||||
check out the
|
||||
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
|
||||
</p>
|
||||
<h3>Installed CLI Plugins</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a>
|
||||
</li>
|
||||
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-pwa" target="_blank" rel="noopener">pwa</a></li>
|
||||
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-router" target="_blank" rel="noopener">router</a></li>
|
||||
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-vuex" target="_blank" rel="noopener">vuex</a></li>
|
||||
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
|
||||
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-typescript" target="_blank" rel="noopener">typescript</a></li>
|
||||
</ul>
|
||||
<h3>Essential Links</h3>
|
||||
<ul>
|
||||
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
|
||||
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
|
||||
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
|
||||
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
|
||||
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
|
||||
</ul>
|
||||
<h3>Ecosystem</h3>
|
||||
<ul>
|
||||
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
|
||||
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
|
||||
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
|
||||
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
|
||||
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'HelloWorld',
|
||||
props: {
|
||||
msg: String,
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped lang="stylus">
|
||||
h3
|
||||
margin 40px 0 0
|
||||
|
||||
ul
|
||||
list-style-type none
|
||||
padding 0
|
||||
|
||||
li
|
||||
display inline-block
|
||||
margin 0 10px
|
||||
|
||||
a
|
||||
color #42b983
|
||||
</style>
|
||||
109
src/components/RegisterAndLogin.vue
Normal file
109
src/components/RegisterAndLogin.vue
Normal file
@@ -0,0 +1,109 @@
|
||||
<script setup lang="ts">
|
||||
import { FormInst, FormItemInst, FormItemRule, FormRules, NButton, NCard, NForm, NFormItem, NInput, NSpace } from 'naive-ui'
|
||||
import { ref } from 'vue'
|
||||
|
||||
interface RegisterModel {
|
||||
username: string
|
||||
email: string
|
||||
password: string
|
||||
reenteredPassword: string
|
||||
}
|
||||
interface LoginModel {
|
||||
account: string
|
||||
password: string
|
||||
}
|
||||
|
||||
const isRegister = ref(false)
|
||||
|
||||
const registerModel = ref<RegisterModel>({} as RegisterModel)
|
||||
const loginModel = ref<LoginModel>({} as LoginModel)
|
||||
|
||||
const formRef = ref<FormInst | null>(null)
|
||||
const rPasswordFormItemRef = ref<FormItemInst | null>(null)
|
||||
const rules: FormRules = {
|
||||
account: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入用户名或邮箱',
|
||||
},
|
||||
],
|
||||
password: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入密码',
|
||||
},
|
||||
],
|
||||
reenteredPassword: [
|
||||
{
|
||||
required: true,
|
||||
message: '请再次输入密码',
|
||||
trigger: ['input', 'blur'],
|
||||
},
|
||||
{
|
||||
validator: validatePasswordStartWith,
|
||||
message: '两次密码输入不一致',
|
||||
trigger: 'input',
|
||||
},
|
||||
{
|
||||
validator: validatePasswordSame,
|
||||
message: '两次密码输入不一致',
|
||||
trigger: ['blur', 'password-input'],
|
||||
},
|
||||
],
|
||||
}
|
||||
function validatePasswordStartWith(rule: FormItemRule, value: string): boolean {
|
||||
return !!registerModel.value.password && registerModel.value.password.startsWith(value) && registerModel.value.password.length >= value.length
|
||||
}
|
||||
function validatePasswordSame(rule: FormItemRule, value: string): boolean {
|
||||
return value === registerModel.value.password
|
||||
}
|
||||
function onPasswordInput() {
|
||||
if (registerModel.value.reenteredPassword) {
|
||||
rPasswordFormItemRef.value?.validate({ trigger: 'password-input' })
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NCard embedded>
|
||||
<template #header>
|
||||
<Transition name="fade" mode="out-in">
|
||||
<span v-if="isRegister"> 注册 </span>
|
||||
<span v-else> 登陆 </span>
|
||||
</Transition>
|
||||
</template>
|
||||
<Transition name="scale" mode="out-in">
|
||||
<div v-if="isRegister">
|
||||
<NForm ref="formRef" :rules="rules" :model="registerModel">
|
||||
<NFormItem path="username" label="用户名">
|
||||
<NInput v-model:value="registerModel.username" />
|
||||
</NFormItem>
|
||||
<NFormItem path="email" label="邮箱">
|
||||
<NInput v-model:value="registerModel.email" />
|
||||
</NFormItem>
|
||||
<NFormItem path="password" label="密码">
|
||||
<NInput v-model:value="registerModel.password" type="password" @input="onPasswordInput" @keydown.enter.prevent />
|
||||
</NFormItem>
|
||||
<NFormItem ref="rPasswordFormItemRef" first path="reenteredPassword" label="重复密码">
|
||||
<NInput v-model:value="registerModel.reenteredPassword" :disabled="!registerModel.password" type="password" @keydown.enter.prevent />
|
||||
</NFormItem>
|
||||
</NForm>
|
||||
<NButton @click="isRegister = false"> 或者现在去登陆 </NButton>
|
||||
</div>
|
||||
<div v-else>
|
||||
<NForm ref="formRef" :rules="rules" :model="registerModel">
|
||||
<NFormItem path="account" label="用户名或邮箱">
|
||||
<NInput v-model:value="loginModel.account" />
|
||||
</NFormItem>
|
||||
<NFormItem path="password" label="密码">
|
||||
<NInput v-model:value="loginModel.password" type="password" @input="onPasswordInput" @keydown.enter.prevent />
|
||||
</NFormItem>
|
||||
</NForm>
|
||||
<NSpace vertical justify="center" align="center">
|
||||
<NButton type="primary" size="large"> 登陆 </NButton>
|
||||
<NButton @click="isRegister = true" size="small" text> 或者现在去注册 </NButton>
|
||||
</NSpace>
|
||||
</div>
|
||||
</Transition>
|
||||
</NCard>
|
||||
</template>
|
||||
132
src/components/SongList.vue
Normal file
132
src/components/SongList.vue
Normal file
@@ -0,0 +1,132 @@
|
||||
<script setup lang="ts">
|
||||
import { SongsInfo } from '@/api/api-models'
|
||||
import { DataTableColumns, NAvatar, NButton, NDataTable, NInput, NList, NListItem, NSpace } from 'naive-ui'
|
||||
import { onMounted, h, ref } from 'vue'
|
||||
import APlayer from 'vue3-aplayer'
|
||||
|
||||
const props = defineProps<{
|
||||
songs: SongsInfo[]
|
||||
canEdit?: boolean
|
||||
}>()
|
||||
const songsInternal = ref<{ [id: string]: SongsInfo }>({})
|
||||
const columns = ref<DataTableColumns<SongsInfo>>()
|
||||
const aplayerMusic = ref<{
|
||||
title: string
|
||||
artist: string
|
||||
src: string
|
||||
pic: string
|
||||
}>()
|
||||
|
||||
const createColumns = (): DataTableColumns<SongsInfo> => [
|
||||
{
|
||||
title: '',
|
||||
key: 'cover',
|
||||
resizable: false,
|
||||
width: 50,
|
||||
render(data) {
|
||||
return h(NAvatar, {
|
||||
src: data.cover,
|
||||
imgProps: {
|
||||
|
||||
}
|
||||
})
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '名称',
|
||||
key: 'name',
|
||||
resizable: true,
|
||||
minWidth: 100,
|
||||
render(data) {
|
||||
return props.canEdit
|
||||
? h(NInput, {
|
||||
value: data.name,
|
||||
onUpdateValue(v) {
|
||||
songsInternal.value[data.id].name = v
|
||||
},
|
||||
})
|
||||
: h('span', data.name)
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '作者',
|
||||
key: 'author',
|
||||
resizable: true,
|
||||
render(data) {
|
||||
return props.canEdit
|
||||
? h(NInput, {
|
||||
value: data.author,
|
||||
onUpdateValue(v) {
|
||||
songsInternal.value[data.id].author = v
|
||||
},
|
||||
})
|
||||
: h('span', data.author)
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '描述',
|
||||
key: 'description',
|
||||
resizable: true,
|
||||
minWidth: 75,
|
||||
render(data) {
|
||||
return props.canEdit
|
||||
? h(NInput, {
|
||||
value: data.desc,
|
||||
onUpdateValue(v) {
|
||||
songsInternal.value[data.id].desc = v
|
||||
},
|
||||
})
|
||||
: h('span', data.desc)
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'manage',
|
||||
minWidth: 75,
|
||||
render(data) {
|
||||
return h(NSpace, [
|
||||
h(
|
||||
NButton,
|
||||
{
|
||||
onClick: () => console.log(1),
|
||||
},
|
||||
{
|
||||
default: () => '保存',
|
||||
}
|
||||
),
|
||||
h(
|
||||
NButton,
|
||||
{
|
||||
type: 'primary',
|
||||
onClick: () => {
|
||||
aplayerMusic.value = {
|
||||
title: data.name,
|
||||
artist: data.author,
|
||||
src: data.url,
|
||||
pic: data.cover,
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
default: () => '播放',
|
||||
}
|
||||
),
|
||||
])
|
||||
},
|
||||
},
|
||||
]
|
||||
onMounted(() => {
|
||||
props.songs.forEach((song) => {
|
||||
songsInternal.value[song.id] = song
|
||||
})
|
||||
columns.value = createColumns()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
歌单 {{ songs.length }}
|
||||
<Transition>
|
||||
<APlayer v-if="aplayerMusic" :music="aplayerMusic" />
|
||||
</Transition>
|
||||
<NDataTable :columns="columns" :data="songs"> </NDataTable>
|
||||
</template>
|
||||
Reference in New Issue
Block a user