feat: style
This commit is contained in:
@@ -18,7 +18,7 @@ function generateMusic(args: { formData: Recordable<any> }) {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Page>
|
||||
<Page auto-content-height>
|
||||
<div class="flex h-full items-stretch">
|
||||
<!-- 模式 -->
|
||||
<Mode class="flex-none" @generate-music="generateMusic" />
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
<script lang="ts" setup>
|
||||
import type { Nullable } from '@vben/types';
|
||||
|
||||
import { inject, reactive, ref } from 'vue';
|
||||
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
@@ -10,9 +8,9 @@ import { Image, Slider } from 'ant-design-vue';
|
||||
|
||||
defineOptions({ name: 'AiMusicAudioBarIndex' });
|
||||
|
||||
const currentSong = inject('currentSong', {});
|
||||
const currentSong = inject<any>('currentSong', {});
|
||||
|
||||
const audioRef = ref<Nullable<HTMLElement>>(null);
|
||||
const audioRef = ref<HTMLAudioElement | null>(null);
|
||||
// 音频相关属性https://www.runoob.com/tags/ref-av-dom.html
|
||||
const audioProps = reactive<any>({
|
||||
autoplay: true,
|
||||
@@ -42,26 +40,24 @@ function audioTimeUpdate(args: any) {
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="b-solid b-1 b-l-none flex h-[72px] items-center justify-between px-2"
|
||||
style="background-color: #fffffd; border-color: #dcdfe6"
|
||||
class="b-1 b-l-none h-18 flex items-center justify-between border border-solid border-rose-100 bg-white px-2"
|
||||
>
|
||||
<!-- 歌曲信息 -->
|
||||
<div class="flex gap-[10px]">
|
||||
<div class="flex gap-2.5">
|
||||
<Image
|
||||
src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png"
|
||||
:width="45"
|
||||
/>
|
||||
<div>
|
||||
<div>{{ currentSong.name }}</div>
|
||||
<div class="text-[12px] text-gray-400">{{ currentSong.singer }}</div>
|
||||
<div class="text-xs text-gray-400">{{ currentSong.singer }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 音频controls -->
|
||||
<div class="flex items-center gap-[12px]">
|
||||
<div class="flex items-center gap-3">
|
||||
<IconifyIcon
|
||||
icon="majesticons:back-circle"
|
||||
:size="20"
|
||||
class="cursor-pointer text-gray-300"
|
||||
class="size-5 cursor-pointer text-gray-300"
|
||||
/>
|
||||
<IconifyIcon
|
||||
:icon="
|
||||
@@ -69,21 +65,19 @@ function audioTimeUpdate(args: any) {
|
||||
? 'mdi:arrow-right-drop-circle'
|
||||
: 'solar:pause-circle-bold'
|
||||
"
|
||||
:size="30"
|
||||
class="cursor-pointer"
|
||||
class="size-7 cursor-pointer"
|
||||
@click="toggleStatus('paused')"
|
||||
/>
|
||||
<IconifyIcon
|
||||
icon="majesticons:next-circle"
|
||||
:size="20"
|
||||
class="cursor-pointer text-gray-300"
|
||||
class="size-5 cursor-pointer text-gray-300"
|
||||
/>
|
||||
<div class="flex items-center gap-[16px]">
|
||||
<div class="flex items-center gap-4">
|
||||
<span>{{ audioProps.currentTime }}</span>
|
||||
<Slider
|
||||
v-model:value="audioProps.duration"
|
||||
color="#409eff"
|
||||
class="w-[160px!important]"
|
||||
class="!w-40"
|
||||
/>
|
||||
<span>{{ audioProps.duration }}</span>
|
||||
</div>
|
||||
@@ -98,18 +92,13 @@ function audioTimeUpdate(args: any) {
|
||||
<!-- <source :src="audioUrl" /> -->
|
||||
</audio>
|
||||
</div>
|
||||
<div class="flex items-center gap-[16px]">
|
||||
<div class="flex items-center gap-4">
|
||||
<IconifyIcon
|
||||
:icon="audioProps.muted ? 'tabler:volume-off' : 'tabler:volume'"
|
||||
:size="20"
|
||||
class="cursor-pointer"
|
||||
class="size-5 cursor-pointer"
|
||||
@click="toggleStatus('muted')"
|
||||
/>
|
||||
<Slider
|
||||
v-model:value="audioProps.volume"
|
||||
color="#409eff"
|
||||
class="w-[160px!important]"
|
||||
/>
|
||||
<Slider v-model:value="audioProps.volume" color="#409eff" class="!w-40" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -74,7 +74,7 @@ provide('currentSong', currentSong);
|
||||
<div class="flex flex-auto overflow-hidden">
|
||||
<Tabs
|
||||
v-model:active-key="currentType"
|
||||
class="flex-auto px-[20px]"
|
||||
class="flex-auto px-5"
|
||||
tab-position="bottom"
|
||||
>
|
||||
<!-- 我的创作 -->
|
||||
|
||||
@@ -16,7 +16,7 @@ defineProps({
|
||||
|
||||
const emits = defineEmits(['play']);
|
||||
|
||||
const currentSong = inject('currentSong', {});
|
||||
const currentSong = inject<any>('currentSong', {});
|
||||
|
||||
function playSong() {
|
||||
emits('play');
|
||||
@@ -24,11 +24,11 @@ function playSong() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="rounded-1 mb-[12px] flex p-[12px]">
|
||||
<div class="mb-3 flex rounded p-3">
|
||||
<div class="relative" @click="playSong">
|
||||
<Image :src="songInfo.imageUrl" class="w-80px flex-none" />
|
||||
<Image :src="songInfo.imageUrl" class="w-20 flex-none" />
|
||||
<div
|
||||
class="bg-op-40 absolute left-0 top-0 flex h-full w-full cursor-pointer items-center justify-center bg-black"
|
||||
class="absolute left-0 top-0 flex h-full w-full cursor-pointer items-center justify-center bg-black bg-opacity-40"
|
||||
>
|
||||
<IconifyIcon
|
||||
:icon="
|
||||
@@ -40,9 +40,9 @@ function playSong() {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ml-[8px]">
|
||||
<div class="ml-2">
|
||||
<div>{{ songInfo.title }}</div>
|
||||
<div class="mt-[8px] line-clamp-2 text-[12px]">
|
||||
<div class="mt-2 line-clamp-2 text-xs">
|
||||
{{ songInfo.desc }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -5,21 +5,21 @@ import { Button, Card, Image } from 'ant-design-vue';
|
||||
|
||||
defineOptions({ name: 'AiMusicSongInfoIndex' });
|
||||
|
||||
const currentSong = inject('currentSong', {});
|
||||
const currentSong = inject<any>('currentSong', {});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Card class="line-height-24px mb-[0!important] w-[300px]">
|
||||
<Image :src="currentSong.imageUrl" style="width: 100%; height: 100%" />
|
||||
<Card class="!mb-0 w-40 leading-6">
|
||||
<Image :src="currentSong.imageUrl" class="h-full w-full" />
|
||||
|
||||
<div class="">{{ currentSong.title }}</div>
|
||||
<div class="line-clamp-1 text-[12px]">
|
||||
<div class="line-clamp-1 text-xs">
|
||||
{{ currentSong.desc }}
|
||||
</div>
|
||||
<div class="text-[12px]">
|
||||
<div class="text-xs">
|
||||
{{ currentSong.date }}
|
||||
</div>
|
||||
<Button size="small" shape="round" class="my-[6px]">信息复用</Button>
|
||||
<div class="text-[12px]" v-html="currentSong.lyric"></div>
|
||||
<Button size="small" shape="round" class="my-2">信息复用</Button>
|
||||
<div class="text-xs" v-html="currentSong.lyric"></div>
|
||||
</Card>
|
||||
</template>
|
||||
|
||||
@@ -33,7 +33,7 @@ defineExpose({
|
||||
/>
|
||||
</Title>
|
||||
|
||||
<Title title="纯音乐" class="mt-[20px]" desc="创建一首没有歌词的歌曲">
|
||||
<Title title="纯音乐" class="mt-5" desc="创建一首没有歌词的歌曲">
|
||||
<template #extra>
|
||||
<Switch v-model:checked="formData.pure" size="small" />
|
||||
</template>
|
||||
|
||||
@@ -27,8 +27,8 @@ function generateMusic() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Card class="mb-[0!important] h-full w-[300px]">
|
||||
<Radio.Group v-model:value="generateMode" class="mb-[15px]">
|
||||
<Card class="!mb-0 h-full w-80">
|
||||
<Radio.Group v-model:value="generateMode" class="mb-4">
|
||||
<Radio.Button value="desc"> 描述模式 </Radio.Button>
|
||||
<Radio.Button value="lyric"> 歌词模式 </Radio.Button>
|
||||
</Radio.Group>
|
||||
|
||||
@@ -37,7 +37,7 @@ defineExpose({
|
||||
|
||||
<Title title="音乐风格">
|
||||
<Space class="flex-wrap">
|
||||
<Tag v-for="tag in tags" :key="tag" class="mb-[8px]">
|
||||
<Tag v-for="tag in tags" :key="tag" class="mb-2">
|
||||
{{ tag }}
|
||||
</Tag>
|
||||
</Space>
|
||||
@@ -46,7 +46,7 @@ defineExpose({
|
||||
:type="showCustom ? 'primary' : 'default'"
|
||||
shape="round"
|
||||
size="small"
|
||||
class="mb-[6px]"
|
||||
class="mb-2"
|
||||
@click="showCustom = !showCustom"
|
||||
>
|
||||
自定义风格
|
||||
@@ -56,7 +56,7 @@ defineExpose({
|
||||
<Title
|
||||
v-show="showCustom"
|
||||
desc="描述您想要的音乐风格,Suno无法识别艺术家的名字,但可以理解流派和氛围"
|
||||
class="mt-[12px]"
|
||||
class="mt-3"
|
||||
>
|
||||
<Textarea
|
||||
v-model="formData.style"
|
||||
|
||||
@@ -14,12 +14,12 @@ defineProps({
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="mb-[12px]">
|
||||
<div class="flex items-center justify-between" style="color: #303133">
|
||||
<div class="mb-3">
|
||||
<div class="flex items-center justify-between text-gray-600">
|
||||
<span>{{ title }}</span>
|
||||
<slot name="extra"></slot>
|
||||
</div>
|
||||
<div class="my-[8px] text-[12px]" style="color: #909399">
|
||||
<div class="my-2 text-xs text-gray-400">
|
||||
{{ desc }}
|
||||
</div>
|
||||
<slot></slot>
|
||||
|
||||
@@ -111,7 +111,7 @@ onMounted(async () => {
|
||||
v-if="row.audioUrl?.length > 0"
|
||||
:href="row.audioUrl"
|
||||
target="_blank"
|
||||
style="padding: 0"
|
||||
class="p-0"
|
||||
>
|
||||
音乐
|
||||
</Button>
|
||||
@@ -120,8 +120,7 @@ onMounted(async () => {
|
||||
v-if="row.videoUrl?.length > 0"
|
||||
:href="row.videoUrl"
|
||||
target="_blank"
|
||||
class="!pl-5px"
|
||||
style="padding: 0"
|
||||
class="p-0 !pl-1"
|
||||
>
|
||||
视频
|
||||
</Button>
|
||||
@@ -130,8 +129,7 @@ onMounted(async () => {
|
||||
v-if="row.imageUrl?.length > 0"
|
||||
:href="row.imageUrl"
|
||||
target="_blank"
|
||||
class="!pl-5px"
|
||||
style="padding: 0"
|
||||
class="p-0 !pl-1"
|
||||
>
|
||||
封面
|
||||
</Button>
|
||||
@@ -144,7 +142,7 @@ onMounted(async () => {
|
||||
/>
|
||||
</template>
|
||||
<template #tags="{ row }">
|
||||
<Tag v-for="tag in row.tags" :key="tag" class="ml-2px">
|
||||
<Tag v-for="tag in row.tags" :key="tag" class="ml-1">
|
||||
{{ tag }}
|
||||
</Tag>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user