├── 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 | 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 | 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 | 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 | 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 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 | 17 | 18 | 23 | 24 | 42 | -------------------------------------------------------------------------------- /music-client/src/base/switches/switches.vue: -------------------------------------------------------------------------------- 1 | 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 | 10 | 11 | 20 | 21 | 55 | -------------------------------------------------------------------------------- /music-client/src/base/progress-circle/progress-circle.vue: -------------------------------------------------------------------------------- 1 | 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 | 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 |
40 | 41 |
47 | 51 | 52 | 53 | 57 | 58 | 59 | 63 | 64 | 65 | 66 | 75 | 76 | 已注册? 登录 77 |
78 |
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 | 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 |
49 | 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 | 2 | 3 | 4 | 5 | 6 | 7 | 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 | --------------------------------------------------------------------------------