Skip to content

Commit

Permalink
Add SUNO support (#82)
Browse files Browse the repository at this point in the history
Co-authored-by: Germey <germey@acedata.cloud>
  • Loading branch information
hyf-github-user and Germey authored Jul 27, 2024
1 parent ffdf6cb commit a46fc4e
Show file tree
Hide file tree
Showing 237 changed files with 9,931 additions and 4,639 deletions.
4 changes: 3 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,5 +72,7 @@
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"cSpell.words": ["Chatdoc"]
"[vue]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,9 @@ Artistic QR Code:
![](https://cdn.acedata.cloud/q3ivan.png)

<img src="https://cdn.acedata.cloud/l11ebv.png" style="width: 300px">

Suno Music:

![](https://cdn.acedata.cloud/mewx2.png)

<img src="https://cdn.acedata.cloud/4mvwe.png" style="width: 300px">
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "major",
"comment": "init suno",
"packageName": "@acedatacloud/nexior",
"email": "office@acedata.cloud",
"dependentChangeType": "patch"
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"@fortawesome/free-regular-svg-icons": "^6.2.1",
"@fortawesome/free-solid-svg-icons": "^6.2.1",
"@fortawesome/vue-fontawesome": "^3.0.2",
"@icon-park/vue-next": "^1.3.6",
"axios": "^1.6.0",
"codemirror": "^6.0.1",
"copy-to-clipboard": "^3.3.3",
Expand Down
3 changes: 3 additions & 0 deletions src/assets/base.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
Binary file added src/assets/img/disk.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/assets/img/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import OpticalDisk from './disk.png';

export { OpticalDisk };
5 changes: 4 additions & 1 deletion src/components/common/HelpEntry.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@
<el-menu :collapse="false" class="menu">
<el-popover :width="350" trigger="hover">
<template #reference>
<el-menu-item v-if="site?.features?.support?.wechat?.enabled" index="1">
<el-menu-item
v-if="site?.features?.support?.wechat?.enabled && site?.features?.support?.wechat?.qr"
index="1"
>
<font-awesome-icon icon="fa-brands fa-weixin" class="mr-2" />
<template #title>{{ $t('common.message.addWeChat') }}</template>
</el-menu-item>
Expand Down
27 changes: 27 additions & 0 deletions src/components/common/IconPark.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<template>
<Component
:is="icon"
:theme="theme"
:size="size"
:spin="spin"
:fill="fill"
:stroke-linecap="strokeLinecap"
:stroke-linejoin="strokeLinejoin"
:stroke-width="strokeWidth"
/>
</template>

<script setup lang="ts">
import type { Icon } from '@icon-park/vue-next/lib/runtime';
defineProps<{
icon: Icon;
theme?: 'outline' | 'filled' | 'two-tone' | 'multi-color';
size?: number | string;
spin?: boolean;
fill?: string | string[];
strokeLinecap?: 'butt' | 'round' | 'square';
strokeLinejoin?: 'miter' | 'round' | 'bevel';
strokeWidth?: number;
}>();
</script>
15 changes: 15 additions & 0 deletions src/components/common/Navigator.vue
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,9 @@ import {
ROUTE_INDEX,
ROUTE_MIDJOURNEY_INDEX,
ROUTE_QRART_INDEX,
ROUTE_SUNO_INDEX,
ROUTE_QRART_HISTORY,
ROUTE_SUNO_HISTORY,
ROUTE_SITE_INDEX
} from '@/router/constants';
import LogoTiny from './LogoTiny.vue';
Expand Down Expand Up @@ -164,6 +166,7 @@ export default defineComponent({
});
}
/*
if (this.$store?.state?.site?.features?.chatdoc?.enabled) {
result.push({
route: {
Expand All @@ -174,6 +177,7 @@ export default defineComponent({
routes: [ROUTE_CHATDOC_INDEX, ROUTE_CHATDOC_CONVERSATION, ROUTE_CHATDOC_MANAGE, ROUTE_CHATDOC_SETTING]
});
}
*/
if (this.$store?.state?.site?.features?.qrart?.enabled) {
result.push({
Expand All @@ -185,6 +189,17 @@ export default defineComponent({
routes: [ROUTE_QRART_INDEX, ROUTE_QRART_HISTORY]
});
}
// Add suno's leftmost icon
if (this.$store?.state?.site?.features?.suno?.enabled) {
result.push({
route: {
name: ROUTE_SUNO_INDEX
},
displayName: this.$t('common.nav.suno'),
icon: 'fa-solid fa-music',
routes: [ROUTE_SUNO_INDEX, ROUTE_SUNO_HISTORY]
});
}
if (this.direction === 'row') {
result.push({
Expand Down
1 change: 1 addition & 0 deletions src/components/common/TopHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
index="/midjourney"
></el-menu-item>
<el-menu-item v-if="site?.features?.qrart?.enabled" v-t="'index.title.qrart'" index="/qrart"></el-menu-item>
<el-menu-item v-if="site?.features?.suno?.enabled" v-t="'index.title.suno'" index="/suno"></el-menu-item>
</el-menu>
</el-col>
<el-col :md="4" :xs="11">
Expand Down
85 changes: 85 additions & 0 deletions src/components/suno/ConfigPanel.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<template>
<div class="panel">
<div class="config">
<type-selector class="mb-4" />
<instrument-switch class="mb-4 instrument" />
<prompt-input v-if="!config?.custom" class="mb-4" />
<lyric-input v-if="config?.custom && !config.instrumental" class="mb-4" />
<style-input v-if="config?.custom" class="mb-4" />
<title-input v-if="config?.custom" class="mb-4" />
<div class="actions">
<el-button type="primary" class="btn w-full" round @click="onGenerate">
<font-awesome-icon icon="fa-solid fa-magic" class="mr-2" />
{{ $t('suno.button.generate') }}
</el-button>
</div>
</div>
</div>
</template>
<script>
import { defineComponent } from 'vue';
import { ElButton } from 'element-plus';
import TypeSelector from './config/TypeSelector.vue';
import PromptInput from './config/PromptInput.vue';
import LyricInput from './config/LyricInput.vue';
import StyleInput from './config/StyleInput.vue';
import TitleInput from './config/TitleInput.vue';
import InstrumentSwitch from './config/InstrumentSwitch.vue';
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
export default defineComponent({
name: 'PresetPanel',
components: {
TypeSelector,
PromptInput,
LyricInput,
InstrumentSwitch,
StyleInput,
TitleInput,
FontAwesomeIcon,
ElButton
},
emits: ['generate'],
computed: {
config() {
return this.$store.state.suno?.config;
}
},
methods: {
onGenerate() {
this.$emit('generate');
}
}
});
</script>
<style lang="scss" scoped>
.panel {
height: 100%;
padding: 15px;
display: flex;
flex-direction: column;
.config {
width: 100%;
height: calc(100% - 50px);
flex: 1;
position: relative;
.instrument {
position: absolute;
top: 50px;
right: -10px;
z-index: 1000;
}
}
.actions {
height: 50px;
display: flex;
justify-content: center;
align-items: center;
.btn {
width: 100%;
}
}
}
</style>
156 changes: 156 additions & 0 deletions src/components/suno/PreviewPanel.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
<template>
<el-scrollbar class="right-panel">
<div v-if="audio?.object" class="card">
<div class="image-container">
<el-image :src="audio.image_url" fit="cover">
<template #error>
<div class="image-slot">
<el-icon><icon-picture /></el-icon>
</div>
</template>
</el-image>
<h2 class="title">{{ audio?.title }}</h2>
</div>
<div class="content">
<div class="artist">
<el-avatar :size="30" :src="audio?.image_url"></el-avatar>
<span>{{ audio?.prompt }}</span>
</div>
<p class="style">{{ audio?.style }}</p>
<p class="time">{{ $dayjs.format(audio?.created_at) }}</p>
<div class="lyrics">
<p>{{ audio?.lyric }}</p>
</div>
</div>
</div>
<div v-else class="gradient-background"></div>
</el-scrollbar>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { ElImage, ElScrollbar, ElAvatar, ElIcon } from 'element-plus';
import { Picture as IconPicture } from '@element-plus/icons-vue';
export default defineComponent({
name: 'TaskPreview',
components: {
ElScrollbar,
IconPicture,
ElImage,
ElAvatar,
ElIcon
},
data() {
return {
showCloseIcon: true
};
},
computed: {
audio() {
return this.$store.state.suno?.audio;
}
},
methods: {
closeCard() {
this.showCloseIcon = !this.showCloseIcon;
}
}
});
</script>
<style scoped>
.right-panel {
padding: 2px;
background-color: (--el-bg-color);
}
.cover-image {
width: 100%;
height: auto;
margin-bottom: 10px;
}
.card-scrollbar {
height: 600px;
width: 300px;
}
.card {
width: 100%;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
.image-container {
position: relative;
height: 300px;
}
.image-container .el-image {
width: 100%;
height: 100%;
}
.close-icon {
position: absolute;
top: 10px;
right: 10px;
cursor: pointer;
background-color: rgba(0, 0, 0, 0.5);
border-radius: 50%;
padding: 5px;
color: white;
z-index: 2;
}
.content {
padding: 15px;
}
.title {
position: absolute;
bottom: 0;
left: 0;
right: 0;
margin: 0;
padding: 15px;
background: linear-gradient(to top, rgba(0, 0, 0, 0.7), rgba(0, 0, 0, 0));
color: white;
z-index: 1;
}
.artist {
display: flex;
align-items: center;
margin: 10px 0;
font-weight: bold;
}
.artist span {
margin-right: 10px;
}
.actions {
display: flex;
justify-content: space-around;
margin: 10px 0;
}
.action-icon {
font-size: 24px;
cursor: pointer;
}
.time {
font-size: 12px;
color: var(--el-text-color-secondary);
}
.lyrics {
margin: 15px 0;
font-size: 14px;
line-height: 25px;
white-space: pre-wrap;
}
</style>
Loading

0 comments on commit a46fc4e

Please sign in to comment.