├── music-client
├── static
│ └── .gitkeep
├── .eslintignore
├── config
│ ├── prod.env.js
│ ├── dev.env.js
│ └── index.js
├── src
│ ├── common
│ │ ├── stylus
│ │ │ ├── index.styl
│ │ │ ├── base.styl
│ │ │ ├── mixin.styl
│ │ │ ├── variable.styl
│ │ │ ├── reset.styl
│ │ │ └── icon.styl
│ │ ├── js
│ │ │ ├── config.js
│ │ │ ├── singer.js
│ │ │ ├── song.js
│ │ │ ├── util.js
│ │ │ ├── dom.js
│ │ │ └── cache.js
│ │ ├── image
│ │ │ └── default.png
│ │ └── fonts
│ │ │ ├── music-icon.eot
│ │ │ ├── music-icon.ttf
│ │ │ └── music-icon.woff
│ ├── base
│ │ ├── loading
│ │ │ ├── loading.gif
│ │ │ └── loading.vue
│ │ ├── song-list
│ │ │ ├── first@2x.png
│ │ │ ├── first@3x.png
│ │ │ ├── third@2x.png
│ │ │ ├── third@3x.png
│ │ │ ├── second@2x.png
│ │ │ ├── second@3x.png
│ │ │ └── song-list.vue
│ │ ├── no-result
│ │ │ ├── no-result@2x.png
│ │ │ ├── no-result@3x.png
│ │ │ └── no-ruselt.vue
│ │ ├── top-tip
│ │ │ └── top-tip.vue
│ │ ├── switches
│ │ │ └── switches.vue
│ │ ├── progress-circle
│ │ │ └── progress-circle.vue
│ │ ├── input-box
│ │ │ └── input-box.vue
│ │ └── scroll
│ │ │ └── scroll.vue
│ ├── components
│ │ ├── m-header
│ │ │ ├── logo@2x.png
│ │ │ ├── logo@3x.png
│ │ │ └── m-header.vue
│ │ └── tab
│ │ │ └── tab.vue
│ ├── store
│ │ ├── state.js
│ │ ├── index.js
│ │ ├── mutation-types.js
│ │ ├── getters.js
│ │ └── mutations.js
│ ├── main.js
│ ├── App.vue
│ ├── router
│ │ └── index.js
│ └── api
│ │ ├── other.js
│ │ ├── finished.js
│ │ ├── pending.js
│ │ └── create.js
├── build
│ ├── logo.png
│ ├── vue-loader.conf.js
│ ├── build.js
│ ├── check-versions.js
│ └── webpack.base.conf.js
├── dist
│ ├── static
│ │ ├── img
│ │ │ ├── default.142f76c.png
│ │ │ └── no-result@3x.2858208.png
│ │ └── js
│ │ │ └── manifest.3733754daf219da97807.js
│ └── index.html
├── .editorconfig
├── .babelrc
├── .postcssrc.js
├── index.html
└── .eslintrc.js
├── auth-client
├── src
│ ├── signup
│ │ ├── Signup.css
│ │ └── Signup.js
│ ├── App.css
│ ├── setupTests.js
│ ├── App.test.js
│ ├── index.css
│ ├── index.js
│ ├── signin
│ │ ├── Signin.css
│ │ └── Signin.js
│ ├── App.js
│ ├── util
│ │ └── ApiUtil.js
│ └── logo.svg
├── build
│ ├── robots.txt
│ ├── signin
│ │ ├── robots.txt
│ │ ├── favicon.ico
│ │ ├── logo192.png
│ │ ├── logo512.png
│ │ ├── manifest.json
│ │ ├── precache-manifest.b0af4b5b1697571716dea783d8f44e59.js
│ │ ├── asset-manifest.json
│ │ ├── service-worker.js
│ │ └── index.html
│ ├── signup
│ │ ├── robots.txt
│ │ ├── favicon.ico
│ │ ├── logo192.png
│ │ ├── logo512.png
│ │ ├── manifest.json
│ │ ├── precache-manifest.b0af4b5b1697571716dea783d8f44e59.js
│ │ ├── asset-manifest.json
│ │ ├── service-worker.js
│ │ └── index.html
│ ├── favicon.ico
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ ├── static
│ │ ├── css
│ │ │ ├── main.33498084.chunk.css
│ │ │ └── main.33498084.chunk.css.map
│ │ └── js
│ │ │ ├── 2.57ec041c.chunk.js.LICENSE.txt
│ │ │ └── runtime-main.b89670ea.js
│ ├── precache-manifest.b0af4b5b1697571716dea783d8f44e59.js
│ ├── asset-manifest.json
│ ├── service-worker.js
│ └── index.html
├── public
│ ├── robots.txt
│ ├── favicon.ico
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ └── index.html
└── package.json
├── svc-serv
├── svc-impl
│ └── src
│ │ └── main
│ │ ├── java
│ │ └── me
│ │ │ └── liuzeyu
│ │ │ └── me
│ │ │ └── aimusic
│ │ │ └── svc
│ │ │ ├── event
│ │ │ ├── EventConstant.java
│ │ │ ├── SvcProducer.java
│ │ │ └── SvcConsumer.java
│ │ │ ├── caculator
│ │ │ ├── SvcTemplate.java
│ │ │ ├── impl
│ │ │ │ ├── ZhangxueyouSvc.java
│ │ │ │ ├── SunyanziSvc.java
│ │ │ │ └── ZhoujielunSvc.java
│ │ │ ├── CalculationFactory.java
│ │ │ └── AbstractSvc.java
│ │ │ ├── feign
│ │ │ ├── FfmpegService.java
│ │ │ └── MusicService.java
│ │ │ ├── Application.java
│ │ │ └── controller
│ │ │ └── SvcController.java
│ │ └── resources
│ │ └── bootstrap.yml
├── svc-api
│ ├── src
│ │ └── main
│ │ │ └── java
│ │ │ └── me
│ │ │ └── liuzeyu
│ │ │ └── aimusic
│ │ │ └── svc
│ │ │ └── api
│ │ │ └── beans
│ │ │ ├── SvcResponse.java
│ │ │ └── Music.java
│ └── pom.xml
└── pom.xml
├── ffmpeg-serv
├── ffmpeg-impl
│ └── src
│ │ └── main
│ │ ├── java
│ │ └── me
│ │ │ └── liuzeyu
│ │ │ └── aimusic
│ │ │ └── ffmpeg
│ │ │ ├── event
│ │ │ ├── EventConstant.java
│ │ │ ├── FfmpegProducer.java
│ │ │ └── FfmpegConsumer.java
│ │ │ ├── feign
│ │ │ └── MusicService.java
│ │ │ ├── Application.java
│ │ │ ├── controller
│ │ │ └── FfmpegController.java
│ │ │ └── caculator
│ │ │ └── FfmpegCaculator.java
│ │ └── resources
│ │ └── bootstrap.yml
├── ffmpeg-api
│ ├── src
│ │ └── main
│ │ │ └── java
│ │ │ └── me
│ │ │ └── liuzeyu
│ │ │ └── aimusic
│ │ │ └── ffmpeg
│ │ │ └── api
│ │ │ └── beans
│ │ │ ├── FfmpegResponse.java
│ │ │ └── Music.java
│ └── pom.xml
└── pom.xml
├── spleeter-serv
├── spleeter-impl
│ └── src
│ │ └── main
│ │ ├── java
│ │ └── me
│ │ │ └── liuzeyu
│ │ │ └── aimusic
│ │ │ └── spleeter
│ │ │ ├── event
│ │ │ ├── EventConstant.java
│ │ │ ├── SpleeterProducer.java
│ │ │ └── SpleeterConsumer.java
│ │ │ ├── feign
│ │ │ ├── MusicService.java
│ │ │ └── SvcService.java
│ │ │ ├── Application.java
│ │ │ ├── controller
│ │ │ └── SpleeterController.java
│ │ │ └── caculator
│ │ │ └── SpleeterCaculator.java
│ │ └── resources
│ │ └── bootstrap.yml
├── spleeter-api
│ ├── src
│ │ └── main
│ │ │ └── java
│ │ │ └── me
│ │ │ └── liuzeyu
│ │ │ └── aimusic
│ │ │ └── spleeter
│ │ │ └── api
│ │ │ └── beans
│ │ │ ├── SvcResponse.java
│ │ │ ├── SpleeterResponse.java
│ │ │ └── Music.java
│ └── pom.xml
└── pom.xml
├── auth-serv
├── auth-api
│ ├── src
│ │ └── main
│ │ │ └── java
│ │ │ └── me
│ │ │ └── liuzeyu
│ │ │ └── aimusic
│ │ │ └── auth
│ │ │ └── api
│ │ │ └── beans
│ │ │ ├── ApiResponse.java
│ │ │ ├── LoginRequest.java
│ │ │ ├── JwtAuthenticationResponse.java
│ │ │ ├── SignUpRequest.java
│ │ │ └── MusicUserDetails.java
│ └── pom.xml
├── auth-impl
│ └── src
│ │ └── main
│ │ ├── java
│ │ └── me
│ │ │ └── liuzeyu
│ │ │ └── aimusic
│ │ │ └── auth
│ │ │ ├── service
│ │ │ ├── intf
│ │ │ │ └── UserService.java
│ │ │ ├── MusicUserDetailsService.java
│ │ │ └── JwtTokenProvider.java
│ │ │ ├── config
│ │ │ └── JwtConfig.java
│ │ │ ├── Application.java
│ │ │ └── controller
│ │ │ └── AuthController.java
│ │ └── resources
│ │ ├── bootstrap.yml
│ │ └── application.yml
├── auth-dao
│ ├── src
│ │ └── main
│ │ │ └── java
│ │ │ └── me
│ │ │ └── liuzeyu
│ │ │ └── aimusic
│ │ │ └── auth
│ │ │ └── dao
│ │ │ ├── UserDao.java
│ │ │ └── entity
│ │ │ └── User.java
│ └── pom.xml
└── pom.xml
├── music-serv
├── music-impl
│ ├── music-impl.iml
│ └── src
│ │ └── main
│ │ ├── java
│ │ └── me
│ │ │ └── liuzeyu
│ │ │ └── aimusic
│ │ │ └── music
│ │ │ ├── converter
│ │ │ ├── MusicConverter.java
│ │ │ └── FileConverter.java
│ │ │ ├── service
│ │ │ └── intf
│ │ │ │ └── MusicService.java
│ │ │ ├── feign
│ │ │ └── SpleeterService.java
│ │ │ ├── Application.java
│ │ │ └── controller
│ │ │ └── MusicController.java
│ │ └── resources
│ │ ├── bootstrap.yml
│ │ └── application.yml
├── music-api
│ ├── src
│ │ └── main
│ │ │ └── java
│ │ │ └── me
│ │ │ └── liuzeyu
│ │ │ └── aimusic
│ │ │ └── music
│ │ │ └── api
│ │ │ ├── beans
│ │ │ ├── MusicListInfo.java
│ │ │ ├── UpdateMusicInfo.java
│ │ │ ├── MusicInfo.java
│ │ │ └── MusicResponse.java
│ │ │ └── enums
│ │ │ └── StatusType.java
│ └── pom.xml
├── music-dao
│ ├── src
│ │ └── main
│ │ │ └── java
│ │ │ └── me
│ │ │ └── liuzeyu
│ │ │ └── aimusic
│ │ │ └── music
│ │ │ └── dao
│ │ │ ├── converter
│ │ │ └── StatusTypeConverter.java
│ │ │ ├── MusicDao.java
│ │ │ └── entity
│ │ │ └── Music.java
│ └── pom.xml
└── pom.xml
├── middleware
├── gateway
│ └── src
│ │ └── main
│ │ ├── java
│ │ └── me
│ │ │ └── liuzeyu
│ │ │ └── gateway
│ │ │ ├── exception
│ │ │ ├── JwtTokenMissingException.java
│ │ │ └── JwtTokenMalformedException.java
│ │ │ ├── GatewayApplication.java
│ │ │ ├── config
│ │ │ └── RoutesConfiguration.java
│ │ │ ├── util
│ │ │ └── JwtUtil.java
│ │ │ └── filter
│ │ │ └── JwtAuthenticationFilter.java
│ │ └── resources
│ │ ├── bootstrap.yml
│ │ └── application.yml
└── pom.xml
├── .gitignore
├── user.sql
└── music.sql
/music-client/static/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/auth-client/src/signup/Signup.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/music-client/.eslintignore:
--------------------------------------------------------------------------------
1 | /build/
2 | /config/
3 | /dist/
4 | /*.js
5 |
--------------------------------------------------------------------------------
/auth-client/build/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/auth-client/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/music-client/config/prod.env.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | module.exports = {
3 | NODE_ENV: '"production"'
4 | }
5 |
--------------------------------------------------------------------------------
/auth-client/build/signin/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/auth-client/build/signup/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/music-client/src/common/stylus/index.styl:
--------------------------------------------------------------------------------
1 | @import "./reset.styl"
2 | @import "./base.styl"
3 | @import "./icon.styl"
--------------------------------------------------------------------------------
/auth-client/build/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/logonod/spring-cloud-ai-music/HEAD/auth-client/build/favicon.ico
--------------------------------------------------------------------------------
/auth-client/build/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/logonod/spring-cloud-ai-music/HEAD/auth-client/build/logo192.png
--------------------------------------------------------------------------------
/auth-client/build/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/logonod/spring-cloud-ai-music/HEAD/auth-client/build/logo512.png
--------------------------------------------------------------------------------
/music-client/build/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/logonod/spring-cloud-ai-music/HEAD/music-client/build/logo.png
--------------------------------------------------------------------------------
/music-client/src/common/js/config.js:
--------------------------------------------------------------------------------
1 | export const playMode = {
2 | sequence: 0,
3 | loop: 1,
4 | random: 2
5 | }
6 |
--------------------------------------------------------------------------------
/auth-client/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/logonod/spring-cloud-ai-music/HEAD/auth-client/public/favicon.ico
--------------------------------------------------------------------------------
/auth-client/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/logonod/spring-cloud-ai-music/HEAD/auth-client/public/logo192.png
--------------------------------------------------------------------------------
/auth-client/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/logonod/spring-cloud-ai-music/HEAD/auth-client/public/logo512.png
--------------------------------------------------------------------------------
/auth-client/build/signin/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/logonod/spring-cloud-ai-music/HEAD/auth-client/build/signin/favicon.ico
--------------------------------------------------------------------------------
/auth-client/build/signin/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/logonod/spring-cloud-ai-music/HEAD/auth-client/build/signin/logo192.png
--------------------------------------------------------------------------------
/auth-client/build/signin/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/logonod/spring-cloud-ai-music/HEAD/auth-client/build/signin/logo512.png
--------------------------------------------------------------------------------
/auth-client/build/signup/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/logonod/spring-cloud-ai-music/HEAD/auth-client/build/signup/favicon.ico
--------------------------------------------------------------------------------
/auth-client/build/signup/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/logonod/spring-cloud-ai-music/HEAD/auth-client/build/signup/logo192.png
--------------------------------------------------------------------------------
/auth-client/build/signup/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/logonod/spring-cloud-ai-music/HEAD/auth-client/build/signup/logo512.png
--------------------------------------------------------------------------------
/music-client/src/base/loading/loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/logonod/spring-cloud-ai-music/HEAD/music-client/src/base/loading/loading.gif
--------------------------------------------------------------------------------
/music-client/src/common/image/default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/logonod/spring-cloud-ai-music/HEAD/music-client/src/common/image/default.png
--------------------------------------------------------------------------------
/music-client/src/base/song-list/first@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/logonod/spring-cloud-ai-music/HEAD/music-client/src/base/song-list/first@2x.png
--------------------------------------------------------------------------------
/music-client/src/base/song-list/first@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/logonod/spring-cloud-ai-music/HEAD/music-client/src/base/song-list/first@3x.png
--------------------------------------------------------------------------------
/music-client/src/base/song-list/third@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/logonod/spring-cloud-ai-music/HEAD/music-client/src/base/song-list/third@2x.png
--------------------------------------------------------------------------------
/music-client/src/base/song-list/third@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/logonod/spring-cloud-ai-music/HEAD/music-client/src/base/song-list/third@3x.png
--------------------------------------------------------------------------------
/music-client/src/common/fonts/music-icon.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/logonod/spring-cloud-ai-music/HEAD/music-client/src/common/fonts/music-icon.eot
--------------------------------------------------------------------------------
/music-client/src/common/fonts/music-icon.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/logonod/spring-cloud-ai-music/HEAD/music-client/src/common/fonts/music-icon.ttf
--------------------------------------------------------------------------------
/music-client/src/base/song-list/second@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/logonod/spring-cloud-ai-music/HEAD/music-client/src/base/song-list/second@2x.png
--------------------------------------------------------------------------------
/music-client/src/base/song-list/second@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/logonod/spring-cloud-ai-music/HEAD/music-client/src/base/song-list/second@3x.png
--------------------------------------------------------------------------------
/music-client/src/common/fonts/music-icon.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/logonod/spring-cloud-ai-music/HEAD/music-client/src/common/fonts/music-icon.woff
--------------------------------------------------------------------------------
/music-client/dist/static/img/default.142f76c.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/logonod/spring-cloud-ai-music/HEAD/music-client/dist/static/img/default.142f76c.png
--------------------------------------------------------------------------------
/music-client/src/base/no-result/no-result@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/logonod/spring-cloud-ai-music/HEAD/music-client/src/base/no-result/no-result@2x.png
--------------------------------------------------------------------------------
/music-client/src/base/no-result/no-result@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/logonod/spring-cloud-ai-music/HEAD/music-client/src/base/no-result/no-result@3x.png
--------------------------------------------------------------------------------
/music-client/src/components/m-header/logo@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/logonod/spring-cloud-ai-music/HEAD/music-client/src/components/m-header/logo@2x.png
--------------------------------------------------------------------------------
/music-client/src/components/m-header/logo@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/logonod/spring-cloud-ai-music/HEAD/music-client/src/components/m-header/logo@3x.png
--------------------------------------------------------------------------------
/auth-client/src/App.css:
--------------------------------------------------------------------------------
1 | @import "~antd/dist/antd.css";
2 |
3 | body {
4 | background-color: #fafafa;
5 | }
6 |
7 | .App {
8 | padding-top: 50px;
9 | }
10 |
--------------------------------------------------------------------------------
/music-client/dist/static/img/no-result@3x.2858208.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/logonod/spring-cloud-ai-music/HEAD/music-client/dist/static/img/no-result@3x.2858208.png
--------------------------------------------------------------------------------
/music-client/config/dev.env.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const merge = require('webpack-merge')
3 | const prodEnv = require('./prod.env')
4 |
5 | module.exports = merge(prodEnv, {
6 | NODE_ENV: '"development"'
7 | })
8 |
--------------------------------------------------------------------------------
/music-client/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
--------------------------------------------------------------------------------
/svc-serv/svc-impl/src/main/java/me/liuzeyu/me/aimusic/svc/event/EventConstant.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.me.aimusic.svc.event;
2 |
3 | public class EventConstant {
4 | public static final String ADD_SVC_EVENT = "addSvc-out-0";
5 | }
6 |
--------------------------------------------------------------------------------
/ffmpeg-serv/ffmpeg-impl/src/main/java/me/liuzeyu/aimusic/ffmpeg/event/EventConstant.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.ffmpeg.event;
2 |
3 | public class EventConstant {
4 | public static final String ADD_FFMPEG_EVENT = "addFfmpeg-out-0";
5 | }
6 |
--------------------------------------------------------------------------------
/spleeter-serv/spleeter-impl/src/main/java/me/liuzeyu/aimusic/spleeter/event/EventConstant.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.spleeter.event;
2 |
3 | public class EventConstant {
4 | public static final String ADD_SPLEETER_EVENT = "addSpleeter-out-0";
5 | }
6 |
--------------------------------------------------------------------------------
/auth-client/src/setupTests.js:
--------------------------------------------------------------------------------
1 | // jest-dom adds custom jest matchers for asserting on DOM nodes.
2 | // allows you to do things like:
3 | // expect(element).toHaveTextContent(/react/i)
4 | // learn more: https://github.com/testing-library/jest-dom
5 | import '@testing-library/jest-dom/extend-expect';
6 |
--------------------------------------------------------------------------------
/music-client/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | ["env", {
4 | "modules": false,
5 | "targets": {
6 | "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
7 | }
8 | }],
9 | "stage-2"
10 | ],
11 | "plugins": ["transform-vue-jsx", "transform-runtime"]
12 | }
13 |
--------------------------------------------------------------------------------
/music-client/.postcssrc.js:
--------------------------------------------------------------------------------
1 | // https://github.com/michael-ciniawsky/postcss-load-config
2 |
3 | module.exports = {
4 | "plugins": {
5 | "postcss-import": {},
6 | "postcss-url": {},
7 | // to edit target browsers: use "browserslist" field in package.json
8 | "autoprefixer": {}
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/auth-client/src/App.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { render } from '@testing-library/react';
3 | import App from './App';
4 |
5 | test('renders learn react link', () => {
6 | const { getByText } = render();
7 | const linkElement = getByText(/learn react/i);
8 | expect(linkElement).toBeInTheDocument();
9 | });
10 |
--------------------------------------------------------------------------------
/auth-serv/auth-api/src/main/java/me/liuzeyu/aimusic/auth/api/beans/ApiResponse.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.auth.api.beans;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 |
6 | @Data
7 | @AllArgsConstructor
8 | public class ApiResponse {
9 | private Boolean success;
10 | private String message;
11 | }
12 |
--------------------------------------------------------------------------------
/music-client/src/common/js/singer.js:
--------------------------------------------------------------------------------
1 | export default class Singer {
2 | constructor({city = '', id, name, mid}) {
3 | this.country = city
4 | this.singer_id = id
5 | this.singer_mid = mid
6 | this.singer_name = name
7 | this.singer_pic = `http://y.gtimg.cn/music/photo_new/T001R150x150M000${mid}.webp`
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/music-client/src/common/stylus/base.styl:
--------------------------------------------------------------------------------
1 | @import "variable.styl"
2 |
3 | body, html
4 | line-height: 1
5 | font-family: 'PingFang SC', 'STHeitiSC-Light', 'Helvetica-Light', arial, sans-serif, 'Droid Sans Fallback'
6 | user-select: none
7 | -webkit-tap-highlight-color: transparent
8 | background: $color-background
9 | color: $color-text
--------------------------------------------------------------------------------
/music-serv/music-impl/music-impl.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/svc-serv/svc-impl/src/main/java/me/liuzeyu/me/aimusic/svc/caculator/SvcTemplate.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.me.aimusic.svc.caculator;
2 |
3 | import java.io.IOException;
4 |
5 | public interface SvcTemplate {
6 | String getCommand();
7 |
8 | void run(String hash, String path, String pythonPath, String svcPath) throws IOException;
9 | }
10 |
--------------------------------------------------------------------------------
/auth-serv/auth-api/src/main/java/me/liuzeyu/aimusic/auth/api/beans/LoginRequest.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.auth.api.beans;
2 |
3 | import lombok.Data;
4 |
5 | import javax.validation.constraints.NotBlank;
6 |
7 | @Data
8 | public class LoginRequest {
9 |
10 | @NotBlank
11 | private String username;
12 |
13 | @NotBlank
14 | private String password;
15 | }
16 |
--------------------------------------------------------------------------------
/music-client/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | AI翻唱
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/music-client/src/store/state.js:
--------------------------------------------------------------------------------
1 | import { playMode } from '../common/js/config'
2 | import { loadPlay } from '../common/js/cache'
3 | const state = {
4 | singer: {},
5 | playing: false,
6 | fullScreen: false,
7 | playlist: [],
8 | sequenceList: [],
9 | mode: playMode.sequence,
10 | currentIndex: -1,
11 | disc: {},
12 | playHistory: loadPlay(),
13 | }
14 |
15 | export default state
16 |
--------------------------------------------------------------------------------
/middleware/gateway/src/main/java/me/liuzeyu/gateway/exception/JwtTokenMissingException.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.gateway.exception;
2 |
3 | import javax.naming.AuthenticationException;
4 |
5 | public class JwtTokenMissingException extends AuthenticationException {
6 |
7 | private static final long serialVersionUID = 1L;
8 |
9 | public JwtTokenMissingException(String msg) {
10 | super(msg);
11 | }
12 |
13 | }
--------------------------------------------------------------------------------
/middleware/gateway/src/main/java/me/liuzeyu/gateway/exception/JwtTokenMalformedException.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.gateway.exception;
2 |
3 | import javax.naming.AuthenticationException;
4 |
5 | public class JwtTokenMalformedException extends AuthenticationException {
6 |
7 | private static final long serialVersionUID = 1L;
8 |
9 | public JwtTokenMalformedException(String msg) {
10 | super(msg);
11 | }
12 |
13 | }
--------------------------------------------------------------------------------
/auth-client/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
5 | sans-serif;
6 | -webkit-font-smoothing: antialiased;
7 | -moz-osx-font-smoothing: grayscale;
8 | }
9 |
10 | code {
11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
12 | monospace;
13 | }
14 |
--------------------------------------------------------------------------------
/auth-serv/auth-api/src/main/java/me/liuzeyu/aimusic/auth/api/beans/JwtAuthenticationResponse.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.auth.api.beans;
2 |
3 | import lombok.Data;
4 | import lombok.NonNull;
5 | import lombok.RequiredArgsConstructor;
6 |
7 | @Data
8 | @RequiredArgsConstructor
9 | public class JwtAuthenticationResponse {
10 |
11 | @NonNull
12 | private String accessToken;
13 | private String tokenType = "Bearer";
14 | }
15 |
--------------------------------------------------------------------------------
/auth-serv/auth-impl/src/main/java/me/liuzeyu/aimusic/auth/service/intf/UserService.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.auth.service.intf;
2 |
3 | import me.liuzeyu.aimusic.auth.dao.entity.User;
4 |
5 | import java.util.Optional;
6 |
7 | public interface UserService {
8 | String loginUser(String username, String password);
9 |
10 | Optional findByUsername(String username);
11 |
12 | User registerUser(User user);
13 | }
14 |
--------------------------------------------------------------------------------
/music-serv/music-api/src/main/java/me/liuzeyu/aimusic/music/api/beans/MusicListInfo.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.music.api.beans;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | import java.util.List;
9 |
10 | @Data
11 | @NoArgsConstructor
12 | @AllArgsConstructor
13 | @Builder
14 | public class MusicListInfo {
15 | public List list;
16 | }
17 |
--------------------------------------------------------------------------------
/middleware/gateway/src/main/resources/bootstrap.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | application:
3 | name: music-gateway
4 | cloud:
5 | nacos:
6 | config:
7 | server-addr: localhost:8848
8 | file-extension: yml
9 | namespace: dev
10 | timeout: 5000
11 | config-long-poll-timeout: 1000
12 | config-retry-time: 100000
13 | max-retry: 3
14 | refresh-enabled: true
15 | enable-remote-sync-config: true
16 |
17 |
--------------------------------------------------------------------------------
/svc-serv/svc-api/src/main/java/me/liuzeyu/aimusic/svc/api/beans/SvcResponse.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.svc.api.beans;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | import javax.validation.constraints.NotNull;
9 |
10 | @Data
11 | @NoArgsConstructor
12 | @AllArgsConstructor
13 | @Builder
14 | public class SvcResponse {
15 | @NotNull
16 | private String status;
17 | }
18 |
--------------------------------------------------------------------------------
/ffmpeg-serv/ffmpeg-api/src/main/java/me/liuzeyu/aimusic/ffmpeg/api/beans/FfmpegResponse.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.ffmpeg.api.beans;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | import javax.validation.constraints.NotNull;
9 |
10 | @Data
11 | @NoArgsConstructor
12 | @AllArgsConstructor
13 | @Builder
14 | public class FfmpegResponse {
15 | @NotNull
16 | private String status;
17 | }
18 |
--------------------------------------------------------------------------------
/spleeter-serv/spleeter-api/src/main/java/me/liuzeyu/aimusic/spleeter/api/beans/SvcResponse.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.spleeter.api.beans;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | import javax.validation.constraints.NotNull;
9 |
10 | @Data
11 | @NoArgsConstructor
12 | @AllArgsConstructor
13 | @Builder
14 | public class SvcResponse {
15 | @NotNull
16 | private String status;
17 | }
18 |
--------------------------------------------------------------------------------
/spleeter-serv/spleeter-api/src/main/java/me/liuzeyu/aimusic/spleeter/api/beans/SpleeterResponse.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.spleeter.api.beans;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | import javax.validation.constraints.NotNull;
9 |
10 | @Data
11 | @NoArgsConstructor
12 | @AllArgsConstructor
13 | @Builder
14 | public class SpleeterResponse {
15 | @NotNull
16 | private String status;
17 | }
18 |
--------------------------------------------------------------------------------
/auth-client/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import './index.css';
4 | import App from './App';
5 | import * as serviceWorker from './serviceWorker';
6 |
7 | ReactDOM.render(
8 | ,
9 | document.getElementById('root')
10 | );
11 |
12 | // If you want your app to work offline and load faster, you can change
13 | // unregister() to register() below. Note this comes with some pitfalls.
14 | // Learn more about service workers: https://bit.ly/CRA-PWA
15 | serviceWorker.unregister();
16 |
--------------------------------------------------------------------------------
/music-client/src/store/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Vuex from 'vuex'
3 | import * as actions from './actions'
4 | import * as getters from './getters'
5 | import state from './state'
6 | import mutations from './mutations'
7 | import createLogger from 'vuex/dist/logger'
8 |
9 | Vue.use(Vuex)
10 |
11 | const debug = process.env.NODE_ENV !== 'production'
12 | export default new Vuex.Store({
13 | actions,
14 | getters,
15 | state,
16 | mutations,
17 | strict: debug,
18 | plugins: debug ? [createLogger()] : []
19 | })
20 |
--------------------------------------------------------------------------------
/music-client/src/store/mutation-types.js:
--------------------------------------------------------------------------------
1 | export const SET_SINGER = 'SET_SINGER'
2 |
3 | export const SET_PLAYING_STATE = 'SET_PLAYING_STATE'
4 |
5 | export const SET_FULL_SCREEN = 'SET_FULL_SCREEN'
6 |
7 | export const SET_PLAYLIST = 'SET_PLAYLIST'
8 |
9 | export const SET_SEQUENCE_LIST = 'SET_SEQUENCE_LIST'
10 |
11 | export const SET_PLAY_MODE = 'SET_PLAY_MODE'
12 |
13 | export const SET_CURRENT_INDEX = 'SET_CURRENT_INDEX'
14 |
15 | export const SET_DISC = 'SET_DISC'
16 |
17 | export const SET_PLAY_HISTORY = 'SET_PLAY_HISTORY'
18 |
19 |
--------------------------------------------------------------------------------
/middleware/gateway/src/main/java/me/liuzeyu/gateway/GatewayApplication.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.gateway;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
6 |
7 | @SpringBootApplication
8 | @EnableDiscoveryClient
9 | public class GatewayApplication {
10 |
11 | public static void main(String[] args) {
12 | SpringApplication.run(GatewayApplication.class, args);
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/music-client/src/common/stylus/mixin.styl:
--------------------------------------------------------------------------------
1 | // 背景图片
2 | bg-image($url)
3 | background-image: url($url + "@2x.png")
4 | @media (-webkit-min-device-pixel-ratio: 3),(min-device-pixel-ratio: 3)
5 | background-image: url($url + "@3x.png")
6 |
7 | // 不换行
8 | no-wrap()
9 | text-overflow: ellipsis
10 | overflow: hidden
11 | white-space: nowrap
12 |
13 | // 扩展点击区域
14 | extend-click()
15 | position: relative
16 | &:before
17 | content: ''
18 | position: absolute
19 | top: -10px
20 | left: -10px
21 | right: -10px
22 | bottom: -10px
--------------------------------------------------------------------------------
/auth-serv/auth-dao/src/main/java/me/liuzeyu/aimusic/auth/dao/UserDao.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.auth.dao;
2 |
3 | import me.liuzeyu.aimusic.auth.dao.entity.User;
4 | import org.springframework.data.jpa.repository.JpaRepository;
5 |
6 | import java.util.List;
7 | import java.util.Optional;
8 |
9 | public interface UserDao
10 | extends JpaRepository {
11 |
12 | Optional findByUsername(String username);
13 |
14 | boolean existsByUsername(String username);
15 |
16 | boolean existsByEmail(String email);
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/music-client/dist/index.html:
--------------------------------------------------------------------------------
1 | AI翻唱
--------------------------------------------------------------------------------
/music-client/src/common/js/song.js:
--------------------------------------------------------------------------------
1 | export default class Song {
2 | constructor({id, mid, singer, name, album, duration, image, url}) {
3 | this.id = id
4 | this.mid = mid
5 | this.singer = singer
6 | this.name = name
7 | this.album = album
8 | this.duration = duration
9 | this.image = image
10 | this.url = url
11 | }
12 | }
13 |
14 | function filterSinger(singer) {
15 | let ret = []
16 | if (!singer) {
17 | return ''
18 | }
19 | singer.forEach(s => {
20 | ret.push(s.name)
21 | })
22 | return ret.join('/')
23 | }
24 |
--------------------------------------------------------------------------------
/svc-serv/svc-impl/src/main/java/me/liuzeyu/me/aimusic/svc/feign/FfmpegService.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.me.aimusic.svc.feign;
2 |
3 | import me.liuzeyu.aimusic.ffmpeg.api.beans.FfmpegResponse;
4 | import me.liuzeyu.aimusic.svc.api.beans.Music;
5 | import org.springframework.cloud.openfeign.FeignClient;
6 | import org.springframework.web.bind.annotation.PostMapping;
7 |
8 |
9 | @FeignClient(value = "ffmpeg-serv", path = "/ffmpeg")
10 | public interface FfmpegService {
11 |
12 | // 创建干声伴奏合成任务
13 | @PostMapping("/request")
14 | FfmpegResponse requestFfmpeg(Music music);
15 |
16 | }
--------------------------------------------------------------------------------
/music-serv/music-api/src/main/java/me/liuzeyu/aimusic/music/api/beans/UpdateMusicInfo.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.music.api.beans;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | import javax.validation.constraints.NotNull;
9 |
10 | @Data
11 | @NoArgsConstructor
12 | @AllArgsConstructor
13 | @Builder
14 | public class UpdateMusicInfo {
15 | @NotNull
16 | private Long user;
17 |
18 | @NotNull
19 | private String hash;
20 |
21 | @NotNull
22 | private String status;
23 | }
24 |
--------------------------------------------------------------------------------
/music-client/src/main.js:
--------------------------------------------------------------------------------
1 | import 'babel-polyfill'
2 | import 'common/stylus/index.styl'
3 | import Vue from 'vue'
4 | import App from './App'
5 | import router from './router'
6 | import store from './store'
7 | import fastclick from 'fastclick'
8 | import VueLazyLoad from 'vue-lazyload'
9 |
10 | Vue.config.productionTip = false
11 |
12 | fastclick.attach(document.body)
13 | /* eslint-disable no-new */
14 |
15 | Vue.use(VueLazyLoad, {
16 | loading: require('./common/image/default.png')
17 | })
18 | new Vue({
19 | el: '#app',
20 | router,
21 | store,
22 | render: h => h(App)
23 | })
24 |
--------------------------------------------------------------------------------
/music-client/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
24 |
25 |
28 |
--------------------------------------------------------------------------------
/auth-client/build/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/auth-client/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/auth-serv/auth-api/src/main/java/me/liuzeyu/aimusic/auth/api/beans/SignUpRequest.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.auth.api.beans;
2 |
3 | import lombok.Data;
4 |
5 | import javax.validation.constraints.Email;
6 | import javax.validation.constraints.NotBlank;
7 | import javax.validation.constraints.Size;
8 |
9 | @Data
10 | public class SignUpRequest {
11 | @NotBlank
12 | @Size(min = 3, max = 15)
13 | private String username;
14 |
15 | @NotBlank
16 | @Size(max = 40)
17 | @Email
18 | private String email;
19 |
20 | @NotBlank
21 | @Size(min = 1, max = 20)
22 | private String password;
23 | }
24 |
--------------------------------------------------------------------------------
/auth-client/build/signin/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/auth-client/build/signup/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/svc-serv/svc-impl/src/main/java/me/liuzeyu/me/aimusic/svc/feign/MusicService.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.me.aimusic.svc.feign;
2 |
3 | import me.liuzeyu.aimusic.music.api.beans.MusicInfo;
4 | import me.liuzeyu.aimusic.music.api.beans.UpdateMusicInfo;
5 | import me.liuzeyu.aimusic.spleeter.api.beans.SvcResponse;
6 | import org.springframework.cloud.openfeign.FeignClient;
7 | import org.springframework.web.bind.annotation.PostMapping;
8 |
9 | @FeignClient(value = "music-serv", path = "/music")
10 | public interface MusicService {
11 | // 修改任务状态
12 | @PostMapping("/update")
13 | MusicInfo updateMusic(UpdateMusicInfo music);
14 | }
15 |
--------------------------------------------------------------------------------
/ffmpeg-serv/ffmpeg-impl/src/main/java/me/liuzeyu/aimusic/ffmpeg/feign/MusicService.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.ffmpeg.feign;
2 |
3 | import me.liuzeyu.aimusic.music.api.beans.MusicInfo;
4 | import me.liuzeyu.aimusic.music.api.beans.UpdateMusicInfo;
5 | import me.liuzeyu.aimusic.spleeter.api.beans.SvcResponse;
6 | import org.springframework.cloud.openfeign.FeignClient;
7 | import org.springframework.web.bind.annotation.PostMapping;
8 |
9 | @FeignClient(value = "music-serv", path = "/music")
10 | public interface MusicService {
11 | // 修改任务状态
12 | @PostMapping("/update")
13 | MusicInfo updateMusic(UpdateMusicInfo music);
14 | }
15 |
--------------------------------------------------------------------------------
/spleeter-serv/spleeter-impl/src/main/java/me/liuzeyu/aimusic/spleeter/feign/MusicService.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.spleeter.feign;
2 |
3 | import me.liuzeyu.aimusic.music.api.beans.MusicInfo;
4 | import me.liuzeyu.aimusic.music.api.beans.UpdateMusicInfo;
5 | import me.liuzeyu.aimusic.spleeter.api.beans.SvcResponse;
6 | import org.springframework.cloud.openfeign.FeignClient;
7 | import org.springframework.web.bind.annotation.PostMapping;
8 |
9 | @FeignClient(value = "music-serv", path = "/music")
10 | public interface MusicService {
11 | // 修改任务状态
12 | @PostMapping("/update")
13 | MusicInfo updateMusic(UpdateMusicInfo music);
14 | }
15 |
--------------------------------------------------------------------------------
/music-client/src/common/stylus/variable.styl:
--------------------------------------------------------------------------------
1 | // 颜色定义规范
2 | $color-background = #222
3 | $color-background-d = rgba(0, 0, 0, 0.3)
4 | $color-highlight-background = #333
5 | $color-dialog-background = #666
6 | $color-theme = #ffcd32
7 | $color-theme-d = rgba(255, 205, 49, 0.5)
8 | $color-sub-theme = #d93f30
9 | $color-text = #fff
10 | $color-text-d = rgba(255, 255, 255, 0.3)
11 | $color-text-l = rgba(255, 255, 255, 0.5)
12 | $color-text-ll = rgba(255, 255, 255, 0.8)
13 |
14 | //字体定义规范
15 | $font-size-small-s = 10px
16 | $font-size-small = 12px
17 | $font-size-medium = 14px
18 | $font-size-medium-x = 16px
19 | $font-size-large = 18px
20 | $font-size-large-x = 22px
--------------------------------------------------------------------------------
/music-client/src/store/getters.js:
--------------------------------------------------------------------------------
1 | export const singer = state => state.singer
2 |
3 | export const playing = state => state.playing
4 |
5 | export const fullScreen = state => state.fullScreen
6 |
7 | export const playlist = state => state.playlist
8 |
9 | export const sequenceList = state => state.sequenceList
10 |
11 | export const mode = state => state.mode
12 |
13 | export const currentIndex = state => state.currentIndex
14 |
15 | export const currentSong = (state) => {
16 | return state.playlist[state.currentIndex] || {}
17 | }
18 |
19 | export const disc = state => state.disc
20 |
21 | export const playHistory = state => state.playHistory
22 |
--------------------------------------------------------------------------------
/music-serv/music-impl/src/main/java/me/liuzeyu/aimusic/music/converter/MusicConverter.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.music.converter;
2 |
3 |
4 | import me.liuzeyu.aimusic.music.api.beans.MusicInfo;
5 | import me.liuzeyu.aimusic.music.dao.entity.Music;
6 |
7 | public class MusicConverter {
8 | public static MusicInfo convertToMusicInfo(Music music) {
9 | return MusicInfo.builder()
10 | .id(music.getId())
11 | .user(music.getUser())
12 | .title(music.getTitle())
13 | .artist(music.getArtist())
14 | .ai(music.getAi())
15 | .build();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/spleeter-serv/spleeter-impl/src/main/java/me/liuzeyu/aimusic/spleeter/feign/SvcService.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.spleeter.feign;
2 |
3 | import me.liuzeyu.aimusic.spleeter.api.beans.Music;
4 | import me.liuzeyu.aimusic.spleeter.api.beans.SpleeterResponse;
5 | import me.liuzeyu.aimusic.spleeter.api.beans.SvcResponse;
6 | import org.springframework.cloud.openfeign.FeignClient;
7 | import org.springframework.web.bind.annotation.PostMapping;
8 |
9 | @FeignClient(value = "svc-serv", path = "/svc")
10 | public interface SvcService {
11 |
12 | // 创建spleeter-serv干声分离任务
13 | @PostMapping("/request")
14 | SvcResponse requestSvc(Music music);
15 |
16 | }
--------------------------------------------------------------------------------
/music-serv/music-api/src/main/java/me/liuzeyu/aimusic/music/api/beans/MusicInfo.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.music.api.beans;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | import javax.validation.constraints.NotNull;
9 |
10 | @Data
11 | @NoArgsConstructor
12 | @AllArgsConstructor
13 | @Builder
14 | public class MusicInfo {
15 | private Long id;
16 |
17 | @NotNull
18 | private Long user;
19 |
20 | @NotNull
21 | private String title;
22 |
23 | @NotNull
24 | private String artist;
25 |
26 | @NotNull
27 | private String ai;
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/music-client/build/vue-loader.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const utils = require('./utils')
3 | const config = require('../config')
4 | const isProduction = process.env.NODE_ENV === 'production'
5 | const sourceMapEnabled = isProduction
6 | ? config.build.productionSourceMap
7 | : config.dev.cssSourceMap
8 |
9 | module.exports = {
10 | loaders: utils.cssLoaders({
11 | sourceMap: sourceMapEnabled,
12 | extract: isProduction
13 | }),
14 | cssSourceMap: sourceMapEnabled,
15 | cacheBusting: config.dev.cacheBusting,
16 | transformToRequire: {
17 | video: ['src', 'poster'],
18 | source: 'src',
19 | img: 'src',
20 | image: 'xlink:href'
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/music-client/src/base/loading/loading.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |

4 |
{{title}}
5 |
6 |
7 |
17 |
28 |
--------------------------------------------------------------------------------
/auth-client/src/signin/Signin.css:
--------------------------------------------------------------------------------
1 | .login-container {
2 | max-width: 420px;
3 | margin: 0 auto;
4 | margin: 0 auto;
5 | margin-top: 40px;
6 | padding: 30px 50px 10px 50px;
7 | border: 1px solid #e1e0e0;
8 | background-color: #fff;
9 | font-size: 32px;
10 | font-weight: 700;
11 | border-radius: 10px;
12 | text-align: center;
13 | }
14 |
15 | .login-form-button {
16 | width: 100%;
17 | background-color: rebeccapurple !important;
18 | color: white !important;
19 | font-weight: 700 !important;
20 | }
21 |
22 | .login-with-facebook {
23 | width: 100%;
24 | background-color: #1877f2 !important;
25 | color: white !important;
26 | font-weight: 700 !important;
27 | }
28 |
--------------------------------------------------------------------------------
/music-client/src/common/js/util.js:
--------------------------------------------------------------------------------
1 | function getRandomInt(min, max) {
2 | return Math.floor(Math.random() * (max - min + 1) + min)
3 | }
4 |
5 | export function shuffle(arr) {
6 | // let length = arr.length
7 | let _arr = arr.slice() // 修改副本
8 | for (let i = 0; i < _arr.length; i++) {
9 | let j = getRandomInt(0, i)
10 | let t = _arr[i]
11 | _arr[i] = _arr[j]
12 | _arr[j] = t
13 | }
14 | return _arr
15 | }
16 |
17 | export function debounce(func, delay) {
18 | let timer
19 | return function(...args) {
20 | if (timer) {
21 | clearTimeout(timer)
22 | }
23 | timer = setTimeout(() => {
24 | func.apply(this, args)
25 | }, delay)
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/music-serv/music-dao/src/main/java/me/liuzeyu/aimusic/music/dao/converter/StatusTypeConverter.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.music.dao.converter;
2 |
3 | import me.liuzeyu.aimusic.music.api.enums.StatusType;
4 |
5 | import javax.persistence.AttributeConverter;
6 | import javax.persistence.Converter;
7 |
8 | @Converter
9 | public class StatusTypeConverter
10 | implements AttributeConverter {
11 | @Override
12 | public String convertToDatabaseColumn(StatusType statusType) {
13 | return statusType.getCode();
14 | }
15 |
16 | @Override
17 | public StatusType convertToEntityAttribute(String code) {
18 | return StatusType.convert(code);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/svc-serv/svc-impl/src/main/java/me/liuzeyu/me/aimusic/svc/caculator/impl/ZhangxueyouSvc.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.me.aimusic.svc.caculator.impl;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import me.liuzeyu.me.aimusic.svc.caculator.AbstractSvc;
5 | import me.liuzeyu.me.aimusic.svc.caculator.SvcTemplate;
6 | import org.springframework.stereotype.Service;
7 |
8 | import java.io.IOException;
9 |
10 | @Slf4j
11 | @Service
12 | public class ZhangxueyouSvc extends AbstractSvc implements SvcTemplate {
13 | static final String COMMAND = "{0} {1}/inference_main.py -m {1}/logs/44k/zhangxueyou.pth -c {1}/configs/zhangxueyou.json -n {2} -s zhangxueyou";
14 |
15 | @Override
16 | public String getCommand() {
17 | return COMMAND;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/auth-client/src/App.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { BrowserRouter, Route, Switch } from "react-router-dom";
3 | import Signin from "./signin/Signin";
4 | import Signup from "./signup/Signup";
5 | import "./App.css";
6 |
7 | const App = (props) => {
8 | return (
9 |
10 |
11 |
12 | }
16 | />
17 | }
21 | />
22 |
23 |
24 |
25 | );
26 | };
27 |
28 | export default App;
29 |
--------------------------------------------------------------------------------
/svc-serv/svc-impl/src/main/java/me/liuzeyu/me/aimusic/svc/Application.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.svc;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
6 | import org.springframework.cloud.openfeign.EnableFeignClients;
7 | import org.springframework.context.annotation.ComponentScan;
8 |
9 | @SpringBootApplication()
10 | @EnableDiscoveryClient
11 | @EnableFeignClients(basePackages = {"me.liuzeyu"})
12 | @ComponentScan(basePackages = {"me.liuzeyu"})
13 | public class Application {
14 |
15 | public static void main(String[] args) {
16 | SpringApplication.run(Application.class, args);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/svc-serv/svc-impl/src/main/java/me/liuzeyu/me/aimusic/svc/caculator/impl/SunyanziSvc.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.me.aimusic.svc.caculator.impl;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import me.liuzeyu.me.aimusic.svc.caculator.AbstractSvc;
5 | import me.liuzeyu.me.aimusic.svc.caculator.SvcTemplate;
6 | import org.springframework.stereotype.Service;
7 |
8 | import java.io.IOException;
9 |
10 | @Slf4j
11 | @Service
12 | public class SunyanziSvc extends AbstractSvc implements SvcTemplate {
13 | static final String COMMAND = "{0} {1}/inference_main.py -m {1}/logs/44k/sunyanzi.pth -c {1}/configs/sunyanzi.json -n {2} -s sunyanzi -cm {1}/logs/44k/sunyanzi.pt";
14 |
15 | @Override
16 | public String getCommand() {
17 | return COMMAND;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/music-serv/music-api/src/main/java/me/liuzeyu/aimusic/music/api/beans/MusicResponse.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.music.api.beans;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | import javax.validation.constraints.NotNull;
9 |
10 | @Data
11 | @NoArgsConstructor
12 | @AllArgsConstructor
13 | @Builder
14 | public class MusicResponse {
15 | private Long id;
16 |
17 | @NotNull
18 | private Long user;
19 |
20 | @NotNull
21 | private String title;
22 |
23 | @NotNull
24 | private String artist;
25 |
26 | @NotNull
27 | private String ai;
28 |
29 | @NotNull
30 | private String status;
31 |
32 | @NotNull
33 | private String hash;
34 |
35 | }
--------------------------------------------------------------------------------
/auth-serv/auth-impl/src/main/java/me/liuzeyu/aimusic/auth/config/JwtConfig.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.auth.config;
2 |
3 | import lombok.Data;
4 | import lombok.NoArgsConstructor;
5 | import org.springframework.stereotype.Component;
6 | import org.springframework.beans.factory.annotation.Value;
7 |
8 | @Data
9 | @NoArgsConstructor
10 | @Component
11 | public class JwtConfig {
12 | @Value("${security.jwt.uri:}")
13 | private String Uri;
14 |
15 | @Value("${security.jwt.header:}")
16 | private String header;
17 |
18 | @Value("${security.jwt.prefix:}")
19 | private String prefix;
20 |
21 | @Value("${security.jwt.expiration:1234}")
22 | private int expiration;
23 |
24 | @Value("${security.jwt.secret:}")
25 | private String secret;
26 | }
27 |
--------------------------------------------------------------------------------
/ffmpeg-serv/ffmpeg-impl/src/main/java/me/liuzeyu/aimusic/ffmpeg/Application.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.ffmpeg;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
6 | import org.springframework.cloud.openfeign.EnableFeignClients;
7 | import org.springframework.context.annotation.ComponentScan;
8 |
9 | @SpringBootApplication()
10 | @EnableDiscoveryClient
11 | @EnableFeignClients(basePackages = {"me.liuzeyu"})
12 | @ComponentScan(basePackages = {"me.liuzeyu"})
13 | public class Application {
14 |
15 | public static void main(String[] args) {
16 | SpringApplication.run(Application.class, args);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/svc-serv/svc-impl/src/main/java/me/liuzeyu/me/aimusic/svc/caculator/impl/ZhoujielunSvc.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.me.aimusic.svc.caculator.impl;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import me.liuzeyu.me.aimusic.svc.caculator.AbstractSvc;
5 | import me.liuzeyu.me.aimusic.svc.caculator.SvcTemplate;
6 | import org.springframework.stereotype.Service;
7 |
8 | import java.io.IOException;
9 |
10 | @Slf4j
11 | @Service
12 | public class ZhoujielunSvc extends AbstractSvc implements SvcTemplate {
13 | static final String COMMAND = "{0} {1}/inference_main.py -m {1}/logs/44k/zhoujielun.pth -c {1}/configs/zhoujielun.json -n {2} -s zhoujielun -cm {1}/logs/44k/zhoujielun.pt";
14 |
15 | @Override
16 | public String getCommand() {
17 | return COMMAND;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/music-serv/music-impl/src/main/java/me/liuzeyu/aimusic/music/service/intf/MusicService.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.music.service.intf;
2 |
3 |
4 | import org.springframework.web.multipart.MultipartFile;
5 |
6 | import java.io.IOException;
7 | import java.security.NoSuchAlgorithmException;
8 | import me.liuzeyu.aimusic.music.api.beans.*;
9 | import me.liuzeyu.aimusic.music.dao.entity.Music;
10 |
11 | public interface MusicService {
12 |
13 | MusicInfo updateMusic(UpdateMusicInfo request);
14 |
15 | MusicInfo createMusic(MusicInfo request, MultipartFile upload) throws IOException, NoSuchAlgorithmException;
16 |
17 | MusicListInfo otherMusic(Long id);
18 |
19 | MusicListInfo pendingMusic(Long id);
20 |
21 | MusicListInfo finishedMusic(Long id);
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/spleeter-serv/spleeter-impl/src/main/java/me/liuzeyu/aimusic/spleeter/Application.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.spleeter;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
6 | import org.springframework.cloud.openfeign.EnableFeignClients;
7 | import org.springframework.context.annotation.ComponentScan;
8 |
9 | @SpringBootApplication()
10 | @EnableDiscoveryClient
11 | @ComponentScan(basePackages = {"me.liuzeyu"})
12 | @EnableFeignClients(basePackages = {"me.liuzeyu"})
13 | public class Application {
14 |
15 | public static void main(String[] args) {
16 | SpringApplication.run(Application.class, args);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/music-serv/music-impl/src/main/java/me/liuzeyu/aimusic/music/feign/SpleeterService.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.music.feign;
2 |
3 | import me.liuzeyu.aimusic.music.dao.entity.Music;
4 | import me.liuzeyu.aimusic.spleeter.api.beans.SpleeterResponse;
5 | import org.springframework.cloud.openfeign.FeignClient;
6 | import org.springframework.web.bind.annotation.GetMapping;
7 | import org.springframework.web.bind.annotation.PostMapping;
8 | import org.springframework.web.bind.annotation.RequestParam;
9 |
10 | import java.util.Collection;
11 | import java.util.Map;
12 |
13 | @FeignClient(value = "spleeter-serv", path = "/spleeter")
14 | public interface SpleeterService {
15 |
16 | // 创建spleeter-serv干声分离任务
17 | @PostMapping("/request")
18 | SpleeterResponse requestSpleeter(Music music);
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/middleware/gateway/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 30000
3 | error:
4 | include-message: always
5 |
6 | spring:
7 | cloud:
8 | nacos:
9 | discovery:
10 | server-addr: localhost:8848
11 | heart-beat-interval: 5000
12 | heart-beat-timeout: 15000
13 | cluster-name: Cluster-A
14 | namespace: dev
15 | group: myGroup
16 | register-enabled: true
17 | watch:
18 | enabled: true
19 | watch-delay: 30000
20 | gateway:
21 | discovery:
22 | locator:
23 | lower-case-service-id: true
24 | enabled: true
25 |
26 |
27 | management:
28 | endpoints:
29 | web:
30 | exposure:
31 | include: "*"
32 |
33 |
34 | jwt:
35 | secret: JwtSecretKey
36 |
37 | #logging:
38 | # level: debug
--------------------------------------------------------------------------------
/music-client/src/base/no-result/no-ruselt.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
18 |
19 |
36 |
--------------------------------------------------------------------------------
/auth-client/build/static/css/main.33498084.chunk.css:
--------------------------------------------------------------------------------
1 | body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","Roboto","Oxygen","Ubuntu","Cantarell","Fira Sans","Droid Sans","Helvetica Neue",sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}code{font-family:source-code-pro,Menlo,Monaco,Consolas,"Courier New",monospace}.login-container{max-width:420px;margin:40px auto 0;padding:30px 50px 10px;border:1px solid #e1e0e0;background-color:#fff;font-size:32px;font-weight:700;border-radius:10px;text-align:center}.login-form-button{background-color:#639!important}.login-form-button,.login-with-facebook{width:100%;color:#fff!important;font-weight:700!important}.login-with-facebook{background-color:#1877f2!important}body{background-color:#fafafa}.App{padding-top:50px}
2 | /*# sourceMappingURL=main.33498084.chunk.css.map */
--------------------------------------------------------------------------------
/middleware/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | aimusic
7 | me.liuzeyu
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | middleware
13 | pom
14 |
15 | gateway
16 |
17 |
18 |
19 | 8
20 | 8
21 |
22 |
23 |
--------------------------------------------------------------------------------
/music-serv/music-api/src/main/java/me/liuzeyu/aimusic/music/api/enums/StatusType.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.music.api.enums;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Getter;
5 |
6 | import java.util.stream.Stream;
7 |
8 | @Getter
9 | @AllArgsConstructor
10 | public enum StatusType {
11 | PENDING("已提交", "0"),
12 | SPLITTED("干声伴唱分离已完成", "1"),
13 | CONVERTTED("干声翻唱已完成", "2"),
14 | FINISHED("完成", "3"),
15 | FAILED("失败", "-1");
16 |
17 | private String description;
18 |
19 | // 存在数据库里的最终code
20 | private String code;
21 |
22 | public static StatusType convert(String code) {
23 | return Stream.of(values())
24 | .filter(statusType -> statusType.code.equalsIgnoreCase(code))
25 | .findFirst()
26 | .orElse(PENDING);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/music-serv/music-dao/src/main/java/me/liuzeyu/aimusic/music/dao/MusicDao.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.music.dao;
2 |
3 | import jdk.net.SocketFlow;
4 | import me.liuzeyu.aimusic.music.api.enums.StatusType;
5 | import org.springframework.data.jpa.repository.JpaRepository;
6 | import me.liuzeyu.aimusic.music.dao.entity.Music;
7 |
8 | import java.util.List;
9 | import java.util.Optional;
10 |
11 | public interface MusicDao
12 | extends JpaRepository {
13 | List findAllByUser(Long userId);
14 |
15 | Optional findByUserAndHash(Long user, String hash);
16 |
17 | List findByUserNotAndStatus(Long userId, StatusType status);
18 |
19 | List findByUserAndStatusNot(Long userId, StatusType status);
20 |
21 | List findByUserAndStatus(Long userId, StatusType status);
22 | }
23 |
--------------------------------------------------------------------------------
/auth-serv/auth-impl/src/main/java/me/liuzeyu/aimusic/auth/Application.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.auth;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
6 | import org.springframework.cloud.openfeign.EnableFeignClients;
7 | import org.springframework.context.annotation.ComponentScan;
8 | import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
9 |
10 | @SpringBootApplication
11 | @EnableJpaAuditing
12 | @EnableDiscoveryClient
13 | @ComponentScan(basePackages = {"me.liuzeyu"})
14 | //@EnableFeignClients(basePackages = {"me.liuzeyu"})
15 | public class Application {
16 |
17 | public static void main(String[] args) {
18 | SpringApplication.run(Application.class, args);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/music-serv/music-impl/src/main/java/me/liuzeyu/aimusic/music/Application.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.music;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
6 | import org.springframework.cloud.openfeign.EnableFeignClients;
7 | import org.springframework.context.annotation.ComponentScan;
8 | import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
9 |
10 | @SpringBootApplication
11 | @EnableJpaAuditing
12 | @EnableDiscoveryClient
13 | @ComponentScan(basePackages = {"me.liuzeyu"})
14 | @EnableFeignClients(basePackages = {"me.liuzeyu"})
15 | public class Application {
16 |
17 | public static void main(String[] args) {
18 | SpringApplication.run(Application.class, args);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/svc-serv/svc-impl/src/main/java/me/liuzeyu/me/aimusic/svc/controller/SvcController.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.me.aimusic.svc.controller;
2 |
3 | import me.liuzeyu.aimusic.svc.api.beans.Music;
4 | import me.liuzeyu.aimusic.svc.api.beans.SvcResponse;
5 | import lombok.extern.slf4j.Slf4j;
6 | import me.liuzeyu.me.aimusic.svc.event.SvcProducer;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.web.bind.annotation.*;
9 |
10 | import javax.validation.Valid;
11 |
12 | @Slf4j
13 | @RestController
14 | @RequestMapping("svc")
15 | public class SvcController {
16 |
17 | @Autowired
18 | private SvcProducer svcProducer;
19 |
20 | @PostMapping("request")
21 | public SvcResponse request(@Valid @RequestBody Music request) {
22 | log.info("received svc request: data={}", request);
23 | return svcProducer.sendSvc(request);
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/music-client/src/store/mutations.js:
--------------------------------------------------------------------------------
1 | import * as types from './mutation-types'
2 |
3 | const matutaions = {
4 | [types.SET_SINGER](state, singer) {
5 | state.singer = singer
6 | },
7 | [types.SET_PLAYING_STATE] (state, flag) {
8 | state.playing = flag
9 | },
10 | [types.SET_FULL_SCREEN] (state, flag) {
11 | state.fullScreen = flag
12 | },
13 | [types.SET_PLAYLIST] (state, list) {
14 | state.playlist = list
15 | },
16 | [types.SET_SEQUENCE_LIST] (state, list) {
17 | state.sequenceList = list
18 | },
19 | [types.SET_PLAY_MODE] (state, mode) {
20 | state.mode = mode
21 | },
22 | [types.SET_CURRENT_INDEX] (state, index) {
23 | state.currentIndex = index
24 | },
25 | [types.SET_DISC] (state, disc) {
26 | state.disc = disc
27 | },
28 | [types.SET_PLAY_HISTORY] (state, history) {
29 | state.playHistory = history
30 | },
31 | }
32 | export default matutaions
33 |
--------------------------------------------------------------------------------
/svc-serv/svc-impl/src/main/resources/bootstrap.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | application:
3 | # 定义项目名称
4 | name: svc-serv
5 | cloud:
6 | nacos:
7 | config:
8 | # nacos config服务器的地址
9 | server-addr: localhost:8848
10 | file-extension: yml
11 | # prefix: 文件名前缀,默认是spring.application.name
12 | # 如果没有指定命令空间,则默认命令空间为PUBLIC
13 | namespace: dev
14 | # 如果没有配置Group,则默认值为DEFAULT_GROUP
15 | group: myGroup
16 | # 从Nacos读取配置项的超时时间
17 | timeout: 5000
18 | # 长轮询超时时间
19 | config-long-poll-timeout: 10000
20 | # 轮询的重试时间
21 | config-retry-time: 2000
22 | # 长轮询最大重试次数
23 | max-retry: 3
24 | # 开启监听和自动刷新
25 | refresh-enabled: true
26 | # Nacos的扩展配置项,数字越大优先级越高
27 | extension-configs:
28 | - dataId: svc-serv
29 | group: myGroup
30 | refresh: true
31 |
32 |
33 |
--------------------------------------------------------------------------------
/auth-serv/auth-impl/src/main/resources/bootstrap.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | application:
3 | # 定义项目名称
4 | name: auth-serv
5 | cloud:
6 | nacos:
7 | config:
8 | # nacos config服务器的地址
9 | server-addr: localhost:8848
10 | file-extension: yml
11 | # prefix: 文件名前缀,默认是spring.application.name
12 | # 如果没有指定命令空间,则默认命令空间为PUBLIC
13 | namespace: dev
14 | # 如果没有配置Group,则默认值为DEFAULT_GROUP
15 | group: myGroup
16 | # 从Nacos读取配置项的超时时间
17 | timeout: 5000
18 | # 长轮询超时时间
19 | config-long-poll-timeout: 10000
20 | # 轮询的重试时间
21 | config-retry-time: 2000
22 | # 长轮询最大重试次数
23 | max-retry: 3
24 | # 开启监听和自动刷新
25 | refresh-enabled: true
26 | # Nacos的扩展配置项,数字越大优先级越高
27 | extension-configs:
28 | - dataId: auth-serv
29 | group: myGroup
30 | refresh: true
31 |
32 |
33 |
--------------------------------------------------------------------------------
/svc-serv/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | aimusic
7 | me.liuzeyu
8 | 1.0-SNAPSHOT
9 | ../pom.xml
10 |
11 | 4.0.0
12 |
13 | svc-serv
14 | pom
15 |
16 | svc-api
17 | svc-impl
18 |
19 |
20 |
21 | 8
22 | 8
23 |
24 |
25 |
--------------------------------------------------------------------------------
/auth-client/build/precache-manifest.b0af4b5b1697571716dea783d8f44e59.js:
--------------------------------------------------------------------------------
1 | self.__precacheManifest = (self.__precacheManifest || []).concat([
2 | {
3 | "revision": "13b73d782626931091c083d47dd5f337",
4 | "url": "/index.html"
5 | },
6 | {
7 | "revision": "bf9a58768b8b33cdc198",
8 | "url": "/static/css/2.c27a359e.chunk.css"
9 | },
10 | {
11 | "revision": "8f151ea9f3c4ac6fb9f3",
12 | "url": "/static/css/main.33498084.chunk.css"
13 | },
14 | {
15 | "revision": "bf9a58768b8b33cdc198",
16 | "url": "/static/js/2.57ec041c.chunk.js"
17 | },
18 | {
19 | "revision": "3453b8997016469371284a28c0e873e2",
20 | "url": "/static/js/2.57ec041c.chunk.js.LICENSE.txt"
21 | },
22 | {
23 | "revision": "8f151ea9f3c4ac6fb9f3",
24 | "url": "/static/js/main.da9beb79.chunk.js"
25 | },
26 | {
27 | "revision": "d806b24dad39f4cb47a7",
28 | "url": "/static/js/runtime-main.b89670ea.js"
29 | }
30 | ]);
--------------------------------------------------------------------------------
/ffmpeg-serv/ffmpeg-impl/src/main/resources/bootstrap.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | application:
3 | # 定义项目名称
4 | name: ffmpeg-serv
5 | cloud:
6 | nacos:
7 | config:
8 | # nacos config服务器的地址
9 | server-addr: localhost:8848
10 | file-extension: yml
11 | # prefix: 文件名前缀,默认是spring.application.name
12 | # 如果没有指定命令空间,则默认命令空间为PUBLIC
13 | namespace: dev
14 | # 如果没有配置Group,则默认值为DEFAULT_GROUP
15 | group: myGroup
16 | # 从Nacos读取配置项的超时时间
17 | timeout: 5000
18 | # 长轮询超时时间
19 | config-long-poll-timeout: 10000
20 | # 轮询的重试时间
21 | config-retry-time: 2000
22 | # 长轮询最大重试次数
23 | max-retry: 3
24 | # 开启监听和自动刷新
25 | refresh-enabled: true
26 | # Nacos的扩展配置项,数字越大优先级越高
27 | extension-configs:
28 | - dataId: ffmpeg-serv
29 | group: myGroup
30 | refresh: true
31 |
32 |
33 |
--------------------------------------------------------------------------------
/ffmpeg-serv/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | aimusic
7 | me.liuzeyu
8 | 1.0-SNAPSHOT
9 | ../pom.xml
10 |
11 | 4.0.0
12 |
13 | ffmpeg-serv
14 | pom
15 |
16 | ffmpeg-api
17 | ffmpeg-impl
18 |
19 |
20 |
21 | 8
22 | 8
23 |
24 |
25 |
--------------------------------------------------------------------------------
/music-serv/music-impl/src/main/resources/bootstrap.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | application:
3 | # 定义项目名称
4 | name: music-serv
5 | cloud:
6 | nacos:
7 | config:
8 | # nacos config服务器的地址
9 | server-addr: localhost:8848
10 | file-extension: yml
11 | # prefix: 文件名前缀,默认是spring.application.name
12 | # 如果没有指定命令空间,则默认命令空间为PUBLIC
13 | namespace: dev
14 | # 如果没有配置Group,则默认值为DEFAULT_GROUP
15 | group: myGroup
16 | # 从Nacos读取配置项的超时时间
17 | timeout: 5000
18 | # 长轮询超时时间
19 | config-long-poll-timeout: 10000
20 | # 轮询的重试时间
21 | config-retry-time: 2000
22 | # 长轮询最大重试次数
23 | max-retry: 3
24 | # 开启监听和自动刷新
25 | refresh-enabled: true
26 | # Nacos的扩展配置项,数字越大优先级越高
27 | extension-configs:
28 | - dataId: music-serv.yml
29 | group: myGroup
30 | refresh: true
31 |
32 |
33 |
--------------------------------------------------------------------------------
/auth-client/build/signin/precache-manifest.b0af4b5b1697571716dea783d8f44e59.js:
--------------------------------------------------------------------------------
1 | self.__precacheManifest = (self.__precacheManifest || []).concat([
2 | {
3 | "revision": "13b73d782626931091c083d47dd5f337",
4 | "url": "/index.html"
5 | },
6 | {
7 | "revision": "bf9a58768b8b33cdc198",
8 | "url": "/static/css/2.c27a359e.chunk.css"
9 | },
10 | {
11 | "revision": "8f151ea9f3c4ac6fb9f3",
12 | "url": "/static/css/main.33498084.chunk.css"
13 | },
14 | {
15 | "revision": "bf9a58768b8b33cdc198",
16 | "url": "/static/js/2.57ec041c.chunk.js"
17 | },
18 | {
19 | "revision": "3453b8997016469371284a28c0e873e2",
20 | "url": "/static/js/2.57ec041c.chunk.js.LICENSE.txt"
21 | },
22 | {
23 | "revision": "8f151ea9f3c4ac6fb9f3",
24 | "url": "/static/js/main.da9beb79.chunk.js"
25 | },
26 | {
27 | "revision": "d806b24dad39f4cb47a7",
28 | "url": "/static/js/runtime-main.b89670ea.js"
29 | }
30 | ]);
--------------------------------------------------------------------------------
/auth-client/build/signup/precache-manifest.b0af4b5b1697571716dea783d8f44e59.js:
--------------------------------------------------------------------------------
1 | self.__precacheManifest = (self.__precacheManifest || []).concat([
2 | {
3 | "revision": "13b73d782626931091c083d47dd5f337",
4 | "url": "/index.html"
5 | },
6 | {
7 | "revision": "bf9a58768b8b33cdc198",
8 | "url": "/static/css/2.c27a359e.chunk.css"
9 | },
10 | {
11 | "revision": "8f151ea9f3c4ac6fb9f3",
12 | "url": "/static/css/main.33498084.chunk.css"
13 | },
14 | {
15 | "revision": "bf9a58768b8b33cdc198",
16 | "url": "/static/js/2.57ec041c.chunk.js"
17 | },
18 | {
19 | "revision": "3453b8997016469371284a28c0e873e2",
20 | "url": "/static/js/2.57ec041c.chunk.js.LICENSE.txt"
21 | },
22 | {
23 | "revision": "8f151ea9f3c4ac6fb9f3",
24 | "url": "/static/js/main.da9beb79.chunk.js"
25 | },
26 | {
27 | "revision": "d806b24dad39f4cb47a7",
28 | "url": "/static/js/runtime-main.b89670ea.js"
29 | }
30 | ]);
--------------------------------------------------------------------------------
/spleeter-serv/spleeter-impl/src/main/resources/bootstrap.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | application:
3 | # 定义项目名称
4 | name: spleeter-serv
5 | cloud:
6 | nacos:
7 | config:
8 | # nacos config服务器的地址
9 | server-addr: localhost:8848
10 | file-extension: yml
11 | # prefix: 文件名前缀,默认是spring.application.name
12 | # 如果没有指定命令空间,则默认命令空间为PUBLIC
13 | namespace: dev
14 | # 如果没有配置Group,则默认值为DEFAULT_GROUP
15 | group: myGroup
16 | # 从Nacos读取配置项的超时时间
17 | timeout: 5000
18 | # 长轮询超时时间
19 | config-long-poll-timeout: 10000
20 | # 轮询的重试时间
21 | config-retry-time: 2000
22 | # 长轮询最大重试次数
23 | max-retry: 3
24 | # 开启监听和自动刷新
25 | refresh-enabled: true
26 | # Nacos的扩展配置项,数字越大优先级越高
27 | extension-configs:
28 | - dataId: spleeter-serv
29 | group: myGroup
30 | refresh: true
31 |
32 |
33 |
--------------------------------------------------------------------------------
/spleeter-serv/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | aimusic
7 | me.liuzeyu
8 | 1.0-SNAPSHOT
9 | ../pom.xml
10 |
11 | 4.0.0
12 |
13 | spleeter-serv
14 | pom
15 |
16 | spleeter-api
17 | spleeter-impl
18 |
19 |
20 |
21 | 8
22 | 8
23 |
24 |
25 |
--------------------------------------------------------------------------------
/music-serv/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | aimusic
7 | me.liuzeyu
8 | 1.0-SNAPSHOT
9 | ../pom.xml
10 |
11 | 4.0.0
12 |
13 | music-serv
14 | pom
15 |
16 | music-api
17 | music-dao
18 | music-impl
19 |
20 |
21 |
22 | 8
23 | 8
24 |
25 |
26 |
--------------------------------------------------------------------------------
/svc-serv/svc-api/src/main/java/me/liuzeyu/aimusic/svc/api/beans/Music.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.svc.api.beans;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | import javax.validation.constraints.NotNull;
9 | import java.io.Serializable;
10 | import java.util.Date;
11 |
12 | @Data
13 | @NoArgsConstructor
14 | @AllArgsConstructor
15 | @Builder
16 | public class Music implements Serializable {
17 |
18 | @NotNull
19 | private Long id;
20 |
21 | @NotNull
22 | private Long user;
23 |
24 | @NotNull
25 | private String hash;
26 |
27 | @NotNull
28 | private String title;
29 |
30 | @NotNull
31 | private String artist;
32 |
33 | @NotNull
34 | private String ai;
35 |
36 | @NotNull
37 | private String status;
38 |
39 | @NotNull
40 | private Date createdTime;
41 |
42 | @NotNull
43 | private Date updatedTime;
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/spleeter-serv/spleeter-impl/src/main/java/me/liuzeyu/aimusic/spleeter/controller/SpleeterController.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.spleeter.controller;
2 |
3 |
4 | import me.liuzeyu.aimusic.spleeter.api.beans.Music;
5 | import me.liuzeyu.aimusic.spleeter.api.beans.SpleeterResponse;
6 | import me.liuzeyu.aimusic.spleeter.event.SpleeterProducer;
7 | import lombok.extern.slf4j.Slf4j;
8 | import org.springframework.beans.factory.annotation.Autowired;
9 | import org.springframework.web.bind.annotation.*;
10 |
11 | import javax.validation.Valid;
12 |
13 | @Slf4j
14 | @RestController
15 | @RequestMapping("spleeter")
16 | public class SpleeterController {
17 |
18 | @Autowired
19 | private SpleeterProducer spleeterProducer;
20 |
21 | @PostMapping("request")
22 | public SpleeterResponse request(@Valid @RequestBody Music request) {
23 | log.info("received spleeter request: data={}", request);
24 | return spleeterProducer.sendSpleeter(request);
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/ffmpeg-serv/ffmpeg-api/src/main/java/me/liuzeyu/aimusic/ffmpeg/api/beans/Music.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.ffmpeg.api.beans;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | import javax.validation.constraints.NotNull;
9 | import java.io.Serializable;
10 | import java.util.Date;
11 |
12 | @Data
13 | @NoArgsConstructor
14 | @AllArgsConstructor
15 | @Builder
16 | public class Music implements Serializable {
17 |
18 | @NotNull
19 | private Long id;
20 |
21 | @NotNull
22 | private Long user;
23 |
24 | @NotNull
25 | private String hash;
26 |
27 | @NotNull
28 | private String title;
29 |
30 | @NotNull
31 | private String artist;
32 |
33 | @NotNull
34 | private String ai;
35 |
36 | @NotNull
37 | private String status;
38 |
39 | @NotNull
40 | private Date createdTime;
41 |
42 | @NotNull
43 | private Date updatedTime;
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/auth-serv/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | me.liuzeyu
8 | aimusic
9 | 1.0-SNAPSHOT
10 |
11 |
12 | auth-serv
13 | pom
14 |
15 | auth-api
16 | auth-dao
17 | auth-impl
18 |
19 |
20 |
21 | 8
22 | 8
23 | UTF-8
24 |
25 |
26 |
--------------------------------------------------------------------------------
/spleeter-serv/spleeter-api/src/main/java/me/liuzeyu/aimusic/spleeter/api/beans/Music.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.spleeter.api.beans;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | import javax.validation.constraints.NotNull;
9 | import java.io.Serializable;
10 | import java.util.Date;
11 |
12 | @Data
13 | @NoArgsConstructor
14 | @AllArgsConstructor
15 | @Builder
16 | public class Music implements Serializable {
17 |
18 | @NotNull
19 | private Long id;
20 |
21 | @NotNull
22 | private Long user;
23 |
24 | @NotNull
25 | private String hash;
26 |
27 | @NotNull
28 | private String title;
29 |
30 | @NotNull
31 | private String artist;
32 |
33 | @NotNull
34 | private String ai;
35 |
36 | @NotNull
37 | private String status;
38 |
39 | @NotNull
40 | private Date createdTime;
41 |
42 | @NotNull
43 | private Date updatedTime;
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/svc-serv/svc-impl/src/main/java/me/liuzeyu/me/aimusic/svc/event/SvcProducer.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.me.aimusic.svc.event;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import me.liuzeyu.aimusic.svc.api.beans.Music;
5 | import me.liuzeyu.aimusic.svc.api.beans.SvcResponse;
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.cloud.stream.function.StreamBridge;
8 | import org.springframework.stereotype.Service;
9 |
10 | import javax.validation.Valid;
11 |
12 | @Service
13 | @Slf4j
14 | public class SvcProducer {
15 | @Autowired
16 | private StreamBridge streamBridge;
17 |
18 | public SvcResponse sendSvc(@Valid Music music) {
19 | log.info("sent: {}", music);
20 | try {
21 | streamBridge.send(EventConstant.ADD_SVC_EVENT, music);
22 | return SvcResponse.builder().status("ok").build();
23 | } catch (Exception e) {
24 | return SvcResponse.builder().status(e.toString()).build();
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/spleeter-serv/spleeter-impl/src/main/java/me/liuzeyu/aimusic/spleeter/event/SpleeterProducer.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.spleeter.event;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import me.liuzeyu.aimusic.spleeter.api.beans.Music;
5 | import me.liuzeyu.aimusic.spleeter.api.beans.SpleeterResponse;
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.cloud.stream.function.StreamBridge;
8 | import org.springframework.stereotype.Service;
9 |
10 | @Service
11 | @Slf4j
12 | public class SpleeterProducer {
13 | @Autowired
14 | private StreamBridge streamBridge;
15 |
16 | public SpleeterResponse sendSpleeter(Music music) {
17 | log.info("sent: {}", music);
18 | try {
19 | streamBridge.send(EventConstant.ADD_SPLEETER_EVENT, music);
20 | return SpleeterResponse.builder().status("ok").build();
21 | } catch (Exception e) {
22 | return SpleeterResponse.builder().status(e.toString()).build();
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/ffmpeg-serv/ffmpeg-impl/src/main/java/me/liuzeyu/aimusic/ffmpeg/event/FfmpegProducer.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.ffmpeg.event;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import me.liuzeyu.aimusic.ffmpeg.api.beans.Music;
5 | import me.liuzeyu.aimusic.ffmpeg.api.beans.FfmpegResponse;
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.cloud.stream.function.StreamBridge;
8 | import org.springframework.stereotype.Service;
9 |
10 | import javax.validation.Valid;
11 |
12 | @Service
13 | @Slf4j
14 | public class FfmpegProducer {
15 | @Autowired
16 | private StreamBridge streamBridge;
17 |
18 | public FfmpegResponse sendFfmpeg(@Valid Music music) {
19 | log.info("sent: {}", music);
20 | try {
21 | streamBridge.send(EventConstant.ADD_FFMPEG_EVENT, music);
22 | return FfmpegResponse.builder().status("ok").build();
23 | } catch (Exception e) {
24 | return FfmpegResponse.builder().status(e.toString()).build();
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/auth-serv/auth-impl/src/main/java/me/liuzeyu/aimusic/auth/service/MusicUserDetailsService.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.auth.service;
2 |
3 | import me.liuzeyu.aimusic.auth.api.beans.MusicUserDetails;
4 | import me.liuzeyu.aimusic.auth.service.intf.UserService;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.security.core.userdetails.UserDetailsService;
7 | import org.springframework.stereotype.Service;
8 | import org.springframework.security.core.userdetails.UsernameNotFoundException;
9 |
10 |
11 | @Service
12 | public class MusicUserDetailsService implements UserDetailsService {
13 |
14 | @Autowired
15 | private UserService userService;
16 |
17 | @Override
18 | public MusicUserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
19 |
20 | return userService
21 | .findByUsername(username)
22 | .map(MusicUserDetails::new)
23 | .orElseThrow(() -> new UsernameNotFoundException("Username not found"));
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/auth-client/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ai-music-login-client",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@ant-design/icons": "^4.2.1",
7 | "@testing-library/jest-dom": "^4.2.4",
8 | "@testing-library/react": "^9.5.0",
9 | "@testing-library/user-event": "^7.2.1",
10 | "antd": "^4.4.0",
11 | "react": "^16.13.1",
12 | "react-dom": "^16.13.1",
13 | "react-router": "^5.2.0",
14 | "react-router-dom": "^5.2.0",
15 | "react-scripts": "3.4.1"
16 | },
17 | "proxy": "http://localhost:30000",
18 | "scripts": {
19 | "start": "react-scripts start",
20 | "build": "react-scripts build",
21 | "test": "react-scripts test",
22 | "eject": "react-scripts eject"
23 | },
24 | "eslintConfig": {
25 | "extends": "react-app"
26 | },
27 | "browserslist": {
28 | "production": [
29 | ">0.2%",
30 | "not dead",
31 | "not op_mini all"
32 | ],
33 | "development": [
34 | "last 1 chrome version",
35 | "last 1 firefox version",
36 | "last 1 safari version"
37 | ]
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | pom.xml.tag
3 | pom.xml.releaseBackup
4 | pom.xml.versionsBackup
5 | pom.xml.next
6 | release.properties
7 | dependency-reduced-pom.xml
8 | buildNumber.properties
9 | .mvn/timing.properties
10 | # https://github.com/takari/maven-wrapper#usage-without-binary-jar
11 | .mvn/wrapper/maven-wrapper.jar
12 |
13 | # Eclipse m2e generated files
14 | # Eclipse Core
15 | .project
16 | # JDT-specific (Eclipse Java Development Tools)
17 | .classpath
18 |
19 |
20 | .DS_Store
21 | node_modules/
22 | /dist/
23 | npm-debug.log*
24 | yarn-debug.log*
25 | yarn-error.log*
26 |
27 | # Editor directories and files
28 | .idea
29 | .vscode
30 | *.suo
31 | *.ntvs*
32 | *.njsproj
33 | *.sln
34 |
35 |
36 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
37 |
38 | # dependencies
39 | /node_modules
40 | /.pnp
41 | .pnp.js
42 |
43 | # testing
44 | /coverage
45 |
46 | # production
47 | /build
48 |
49 | # misc
50 | .DS_Store
51 | .env.local
52 | .env.development.local
53 | .env.test.local
54 | .env.production.local
55 |
56 | npm-debug.log*
57 | yarn-debug.log*
58 | yarn-error.log*
59 |
--------------------------------------------------------------------------------
/auth-client/src/util/ApiUtil.js:
--------------------------------------------------------------------------------
1 | const request = (options) => {
2 | const headers = new Headers();
3 |
4 | if (options.setContentType !== false) {
5 | headers.append("Content-Type", "application/json");
6 | }
7 |
8 | if (localStorage.getItem("accessToken")) {
9 | headers.append(
10 | "Authorization",
11 | "Bearer " + localStorage.getItem("accessToken")
12 | );
13 | }
14 |
15 | const defaults = { headers: headers };
16 | options = Object.assign({}, defaults, options);
17 |
18 | return fetch(options.url, options).then((response) =>
19 | response.json().then((json) => {
20 | if (!response.ok) {
21 | return Promise.reject(json);
22 | }
23 | return json;
24 | })
25 | );
26 | };
27 |
28 | export function login(loginRequest) {
29 | return request({
30 | url: "/api/user/signin",
31 | method: "POST",
32 | body: JSON.stringify(loginRequest),
33 | });
34 | }
35 |
36 | export function signup(signupRequest) {
37 | return request({
38 | url: "/api/user/signup",
39 | method: "POST",
40 | body: JSON.stringify(signupRequest),
41 | });
42 | }
43 |
44 |
--------------------------------------------------------------------------------
/ffmpeg-serv/ffmpeg-impl/src/main/java/me/liuzeyu/aimusic/ffmpeg/controller/FfmpegController.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.ffmpeg.controller;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import me.liuzeyu.aimusic.ffmpeg.api.beans.Music;
5 | import me.liuzeyu.aimusic.ffmpeg.api.beans.FfmpegResponse;
6 | import me.liuzeyu.aimusic.ffmpeg.event.FfmpegProducer;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.web.bind.annotation.PostMapping;
9 | import org.springframework.web.bind.annotation.RequestBody;
10 | import org.springframework.web.bind.annotation.RequestMapping;
11 | import org.springframework.web.bind.annotation.RestController;
12 |
13 | import javax.validation.Valid;
14 |
15 | @Slf4j
16 | @RestController
17 | @RequestMapping("ffmpeg")
18 | public class FfmpegController {
19 | @Autowired
20 | private FfmpegProducer ffmpegProducer;
21 |
22 | @PostMapping("request")
23 | public FfmpegResponse request(@Valid @RequestBody Music request) {
24 | log.info("received svc request: data={}", request);
25 | return ffmpegProducer.sendFfmpeg(request);
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/music-client/src/base/top-tip/top-tip.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
36 |
37 |
51 |
--------------------------------------------------------------------------------
/auth-serv/auth-api/src/main/java/me/liuzeyu/aimusic/auth/api/beans/MusicUserDetails.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.auth.api.beans;
2 |
3 | import me.liuzeyu.aimusic.auth.dao.entity.User;
4 | import org.springframework.security.core.GrantedAuthority;
5 | import org.springframework.security.core.userdetails.UserDetails;
6 |
7 | import java.util.Collection;
8 | import java.util.Collections;
9 |
10 | public class MusicUserDetails extends User implements UserDetails {
11 | public MusicUserDetails(final User user) {
12 | super(user);
13 | }
14 |
15 | @Override
16 | public Collection extends GrantedAuthority> getAuthorities() {
17 | return Collections.emptySet();
18 | }
19 |
20 | @Override
21 | public boolean isAccountNonExpired() {
22 | return isActive();
23 | }
24 |
25 | @Override
26 | public boolean isAccountNonLocked() {
27 | return isActive();
28 | }
29 |
30 | @Override
31 | public boolean isCredentialsNonExpired() {
32 | return isActive();
33 | }
34 |
35 | @Override
36 | public boolean isEnabled() {
37 | return isActive();
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/music-client/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Router from 'vue-router'
3 |
4 | Vue.use(Router)
5 | const Other = resolve => {
6 | import('../pages/other/other').then((module) => {
7 | resolve(module)
8 | })
9 | }
10 |
11 | const Pending = resolve => {
12 | import('../pages/pending/pending').then((module) => {
13 | resolve(module)
14 | })
15 | }
16 |
17 | const Finished = resolve => {
18 | import('../pages/finished/finished').then((module) => {
19 | resolve(module)
20 | })
21 | }
22 |
23 | const Create = resolve => {
24 | import('../pages/create/create').then((module) => {
25 | resolve(module)
26 | })
27 | }
28 |
29 | export default new Router({
30 | routes: [
31 | {
32 | path: '/',
33 | redirect: '/other',
34 | },
35 | {
36 | path: '/other',
37 | component: Other,
38 | },
39 | {
40 | path: '/pending',
41 | component: Pending,
42 | },
43 | {
44 | path: '/finished',
45 | component: Finished,
46 | },
47 | {
48 | path: '/create',
49 | component: Create,
50 | },
51 | ]
52 | })
53 |
--------------------------------------------------------------------------------
/music-client/src/components/tab/tab.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 随便听听
5 |
6 |
7 | 已完成
8 |
9 |
10 | 待完成
11 |
12 |
13 | 创建翻唱
14 |
15 |
16 |
17 |
18 |
23 |
24 |
42 |
--------------------------------------------------------------------------------
/music-client/src/base/switches/switches.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
6 | {{item.name}}
7 |
8 |
9 |
10 |
11 |
32 |
33 |
53 |
--------------------------------------------------------------------------------
/music-client/.eslintrc.js:
--------------------------------------------------------------------------------
1 | // https://eslint.org/docs/user-guide/configuring
2 |
3 | module.exports = {
4 | root: true,
5 | parserOptions: {
6 | parser: 'babel-eslint'
7 | },
8 | env: {
9 | browser: true,
10 | },
11 | extends: [
12 | // https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention
13 | // consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules.
14 | 'plugin:vue/essential',
15 | // https://github.com/standard/standard/blob/master/docs/RULES-en.md
16 | 'standard'
17 | ],
18 | // required to lint *.vue files
19 | plugins: [
20 | 'vue'
21 | ],
22 | // add your custom rules here
23 | rules: {
24 | // allow async-await
25 | //'generator-star-spacing': 'off',
26 | // allow debugger during development
27 | //'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
28 | // allow paren-less arrow functions
29 | 'arrow-parens': 0,
30 | // allow async-await
31 | 'generator-star-spacing': 0,
32 | // allow debugger during development
33 | 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
34 | 'eol-last': 0,
35 | 'space-before-function-paren': 0
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/auth-client/build/asset-manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "files": {
3 | "main.css": "/static/css/main.33498084.chunk.css",
4 | "main.js": "/static/js/main.da9beb79.chunk.js",
5 | "main.js.map": "/static/js/main.da9beb79.chunk.js.map",
6 | "runtime-main.js": "/static/js/runtime-main.b89670ea.js",
7 | "runtime-main.js.map": "/static/js/runtime-main.b89670ea.js.map",
8 | "static/css/2.c27a359e.chunk.css": "/static/css/2.c27a359e.chunk.css",
9 | "static/js/2.57ec041c.chunk.js": "/static/js/2.57ec041c.chunk.js",
10 | "static/js/2.57ec041c.chunk.js.map": "/static/js/2.57ec041c.chunk.js.map",
11 | "index.html": "/index.html",
12 | "precache-manifest.b0af4b5b1697571716dea783d8f44e59.js": "/precache-manifest.b0af4b5b1697571716dea783d8f44e59.js",
13 | "service-worker.js": "/service-worker.js",
14 | "static/css/2.c27a359e.chunk.css.map": "/static/css/2.c27a359e.chunk.css.map",
15 | "static/css/main.33498084.chunk.css.map": "/static/css/main.33498084.chunk.css.map",
16 | "static/js/2.57ec041c.chunk.js.LICENSE.txt": "/static/js/2.57ec041c.chunk.js.LICENSE.txt"
17 | },
18 | "entrypoints": [
19 | "static/js/runtime-main.b89670ea.js",
20 | "static/css/2.c27a359e.chunk.css",
21 | "static/js/2.57ec041c.chunk.js",
22 | "static/css/main.33498084.chunk.css",
23 | "static/js/main.da9beb79.chunk.js"
24 | ]
25 | }
--------------------------------------------------------------------------------
/auth-client/build/signin/asset-manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "files": {
3 | "main.css": "/static/css/main.33498084.chunk.css",
4 | "main.js": "/static/js/main.da9beb79.chunk.js",
5 | "main.js.map": "/static/js/main.da9beb79.chunk.js.map",
6 | "runtime-main.js": "/static/js/runtime-main.b89670ea.js",
7 | "runtime-main.js.map": "/static/js/runtime-main.b89670ea.js.map",
8 | "static/css/2.c27a359e.chunk.css": "/static/css/2.c27a359e.chunk.css",
9 | "static/js/2.57ec041c.chunk.js": "/static/js/2.57ec041c.chunk.js",
10 | "static/js/2.57ec041c.chunk.js.map": "/static/js/2.57ec041c.chunk.js.map",
11 | "index.html": "/index.html",
12 | "precache-manifest.b0af4b5b1697571716dea783d8f44e59.js": "/precache-manifest.b0af4b5b1697571716dea783d8f44e59.js",
13 | "service-worker.js": "/service-worker.js",
14 | "static/css/2.c27a359e.chunk.css.map": "/static/css/2.c27a359e.chunk.css.map",
15 | "static/css/main.33498084.chunk.css.map": "/static/css/main.33498084.chunk.css.map",
16 | "static/js/2.57ec041c.chunk.js.LICENSE.txt": "/static/js/2.57ec041c.chunk.js.LICENSE.txt"
17 | },
18 | "entrypoints": [
19 | "static/js/runtime-main.b89670ea.js",
20 | "static/css/2.c27a359e.chunk.css",
21 | "static/js/2.57ec041c.chunk.js",
22 | "static/css/main.33498084.chunk.css",
23 | "static/js/main.da9beb79.chunk.js"
24 | ]
25 | }
--------------------------------------------------------------------------------
/auth-client/build/signup/asset-manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "files": {
3 | "main.css": "/static/css/main.33498084.chunk.css",
4 | "main.js": "/static/js/main.da9beb79.chunk.js",
5 | "main.js.map": "/static/js/main.da9beb79.chunk.js.map",
6 | "runtime-main.js": "/static/js/runtime-main.b89670ea.js",
7 | "runtime-main.js.map": "/static/js/runtime-main.b89670ea.js.map",
8 | "static/css/2.c27a359e.chunk.css": "/static/css/2.c27a359e.chunk.css",
9 | "static/js/2.57ec041c.chunk.js": "/static/js/2.57ec041c.chunk.js",
10 | "static/js/2.57ec041c.chunk.js.map": "/static/js/2.57ec041c.chunk.js.map",
11 | "index.html": "/index.html",
12 | "precache-manifest.b0af4b5b1697571716dea783d8f44e59.js": "/precache-manifest.b0af4b5b1697571716dea783d8f44e59.js",
13 | "service-worker.js": "/service-worker.js",
14 | "static/css/2.c27a359e.chunk.css.map": "/static/css/2.c27a359e.chunk.css.map",
15 | "static/css/main.33498084.chunk.css.map": "/static/css/main.33498084.chunk.css.map",
16 | "static/js/2.57ec041c.chunk.js.LICENSE.txt": "/static/js/2.57ec041c.chunk.js.LICENSE.txt"
17 | },
18 | "entrypoints": [
19 | "static/js/runtime-main.b89670ea.js",
20 | "static/css/2.c27a359e.chunk.css",
21 | "static/js/2.57ec041c.chunk.js",
22 | "static/css/main.33498084.chunk.css",
23 | "static/js/main.da9beb79.chunk.js"
24 | ]
25 | }
--------------------------------------------------------------------------------
/svc-serv/svc-impl/src/main/java/me/liuzeyu/me/aimusic/svc/caculator/CalculationFactory.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.me.aimusic.svc.caculator;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import me.liuzeyu.aimusic.svc.api.beans.Music;
5 | import me.liuzeyu.me.aimusic.svc.caculator.impl.SunyanziSvc;
6 | import me.liuzeyu.me.aimusic.svc.caculator.impl.ZhangxueyouSvc;
7 | import me.liuzeyu.me.aimusic.svc.caculator.impl.ZhoujielunSvc;
8 | import org.springframework.beans.factory.annotation.Autowired;
9 | import org.springframework.stereotype.Component;
10 |
11 | @Component
12 | @Slf4j
13 | public class CalculationFactory {
14 |
15 | @Autowired
16 | private SunyanziSvc sunyanziSvc;
17 |
18 | @Autowired
19 | private ZhangxueyouSvc zhangxueyouSvc;
20 |
21 | @Autowired
22 | private ZhoujielunSvc zhoujielunSvc;
23 |
24 | public SvcTemplate getSvc(Music music) {
25 | String ai = music.getAi();
26 |
27 | switch (ai) {
28 | // 孙燕姿
29 | case "孙燕姿":
30 | return sunyanziSvc;
31 | // 张学友
32 | case "张学友":
33 | return zhangxueyouSvc;
34 | // 周杰伦
35 | case "周杰伦":
36 | return zhoujielunSvc;
37 | // default
38 | default:
39 | return sunyanziSvc;
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/auth-client/build/service-worker.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Welcome to your Workbox-powered service worker!
3 | *
4 | * You'll need to register this file in your web app and you should
5 | * disable HTTP caching for this file too.
6 | * See https://goo.gl/nhQhGp
7 | *
8 | * The rest of the code is auto-generated. Please don't update this file
9 | * directly; instead, make changes to your Workbox build configuration
10 | * and re-run your build process.
11 | * See https://goo.gl/2aRDsh
12 | */
13 |
14 | importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js");
15 |
16 | importScripts(
17 | "/precache-manifest.b0af4b5b1697571716dea783d8f44e59.js"
18 | );
19 |
20 | self.addEventListener('message', (event) => {
21 | if (event.data && event.data.type === 'SKIP_WAITING') {
22 | self.skipWaiting();
23 | }
24 | });
25 |
26 | workbox.core.clientsClaim();
27 |
28 | /**
29 | * The workboxSW.precacheAndRoute() method efficiently caches and responds to
30 | * requests for URLs in the manifest.
31 | * See https://goo.gl/S9QRab
32 | */
33 | self.__precacheManifest = [].concat(self.__precacheManifest || []);
34 | workbox.precaching.precacheAndRoute(self.__precacheManifest, {});
35 |
36 | workbox.routing.registerNavigationRoute(workbox.precaching.getCacheKeyForURL("/index.html"), {
37 |
38 | blacklist: [/^\/_/,/\/[^/?]+\.[^/]+$/],
39 | });
40 |
--------------------------------------------------------------------------------
/auth-client/build/signin/service-worker.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Welcome to your Workbox-powered service worker!
3 | *
4 | * You'll need to register this file in your web app and you should
5 | * disable HTTP caching for this file too.
6 | * See https://goo.gl/nhQhGp
7 | *
8 | * The rest of the code is auto-generated. Please don't update this file
9 | * directly; instead, make changes to your Workbox build configuration
10 | * and re-run your build process.
11 | * See https://goo.gl/2aRDsh
12 | */
13 |
14 | importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js");
15 |
16 | importScripts(
17 | "/precache-manifest.b0af4b5b1697571716dea783d8f44e59.js"
18 | );
19 |
20 | self.addEventListener('message', (event) => {
21 | if (event.data && event.data.type === 'SKIP_WAITING') {
22 | self.skipWaiting();
23 | }
24 | });
25 |
26 | workbox.core.clientsClaim();
27 |
28 | /**
29 | * The workboxSW.precacheAndRoute() method efficiently caches and responds to
30 | * requests for URLs in the manifest.
31 | * See https://goo.gl/S9QRab
32 | */
33 | self.__precacheManifest = [].concat(self.__precacheManifest || []);
34 | workbox.precaching.precacheAndRoute(self.__precacheManifest, {});
35 |
36 | workbox.routing.registerNavigationRoute(workbox.precaching.getCacheKeyForURL("/index.html"), {
37 |
38 | blacklist: [/^\/_/,/\/[^/?]+\.[^/]+$/],
39 | });
40 |
--------------------------------------------------------------------------------
/auth-client/build/signup/service-worker.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Welcome to your Workbox-powered service worker!
3 | *
4 | * You'll need to register this file in your web app and you should
5 | * disable HTTP caching for this file too.
6 | * See https://goo.gl/nhQhGp
7 | *
8 | * The rest of the code is auto-generated. Please don't update this file
9 | * directly; instead, make changes to your Workbox build configuration
10 | * and re-run your build process.
11 | * See https://goo.gl/2aRDsh
12 | */
13 |
14 | importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js");
15 |
16 | importScripts(
17 | "/precache-manifest.b0af4b5b1697571716dea783d8f44e59.js"
18 | );
19 |
20 | self.addEventListener('message', (event) => {
21 | if (event.data && event.data.type === 'SKIP_WAITING') {
22 | self.skipWaiting();
23 | }
24 | });
25 |
26 | workbox.core.clientsClaim();
27 |
28 | /**
29 | * The workboxSW.precacheAndRoute() method efficiently caches and responds to
30 | * requests for URLs in the manifest.
31 | * See https://goo.gl/S9QRab
32 | */
33 | self.__precacheManifest = [].concat(self.__precacheManifest || []);
34 | workbox.precaching.precacheAndRoute(self.__precacheManifest, {});
35 |
36 | workbox.routing.registerNavigationRoute(workbox.precaching.getCacheKeyForURL("/index.html"), {
37 |
38 | blacklist: [/^\/_/,/\/[^/?]+\.[^/]+$/],
39 | });
40 |
--------------------------------------------------------------------------------
/music-client/build/build.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | require('./check-versions')()
3 |
4 | process.env.NODE_ENV = 'production'
5 |
6 | const ora = require('ora')
7 | const rm = require('rimraf')
8 | const path = require('path')
9 | const chalk = require('chalk')
10 | const webpack = require('webpack')
11 | const config = require('../config')
12 | const webpackConfig = require('./webpack.prod.conf')
13 |
14 | const spinner = ora('building for production...')
15 | spinner.start()
16 |
17 | rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
18 | if (err) throw err
19 | webpack(webpackConfig, (err, stats) => {
20 | spinner.stop()
21 | if (err) throw err
22 | process.stdout.write(stats.toString({
23 | colors: true,
24 | modules: false,
25 | children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
26 | chunks: false,
27 | chunkModules: false
28 | }) + '\n\n')
29 |
30 | if (stats.hasErrors()) {
31 | console.log(chalk.red(' Build failed with errors.\n'))
32 | process.exit(1)
33 | }
34 |
35 | console.log(chalk.cyan(' Build complete.\n'))
36 | console.log(chalk.yellow(
37 | ' Tip: built files are meant to be served over an HTTP server.\n' +
38 | ' Opening index.html over file:// won\'t work.\n'
39 | ))
40 | })
41 | })
42 |
--------------------------------------------------------------------------------
/music-client/src/components/m-header/m-header.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
20 |
21 |
55 |
--------------------------------------------------------------------------------
/music-client/src/base/progress-circle/progress-circle.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
10 |
11 |
35 |
36 |
51 |
--------------------------------------------------------------------------------
/auth-client/build/static/js/2.57ec041c.chunk.js.LICENSE.txt:
--------------------------------------------------------------------------------
1 | /*
2 | object-assign
3 | (c) Sindre Sorhus
4 | @license MIT
5 | */
6 |
7 | /*!
8 | Copyright (c) 2017 Jed Watson.
9 | Licensed under the MIT License (MIT), see
10 | http://jedwatson.github.io/classnames
11 | */
12 |
13 | /** @license React v0.19.1
14 | * scheduler.production.min.js
15 | *
16 | * Copyright (c) Facebook, Inc. and its affiliates.
17 | *
18 | * This source code is licensed under the MIT license found in the
19 | * LICENSE file in the root directory of this source tree.
20 | */
21 |
22 | /** @license React v16.13.1
23 | * react-dom.production.min.js
24 | *
25 | * Copyright (c) Facebook, Inc. and its affiliates.
26 | *
27 | * This source code is licensed under the MIT license found in the
28 | * LICENSE file in the root directory of this source tree.
29 | */
30 |
31 | /** @license React v16.13.1
32 | * react-is.production.min.js
33 | *
34 | * Copyright (c) Facebook, Inc. and its affiliates.
35 | *
36 | * This source code is licensed under the MIT license found in the
37 | * LICENSE file in the root directory of this source tree.
38 | */
39 |
40 | /** @license React v16.13.1
41 | * react.production.min.js
42 | *
43 | * Copyright (c) Facebook, Inc. and its affiliates.
44 | *
45 | * This source code is licensed under the MIT license found in the
46 | * LICENSE file in the root directory of this source tree.
47 | */
48 |
--------------------------------------------------------------------------------
/music-client/src/common/js/dom.js:
--------------------------------------------------------------------------------
1 | // import { getDefaultSettings } from "http2";
2 |
3 | export function addClass(el, className) {
4 | if (hasClass(el, className)) {
5 | return
6 | }
7 | let newClass = el.className.split(' ')
8 | newClass.push(className)
9 | el.className = newClass.join(' ')
10 | }
11 |
12 | export function hasClass(el, className) {
13 | let reg = new RegExp('(^|\\s)' + className + '(\\s|$)')
14 | return reg.test(el.className)
15 | }
16 |
17 | export function getData(el, name, val) {
18 | const prefix = 'data-'
19 | name = prefix + name
20 | if (val) {
21 | return el.setAttribute(name, val)
22 | } else {
23 | return el.getAttribute(name)
24 | }
25 | }
26 |
27 | let elementStyle = document.createElement('div').style
28 | let vendor = (() => {
29 | let transformNames = {
30 | webkit: 'webkitTransform',
31 | Moz: 'MozTransform',
32 | O: 'OTransform',
33 | ms: 'msTransform',
34 | standard: 'transform'
35 | }
36 |
37 | for (let key in transformNames) {
38 | if (elementStyle[transformNames[key]] !== undefined) {
39 | return key
40 | }
41 | }
42 |
43 | return false
44 | })()
45 |
46 | export function prefixStyle(style) {
47 | if (vendor === false) {
48 | return false
49 | }
50 |
51 | if (vendor === 'standard') {
52 | return style
53 | }
54 | return vendor + style.charAt(0).toUpperCase() + style.substr(1)
55 | }
56 |
--------------------------------------------------------------------------------
/user.sql:
--------------------------------------------------------------------------------
1 | /*
2 | Navicat Premium Data Transfer
3 |
4 | Source Server : mysql
5 | Source Server Type : MySQL
6 | Source Server Version : 80033
7 | Source Host : localhost:3306
8 | Source Schema : ai_music_db
9 |
10 | Target Server Type : MySQL
11 | Target Server Version : 80033
12 | File Encoding : 65001
13 |
14 | Date: 05/06/2023 23:46:43
15 | */
16 |
17 | SET NAMES utf8mb4;
18 | SET FOREIGN_KEY_CHECKS = 0;
19 |
20 | -- ----------------------------
21 | -- Table structure for user
22 | -- ----------------------------
23 | DROP TABLE IF EXISTS `user`;
24 | CREATE TABLE `user` (
25 | `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
26 | `username` varchar(32) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT '用户名',
27 | `password` varchar(80) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT '密码',
28 | `email` varchar(40) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT 'email',
29 | `active` tinyint(1) NOT NULL COMMENT '启用',
30 | `created_time` datetime(0) NOT NULL COMMENT '创建时间',
31 | `updated_time` datetime(0) NOT NULL COMMENT '修改时间',
32 | PRIMARY KEY (`id`) USING BTREE,
33 | INDEX `idx_username`(`username`) USING BTREE,
34 | INDEX `idx_email`(`email`) USING BTREE
35 | ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci COMMENT = '用户' ROW_FORMAT = Dynamic;
36 |
37 | SET FOREIGN_KEY_CHECKS = 1;
38 |
--------------------------------------------------------------------------------
/music-client/src/api/other.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 |
3 | function parseJwt (token) {
4 | var base64Url = token.split('.')[1]
5 | var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/')
6 | var jsonPayload = decodeURIComponent(window.atob(base64).split('').map(function(c) {
7 | return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
8 | }).join(''))
9 |
10 | return JSON.parse(jsonPayload)
11 | }
12 |
13 | export async function getOther() {
14 | const token = localStorage.getItem('accessToken')
15 | if (token) {
16 | const jwt = parseJwt(token)
17 | const id = jwt.id
18 | const response = await axios.get('/api/music/other', {
19 | params: { id },
20 | headers: {
21 | 'Authorization': `Bearer ${token}`
22 | }
23 | })
24 | response.data.list.forEach(
25 | (item, index, arr) => {
26 | if (item.ai == '周杰伦') {
27 | arr[index].cover = "http://asset.liuzeyu.me/zhoujielun.png"
28 | } else if (item.ai == '孙燕姿') {
29 | arr[index].cover = "http://asset.liuzeyu.me/sunyanzi.png"
30 | } else if (item.ai == '张学友') {
31 | arr[index].cover = "http://asset.liuzeyu.me/zhangxueyou.png"
32 | }
33 | }
34 | )
35 | return response.data.list
36 | } else {
37 | window.location.href = '/signin';
38 | }
39 | return []
40 | }
--------------------------------------------------------------------------------
/music-client/src/common/stylus/reset.styl:
--------------------------------------------------------------------------------
1 | /**
2 | * Eric Meyer's Reset CSS v2.0 (http://meyerweb.com/eric/tools/css/reset/)
3 | * http://cssreset.com
4 | */
5 | html, body, div, span, applet, object, iframe,
6 | h1, h2, h3, h4, h5, h6, p, blockquote, pre,
7 | a, abbr, acronym, address, big, cite, code,
8 | del, dfn, em, img, ins, kbd, q, s, samp,
9 | small, strike, strong, sub, sup, tt, var,
10 | b, u, i, center,
11 | dl, dt, dd, ol, ul, li,
12 | fieldset, form, label, legend,
13 | table, caption, tbody, tfoot, thead, tr, th, td,
14 | article, aside, canvas, details, embed,
15 | figure, figcaption, footer, header,
16 | menu, nav, output, ruby, section, summary,
17 | time, mark, audio, video, input
18 | margin: 0
19 | padding: 0
20 | border: 0
21 | font-size: 100%
22 | font-weight: normal
23 | vertical-align: baseline
24 |
25 | /* HTML5 display-role reset for older browsers */
26 | article, aside, details, figcaption, figure,
27 | footer, header, menu, nav, section
28 | display: block
29 |
30 | body
31 | line-height: 1
32 |
33 | blockquote, q
34 | quotes: none
35 |
36 | blockquote:before, blockquote:after,
37 | q:before, q:after
38 | content: none
39 |
40 | table
41 | border-collapse: collapse
42 | border-spacing: 0
43 |
44 | /* custom */
45 |
46 | a
47 | color: #7e8c8d
48 | -webkit-backface-visibility: hidden
49 | text-decoration: none
50 |
51 | li
52 | list-style: none
53 |
54 | body
55 | -webkit-text-size-adjust: none
56 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0)
57 |
--------------------------------------------------------------------------------
/music-client/src/api/finished.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 |
3 | function parseJwt (token) {
4 | var base64Url = token.split('.')[1]
5 | var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/')
6 | var jsonPayload = decodeURIComponent(window.atob(base64).split('').map(function(c) {
7 | return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
8 | }).join(''))
9 |
10 | return JSON.parse(jsonPayload)
11 | }
12 |
13 | export async function getFinished() {
14 | const token = localStorage.getItem('accessToken')
15 | if (token) {
16 | const jwt = parseJwt(token)
17 | const id = jwt.id
18 | const response = await axios.get('/api/music/finished', {
19 | params: { id },
20 | headers: {
21 | 'Authorization': `Bearer ${token}`
22 | }
23 | })
24 | response.data.list.forEach(
25 | (item, index, arr) => {
26 | if (item.ai == '周杰伦') {
27 | arr[index].cover = "http://asset.liuzeyu.me/zhoujielun.png"
28 | } else if (item.ai == '孙燕姿') {
29 | arr[index].cover = "http://asset.liuzeyu.me/sunyanzi.png"
30 | } else if (item.ai == '张学友') {
31 | arr[index].cover = "http://asset.liuzeyu.me/zhangxueyou.png"
32 | }
33 | }
34 | )
35 | return response.data.list
36 | } else {
37 | window.location.href = '/signin';
38 | }
39 | return []
40 | }
--------------------------------------------------------------------------------
/music-client/build/check-versions.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const chalk = require('chalk')
3 | const semver = require('semver')
4 | const packageConfig = require('../package.json')
5 | const shell = require('shelljs')
6 |
7 | function exec (cmd) {
8 | return require('child_process').execSync(cmd).toString().trim()
9 | }
10 |
11 | const versionRequirements = [
12 | {
13 | name: 'node',
14 | currentVersion: semver.clean(process.version),
15 | versionRequirement: packageConfig.engines.node
16 | }
17 | ]
18 |
19 | if (shell.which('npm')) {
20 | versionRequirements.push({
21 | name: 'npm',
22 | currentVersion: exec('npm --version'),
23 | versionRequirement: packageConfig.engines.npm
24 | })
25 | }
26 |
27 | module.exports = function () {
28 | const warnings = []
29 |
30 | for (let i = 0; i < versionRequirements.length; i++) {
31 | const mod = versionRequirements[i]
32 |
33 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
34 | warnings.push(mod.name + ': ' +
35 | chalk.red(mod.currentVersion) + ' should be ' +
36 | chalk.green(mod.versionRequirement)
37 | )
38 | }
39 | }
40 |
41 | if (warnings.length) {
42 | console.log('')
43 | console.log(chalk.yellow('To use this template, you must update following to modules:'))
44 | console.log()
45 |
46 | for (let i = 0; i < warnings.length; i++) {
47 | const warning = warnings[i]
48 | console.log(' ' + warning)
49 | }
50 |
51 | console.log()
52 | process.exit(1)
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/music-client/dist/static/js/manifest.3733754daf219da97807.js:
--------------------------------------------------------------------------------
1 | !function(e){var n=window.webpackJsonp;window.webpackJsonp=function(r,c,a){for(var i,u,f,s=0,d=[];s
2 |
3 |
6 |
7 |
8 |
9 |
10 |
42 |
43 |
70 |
--------------------------------------------------------------------------------
/middleware/gateway/src/main/java/me/liuzeyu/gateway/config/RoutesConfiguration.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.gateway.config;
2 |
3 | import me.liuzeyu.gateway.filter.JwtAuthenticationFilter;
4 | import org.springframework.beans.factory.annotation.Autowired;
5 | import org.springframework.beans.factory.annotation.Qualifier;
6 | import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
7 | import org.springframework.cloud.gateway.filter.ratelimit.RateLimiter;
8 | import org.springframework.cloud.gateway.route.RouteLocator;
9 | import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
10 | import org.springframework.context.annotation.Bean;
11 | import org.springframework.context.annotation.Configuration;
12 | import org.springframework.http.HttpStatus;
13 | import org.springframework.web.cors.CorsConfiguration;
14 | import org.springframework.web.cors.reactive.CorsWebFilter;
15 | import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
16 |
17 | @Configuration
18 | public class RoutesConfiguration {
19 |
20 | @Autowired
21 | private JwtAuthenticationFilter filter;
22 |
23 | @Bean
24 | public RouteLocator declare(RouteLocatorBuilder builder) {
25 | return builder.routes()
26 | .route(route -> route.path("/api/user/**")
27 | .filters(f -> f.stripPrefix(1)
28 | )
29 | .uri("lb://auth-serv")
30 | ).route(route -> route
31 | .path("/api/music/**")
32 | .filters(f -> f.stripPrefix(1)
33 | .filter(filter)
34 | )
35 | .uri("lb://music-serv")
36 | ).build();
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/music-serv/music-dao/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | music-serv
7 | me.liuzeyu
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | music-dao
13 |
14 |
15 | 8
16 | 8
17 |
18 |
19 |
20 |
21 | org.springframework.boot
22 | spring-boot-starter-data-jpa
23 |
24 |
25 |
26 | org.projectlombok
27 | lombok
28 |
29 |
30 |
31 | org.springframework.boot
32 | spring-boot-starter-validation
33 |
34 |
35 |
36 | mysql
37 | mysql-connector-java
38 | 8.0.21
39 | runtime
40 |
41 |
42 | me.liuzeyu
43 | music-api
44 | 1.0-SNAPSHOT
45 | compile
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/music-client/src/api/pending.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 |
3 | function parseJwt (token) {
4 | var base64Url = token.split('.')[1]
5 | var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/')
6 | var jsonPayload = decodeURIComponent(window.atob(base64).split('').map(function(c) {
7 | return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
8 | }).join(''))
9 |
10 | return JSON.parse(jsonPayload)
11 | }
12 |
13 | export async function getPending() {
14 | const token = localStorage.getItem('accessToken')
15 | if (token) {
16 | const jwt = parseJwt(token)
17 | const id = jwt.id
18 | const response = await axios.get('/api/music/pending', {
19 | params: { id },
20 | headers: {
21 | 'Authorization': `Bearer ${token}`
22 | }
23 | })
24 | response.data.list.forEach(
25 | (item, index, arr) => {
26 | if (item.ai == '周杰伦') {
27 | arr[index].cover = "http://asset.liuzeyu.me/zhoujielun.png"
28 | } else if (item.ai == '孙燕姿') {
29 | arr[index].cover = "http://asset.liuzeyu.me/sunyanzi.png"
30 | } else if (item.ai == '张学友') {
31 | arr[index].cover = "http://asset.liuzeyu.me/zhangxueyou.png"
32 | }
33 | if (item.status == '0') {
34 | arr[index].status = "干声分离中..."
35 | } else if (item.status == '1') {
36 | arr[index].status = "AI处理中..."
37 | } else if (item.status == '2') {
38 | arr[index].status = "后期合成中..."
39 | }
40 | }
41 | )
42 | return response.data.list
43 | } else {
44 | window.location.href = '/signin';
45 | }
46 | return []
47 | }
--------------------------------------------------------------------------------
/music-serv/music-dao/src/main/java/me/liuzeyu/aimusic/music/dao/entity/Music.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.music.dao.entity;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 | import me.liuzeyu.aimusic.music.dao.converter.StatusTypeConverter;
8 | import me.liuzeyu.aimusic.music.api.enums.StatusType;
9 | import org.springframework.data.annotation.CreatedDate;
10 | import org.springframework.data.annotation.LastModifiedDate;
11 | import org.springframework.data.jpa.domain.support.AuditingEntityListener;
12 |
13 | import javax.persistence.*;
14 | import java.io.Serializable;
15 | import java.util.Date;
16 |
17 | @Data
18 | @NoArgsConstructor
19 | @AllArgsConstructor
20 | @Entity
21 | @Builder
22 | @EntityListeners(AuditingEntityListener.class)
23 | @Table(name = "music")
24 | public class Music implements Serializable {
25 |
26 | @Id
27 | @GeneratedValue(strategy = GenerationType.IDENTITY)
28 | @Column(name = "id", nullable = false)
29 | private Long id;
30 |
31 | @Column(name = "user", nullable = false)
32 | private Long user;
33 |
34 | @Column(name = "hash", nullable = false)
35 | private String hash;
36 |
37 | @Column(name = "title", nullable = false)
38 | private String title;
39 |
40 | @Column(name = "artist", nullable = false)
41 | private String artist;
42 |
43 | @Column(name = "ai", nullable = false)
44 | private String ai;
45 |
46 | @Column(name = "status", nullable = false)
47 | @Convert(converter = StatusTypeConverter.class)
48 | private StatusType status;
49 |
50 | @CreatedDate
51 | @Column(name = "created_time", nullable = false)
52 | private Date createdTime;
53 |
54 | @LastModifiedDate
55 | @Column(name = "updated_time", nullable = false)
56 | private Date updatedTime;
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/auth-client/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
17 |
18 |
27 | AI翻唱
28 |
29 |
30 |
31 |
32 |
33 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/ffmpeg-serv/ffmpeg-impl/src/main/java/me/liuzeyu/aimusic/ffmpeg/event/FfmpegConsumer.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.ffmpeg.event;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import me.liuzeyu.aimusic.ffmpeg.caculator.FfmpegCaculator;
5 | import me.liuzeyu.aimusic.ffmpeg.feign.MusicService;
6 | import me.liuzeyu.aimusic.music.api.beans.UpdateMusicInfo;
7 | import me.liuzeyu.aimusic.music.api.enums.StatusType;
8 | import me.liuzeyu.aimusic.spleeter.api.beans.SvcResponse;
9 | import me.liuzeyu.aimusic.svc.api.beans.Music;
10 | import org.springframework.beans.factory.annotation.Autowired;
11 | import org.springframework.beans.factory.annotation.Value;
12 | import org.springframework.context.annotation.Bean;
13 | import org.springframework.stereotype.Service;
14 |
15 | import java.io.IOException;
16 | import java.util.function.Consumer;
17 |
18 | @Slf4j
19 | @Service
20 | public class FfmpegConsumer {
21 | @Autowired
22 | private FfmpegCaculator ffmpegCaculator;
23 |
24 | @Autowired
25 | private MusicService musicService;
26 |
27 | @Value("${ffmpeg.path}")
28 | private String ffmpegPath;
29 |
30 | @Value("${file.upload.path}")
31 | private String path;
32 |
33 | @Bean
34 | public Consumer addFfmpeg() {
35 | return request -> {
36 | log.info("received: {}", request);
37 | try {
38 | ffmpegCaculator.run(request.getHash(), path, ffmpegPath);
39 |
40 | UpdateMusicInfo music = UpdateMusicInfo
41 | .builder()
42 | .hash(request.getHash())
43 | .user(request.getUser())
44 | .status(StatusType.FINISHED.getCode())
45 | .build();
46 | musicService.updateMusic(music);
47 | } catch (IOException e) {
48 | throw new RuntimeException(e);
49 | }
50 | };
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/music.sql:
--------------------------------------------------------------------------------
1 | /*
2 | Navicat Premium Data Transfer
3 |
4 | Source Server : mysql
5 | Source Server Type : MySQL
6 | Source Server Version : 80033
7 | Source Host : localhost:3306
8 | Source Schema : ai_music_db
9 |
10 | Target Server Type : MySQL
11 | Target Server Version : 80033
12 | File Encoding : 65001
13 |
14 | Date: 30/05/2023 20:48:33
15 | */
16 |
17 | SET NAMES utf8mb4;
18 | SET FOREIGN_KEY_CHECKS = 0;
19 |
20 | -- ----------------------------
21 | -- Table structure for music
22 | -- ----------------------------
23 | DROP TABLE IF EXISTS `music`;
24 | CREATE TABLE `music` (
25 | `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
26 | `user` bigint unsigned NOT NULL COMMENT '用户ID',
27 | `hash` varchar(32) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT '文件Hash',
28 | `title` varchar(256) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT '歌曲标题',
29 | `artist` varchar(128) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT '原唱歌手',
30 | `ai` varchar(128) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT 'AI翻唱歌手',
31 | `status` varchar(32) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT 'AI处理状态',
32 | `created_time` datetime(0) NOT NULL COMMENT '创建时间',
33 | `updated_time` datetime(0) NOT NULL COMMENT '修改时间',
34 | PRIMARY KEY (`id`) USING BTREE,
35 | INDEX `idx_user`(`user`) USING BTREE,
36 | UNIQUE INDEX `unique_user_hash`(`user`, `hash`) USING BTREE
37 | ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci COMMENT = '歌曲' ROW_FORMAT = Dynamic;
38 |
39 | SET FOREIGN_KEY_CHECKS = 1;
40 |
--------------------------------------------------------------------------------
/auth-serv/auth-dao/src/main/java/me/liuzeyu/aimusic/auth/dao/entity/User.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.auth.dao.entity;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 | import org.springframework.data.annotation.CreatedDate;
8 | import org.springframework.data.annotation.LastModifiedDate;
9 | import org.springframework.data.jpa.domain.support.AuditingEntityListener;
10 |
11 | import javax.persistence.*;
12 | import javax.validation.constraints.Max;
13 | import javax.validation.constraints.Min;
14 | import java.io.Serializable;
15 | import java.util.Date;
16 |
17 | @Data
18 | @NoArgsConstructor
19 | @AllArgsConstructor
20 | @Entity
21 | @Builder
22 | @EntityListeners(AuditingEntityListener.class)
23 | @Table(name = "user")
24 | public class User implements Serializable {
25 |
26 | public User(User user) {
27 | this.id = user.id;
28 | this.username = user.username;
29 | this.password = user.password;
30 | this.email = user.email;
31 | this.createdTime = user.getCreatedTime();
32 | this.updatedTime = user.getUpdatedTime();
33 | this.active = user.active;
34 | }
35 |
36 | @Id
37 | @GeneratedValue(strategy = GenerationType.IDENTITY)
38 | @Column(name = "id", nullable = false)
39 | private Long id;
40 |
41 | @Column(name = "username", nullable = false)
42 | private String username;
43 |
44 | @Column(name = "password", nullable = false)
45 | private String password;
46 |
47 | @Column(name = "email", nullable = false)
48 | private String email;
49 |
50 | @Column(name = "active", nullable = false)
51 | private boolean active;
52 |
53 | @CreatedDate
54 | @Column(name = "created_time", nullable = false)
55 | private Date createdTime;
56 |
57 | @LastModifiedDate
58 | @Column(name = "updated_time", nullable = false)
59 | private Date updatedTime;
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/spleeter-serv/spleeter-impl/src/main/java/me/liuzeyu/aimusic/spleeter/caculator/SpleeterCaculator.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.spleeter.caculator;
2 |
3 | import com.google.common.base.Throwables;
4 | import lombok.extern.slf4j.Slf4j;
5 | import org.springframework.stereotype.Service;
6 |
7 | import java.io.*;
8 | import java.nio.file.Paths;
9 | import java.util.ArrayList;
10 | import java.util.List;
11 |
12 | @Slf4j
13 | @Service
14 | public class SpleeterCaculator {
15 |
16 | public void run(String hash, String path, String command) throws IOException {
17 |
18 | String str;
19 |
20 | String outputPath = Paths.get(path).toString();
21 |
22 | String inputPath = Paths.get(path, hash+".mp3").toString();
23 |
24 | List envp = new ArrayList();
25 | for( Object o : System.getenv().entrySet() ){
26 | envp.add(o.toString());
27 | }
28 | String[] envs = envp.stream().toArray(String[]::new);
29 |
30 | File dir = new File(path);
31 |
32 | Process p = Runtime.getRuntime().exec(String.format(command, outputPath, inputPath), envs, dir);
33 |
34 | BufferedReader stdInput = new BufferedReader(new
35 | InputStreamReader(p.getInputStream()));
36 |
37 | BufferedReader stdError = new BufferedReader(new
38 | InputStreamReader(p.getErrorStream()));
39 |
40 | boolean isError = false;
41 |
42 | // read the output from the command
43 | while ((str = stdInput.readLine()) != null) {
44 | log.info(str);
45 | if (str.contains("ERROR")) {
46 | isError = true;
47 | }
48 | }
49 |
50 | // read any errors from the attempted command
51 | while ((str = stdError.readLine()) != null) {
52 | log.error(str);
53 | isError = true;
54 | }
55 | if (isError) {
56 | throw new RuntimeException("spleeter error");
57 | }
58 |
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/music-client/src/api/create.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 | import FormData from 'form-data'
3 |
4 | function parseJwt (token) {
5 | var base64Url = token.split('.')[1]
6 | var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/')
7 | var jsonPayload = decodeURIComponent(window.atob(base64).split('').map(function(c) {
8 | return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
9 | }).join(''))
10 |
11 | return JSON.parse(jsonPayload)
12 | }
13 |
14 | export async function postCreate(file, title, artist, ai, onUploadProgress) {
15 | const token = localStorage.getItem('accessToken')
16 | if (token) {
17 | const jwt = parseJwt(token)
18 | const id = jwt.id
19 |
20 | var formData = new FormData()
21 | formData.append("file", file)
22 | formData.append('info', new Blob([JSON.stringify({
23 | "user": id,
24 | "title": title,
25 | "artist": artist,
26 | "ai": ai
27 | })], {
28 | type: "application/json"
29 | }))
30 | const response = await axios({
31 | method: "post",
32 | url: "/api/music/add",
33 | data: formData,
34 | headers: {
35 | "Content-Type": "multipart/form-data",
36 | 'Authorization': `Bearer ${token}`
37 | },
38 | onUploadProgress: onUploadProgress
39 | })
40 | .then(function (response) {
41 | return response
42 | })
43 | .catch(function (response) {
44 | return response
45 | });
46 |
47 | return response
48 | } else {
49 | window.location.href = '/signin';
50 | }
51 | return []
52 | }
--------------------------------------------------------------------------------
/svc-serv/svc-impl/src/main/java/me/liuzeyu/me/aimusic/svc/caculator/AbstractSvc.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.me.aimusic.svc.caculator;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import lombok.Data;
5 |
6 | import java.io.BufferedReader;
7 | import java.io.File;
8 | import java.io.IOException;
9 | import java.io.InputStreamReader;
10 | import java.nio.file.Paths;
11 | import java.text.MessageFormat;
12 | import java.util.ArrayList;
13 | import java.util.List;
14 |
15 | @Slf4j
16 | public abstract class AbstractSvc implements SvcTemplate {
17 |
18 | @Override
19 | public void run(String hash, String path, String pythonPath, String svcPath) throws IOException {
20 | String str;
21 |
22 | String inputPath = Paths.get(path, hash, "vocals.wav").toString();
23 |
24 | List envp = new ArrayList();
25 | for( Object o : System.getenv().entrySet() ){
26 | envp.add(o.toString());
27 | }
28 | String[] envs = envp.stream().toArray(String[]::new);
29 |
30 | File dir = new File(svcPath);
31 |
32 | Process p = Runtime.getRuntime().exec(MessageFormat.format(getCommand(), pythonPath, svcPath, inputPath), envs, dir);
33 |
34 | BufferedReader stdInput = new BufferedReader(new
35 | InputStreamReader(p.getInputStream()));
36 |
37 | BufferedReader stdError = new BufferedReader(new
38 | InputStreamReader(p.getErrorStream()));
39 |
40 | boolean isError = false;
41 |
42 | // read the output from the command
43 | while ((str = stdInput.readLine()) != null) {
44 | log.info(str);
45 | if (str.contains("ERROR")) {
46 | isError = true;
47 | }
48 | }
49 |
50 | // read any errors from the attempted command
51 | while ((str = stdError.readLine()) != null) {
52 | log.error(str);
53 | isError = true;
54 | }
55 | if (isError) {
56 | throw new RuntimeException("svc error");
57 | }
58 |
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/music-client/src/common/stylus/icon.styl:
--------------------------------------------------------------------------------
1 | @font-face
2 | font-family: 'music-icon'
3 | src: url('../fonts/music-icon.eot?2qevqt')
4 | src: url('../fonts/music-icon.eot?2qevqt#iefix') format('embedded-opentype'),
5 | url('../fonts/music-icon.ttf?2qevqt') format('truetype'),
6 | url('../fonts/music-icon.woff?2qevqt') format('woff'),
7 | url('../fonts/music-icon.svg?2qevqt#music-icon') format('svg')
8 | font-weight: normal
9 | font-style: normal
10 |
11 | [class^="icon-"], [class*=" icon-"]
12 | /* use !important to prevent issues with browser extensions that change fonts */
13 | font-family: 'music-icon' !important
14 | speak: none
15 | font-style: normal
16 | font-weight: normal
17 | font-variant: normal
18 | text-transform: none
19 | line-height: 1
20 |
21 | /* Better Font Rendering =========== */
22 | -webkit-font-smoothing: antialiased
23 | -moz-osx-font-smoothing: grayscale
24 |
25 | .icon-ok:before
26 | content: "\e900"
27 |
28 | .icon-close:before
29 | content: "\e901"
30 |
31 | .icon-add:before
32 | content: "\e902"
33 |
34 | .icon-play-mini:before
35 | content: "\e903"
36 |
37 | .icon-playlist:before
38 | content: "\e904"
39 |
40 | .icon-music:before
41 | content: "\e905"
42 |
43 | .icon-search:before
44 | content: "\e906"
45 |
46 | .icon-clear:before
47 | content: "\e907"
48 |
49 | .icon-delete:before
50 | content: "\e908"
51 |
52 | .icon-favorite:before
53 | content: "\e909"
54 |
55 | .icon-not-favorite:before
56 | content: "\e90a"
57 |
58 | .icon-pause:before
59 | content: "\e90b"
60 |
61 | .icon-play:before
62 | content: "\e90c"
63 |
64 | .icon-prev:before
65 | content: "\e90d"
66 |
67 | .icon-loop:before
68 | content: "\e90e"
69 |
70 | .icon-sequence:before
71 | content: "\e90f"
72 |
73 | .icon-random:before
74 | content: "\e910"
75 |
76 | .icon-back:before
77 | content: "\e911"
78 |
79 | .icon-mine:before
80 | content: "\e912"
81 |
82 | .icon-next:before
83 | content: "\e913"
84 |
85 | .icon-dismiss:before
86 | content: "\e914"
87 |
88 | .icon-pause-mini:before
89 | content: "\e915"
90 |
--------------------------------------------------------------------------------
/auth-serv/auth-dao/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | auth-serv
7 | me.liuzeyu
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | auth-dao
13 |
14 |
15 | 8
16 | 8
17 |
18 |
19 |
20 |
21 | org.springframework.boot
22 | spring-boot-starter-data-jpa
23 |
24 |
25 |
26 | org.projectlombok
27 | lombok
28 |
29 |
30 |
31 | org.springframework.boot
32 | spring-boot-starter-validation
33 |
34 |
35 |
36 | mysql
37 | mysql-connector-java
38 | 8.0.21
39 | runtime
40 |
41 |
42 | me.liuzeyu
43 | music-api
44 | 1.0-SNAPSHOT
45 | compile
46 |
47 |
48 | org.projectlombok
49 | lombok
50 |
51 |
52 | org.springframework.boot
53 | spring-boot-starter-security
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/music-serv/music-impl/src/main/java/me/liuzeyu/aimusic/music/converter/FileConverter.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.music.converter;
2 |
3 | import org.apache.tika.Tika;
4 | import org.springframework.web.multipart.MultipartFile;
5 |
6 | import java.io.File;
7 | import java.io.IOException;
8 | import java.math.BigInteger;
9 | import java.nio.file.Files;
10 | import java.nio.file.Path;
11 | import java.security.MessageDigest;
12 | import java.security.NoSuchAlgorithmException;
13 | import java.util.UUID;
14 | import java.nio.file.Paths;
15 |
16 | public class FileConverter {
17 |
18 | public static String convertToUUID() {
19 | return UUID.randomUUID().toString();
20 | }
21 |
22 | public static String convertToHash(MultipartFile upload, File uuidFile, String path, Long user, String ai) throws IOException, NoSuchAlgorithmException {
23 | byte[] uploadBytes = upload.getBytes();
24 | MessageDigest md5 = MessageDigest.getInstance("MD5");
25 | byte[] digest = md5.digest(uploadBytes);
26 | String hashString = new BigInteger(1, digest).toString(16);
27 | String finalString = hashString+user.toString()+ai;
28 | byte[] bytesOfMessage = finalString.getBytes("UTF-8");
29 | byte[] theMD5digest = md5.digest(bytesOfMessage);
30 | String finalHashString = new BigInteger(1, theMD5digest).toString(16);
31 | uuidFile.renameTo(new File(Paths.get(path, finalHashString+".mp3").toString()));
32 | return finalHashString;
33 | }
34 |
35 | public static File convertFromMultipartFile(MultipartFile upload, String path) throws IOException {
36 | Path filePath = Paths.get(path, convertToUUID());
37 | Files.copy(upload.getInputStream(), filePath);
38 | return new File(filePath.toString());
39 | }
40 |
41 | public static File convertToMP3(File file) throws IOException {
42 | Tika tika = new Tika();
43 | String type = tika.detect(file);
44 | if(!type.equals("audio/mpeg")) {
45 | throw new RuntimeException("Upload file is not mp3");
46 | }
47 | return file;
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/music-serv/music-api/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | music-serv
7 | me.liuzeyu
8 | 1.0-SNAPSHOT
9 | ../pom.xml
10 |
11 | 4.0.0
12 |
13 | music-api
14 |
15 |
16 | 8
17 | 8
18 |
19 |
20 |
21 |
22 | org.apache.commons
23 | commons-lang3
24 |
25 |
26 |
27 | org.apache.commons
28 | commons-collections4
29 |
30 |
31 |
32 | commons-codec
33 | commons-codec
34 |
35 |
36 |
37 |
38 | com.alibaba
39 | fastjson
40 |
41 |
42 |
43 | org.projectlombok
44 | lombok
45 |
46 |
47 |
48 | jakarta.validation
49 | jakarta.validation-api
50 |
51 |
52 |
53 | com.google.guava
54 | guava
55 |
56 |
57 | org.projectlombok
58 | lombok
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/spleeter-serv/spleeter-api/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | spleeter-serv
7 | me.liuzeyu
8 | 1.0-SNAPSHOT
9 | ../pom.xml
10 |
11 | 4.0.0
12 |
13 | spleeter-api
14 |
15 |
16 | 8
17 | 8
18 |
19 |
20 |
21 |
22 | org.apache.commons
23 | commons-lang3
24 |
25 |
26 |
27 | org.apache.commons
28 | commons-collections4
29 |
30 |
31 |
32 | commons-codec
33 | commons-codec
34 |
35 |
36 |
37 |
38 | com.alibaba
39 | fastjson
40 |
41 |
42 |
43 | org.projectlombok
44 | lombok
45 |
46 |
47 |
48 | jakarta.validation
49 | jakarta.validation-api
50 |
51 |
52 |
53 | com.google.guava
54 | guava
55 |
56 |
57 | org.projectlombok
58 | lombok
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/middleware/gateway/src/main/java/me/liuzeyu/gateway/util/JwtUtil.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.gateway.util;
2 |
3 | import org.springframework.beans.factory.annotation.Value;
4 | import org.springframework.stereotype.Component;
5 |
6 | import me.liuzeyu.gateway.exception.JwtTokenMalformedException;
7 | import me.liuzeyu.gateway.exception.JwtTokenMissingException;
8 |
9 | import io.jsonwebtoken.Claims;
10 | import io.jsonwebtoken.ExpiredJwtException;
11 | import io.jsonwebtoken.Jwts;
12 | import io.jsonwebtoken.MalformedJwtException;
13 | import io.jsonwebtoken.SignatureException;
14 | import io.jsonwebtoken.UnsupportedJwtException;
15 |
16 | import java.nio.charset.Charset;
17 |
18 | @Component
19 | public class JwtUtil {
20 |
21 | @Value("${jwt.secret}")
22 | private String jwtSecret;
23 |
24 | public Claims getClaims(final String token) {
25 | try {
26 | Claims body = Jwts.parser().setSigningKey(jwtSecret.getBytes(Charset.forName("UTF-8"))).parseClaimsJws(token.substring(7)).getBody();
27 | return body;
28 | } catch (Exception e) {
29 | System.out.println(e.getMessage() + " => " + e);
30 | }
31 | return null;
32 | }
33 |
34 | public void validateToken(final String token) throws JwtTokenMalformedException, JwtTokenMissingException {
35 | try {
36 | Jwts.parser()
37 | .setSigningKey(jwtSecret
38 | .getBytes(Charset.forName("UTF-8")))
39 | .parseClaimsJws(token.substring(7));
40 | } catch (SignatureException ex) {
41 | throw new JwtTokenMalformedException("Invalid JWT signature");
42 | } catch (MalformedJwtException ex) {
43 | throw new JwtTokenMalformedException("Invalid JWT token");
44 | } catch (ExpiredJwtException ex) {
45 | throw new JwtTokenMalformedException("Expired JWT token");
46 | } catch (UnsupportedJwtException ex) {
47 | throw new JwtTokenMalformedException("Unsupported JWT token");
48 | } catch (IllegalArgumentException ex) {
49 | throw new JwtTokenMissingException("JWT claims string is empty.");
50 | }
51 | }
52 |
53 | }
--------------------------------------------------------------------------------
/auth-client/build/index.html:
--------------------------------------------------------------------------------
1 | AI翻唱
--------------------------------------------------------------------------------
/auth-client/build/signin/index.html:
--------------------------------------------------------------------------------
1 | AI翻唱
--------------------------------------------------------------------------------
/auth-client/build/signup/index.html:
--------------------------------------------------------------------------------
1 | AI翻唱
--------------------------------------------------------------------------------
/music-serv/music-impl/src/main/java/me/liuzeyu/aimusic/music/controller/MusicController.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.music.controller;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import org.springframework.beans.factory.annotation.Autowired;
5 | import org.springframework.web.bind.annotation.*;
6 | import org.springframework.web.multipart.MultipartFile;
7 |
8 | import javax.validation.Valid;
9 | import javax.validation.constraints.NotBlank;
10 | import javax.validation.constraints.NotNull;
11 | import java.io.IOException;
12 | import java.security.NoSuchAlgorithmException;
13 | import me.liuzeyu.aimusic.music.api.beans.*;
14 | import me.liuzeyu.aimusic.music.dao.entity.Music;
15 | import me.liuzeyu.aimusic.music.service.intf.MusicService;
16 |
17 | @Slf4j
18 | @RestController
19 | @RequestMapping("music")
20 | public class MusicController {
21 |
22 | @Autowired
23 | private MusicService musicService;
24 |
25 | @PostMapping("update")
26 | public MusicInfo update(@Valid @RequestBody UpdateMusicInfo request) {
27 | log.info("Create music: data={}", request);
28 | return musicService.updateMusic(request);
29 | }
30 |
31 | @RequestMapping(value = "add", method = RequestMethod.POST, consumes = {"multipart/form-data"})
32 | @ResponseBody
33 | public MusicInfo create(@RequestPart("info") @Valid MusicInfo request, @RequestPart("file") @Valid @NotNull @NotBlank MultipartFile upload) throws IOException, NoSuchAlgorithmException {
34 | log.info("Create music: data={}", request);
35 | return musicService.createMusic(request, upload);
36 | }
37 |
38 | @GetMapping("other")
39 | public MusicListInfo other(@RequestParam("id") Long id) {
40 | log.info("Query other music: user_id={}", id);
41 | return musicService.otherMusic(id);
42 | }
43 |
44 | @GetMapping("pending")
45 | public MusicListInfo pending(@RequestParam("id") Long id) {
46 | log.info("Query pending music: user_id={}", id);
47 | return musicService.pendingMusic(id);
48 | }
49 |
50 | @GetMapping("finished")
51 | public MusicListInfo finished(@RequestParam("id") Long id) {
52 | log.info("Query finished music: user_id={}", id);
53 | return musicService.finishedMusic(id);
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/ffmpeg-serv/ffmpeg-impl/src/main/java/me/liuzeyu/aimusic/ffmpeg/caculator/FfmpegCaculator.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.ffmpeg.caculator;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import org.springframework.stereotype.Service;
5 |
6 | import java.io.BufferedReader;
7 | import java.io.File;
8 | import java.io.IOException;
9 | import java.io.InputStreamReader;
10 | import java.nio.file.Paths;
11 | import java.text.MessageFormat;
12 | import java.util.ArrayList;
13 | import java.util.List;
14 |
15 | @Slf4j
16 | @Service
17 | public class FfmpegCaculator {
18 |
19 | public static final String COMMAND = "{0} -loglevel error -i {1}/ai-vocals.wav -i {1}/accompaniment.wav -filter_complex amix=inputs=2:duration=longest {2}";
20 |
21 | public void run(String hash, String path, String ffmpegPath) throws IOException {
22 |
23 | String str;
24 |
25 | String outputPath = Paths.get(path, hash+".wav").toString();
26 |
27 | String inputPath = Paths.get(path, hash).toString();
28 |
29 | List envp = new ArrayList();
30 | for( Object o : System.getenv().entrySet() ){
31 | envp.add(o.toString());
32 | }
33 | String[] envs = envp.stream().toArray(String[]::new);
34 |
35 | File dir = new File(path);
36 |
37 | Process p = Runtime.getRuntime().exec(MessageFormat.format(COMMAND, ffmpegPath, inputPath, outputPath), envs, dir);
38 |
39 | BufferedReader stdInput = new BufferedReader(new
40 | InputStreamReader(p.getInputStream()));
41 |
42 | BufferedReader stdError = new BufferedReader(new
43 | InputStreamReader(p.getErrorStream()));
44 |
45 | boolean isError = false;
46 |
47 | // read the output from the command
48 | while ((str = stdInput.readLine()) != null) {
49 | log.info(str);
50 | if (str.contains("ERROR")) {
51 | isError = true;
52 | }
53 | }
54 |
55 | // read any errors from the attempted command
56 | while ((str = stdError.readLine()) != null) {
57 | log.error(str);
58 | isError = true;
59 | }
60 | if (isError) {
61 | throw new RuntimeException("spleeter error");
62 | }
63 |
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/auth-serv/auth-impl/src/main/java/me/liuzeyu/aimusic/auth/service/JwtTokenProvider.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.auth.service;
2 |
3 | import com.google.common.base.Throwables;
4 | import lombok.extern.slf4j.Slf4j;
5 | import me.liuzeyu.aimusic.auth.api.beans.MusicUserDetails;
6 | import me.liuzeyu.aimusic.auth.config.JwtConfig;
7 | import me.liuzeyu.aimusic.auth.dao.entity.User;
8 | import org.springframework.stereotype.Service;
9 | import io.jsonwebtoken.*;
10 | import org.springframework.security.core.Authentication;
11 | import org.springframework.security.core.GrantedAuthority;
12 |
13 | import java.util.Date;
14 | import java.util.stream.Collectors;
15 |
16 | @Service
17 | @Slf4j
18 | public class JwtTokenProvider {
19 |
20 | private final JwtConfig jwtConfig;
21 |
22 | public JwtTokenProvider(JwtConfig jwtConfig) {
23 | this.jwtConfig = jwtConfig;
24 | }
25 |
26 | public String generateToken(Authentication authentication) {
27 |
28 | User user = (User) authentication.getDetails();
29 | Long now = System.currentTimeMillis();
30 | return Jwts.builder()
31 | .setSubject(authentication.getName())
32 | .claim("authorities", authentication.getAuthorities().stream()
33 | .map(GrantedAuthority::getAuthority).collect(Collectors.toList()))
34 | .claim("id", user.getId())
35 | .setIssuedAt(new Date(now))
36 | .setExpiration(new Date(now + jwtConfig.getExpiration() * 1000)) // in milliseconds
37 | .signWith(SignatureAlgorithm.HS512, jwtConfig.getSecret().getBytes())
38 | .compact();
39 | }
40 |
41 | public Claims getClaimsFromJWT(String token) {
42 | return Jwts.parser()
43 | .setSigningKey(jwtConfig.getSecret().getBytes())
44 | .parseClaimsJws(token)
45 | .getBody();
46 | }
47 |
48 | public boolean validateToken(String authToken) {
49 | try {
50 | Jwts.parser()
51 | .setSigningKey(jwtConfig.getSecret().getBytes())
52 | .parseClaimsJws(authToken);
53 |
54 | return true;
55 | } catch (Exception e) {
56 | log.error(Throwables.getStackTraceAsString(e));
57 | }
58 | return false;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/music-client/src/common/js/cache.js:
--------------------------------------------------------------------------------
1 | import storage from 'good-storage'
2 |
3 | const SEARCH_KEY = '_search_'
4 | const SEARCH_MAX_LENGTH = 15
5 |
6 | const PLAY_KEY = '_play_'
7 | const PLAY_MAX_LENGTH = 200
8 |
9 | const FAVORITE_KEY = '_favorite_'
10 | const FAVORITE_MAX_LENGTH = 200
11 |
12 | function insertArray(arr, val, compare, maxlen) {
13 | const index = arr.findIndex(compare)
14 | if (index === 0) {
15 | return
16 | }
17 | if (index > 0) {
18 | arr.splice(index, 1)
19 | }
20 | arr.unshift(val)
21 | if (maxlen && arr.length > maxlen) {
22 | arr.pop()
23 | }
24 | }
25 |
26 | function deleteFromArray(arr, compare) {
27 | const index = arr.findIndex(compare)
28 | if (index > -1) {
29 | arr.splice(index, 1)
30 | }
31 | }
32 | export function saveSearch(query) {
33 | let searches = storage.get(SEARCH_KEY, [])
34 | insertArray(searches, query, (item) => {
35 | return item === query
36 | }, SEARCH_MAX_LENGTH)
37 |
38 | storage.set(SEARCH_KEY, searches)
39 | return searches
40 | }
41 |
42 | export function loadSearch() {
43 | return storage.get(SEARCH_KEY, [])
44 | }
45 |
46 | export function deleteSearch(query) {
47 | let searches = storage.get(SEARCH_KEY, [])
48 | deleteFromArray(searches, (item) => {
49 | return item === query
50 | })
51 | storage.set(SEARCH_KEY, searches)
52 | return searches
53 | }
54 |
55 | export function clearSearch() {
56 | storage.remove(SEARCH_KEY)
57 | return []
58 | }
59 |
60 | export function savePlay(song) {
61 | let songs = storage.get(PLAY_KEY, [])
62 | insertArray(songs, song, (item) => {
63 | return item.id === song.id
64 | }, PLAY_MAX_LENGTH)
65 | storage.set(PLAY_KEY, songs)
66 |
67 | return songs
68 | }
69 |
70 | export function loadPlay() {
71 | return storage.get(PLAY_KEY, [])
72 | }
73 |
74 | export function saveFaverite(song) {
75 | let songs = storage.get(FAVORITE_KEY, [])
76 | insertArray(songs, song, (item) => {
77 | return song.id === item.id
78 | }, FAVORITE_MAX_LENGTH)
79 | storage.set(FAVORITE_KEY, songs)
80 | return songs
81 | }
82 |
83 | export function deleteFavorite(song) {
84 | let songs = storage.get(FAVORITE_KEY, [])
85 | deleteFromArray(songs, (item) => {
86 | return song.id === item.id
87 | })
88 | storage.set(FAVORITE_KEY, songs)
89 | return songs
90 | }
91 |
92 | export function loadFavorite() {
93 | return storage.get(FAVORITE_KEY, [])
94 | }
95 |
--------------------------------------------------------------------------------
/svc-serv/svc-api/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | svc-serv
7 | me.liuzeyu
8 | 1.0-SNAPSHOT
9 | ../pom.xml
10 |
11 | 4.0.0
12 |
13 | svc-api
14 |
15 |
16 | 8
17 | 8
18 |
19 |
20 |
21 |
22 | org.apache.commons
23 | commons-lang3
24 |
25 |
26 |
27 | org.apache.commons
28 | commons-collections4
29 |
30 |
31 |
32 | commons-codec
33 | commons-codec
34 |
35 |
36 |
37 |
38 | com.alibaba
39 | fastjson
40 |
41 |
42 |
43 | org.projectlombok
44 | lombok
45 |
46 |
47 |
48 | jakarta.validation
49 | jakarta.validation-api
50 |
51 |
52 |
53 | com.google.guava
54 | guava
55 |
56 |
57 | org.projectlombok
58 | lombok
59 |
60 |
61 | org.projectlombok
62 | lombok
63 |
64 |
65 | org.projectlombok
66 | lombok
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/spleeter-serv/spleeter-impl/src/main/java/me/liuzeyu/aimusic/spleeter/event/SpleeterConsumer.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.spleeter.event;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import me.liuzeyu.aimusic.music.api.beans.UpdateMusicInfo;
5 | import me.liuzeyu.aimusic.music.api.enums.StatusType;
6 | import me.liuzeyu.aimusic.spleeter.api.beans.Music;
7 | import me.liuzeyu.aimusic.spleeter.api.beans.SpleeterResponse;
8 | import me.liuzeyu.aimusic.spleeter.api.beans.SvcResponse;
9 | import me.liuzeyu.aimusic.spleeter.caculator.SpleeterCaculator;
10 | import me.liuzeyu.aimusic.spleeter.feign.MusicService;
11 | import me.liuzeyu.aimusic.spleeter.feign.SvcService;
12 | import org.bouncycastle.dvcs.DVCSResponse;
13 | import org.springframework.beans.factory.annotation.Autowired;
14 | import org.springframework.beans.factory.annotation.Value;
15 | import org.springframework.context.annotation.Bean;
16 | import org.springframework.stereotype.Service;
17 |
18 | import java.io.IOException;
19 | import java.util.function.Consumer;
20 |
21 | @Slf4j
22 | @Service
23 | public class SpleeterConsumer {
24 |
25 | @Autowired
26 | private SpleeterCaculator spleeterCaculator;
27 |
28 | @Autowired
29 | private SvcService svcService;
30 |
31 | @Autowired
32 | private MusicService musicService;
33 |
34 | @Value("${spleeter.command}")
35 | private String command;
36 |
37 | @Value("${file.upload.path}")
38 | private String path;
39 |
40 | @Bean
41 | public Consumer addSpleeter() {
42 | return request -> {
43 | log.info("received: {}", request);
44 | try {
45 | spleeterCaculator.run(request.getHash(), path, command);
46 |
47 | SvcResponse svcResponse = svcService.requestSvc(request);
48 | if(!svcResponse.getStatus().equals("ok")) {
49 | throw new RuntimeException("svc message queue request failed");
50 | }
51 | UpdateMusicInfo music = UpdateMusicInfo
52 | .builder()
53 | .hash(request.getHash())
54 | .user(request.getUser())
55 | .status(StatusType.SPLITTED.getCode())
56 | .build();
57 | musicService.updateMusic(music);
58 | } catch (IOException e) {
59 | throw new RuntimeException(e);
60 | }
61 | };
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/music-client/src/base/song-list/song-list.vue:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
17 |
54 |
55 |
98 |
--------------------------------------------------------------------------------
/auth-client/src/signup/Signup.js:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from "react";
2 | import { Form, Input, Button, notification } from "antd";
3 | import { ThunderboltTwoTone } from "@ant-design/icons";
4 | import { signup } from "../util/ApiUtil";
5 | import "./Signup.css";
6 |
7 | const Signup = (props) => {
8 | const [loading, setLoading] = useState(false);
9 |
10 | useEffect(() => {
11 | if (localStorage.getItem("accessToken") !== null) {
12 | window.location.href = '/';
13 | }
14 | }, []);
15 |
16 | const onFinish = (values) => {
17 | setLoading(true);
18 | signup(values)
19 | .then((response) => {
20 | notification.success({
21 | message: "Success",
22 | description:
23 | "感谢使用! 您已成功注册. 请登录使用!",
24 | });
25 | props.history.push("/signin");
26 | setLoading(false);
27 | })
28 | .catch((error) => {
29 | notification.error({
30 | message: "Error",
31 | description:
32 | error.message || "抱歉! 注册错误. 请稍后重试!",
33 | });
34 | setLoading(false);
35 | });
36 | };
37 |
38 | return (
39 |
79 | );
80 | };
81 |
82 | export default Signup;
83 |
--------------------------------------------------------------------------------
/auth-serv/auth-api/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | auth-serv
7 | me.liuzeyu
8 | 1.0-SNAPSHOT
9 | ../pom.xml
10 |
11 | 4.0.0
12 |
13 | auth-api
14 |
15 |
16 | 8
17 | 8
18 |
19 |
20 |
21 |
22 | org.apache.commons
23 | commons-lang3
24 |
25 |
26 |
27 | org.apache.commons
28 | commons-collections4
29 |
30 |
31 |
32 | commons-codec
33 | commons-codec
34 |
35 |
36 |
37 |
38 | com.alibaba
39 | fastjson
40 |
41 |
42 |
43 | org.projectlombok
44 | lombok
45 |
46 |
47 |
48 | jakarta.validation
49 | jakarta.validation-api
50 |
51 |
52 |
53 | com.google.guava
54 | guava
55 |
56 |
57 | org.projectlombok
58 | lombok
59 |
60 |
61 | org.projectlombok
62 | lombok
63 |
64 |
65 | me.liuzeyu
66 | auth-dao
67 | 1.0-SNAPSHOT
68 | compile
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/svc-serv/svc-impl/src/main/java/me/liuzeyu/me/aimusic/svc/event/SvcConsumer.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.me.aimusic.svc.event;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import me.liuzeyu.aimusic.ffmpeg.api.beans.FfmpegResponse;
5 | import me.liuzeyu.aimusic.music.api.beans.UpdateMusicInfo;
6 | import me.liuzeyu.aimusic.music.api.enums.StatusType;
7 | import me.liuzeyu.aimusic.svc.api.beans.Music;
8 | import me.liuzeyu.me.aimusic.svc.caculator.CalculationFactory;
9 | import me.liuzeyu.me.aimusic.svc.caculator.SvcTemplate;
10 | import me.liuzeyu.me.aimusic.svc.feign.FfmpegService;
11 | import me.liuzeyu.me.aimusic.svc.feign.MusicService;
12 | import org.springframework.beans.factory.annotation.Autowired;
13 | import org.springframework.beans.factory.annotation.Value;
14 | import org.springframework.context.annotation.Bean;
15 | import org.springframework.stereotype.Service;
16 |
17 | import java.io.IOException;
18 | import java.util.function.Consumer;
19 |
20 | @Slf4j
21 | @Service
22 | public class SvcConsumer {
23 | @Autowired
24 | private CalculationFactory calculationFactory;
25 |
26 | @Autowired
27 | private FfmpegService ffmpegService;
28 |
29 | @Autowired
30 | private MusicService musicService;
31 |
32 | @Value("${python.path}")
33 | private String pythonPath;
34 |
35 | @Value("${svc.svcPath}")
36 | private String svcPath;
37 |
38 | @Value("${file.upload.path}")
39 | private String path;
40 |
41 | @Bean
42 | public Consumer addSvc() {
43 | return request -> {
44 | log.info("received: {}", request);
45 | try {
46 | SvcTemplate svc = calculationFactory.getSvc(request);
47 | svc.run(request.getHash(), path, pythonPath, svcPath);
48 | FfmpegResponse ffmpegResponse = ffmpegService.requestFfmpeg(request);
49 | if(!ffmpegResponse.getStatus().equals("ok")) {
50 | throw new RuntimeException("svc message queue request failed");
51 | }
52 | UpdateMusicInfo music = UpdateMusicInfo
53 | .builder()
54 | .hash(request.getHash())
55 | .user(request.getUser())
56 | .status(StatusType.CONVERTTED.getCode())
57 | .build();
58 | musicService.updateMusic(music);
59 | } catch (IOException e) {
60 | throw new RuntimeException(e);
61 | }
62 | };
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/music-client/src/base/scroll/scroll.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
100 |
101 |
104 |
--------------------------------------------------------------------------------
/auth-serv/auth-impl/src/main/java/me/liuzeyu/aimusic/auth/controller/AuthController.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.aimusic.auth.controller;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import me.liuzeyu.aimusic.auth.api.beans.ApiResponse;
5 | import me.liuzeyu.aimusic.auth.api.beans.JwtAuthenticationResponse;
6 | import me.liuzeyu.aimusic.auth.api.beans.LoginRequest;
7 | import me.liuzeyu.aimusic.auth.api.beans.SignUpRequest;
8 | import me.liuzeyu.aimusic.auth.dao.entity.User;
9 | import me.liuzeyu.aimusic.auth.service.intf.UserService;
10 | import me.liuzeyu.aimusic.music.api.beans.MusicInfo;
11 | import me.liuzeyu.aimusic.music.api.beans.UpdateMusicInfo;
12 | import org.springframework.beans.factory.annotation.Autowired;
13 | import org.springframework.http.MediaType;
14 | import org.springframework.web.bind.annotation.*;
15 | import org.springframework.web.multipart.MultipartFile;
16 | import java.net.URI;
17 | import javax.validation.Valid;
18 | import org.springframework.http.ResponseEntity;
19 | import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
20 |
21 | @Slf4j
22 | @RestController
23 | @RequestMapping("user")
24 | public class AuthController {
25 |
26 | @Autowired
27 | private UserService userService;
28 |
29 | @PostMapping("signin")
30 | public ResponseEntity> authenticateUser(@Valid @RequestBody LoginRequest loginRequest) {
31 | log.info("login user: data={}", loginRequest);
32 | String token = userService.loginUser(loginRequest.getUsername(), loginRequest.getPassword());
33 | return ResponseEntity.ok(new JwtAuthenticationResponse(token));
34 | }
35 |
36 | @PostMapping(value = "signup", produces = MediaType.APPLICATION_JSON_VALUE)
37 | public ResponseEntity> createUser(@Valid @RequestBody SignUpRequest payload) {
38 | log.info("creating user {}", payload.getUsername());
39 |
40 | User user = User
41 | .builder()
42 | .username(payload.getUsername())
43 | .email(payload.getEmail())
44 | .password(payload.getPassword())
45 | .active(true)
46 | .build();
47 |
48 | userService.registerUser(user);
49 |
50 | URI location = ServletUriComponentsBuilder
51 | .fromCurrentContextPath().path("/users/{username}")
52 | .buildAndExpand(user.getUsername()).toUri();
53 |
54 | return ResponseEntity
55 | .created(location)
56 | .body(new ApiResponse(true,"User registered successfully"));
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/auth-client/src/signin/Signin.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import { Form, Input, Button, notification } from "antd";
3 | import {
4 | UserOutlined,
5 | LockOutlined,
6 | ThunderboltTwoTone,
7 | } from "@ant-design/icons";
8 | import { login } from "../util/ApiUtil";
9 | import "./Signin.css";
10 |
11 |
12 | const Signin = (props) => {
13 | const [loading, setLoading] = useState(false);
14 |
15 | const onFinish = (values) => {
16 | setLoading(true);
17 | login(values)
18 | .then((response) => {
19 | localStorage.setItem("accessToken", response.accessToken);
20 | window.location.href = '/';
21 | setLoading(false);
22 | })
23 | .catch((error) => {
24 | if (error.status === 401) {
25 | notification.error({
26 | message: "Error",
27 | description: "用户名或密码错误,请重试!",
28 | });
29 | } else {
30 | notification.error({
31 | message: "Error",
32 | description:
33 | error.message || "抱歉! 登录错误. 请稍后重试!",
34 | });
35 | }
36 | setLoading(false);
37 | });
38 | };
39 |
40 | return (
41 |
42 |
43 |
53 | }
56 | placeholder="用户名"
57 | />
58 |
59 |
63 | }
66 | type="password"
67 | placeholder="密码"
68 | />
69 |
70 |
71 |
80 |
81 | 未注册?
注册
82 |
83 |
84 | );
85 | };
86 |
87 | export default Signin;
88 |
--------------------------------------------------------------------------------
/ffmpeg-serv/ffmpeg-api/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | ffmpeg-serv
7 | me.liuzeyu
8 | 1.0-SNAPSHOT
9 | ../pom.xml
10 |
11 | 4.0.0
12 |
13 | ffmpeg-api
14 |
15 |
16 | 8
17 | 8
18 |
19 |
20 |
21 |
22 | org.apache.commons
23 | commons-lang3
24 |
25 |
26 |
27 | org.apache.commons
28 | commons-collections4
29 |
30 |
31 |
32 | commons-codec
33 | commons-codec
34 |
35 |
36 |
37 |
38 | com.alibaba
39 | fastjson
40 |
41 |
42 |
43 | org.projectlombok
44 | lombok
45 |
46 |
47 |
48 | jakarta.validation
49 | jakarta.validation-api
50 |
51 |
52 |
53 | com.google.guava
54 | guava
55 |
56 |
57 | org.projectlombok
58 | lombok
59 |
60 |
61 | org.projectlombok
62 | lombok
63 |
64 |
65 | org.projectlombok
66 | lombok
67 |
68 |
69 | org.projectlombok
70 | lombok
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/music-serv/music-impl/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | # 项目的启动端口
2 | server:
3 | port: 20000
4 | error:
5 | include-message: always
6 |
7 | spring:
8 | application:
9 | # 定义项目名称
10 | name: music-serv
11 | servlet:
12 | multipart:
13 | max-file-size: 20MB
14 | max-request-size: 20MB
15 | datasource:
16 | # mysql数据源
17 | username: root
18 | password: 1234
19 | url: jdbc:mysql://127.0.0.1:3306/ai_music_db?autoReconnect=true&useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true&zeroDateTimeBehavior=convertToNull&serverTimezone=UTC
20 | type: com.zaxxer.hikari.HikariDataSource
21 | driver-class-name: com.mysql.cj.jdbc.Driver
22 | # 连接池
23 | hikari:
24 | pool-name: MusicHikari
25 | connection-timeout: 5000
26 | idle-timeout: 30000
27 | maximum-pool-size: 10
28 | minimum-idle: 5
29 | max-lifetime: 60000
30 | auto-commit: true
31 | jpa:
32 | show-sql: true
33 | hibernate:
34 | # 在生产环境全部为none,防止ddl结构被自动执行
35 | ddl-auto: none
36 | properties:
37 | hibernate.format_sql: true
38 | hibernate.show_sql: true
39 | open-in-view: false
40 | cloud:
41 | nacos:
42 | discovery:
43 | # 可以配置多个,逗号分隔
44 | server-addr: localhost:8848
45 | # 默认就是application name,一般不用配置
46 | service: music-serv
47 | # nacos客户端向服务端发送心跳的时间间隔,时间单位其实是ms
48 | heart-beat-interval: 5000
49 | # 服务端没有接受到客户端心跳请求就将其设为不健康的时间间隔,默认为15s
50 | # 注:推荐值该值为15s即可,如果有的业务线希望服务下线或者出故障时希望尽快被发现,可以适当减少该值
51 | heart-beat-timeout: 15000
52 | # [注意] 这个IP地址如果更换网络后变化,会导致服务调用失败,建议先不要设置
53 | # ip: 172.20.7.228
54 | # 元数据部分 - 可以自己随便定制
55 | # metadata:
56 | # mydata: abc
57 | # 客户端在启动时是否读取本地配置项(一个文件)来获取服务列表
58 | # 注:推荐该值为false,若改成true。则客户端会在本地的一个文件中保存服务信息,当下次宕机启动时,会优先读取本地的配置对外提供服务。
59 | naming-load-cache-at-start: false
60 | # 创建不同的集群
61 | cluster-name: Cluster-A
62 | # 命名空间ID,Nacos通过不同的命名空间来区分不同的环境,进行数据隔离,
63 | # 服务消费时只能消费到对应命名空间下的服务。
64 | # [注意]需要在nacos-server中创建好namespace,然后把id copy进来
65 | namespace: dev
66 | # [注意]两个服务如果存在上下游调用关系,必须配置相同的group才能发起访问
67 | group: myGroup
68 | # 向注册中心注册服务,默认为true
69 | # 如果只消费服务,不作为服务提供方,倒是可以设置成false,减少开销
70 | register-enabled: true
71 | # 类似长连接监听服务端信息变化的功能
72 | watch:
73 | enabled: true
74 | watch-delay: 30000
75 |
76 |
77 | file:
78 | upload:
79 | path: D:\Downloads\tmp\upload-tmp
80 |
81 | logging:
82 | level:
83 | com.broadview.coupon: debug
--------------------------------------------------------------------------------
/auth-client/src/logo.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/middleware/gateway/src/main/java/me/liuzeyu/gateway/filter/JwtAuthenticationFilter.java:
--------------------------------------------------------------------------------
1 | package me.liuzeyu.gateway.filter;
2 |
3 | import java.util.Arrays;
4 | import java.util.List;
5 | import java.util.function.Predicate;
6 |
7 | import io.jsonwebtoken.Claims;
8 | import me.liuzeyu.gateway.exception.JwtTokenMalformedException;
9 | import me.liuzeyu.gateway.exception.JwtTokenMissingException;
10 | import me.liuzeyu.gateway.util.JwtUtil;
11 | import org.springframework.beans.factory.annotation.Autowired;
12 | import org.springframework.cloud.gateway.filter.GatewayFilter;
13 | import org.springframework.cloud.gateway.filter.GatewayFilterChain;
14 | import org.springframework.http.HttpStatus;
15 | import org.springframework.http.server.reactive.ServerHttpRequest;
16 | import org.springframework.http.server.reactive.ServerHttpResponse;
17 | import org.springframework.stereotype.Component;
18 | import org.springframework.web.server.ServerWebExchange;
19 |
20 |
21 | import reactor.core.publisher.Mono;
22 |
23 | @Component
24 | public class JwtAuthenticationFilter implements GatewayFilter {
25 |
26 | @Autowired
27 | private JwtUtil jwtUtil;
28 |
29 | @Override
30 | public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
31 | ServerHttpRequest request = (ServerHttpRequest) exchange.getRequest();
32 |
33 | final List apiEndpoints = Arrays.asList(new String[]{"/user"}) ;
34 |
35 | Predicate isApiSecured = r -> apiEndpoints.stream()
36 | .noneMatch(uri -> r.getURI().getPath().contains(uri));
37 |
38 | if (isApiSecured.test(request)) {
39 | if (!request.getHeaders().containsKey("Authorization")) {
40 | ServerHttpResponse response = exchange.getResponse();
41 | response.setStatusCode(HttpStatus.UNAUTHORIZED);
42 |
43 | return response.setComplete();
44 | }
45 |
46 | final String token = request.getHeaders().getOrEmpty("Authorization").get(0);
47 |
48 | try {
49 | jwtUtil.validateToken(token);
50 | } catch (JwtTokenMalformedException | JwtTokenMissingException e) {
51 |
52 | ServerHttpResponse response = exchange.getResponse();
53 | response.setStatusCode(HttpStatus.BAD_REQUEST);
54 |
55 | return response.setComplete();
56 | }
57 |
58 | Claims claims = jwtUtil.getClaims(token);
59 | exchange.getRequest().mutate().header("id", String.valueOf(claims.get("id"))).build();
60 | }
61 |
62 | return chain.filter(exchange);
63 | }
64 |
65 | }
--------------------------------------------------------------------------------
/auth-serv/auth-impl/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | # 项目的启动端口
2 | server:
3 | port: 20004
4 | error:
5 | include-message: always
6 |
7 | spring:
8 | application:
9 | # 定义项目名称
10 | name: auth-serv
11 | servlet:
12 | multipart:
13 | max-file-size: 20MB
14 | max-request-size: 20MB
15 | datasource:
16 | # mysql数据源
17 | username: root
18 | password: 1234
19 | url: jdbc:mysql://127.0.0.1:3306/ai_music_db?autoReconnect=true&useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true&zeroDateTimeBehavior=convertToNull&serverTimezone=UTC
20 | type: com.zaxxer.hikari.HikariDataSource
21 | driver-class-name: com.mysql.cj.jdbc.Driver
22 | # 连接池
23 | hikari:
24 | pool-name: AuthHikari
25 | connection-timeout: 5000
26 | idle-timeout: 30000
27 | maximum-pool-size: 10
28 | minimum-idle: 5
29 | max-lifetime: 60000
30 | auto-commit: true
31 | jpa:
32 | show-sql: true
33 | hibernate:
34 | # 在生产环境全部为none,防止ddl结构被自动执行
35 | ddl-auto: none
36 | properties:
37 | hibernate.format_sql: true
38 | hibernate.show_sql: true
39 | open-in-view: false
40 | cloud:
41 | nacos:
42 | discovery:
43 | # 可以配置多个,逗号分隔
44 | server-addr: localhost:8848
45 | # 默认就是application name,一般不用配置
46 | service: auth-serv
47 | # nacos客户端向服务端发送心跳的时间间隔,时间单位其实是ms
48 | heart-beat-interval: 5000
49 | # 服务端没有接受到客户端心跳请求就将其设为不健康的时间间隔,默认为15s
50 | # 注:推荐值该值为15s即可,如果有的业务线希望服务下线或者出故障时希望尽快被发现,可以适当减少该值
51 | heart-beat-timeout: 15000
52 | # [注意] 这个IP地址如果更换网络后变化,会导致服务调用失败,建议先不要设置
53 | # ip: 172.20.7.228
54 | # 元数据部分 - 可以自己随便定制
55 | # metadata:
56 | # mydata: abc
57 | # 客户端在启动时是否读取本地配置项(一个文件)来获取服务列表
58 | # 注:推荐该值为false,若改成true。则客户端会在本地的一个文件中保存服务信息,当下次宕机启动时,会优先读取本地的配置对外提供服务。
59 | naming-load-cache-at-start: false
60 | # 创建不同的集群
61 | cluster-name: Cluster-A
62 | # 命名空间ID,Nacos通过不同的命名空间来区分不同的环境,进行数据隔离,
63 | # 服务消费时只能消费到对应命名空间下的服务。
64 | # [注意]需要在nacos-server中创建好namespace,然后把id copy进来
65 | namespace: dev
66 | # [注意]两个服务如果存在上下游调用关系,必须配置相同的group才能发起访问
67 | group: myGroup
68 | # 向注册中心注册服务,默认为true
69 | # 如果只消费服务,不作为服务提供方,倒是可以设置成false,减少开销
70 | register-enabled: true
71 | # 类似长连接监听服务端信息变化的功能
72 | watch:
73 | enabled: true
74 | watch-delay: 30000
75 |
76 | logging:
77 | level:
78 | com.broadview.coupon: debug
79 |
80 | security:
81 | basic:
82 | enable: false
83 |
84 | jwt:
85 | uri: /user/**
86 | header: Authorization
87 | prefix: Bearer
88 | expiration: 864000000
89 | secret: JwtSecretKey
--------------------------------------------------------------------------------
/music-client/config/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | // Template version: 1.3.1
3 | // see http://vuejs-templates.github.io/webpack for documentation.
4 |
5 | const path = require('path')
6 |
7 | module.exports = {
8 | dev: {
9 |
10 | // Paths
11 | assetsSubDirectory: 'static',
12 | assetsPublicPath: '/',
13 | proxyTable: {},
14 |
15 |
16 | // Proxy
17 | proxyTable: {
18 | "/api": {
19 | target: 'http://localhost:30000',
20 | }
21 | },
22 |
23 | // Various Dev Server settings
24 | host: 'localhost', // can be overwritten by process.env.HOST
25 | port: 3000, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
26 | autoOpenBrowser: false,
27 | errorOverlay: true,
28 | notifyOnErrors: true,
29 | poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
30 |
31 | // Use Eslint Loader?
32 | // If true, your code will be linted during bundling and
33 | // linting errors and warnings will be shown in the console.
34 | useEslint: true,
35 | // If true, eslint errors and warnings will also be shown in the error overlay
36 | // in the browser.
37 | showEslintErrorsInOverlay: false,
38 |
39 | /**
40 | * Source Maps
41 | */
42 |
43 | // https://webpack.js.org/configuration/devtool/#development
44 | devtool: 'cheap-module-eval-source-map',
45 |
46 | // If you have problems debugging vue-files in devtools,
47 | // set this to false - it *may* help
48 | // https://vue-loader.vuejs.org/en/options.html#cachebusting
49 | cacheBusting: true,
50 |
51 | cssSourceMap: true
52 | },
53 |
54 | build: {
55 | // Template for index.html
56 | index: path.resolve(__dirname, '../dist/index.html'),
57 |
58 | // Paths
59 | assetsRoot: path.resolve(__dirname, '../dist'),
60 | assetsSubDirectory: 'static',
61 | assetsPublicPath: '/',
62 |
63 | /**
64 | * Source Maps
65 | */
66 |
67 | productionSourceMap: true,
68 | // https://webpack.js.org/configuration/devtool/#production
69 | devtool: '#source-map',
70 |
71 | // Gzip off by default as many popular static hosts such as
72 | // Surge or Netlify already gzip all static assets for you.
73 | // Before setting to `true`, make sure to:
74 | // npm install --save-dev compression-webpack-plugin
75 | productionGzip: false,
76 | productionGzipExtensions: ['js', 'css'],
77 |
78 | // Run the build command with an extra argument to
79 | // View the bundle analyzer report after build finishes:
80 | // `npm run build --report`
81 | // Set to `true` or `false` to always turn it on or off
82 | bundleAnalyzerReport: process.env.npm_config_report
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/music-client/build/webpack.base.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 | const utils = require('./utils')
4 | const config = require('../config')
5 | const vueLoaderConfig = require('./vue-loader.conf')
6 |
7 | function resolve (dir) {
8 | return path.join(__dirname, '..', dir)
9 | }
10 |
11 | const createLintingRule = () => ({
12 | test: /\.(js|vue)$/,
13 | loader: 'eslint-loader',
14 | enforce: 'pre',
15 | include: [resolve('src'), resolve('test')],
16 | options: {
17 | formatter: require('eslint-friendly-formatter'),
18 | emitWarning: !config.dev.showEslintErrorsInOverlay
19 | }
20 | })
21 |
22 | module.exports = {
23 | context: path.resolve(__dirname, '../'),
24 | entry: {
25 | app: './src/main.js'
26 | },
27 | output: {
28 | path: config.build.assetsRoot,
29 | filename: '[name].js',
30 | publicPath: process.env.NODE_ENV === 'production'
31 | ? config.build.assetsPublicPath
32 | : config.dev.assetsPublicPath
33 | },
34 | resolve: {
35 | extensions: ['.js', '.vue', '.json'],
36 | alias: {
37 | 'src': resolve('src'),
38 | 'common': resolve('src/common'),
39 | 'components': resolve('src/components'),
40 | 'api': resolve('src/api')
41 | }
42 | },
43 | module: {
44 | rules: [
45 | // ...(config.dev.useEslint ? [createLintingRule()] : []),
46 | {
47 | test: /\.vue$/,
48 | loader: 'vue-loader',
49 | options: vueLoaderConfig
50 | },
51 | {
52 | test: /\.js$/,
53 | loader: 'babel-loader',
54 | include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
55 | },
56 | {
57 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
58 | loader: 'url-loader',
59 | options: {
60 | limit: 10000,
61 | name: utils.assetsPath('img/[name].[hash:7].[ext]')
62 | }
63 | },
64 | {
65 | test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
66 | loader: 'url-loader',
67 | options: {
68 | limit: 10000,
69 | name: utils.assetsPath('media/[name].[hash:7].[ext]')
70 | }
71 | },
72 | {
73 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
74 | loader: 'url-loader',
75 | options: {
76 | limit: 10000,
77 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
78 | }
79 | }
80 | ]
81 | },
82 | node: {
83 | // prevent webpack from injecting useless setImmediate polyfill because Vue
84 | // source contains it (although only uses it if it's native).
85 | setImmediate: false,
86 | // prevent webpack from injecting mocks to Node native modules
87 | // that does not make sense for the client
88 | dgram: 'empty',
89 | fs: 'empty',
90 | net: 'empty',
91 | tls: 'empty',
92 | child_process: 'empty'
93 | }
94 | }
95 |
--------------------------------------------------------------------------------