mirror of
https://github.com/yangjian102621/geekai.git
synced 2025-09-18 01:06:39 +08:00
add suno page
This commit is contained in:
parent
37368fe13f
commit
b248560ba2
32
api/store/model/suno_job.go
Normal file
32
api/store/model/suno_job.go
Normal file
@ -0,0 +1,32 @@
|
||||
package model
|
||||
|
||||
import "time"
|
||||
|
||||
type SunoJob struct {
|
||||
Id uint `gorm:"primarykey;column:id"`
|
||||
UserId int
|
||||
Title string
|
||||
Type string
|
||||
TaskId string
|
||||
ReferenceId string // 续写的任务id
|
||||
Tags string // 歌曲风格和标签
|
||||
Instrumental bool // 是否生成纯音乐
|
||||
ExtendSecs int // 续写秒数
|
||||
SongId int // 续写的歌曲id
|
||||
Prompt string // 提示词
|
||||
ThumbImgURL string // 缩略图 URL
|
||||
CoverImgURL string // 封面图 URL
|
||||
AudioURL string // 音频 URL
|
||||
ModelName string // 模型名称
|
||||
Progress int // 任务进度
|
||||
Duration int // 银屏时长,秒
|
||||
Publish bool // 是否发布
|
||||
ErrMsg string // 错误信息
|
||||
RawData string // 原始数据 json
|
||||
Power int // 消耗算力
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
func (SunoJob) TableName() string {
|
||||
return "chatgpt_suno_jobs"
|
||||
}
|
32
api/store/vo/suno_job.go
Normal file
32
api/store/vo/suno_job.go
Normal file
@ -0,0 +1,32 @@
|
||||
package vo
|
||||
|
||||
import "time"
|
||||
|
||||
type SunoJob struct {
|
||||
Id uint `json:"id"`
|
||||
UserId int `json:"user_id"`
|
||||
Title string `json:"title"`
|
||||
Type string `json:"type"`
|
||||
TaskId string `json:"task_id"`
|
||||
ReferenceId string `json:"reference_id"` // 续写的任务id
|
||||
Tags string `json:"tags"` // 歌曲风格和标签
|
||||
Instrumental bool `json:"instrumental"` // 是否生成纯音乐
|
||||
ExtendSecs int `json:"extend_secs"` // 续写秒数
|
||||
SongId int `json:"song_id"` // 续写的歌曲id
|
||||
Prompt string `json:"prompt"` // 提示词
|
||||
ThumbImgURL string `json:"thumb_img_url"` // 缩略图 URL
|
||||
CoverImgURL string `json:"cover_img_url"` // 封面图 URL
|
||||
AudioURL string `json:"audio_url"` // 音频 URL
|
||||
ModelName string `json:"model_name"` // 模型名称
|
||||
Progress int `json:"progress"` // 任务进度
|
||||
Duration int `json:"duration"` // 银屏时长,秒
|
||||
Publish bool `json:"publish"` // 是否发布
|
||||
ErrMsg string `json:"err_msg"` // 错误信息
|
||||
RawData string `json:"raw_data"` // 原始数据 json
|
||||
Power int `json:"power"` // 消耗算力
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
func (SunoJob) TableName() string {
|
||||
return "chatgpt_suno_jobs"
|
||||
}
|
35
database/update-v4.1.1.sql
Normal file
35
database/update-v4.1.1.sql
Normal file
@ -0,0 +1,35 @@
|
||||
CREATE TABLE `chatgpt_suno_jobs` (
|
||||
`id` int NOT NULL,
|
||||
`user_id` int NOT NULL COMMENT '用户 ID',
|
||||
`title` varchar(100) DEFAULT NULL COMMENT '歌曲标题',
|
||||
`type` tinyint(1) DEFAULT '0' COMMENT '任务类型,1:灵感创作,2:自定义创作',
|
||||
`task_id` varchar(50) DEFAULT NULL COMMENT '任务 ID',
|
||||
`reference_id` char(50) DEFAULT NULL COMMENT '引用任务 ID',
|
||||
`tags` varchar(100) DEFAULT NULL COMMENT '歌曲风格',
|
||||
`instrumental` tinyint(1) DEFAULT '0' COMMENT '是否为纯音乐',
|
||||
`extend_secs` smallint DEFAULT '0' COMMENT '延长秒数',
|
||||
`song_id` varchar(50) DEFAULT NULL COMMENT '要续写的歌曲 ID',
|
||||
`prompt` varchar(2000) NOT NULL COMMENT '提示词',
|
||||
`thumb_img_url` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '缩略图地址',
|
||||
`cover_img_url` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '封面图地址',
|
||||
`audio_url` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '音频地址',
|
||||
`model_name` varchar(30) DEFAULT NULL COMMENT '模型地址',
|
||||
`progress` smallint DEFAULT '0' COMMENT '任务进度',
|
||||
`duration` smallint NOT NULL DEFAULT '0' COMMENT '歌曲时长',
|
||||
`publish` tinyint(1) NOT NULL COMMENT '是否发布',
|
||||
`err_msg` varchar(255) DEFAULT NULL COMMENT '错误信息',
|
||||
`raw_data` text COMMENT '原始数据',
|
||||
`power` smallint NOT NULL DEFAULT '0' COMMENT '消耗算力',
|
||||
`created_at` datetime NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='MidJourney 任务表';
|
||||
|
||||
--
|
||||
-- 转储表的索引
|
||||
--
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_suno_jobs`
|
||||
--
|
||||
ALTER TABLE `chatgpt_suno_jobs`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `task_id` (`task_id`);
|
BIN
web/public/files/suno.mp3
Normal file
BIN
web/public/files/suno.mp3
Normal file
Binary file not shown.
9
web/public/images/create-new.svg
Normal file
9
web/public/images/create-new.svg
Normal file
@ -0,0 +1,9 @@
|
||||
<svg width="21" height="20" viewBox="0 0 21 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="Frame 38">
|
||||
<g id="Union">
|
||||
<path d="M14.6368 0.5L15.7493 0.501512L16.0214 0.5C16.0346 0.554416 16.0476 0.608661 16.0605 0.662705C16.2469 1.44179 16.4236 2.18 17.0437 2.79343C17.7009 3.44502 18.6579 3.76096 19.5 3.96203V5.34684C18.6472 5.5464 17.8202 5.85629 17.1554 6.51393C16.4921 7.16854 16.2231 7.96829 16.0214 8.80887L14.9089 8.80735L14.6368 8.80887C14.6235 8.75426 14.6105 8.69983 14.5975 8.64561C14.4111 7.86652 14.2346 7.12887 13.6145 6.51544C12.9573 5.86384 12.0173 5.54791 11.1752 5.34684V3.96203C12.028 3.76247 12.838 3.45258 13.5028 2.79494C14.166 2.14032 14.435 1.34057 14.6368 0.5Z" fill="#FAF7F5"/>
|
||||
<path d="M5.6368 6.73166L9.79064 6.03924L10.3222 6.13571C11.2831 6.36516 12.2179 6.69917 12.8413 7.31731L12.8419 7.31787C13.2892 7.7604 13.4912 8.27113 13.6667 8.92773L7.02141 10.1937V15.0405C7.02139 15.3867 6.99557 16.0106 6.94422 16.1683C6.77918 16.9615 6.03702 17.7656 4.97255 18.1954C3.43283 18.8171 2.00551 18.4478 1.60063 17.4448C1.19576 16.4417 2.04898 15.1516 3.50636 14.5631C4.25499 14.2609 5.01741 14.2026 5.6368 14.3533V6.73166Z" fill="#FAF7F5"/>
|
||||
<path d="M16.0215 14.0019C16.0215 13.6557 16.0215 10.1937 16.0215 10.1937H14.6369V13.1465C14.0043 12.9713 13.2094 13.0215 12.4295 13.3364C10.9721 13.9248 10.1189 15.215 10.5237 16.218C10.9286 17.221 12.4383 17.5571 13.8956 16.9687C14.9829 16.5296 15.6752 15.7329 15.8771 14.8905C15.8802 14.8779 15.8842 14.8619 15.8889 14.843C15.929 14.6822 16.0214 14.3118 16.0215 14.0019Z" fill="#FAF7F5"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
BIN
web/public/images/menu/music.png
Normal file
BIN
web/public/images/menu/music.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 822 B |
BIN
web/public/images/menu/suno.png
Normal file
BIN
web/public/images/menu/suno.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 836 B |
180
web/src/assets/css/suno.styl
Normal file
180
web/src/assets/css/suno.styl
Normal file
@ -0,0 +1,180 @@
|
||||
.page-suno {
|
||||
display flex
|
||||
height 100%
|
||||
background-color #0E0808
|
||||
overflow auto
|
||||
|
||||
.left-bar {
|
||||
max-width 340px
|
||||
min-width 340px
|
||||
padding 20px 30px
|
||||
|
||||
.bar-top {
|
||||
display flex
|
||||
flex-flow row
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.params {
|
||||
padding 20px 0
|
||||
color rgb(250 247 245)
|
||||
position relative
|
||||
|
||||
.pure-music {
|
||||
position absolute
|
||||
right 0
|
||||
top 24px
|
||||
display flex
|
||||
|
||||
.text {
|
||||
margin-top 5px
|
||||
margin-left 5px
|
||||
}
|
||||
}
|
||||
|
||||
.label {
|
||||
padding 10px 0
|
||||
|
||||
.text {
|
||||
margin-right 10px
|
||||
}
|
||||
}
|
||||
.item {
|
||||
margin-bottom: 20px
|
||||
|
||||
.create-btn {
|
||||
margin 20px 0
|
||||
background-image url("~@/assets/img/suno-create-bg.svg")
|
||||
background-size: cover;
|
||||
background-position: 50% 50%;
|
||||
transition: background 1s ease-in-out;
|
||||
overflow: hidden;
|
||||
font-size 16px
|
||||
width 100%
|
||||
padding 16px
|
||||
border-radius 25px
|
||||
border none
|
||||
cursor pointer
|
||||
|
||||
img {
|
||||
position relative
|
||||
top 3px
|
||||
margin-right 5px
|
||||
}
|
||||
|
||||
&:hover {
|
||||
opacity: 0.9;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.right-box {
|
||||
width 100%
|
||||
color rgb(250 247 245)
|
||||
|
||||
.list-box {
|
||||
padding 0 0 0 20px
|
||||
.item {
|
||||
display flex
|
||||
flex-flow row
|
||||
padding 5px 0
|
||||
cursor pointer
|
||||
|
||||
&:hover {
|
||||
background-color #1C1616
|
||||
}
|
||||
|
||||
.left {
|
||||
.container {
|
||||
width 60px
|
||||
height 90px
|
||||
position relative
|
||||
|
||||
.el-image {
|
||||
height 90px
|
||||
border-radius 5px
|
||||
}
|
||||
|
||||
.duration {
|
||||
position absolute
|
||||
bottom 0
|
||||
right 0
|
||||
background-color rgba(14,8,8,.7)
|
||||
padding 0 2px
|
||||
font-family 'Input Sans'
|
||||
font-size 14px
|
||||
font-weight 700
|
||||
border-radius .125rem
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.center {
|
||||
width 100%
|
||||
//border 1px solid saddlebrown
|
||||
display flex
|
||||
justify-content center
|
||||
align-items flex-start
|
||||
flex-flow column
|
||||
height 90px
|
||||
padding 0 20px
|
||||
|
||||
.title {
|
||||
padding 6px 0
|
||||
font-size 16px
|
||||
font-weight 700
|
||||
|
||||
.model {
|
||||
color #E2E8F0
|
||||
background-color #1C1616
|
||||
border 1px solid #8f8f8f
|
||||
font-weight normal
|
||||
font-size 14px
|
||||
padding 1px 3px
|
||||
border-radius 5px
|
||||
margin-left 10px
|
||||
}
|
||||
}
|
||||
|
||||
.tags {
|
||||
font-size 14px
|
||||
color #d1d1d1
|
||||
padding 3px 0
|
||||
}
|
||||
}
|
||||
|
||||
.right {
|
||||
width 200px;
|
||||
font-size 14px
|
||||
padding 0 15px
|
||||
|
||||
.tools {
|
||||
display flex
|
||||
justify-content left
|
||||
align-items center
|
||||
flex-flow row
|
||||
height 90px
|
||||
|
||||
.btn {
|
||||
background-color #363030
|
||||
border none
|
||||
border-radius 5px
|
||||
padding 5px 10px
|
||||
cursor pointer
|
||||
|
||||
&:hover {
|
||||
background-color #5F5958
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.item.active {
|
||||
background-color #2A2525
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
47
web/src/assets/img/suno-create-bg.svg
Normal file
47
web/src/assets/img/suno-create-bg.svg
Normal file
@ -0,0 +1,47 @@
|
||||
<svg width="385" height="88" viewBox="0 0 385 88" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_137_12468)">
|
||||
<rect width="385" height="88" fill="#F24018"/>
|
||||
<rect width="385" height="88" fill="url(#paint0_radial_137_12468)" fill-opacity="0.25" style="mix-blend-mode:plus-lighter"/>
|
||||
<g opacity="0.65" filter="url(#filter0_f_137_12468)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M111.347 35.6229C151.009 57.6671 209.015 49.1739 230.965 88.9126C255.253 132.884 248.592 191.777 220.732 233.655C193.951 273.912 142.319 284.869 94.8085 293.578C52.1601 301.396 10.1351 297.096 -29.4684 279.522C-74.979 259.325 -135.081 238.424 -141.005 188.932C-146.904 139.646 -81.2632 116.551 -53.9401 75.0726C-29.8623 38.5207 -35.6231 -25.4633 6.91152 -35.6152C49.5563 -45.7935 73.0569 14.3417 111.347 35.6229Z" fill="#1000C0" style="mix-blend-mode:plus-lighter"/>
|
||||
</g>
|
||||
<g opacity="0.75" filter="url(#filter1_f_137_12468)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M332.217 262.301C293.589 260.201 253.893 255.317 227.782 226.721C199.552 195.803 185.551 152.726 194.871 111.877C204.187 71.0419 233.315 31.0675 274.306 22.8078C310.373 15.5401 331.935 59.2082 363.663 77.865C389.371 92.9816 423.695 92.907 438.039 119.086C458.358 156.168 477.027 204.906 451.904 238.906C426.46 273.342 374.92 264.623 332.217 262.301Z" fill="#1000C0" style="mix-blend-mode:plus-lighter"/>
|
||||
</g>
|
||||
<g opacity="0.5" filter="url(#filter2_f_137_12468)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M25.4648 -39.9253C-7.15838 -71.5039 -65.3436 -78.3935 -76.3165 -122.436C-88.4582 -171.17 -66.8828 -226.25 -29.217 -259.404C6.9909 -291.275 59.6564 -288.42 107.765 -284.468C150.95 -280.92 190.417 -265.845 224.132 -238.593C262.877 -207.277 315.527 -171.486 308.519 -122.202C301.54 -73.1229 232.229 -67.9118 195.184 -35.0033C162.539 -6.00341 151.647 57.2182 107.972 55.9516C64.1833 54.6817 56.9587 -9.43976 25.4648 -39.9253Z" fill="#E1B1F8" style="mix-blend-mode:color-dodge"/>
|
||||
</g>
|
||||
<g filter="url(#filter3_f_137_12468)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M188.082 0.67854C155.276 -1.12779 121.563 -5.32785 99.3885 -29.9233C75.4135 -56.5155 63.5228 -93.5648 71.4379 -128.698C79.3502 -163.82 104.088 -198.201 138.899 -205.305C169.53 -211.556 187.842 -173.998 214.787 -157.952C236.62 -144.95 265.77 -145.014 277.953 -122.498C295.209 -90.6045 311.063 -48.6858 289.727 -19.4429C268.118 10.1745 224.347 2.6754 188.082 0.67854Z" fill="#F24018" style="mix-blend-mode:plus-lighter"/>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_f_137_12468" x="-181.377" y="-76.7656" width="467.29" height="414.089" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="20" result="effect1_foregroundBlur_137_12468"/>
|
||||
</filter>
|
||||
<filter id="filter1_f_137_12468" x="136" y="-34" width="384" height="355" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="28" result="effect1_foregroundBlur_137_12468"/>
|
||||
</filter>
|
||||
<filter id="filter2_f_137_12468" x="-135.707" y="-342.825" width="500.858" height="454.795" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="28" result="effect1_foregroundBlur_137_12468"/>
|
||||
</filter>
|
||||
<filter id="filter3_f_137_12468" x="-3" y="-278" width="375" height="353" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="36" result="effect1_foregroundBlur_137_12468"/>
|
||||
</filter>
|
||||
<radialGradient id="paint0_radial_137_12468" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(210.237 44) rotate(172.274) scale(178.996 234.083)">
|
||||
<stop stop-color="white"/>
|
||||
<stop offset="1" stop-color="white" stop-opacity="0"/>
|
||||
</radialGradient>
|
||||
<clipPath id="clip0_137_12468">
|
||||
<rect width="385" height="88" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 4.3 KiB |
@ -58,8 +58,8 @@ import {httpGet} from "@/utils/http";
|
||||
import {ElMessage} from "element-plus";
|
||||
import {useRoute} from "vue-router";
|
||||
|
||||
const title = ref('Chat-Plus-Admin')
|
||||
const logo = ref('/images/logo.png')
|
||||
const title = ref('')
|
||||
const logo = ref('')
|
||||
|
||||
// 加载系统配置
|
||||
httpGet('/api/admin/config/get?key=system').then(res => {
|
||||
|
53
web/src/components/ui/BlackInput.vue
Normal file
53
web/src/components/ui/BlackInput.vue
Normal file
@ -0,0 +1,53 @@
|
||||
<template>
|
||||
<div class="black-input-wrapper">
|
||||
<el-input v-model="model" :type="type" :rows="rows"
|
||||
@input="$emit('update:value', $event)"
|
||||
style="--el-input-bg-color:#252020;
|
||||
--el-input-border-color:#414141;
|
||||
--el-input-focus-border-color:#414141;
|
||||
--el-text-color-regular: #f1f1f1;
|
||||
--el-input-border-radius: 10px;
|
||||
--el-border-color-hover:#616161"
|
||||
resize="none"
|
||||
:placeholder="placeholder"/>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'BlackInput',
|
||||
props: {
|
||||
value : {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'input',
|
||||
},
|
||||
rows: {
|
||||
type: Number,
|
||||
default: 5,
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
model: this.value
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus">
|
||||
.black-input-wrapper {
|
||||
.el-textarea__inner {
|
||||
padding: 20px;
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
</style>
|
43
web/src/components/ui/BlackSelect.vue
Normal file
43
web/src/components/ui/BlackSelect.vue
Normal file
@ -0,0 +1,43 @@
|
||||
<template>
|
||||
|
||||
<el-select v-model="model" :placeholder="placeholder"
|
||||
:value="value" @change="$emit('update:value', $event)"
|
||||
style="--el-fill-color-blank:#252020;
|
||||
--el-text-color-regular: #a1a1a1;
|
||||
--el-select-disabled-color:#0E0808;
|
||||
--el-color-primary-light-9:#0E0808;
|
||||
--el-border-radius-base:20px;
|
||||
--el-border-color:#0E0808;">
|
||||
<el-option v-for="item in options"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'BlackSelect',
|
||||
props: {
|
||||
value : {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '请选择',
|
||||
},
|
||||
options: {
|
||||
type: Array,
|
||||
default: []
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
model: this.value
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
25
web/src/components/ui/BlackSwitch.vue
Normal file
25
web/src/components/ui/BlackSwitch.vue
Normal file
@ -0,0 +1,25 @@
|
||||
<template>
|
||||
|
||||
<el-switch v-model="model" :size="size"
|
||||
@change="$emit('update:value', $event)"
|
||||
style="--el-switch-on-color:#555555;--el-color-white:#0E0808"/>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'BlackSwitch',
|
||||
props: {
|
||||
value : Boolean,
|
||||
size: {
|
||||
type: String,
|
||||
default: 'default',
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
model: this.value
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@ -82,6 +82,12 @@ const routes = [
|
||||
meta: {title: 'DALLE-3'},
|
||||
component: () => import('@/views/Dalle.vue'),
|
||||
},
|
||||
{
|
||||
name: 'suno',
|
||||
path: '/suno',
|
||||
meta: {title: 'Suno音乐创作'},
|
||||
component: () => import('@/views/Suno.vue'),
|
||||
},
|
||||
{
|
||||
name: 'ExternalLink',
|
||||
path: '/external',
|
||||
|
@ -146,7 +146,7 @@ import ConfigDialog from "@/components/UserInfoDialog.vue";
|
||||
import {showMessageError} from "@/utils/dialog";
|
||||
|
||||
const router = useRouter();
|
||||
const logo = ref('/images/logo.png');
|
||||
const logo = ref('');
|
||||
const mainNavs = ref([])
|
||||
const moreNavs = ref([])
|
||||
const curPath = ref(router.currentRoute.value.path)
|
||||
|
@ -77,9 +77,9 @@ if (isMobile()) {
|
||||
router.push("/mobile")
|
||||
}
|
||||
|
||||
const title = ref("Geek-AI 创作系统")
|
||||
const logo = ref("/images/logo.png")
|
||||
const slogan = ref("我辈之人,先干为敬,陪您先把 AI 用起来")
|
||||
const title = ref("")
|
||||
const logo = ref("")
|
||||
const slogan = ref("")
|
||||
const license = ref({})
|
||||
const winHeight = window.innerHeight - 150
|
||||
const bgImgUrl = ref('')
|
||||
|
@ -79,7 +79,7 @@ const title = ref('Geek-AI');
|
||||
const username = ref(process.env.VUE_APP_USER);
|
||||
const password = ref(process.env.VUE_APP_PASS);
|
||||
const showResetPass = ref(false)
|
||||
const logo = ref("/images/logo.png")
|
||||
const logo = ref("")
|
||||
const licenseConfig = ref({})
|
||||
const wechatLoginURL = ref('')
|
||||
|
||||
|
@ -183,8 +183,8 @@ import {validateEmail, validateMobile} from "@/utils/validate";
|
||||
import {showMessageError, showMessageOK} from "@/utils/dialog";
|
||||
|
||||
const router = useRouter();
|
||||
const title = ref('Geek-AI 用户注册');
|
||||
const logo = ref("/images/logo")
|
||||
const title = ref('');
|
||||
const logo = ref("")
|
||||
const data = ref({
|
||||
username: '',
|
||||
password: '',
|
||||
|
205
web/src/views/Suno.vue
Normal file
205
web/src/views/Suno.vue
Normal file
@ -0,0 +1,205 @@
|
||||
<template>
|
||||
<div class="page-suno" :style="{ height: winHeight + 'px' }">
|
||||
<div class="left-bar">
|
||||
<div class="bar-top">
|
||||
<el-tooltip effect="light" content="定义模式" placement="top">
|
||||
<black-switch v-model:value="custom" size="large" />
|
||||
</el-tooltip>
|
||||
<black-select v-model:value="data.model" :options="models" placeholder="请选择模型" style="width: 100px" />
|
||||
</div>
|
||||
|
||||
<div class="params">
|
||||
<div class="pure-music">
|
||||
<span class="switch"><black-switch v-model:value="instrumental" size="default" /></span>
|
||||
<span class="text">纯音乐</span>
|
||||
</div>
|
||||
<div v-if="custom">
|
||||
<div class="item-group" v-if="!instrumental">
|
||||
<div class="label">
|
||||
<span class="text">歌词</span>
|
||||
<el-popover placement="right"
|
||||
:width="200"
|
||||
trigger="hover" content="自己写歌词或寻求 AI 的帮助。使用两节歌词(8 行)可获得最佳效果。">
|
||||
<template #reference>
|
||||
<el-icon>
|
||||
<InfoFilled/>
|
||||
</el-icon>
|
||||
</template>
|
||||
</el-popover>
|
||||
</div>
|
||||
<div class="item">
|
||||
<black-input v-model:value="data.lyrics" type="textarea" :rows="10" placeholder="请在这里输入你自己写的歌词..."/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item-group">
|
||||
<div class="label">
|
||||
<span class="text">音乐风格</span>
|
||||
<el-popover placement="right"
|
||||
:width="200"
|
||||
trigger="hover" content="描述您想要的音乐风格(例如“原声流行音乐”)。Sunos 模特无法识别艺术家的名字,但能够理解音乐流派和氛围。">
|
||||
<template #reference>
|
||||
<el-icon>
|
||||
<InfoFilled/>
|
||||
</el-icon>
|
||||
</template>
|
||||
</el-popover>
|
||||
</div>
|
||||
<div class="item">
|
||||
<black-input v-model:value="data.tags" type="textarea" :rows="3" placeholder="请输入音乐风格,多个风格之间用英文逗号隔开..."/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item-group">
|
||||
<div class="label">
|
||||
<span class="text">歌曲名称</span>
|
||||
<el-popover placement="right"
|
||||
:width="200"
|
||||
trigger="hover" content="给你的歌曲起一个标题,以便于分享、发现和组织。">
|
||||
<template #reference>
|
||||
<el-icon>
|
||||
<InfoFilled/>
|
||||
</el-icon>
|
||||
</template>
|
||||
</el-popover>
|
||||
</div>
|
||||
<div class="item">
|
||||
<black-input v-model:value="data.title" type="textarea" :rows="2" placeholder="请输入歌曲名称..."/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else>
|
||||
<div class="label">
|
||||
<span class="text">歌曲描述</span>
|
||||
<el-popover placement="right"
|
||||
:width="200"
|
||||
trigger="hover" content="描述您想要的音乐风格和主题(例如:关于假期的流行音乐)。请使用流派和氛围,而不是特定的艺术家和歌曲风格,AI无法识别。">
|
||||
<template #reference>
|
||||
<el-icon>
|
||||
<InfoFilled/>
|
||||
</el-icon>
|
||||
</template>
|
||||
</el-popover>
|
||||
</div>
|
||||
<div class="item">
|
||||
<black-input v-model:value="data.lyrics" type="textarea" :rows="10" placeholder="例如:一首关于鸟人的摇滚歌曲..."/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="item">
|
||||
<button class="create-btn" @click="create">
|
||||
<img src="/images/create-new.svg" alt=""/>
|
||||
<span>生成音乐</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right-box">
|
||||
<div class="list-box" v-if="list.length > 0">
|
||||
<div class="item" v-for="item in list">
|
||||
<div class="left">
|
||||
<div class="container">
|
||||
<el-image :src="item.thumb_img_url" fit="cover" />
|
||||
<div class="duration">{{duration(item.duration)}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="center">
|
||||
<div class="title">
|
||||
<span>{{item.title}}</span>
|
||||
<span class="model">{{item.model}}</span>
|
||||
</div>
|
||||
<div class="tags">{{item.tags}}</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<div class="tools">
|
||||
<el-tooltip effect="light" content="以当前歌曲为素材继续创作" placement="top">
|
||||
<button class="btn">续写</button>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-empty :image-size="100" description="没有任何作品,赶紧去创作吧!" v-else/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {ref} from "vue"
|
||||
import {InfoFilled} from "@element-plus/icons-vue";
|
||||
import BlackSelect from "@/components/ui/BlackSelect.vue";
|
||||
import BlackSwitch from "@/components/ui/BlackSwitch.vue";
|
||||
import BlackInput from "@/components/ui/BlackInput.vue";
|
||||
import ImageDall from "@/views/mobile/pages/ImageDall.vue";
|
||||
|
||||
const winHeight = ref(window.innerHeight - 60)
|
||||
const custom = ref(false)
|
||||
const instrumental = ref(false)
|
||||
const models = ref([
|
||||
{label: "v3.0", value: "chirp-v3-0"},
|
||||
{label: "v3.5", value:"chirp-v3-5"}
|
||||
])
|
||||
const data = ref({
|
||||
model: "chirp-v3-0",
|
||||
tags: "",
|
||||
lyrics: "",
|
||||
prompt: "",
|
||||
title: ""
|
||||
})
|
||||
|
||||
const list = ref([
|
||||
{
|
||||
id: 1,
|
||||
title: "鸟人传说 (Birdman Legend)",
|
||||
model: "v3",
|
||||
tags: "uplifting pop",
|
||||
thumb_img_url: "https://cdn2.suno.ai/image_047796ce-7bf3-4051-a59c-66ce60448ff2.jpeg?width=100",
|
||||
audio_url: "/files/suno.mp3",
|
||||
duration: 134,
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
title: "我是一个鸟人",
|
||||
model: "v3",
|
||||
tags: "摇滚",
|
||||
thumb_img_url: "https://cdn2.suno.ai/image_e5d25fd0-06a5-4cd7-910c-4b62872cd503.jpeg?width=100",
|
||||
audio_url: "/files/suno.mp3",
|
||||
duration: 194,
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
title: "鸟人传说 (Birdman Legend)",
|
||||
model: "v3",
|
||||
tags: "uplifting pop",
|
||||
thumb_img_url: "https://cdn2.suno.ai/image_047796ce-7bf3-4051-a59c-66ce60448ff2.jpeg?width=100",
|
||||
audio_url: "/files/suno.mp3",
|
||||
duration: 138,
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
title: "我是一个鸟人",
|
||||
model: "v3",
|
||||
tags: "摇滚",
|
||||
thumb_img_url: "https://cdn2.suno.ai/image_e5d25fd0-06a5-4cd7-910c-4b62872cd503.jpeg?width=100",
|
||||
audio_url: "/files/suno.mp3",
|
||||
duration: 144,
|
||||
},
|
||||
])
|
||||
|
||||
const create = () => {
|
||||
console.log(data.value)
|
||||
}
|
||||
|
||||
// 格式化音频时长
|
||||
const duration = (secs) => {
|
||||
const minutes =Math.floor(secs/60)
|
||||
const seconds = secs%60
|
||||
return `${minutes}:${seconds}`
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
@import "@/assets/css/suno.styl"
|
||||
</style>
|
@ -59,7 +59,7 @@ const router = useRouter();
|
||||
const title = ref('Geek-AI Console');
|
||||
const username = ref(process.env.VUE_APP_ADMIN_USER);
|
||||
const password = ref(process.env.VUE_APP_ADMIN_PASS);
|
||||
const logo = ref("/images/logo.png")
|
||||
const logo = ref("")
|
||||
|
||||
checkAdminSession().then(() => {
|
||||
router.push("/admin")
|
||||
|
Loading…
Reference in New Issue
Block a user