最新优化版本

This commit is contained in:
P1kaj1uu 2024-02-05 12:39:26 +08:00
parent 4ab622670e
commit de0d551f80
25 changed files with 1227 additions and 267 deletions

40
package-lock.json generated
View File

@ -4460,6 +4460,15 @@
"resolved": "https://registry.npmmirror.com/interpret/-/interpret-2.2.0.tgz",
"integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw=="
},
"ip-address": {
"version": "8.1.0",
"resolved": "https://registry.npmmirror.com/ip-address/-/ip-address-8.1.0.tgz",
"integrity": "sha512-Wz91gZKpNKoXtqvY8ScarKYwhXoK4r/b5QuT+uywe/azv0/nUCo7Bh0IRRI7F9DHR06kJNWtzMGLIbXavngbKA==",
"requires": {
"jsbn": "1.1.0",
"sprintf-js": "1.1.2"
}
},
"ipaddr.js": {
"version": "2.0.1",
"resolved": "https://registry.npmmirror.com/ipaddr.js/-/ipaddr.js-2.0.1.tgz",
@ -4654,6 +4663,11 @@
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
"dev": true
},
"jsbn": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/jsbn/-/jsbn-1.1.0.tgz",
"integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A=="
},
"jsesc": {
"version": "2.5.2",
"resolved": "https://registry.npmmirror.com/jsesc/-/jsesc-2.5.2.tgz",
@ -6891,6 +6905,11 @@
"integrity": "sha512-8o/QEhSSRb1a5i7TFR0iM4G16Z0vYB2OQVs4G3aAFXjn3T6yEx8AZxy1PgDF7I00LZHYA3WxaSYIf5e5sAX8Rw==",
"dev": true
},
"shvl": {
"version": "2.0.3",
"resolved": "https://registry.npmmirror.com/shvl/-/shvl-2.0.3.tgz",
"integrity": "sha512-V7C6S9Hlol6SzOJPnQ7qzOVEWUQImt3BNmmzh40wObhla3XOYMe4gGiYzLrJd5TFa+cI2f9LKIRJTTKZSTbWgw=="
},
"side-channel": {
"version": "1.0.4",
"resolved": "https://registry.npmmirror.com/side-channel/-/side-channel-1.0.4.tgz",
@ -7027,6 +7046,11 @@
"wbuf": "^1.7.3"
}
},
"sprintf-js": {
"version": "1.1.2",
"resolved": "https://registry.npmmirror.com/sprintf-js/-/sprintf-js-1.1.2.tgz",
"integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug=="
},
"ssri": {
"version": "8.0.1",
"resolved": "https://registry.npmmirror.com/ssri/-/ssri-8.0.1.tgz",
@ -7549,6 +7573,22 @@
"resolved": "https://registry.npmmirror.com/vuex/-/vuex-3.6.2.tgz",
"integrity": "sha512-ETW44IqCgBpVomy520DT5jf8n0zoCac+sxWnn+hMe/CzaSejb/eVw2YToiXYX+Ex/AuHHia28vWTq4goAexFbw=="
},
"vuex-persistedstate": {
"version": "4.1.0",
"resolved": "https://registry.npmmirror.com/vuex-persistedstate/-/vuex-persistedstate-4.1.0.tgz",
"integrity": "sha512-3SkEj4NqwM69ikJdFVw6gObeB0NHyspRYMYkR/EbhR0hbvAKyR5gksVhtAfY1UYuWUOCCA0QNGwv9pOwdj+XUQ==",
"requires": {
"deepmerge": "^4.2.2",
"shvl": "^2.0.3"
},
"dependencies": {
"deepmerge": {
"version": "4.3.1",
"resolved": "https://registry.npmmirror.com/deepmerge/-/deepmerge-4.3.1.tgz",
"integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="
}
}
},
"watchpack": {
"version": "2.4.0",
"resolved": "https://registry.npmmirror.com/watchpack/-/watchpack-2.4.0.tgz",

View File

@ -11,6 +11,7 @@
"core-js": "^3.8.3",
"element-ui": "^2.15.12",
"highlight.js": "^11.8.0",
"ip-address": "^8.1.0",
"js-md5": "^0.7.3",
"lib-flexible": "^0.3.2",
"markdown-it": "^13.0.1",
@ -20,7 +21,8 @@
"vue": "^2.6.14",
"vue-puzzle-vcode": "^1.1.10",
"vue-router": "^3.5.1",
"vuex": "^3.6.2"
"vuex": "^3.6.2",
"vuex-persistedstate": "^4.1.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~5.0.0",

View File

@ -6,29 +6,84 @@
</template>
<script>
import axios from 'axios'
import { mapMutations } from 'vuex'
import { sleep } from '@/utils/sleep'
export default {
name: 'App',
created () {
console.info("%c欢迎您访问不见水星记的网站预祝使用愉快\n\n%c _oo0oo_\n o8888888o\n 88\" . \"88\n (| -_- |)\n 0\\ = /0\n ___/---\\___\n .' \\\\| |// '.\n / \\\\||| : |||// \\\n/ _||||| -:- |||||- \\\n| | \\\\\\ - /// | |\n| \\_| ''\\---/'' |_/ |\n \\ .-\\__ '-' ___/-. /\n'-.____'-.____\\<><>/.____.-'\n '=---='\n\n 佛祖保佑永无bug", "font-family: 'Microsoft YaHei'; font-size: 24px; color: #00BFFF; text-shadow: 1px 1px #D3D3D3;", "font-size: 18px;color: green;");
methods: {
...mapMutations('funAi', ['setToken', 'setUserId']),
},
created() {
axios({
url: '/api/user/login',
method: 'POST',
data: {
'loginAcct': 'FunAi',
'loginType': 2,
'password': '*****',
}
}).then(res => {
const { token, userId } = res.data.data
this.setToken(token)
this.setUserId(userId)
}).catch(error => {
console.log(error)
})
document.addEventListener('contextmenu', function (e) {
e.preventDefault()
})
console.info(
"%c欢迎您访问不见水星记的网站预祝使用愉快\n\n%c _oo0oo_\n o8888888o\n 88\" . \"88\n (| -_- |)\n 0\\ = /0\n ___/---\\___\n .' \\\\| |// '.\n / \\\\||| : |||// \\\n/ _||||| -:- |||||- \\\n| | \\\\\\ - /// | |\n| \\_| ''\\---/'' |_/ |\n \\ .-\\__ '-' ___/-. /\n'-.____'-.____\\<><>/.____.-'\n '=---='\n\n 佛祖保佑永无bug",
"font-family: 'Microsoft YaHei'; font-size: 24px; color: #00BFFF; text-shadow: 1px 1px #D3D3D3;",
'font-size: 18px;color: green;'
)
;(function () {
sleep(210).then(() => {
if (localStorage.getItem('WEBS_VERSION') !== 'V3.0.0') {
const res = confirm(
'系统消息hi~您好,欢迎访问不见水星记的网站!我的网站有新版本发布哦,是否更新?'
)
if (res) {
localStorage.setItem('WEBS_VERSION', 'V3.0.0')
location.reload()
}
}
})
})()
//
(function () {
;(function () {
var a_idx = 0
window.onclick = function (event) {
var a = new Array("富强", "民主", "文明", "和谐", "自由", "平等", "公正", "法治", "爱国",
"敬业", "诚信", "友善");
var a = new Array(
'富强',
'民主',
'文明',
'和谐',
'自由',
'平等',
'公正',
'法治',
'爱国',
'敬业',
'诚信',
'友善'
)
// b
var heart = document.createElement("b")
var heart = document.createElement('b')
//
heart.onselectstart = new Function('event.returnValue = false')
// b
document.body.appendChild(heart).innerHTML = a[a_idx]
a_idx = (a_idx + 1) % a.length
// p
heart.style.cssText = "position: fixed; left: -100%;"
heart.style.cssText = 'position: fixed; left: -100%;'
var f = 16, //
x = event.clientX - f / 2, //
@ -37,31 +92,46 @@ export default {
a = 1, //
s = 1.2 //
var timer = setInterval(function () { //
var timer = setInterval(function () {
//
if (a <= 0) {
document.body.removeChild(heart)
clearInterval(timer)
} else {
heart.style.cssText = "font-size: 16px; cursor: default; position: fixed; color:" +
c + "; left:" + x + "px; top:" + y + "px; opacity:" + a + "; transform:scale(" +
s + ");"
heart.style.cssText =
'font-size: 16px; cursor: default; position: fixed; color:' +
c +
'; left:' +
x +
'px; top:' +
y +
'px; opacity:' +
a +
'; transform:scale(' +
s +
');'
y--
a -= 0.016
s += 0.002
}
}, 15)
}
//
function randomColor() {
return "rgb(" + (~~(Math.random() * 255)) + "," + (~~(Math.random() * 255)) + "," + (~~(Math.random() * 255)) + ")"
return (
'rgb(' +
~~(Math.random() * 255) +
',' +
~~(Math.random() * 255) +
',' +
~~(Math.random() * 255) +
')'
)
}
}())
})()
}
}
</script>
<style lang="less" scoped>
</style>
<style lang="less" scoped></style>

View File

@ -9,8 +9,8 @@ export const getData = () => {
var data = [
{
name: '视频解析接口不对外开放',
url: '******'
name: '本地不展示',
url: 'XXX'
}
]

View File

@ -5,7 +5,6 @@ body,
margin: 0;
padding: 0;
height: 100%;
min-width: 1366px;
}
.el-breadcrumb {

View File

@ -0,0 +1,80 @@
#chat-markdown ol {
padding-left: 2em;
}
#chat-markdown .hljs {
border-radius: 5px;
padding: 50px 15px 15px 15px;
position: relative;
overflow: auto;
background: #292b33;
}
#chat-markdown .hljs::-webkit-scrollbar {
height: 9px;
}
#chat-markdown .hljs::-webkit-scrollbar-track {
background-color: #fff;
}
#chat-markdown .hljs::-webkit-scrollbar-thumb {
background-color: #d8d8d8;
border-radius: 5px;
}
#chat-markdown .hljs .code-header {
display: flex;
justify-content: space-between;
height: 35px;
width: 100%;
background-color: rgb(50, 55, 65);
position: absolute;
left: 0;
top: 0;
border-radius: 5px 5px 0 0;
font-family: SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;
}
#chat-markdown .hljs .code-header .copy {
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
padding-right: 10px;
font-size: 12px;
}
#chat-markdown .hljs .code-header .copy img {
height: 19px;
width: 19px;
}
#chat-markdown .hljs .code-header .copy p {
color: #fff;
}
#chat-markdown .hljs .code-header .lang {
font-size: 12px;
height: 35px;
cursor: pointer;
color: #fff;
line-height: 35px;
padding-left: 15px;
}
#chat-markdown .hljs code {
font-family: SFMono-Regular,Menlo,Monaco,Consolas,monospace !important;
}
#chat-markdown .hljs code {
color: rgb(212, 212, 212);
}
#chat-markdown .hljs code span {
color: rgb(212, 212, 212);
}
#chat-markdown .hljs code .hljs-comment {
color: rgb(106, 153, 85);
}
#chat-markdown .hljs code .hljs-keyword {
color: rgb(86, 156, 214);
}
#chat-markdown .hljs code .function_ {
color: rgb(220, 220, 170);
}
#chat-markdown .hljs code .hljs-params {
color: rgb(156, 220, 254);
}
#chat-markdown .hljs code .class_ {
color: rgb(78, 201, 176);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 451 B

View File

@ -6,6 +6,7 @@ import '@/utils/flexible'
import './plugins/element.js'
//
import './assets/css/global.css'
import './assets/css/markdown.css'
//
import '@/plugins/sakura'

View File

@ -28,7 +28,10 @@ import {
Message,
MessageBox,
Tooltip,
Loading
Loading,
Backtop,
Image,
Slider
} from 'element-ui'
Vue.use(Button)
@ -52,9 +55,13 @@ import {
Vue.use(Option)
Vue.use(Input)
Vue.use(Tooltip)
Vue.use(Backtop)
Vue.use(Image)
Vue.use(Slider)
Vue.prototype.$notify = Notification
Vue.prototype.$message = Message
Vue.prototype.$msgbox = MessageBox
Vue.prototype.$confirm = MessageBox.confirm
Vue.prototype.$prompt = MessageBox.prompt
Vue.prototype.$loading = Loading.service

View File

@ -46,6 +46,11 @@ const routes = [
name: 'chatgpt',
component: () => import(/* webpackChunkName: "chatgpt" */ '../views/GPT.vue')
},
{
path: 'textToImg',
name: 'textToImg',
component: () => import(/* webpackChunkName: "textToImg" */ '../views/TextToPhoto.vue')
},
{
path: 'help',
name: 'help',

28
src/store/funAi.js Normal file
View File

@ -0,0 +1,28 @@
const state = {
token: '',
userId: ''
}
const mutations = {
setToken (state, token) {
state.token = token
},
setUserId (state, userId) {
state.userId = userId
}
}
const actions = {}
const getters = {
token: (state) => state.token,
userId: (state) => state.userId
}
export default {
namespaced: true,
state,
mutations,
actions,
getters
}

View File

@ -1,5 +1,8 @@
import createPersistedState from 'vuex-persistedstate'
import Vue from 'vue'
import Vuex from 'vuex'
import slide from './slide'
import funAi from './funAi'
Vue.use(Vuex)
@ -13,5 +16,8 @@ export default new Vuex.Store({
actions: {
},
modules: {
}
slide,
funAi
},
plugins: [createPersistedState()],
})

23
src/store/slide.js Normal file
View File

@ -0,0 +1,23 @@
const state = {
currentMenu: '/home/music'
}
const mutations = {
setCurrentMenu (state, currentMenu) {
state.currentMenu = currentMenu
}
}
const actions = {}
const getters = {
currentMenu: (state) => state.currentMenu
}
export default {
namespaced: true,
state,
mutations,
actions,
getters
}

59
src/utils/compressImg.js Normal file
View File

@ -0,0 +1,59 @@
/**
* @Description: 压缩图片到指定大小
* @Author: 不见水星记P1kaj1uu
* @param baseImg base64图片
* @param maxSize 单位kb
*/
export function compressImgBySize(baseImg, maxSize = 200) {
return new Promise((resolve) => {
//
const strLength = baseImg.length
const fileLength = parseInt(strLength - (strLength / 8) * 2)
let size = parseInt((fileLength / 1024).toFixed(2))
//
if (size <= maxSize) {
resolve(baseImg)
return
}
// image
const img = new Image()
if (baseImg.indexOf('data:image/') !== -1) {
img.src = baseImg
} else {
img.src = 'data:image/jpeg;base64,' + baseImg
}
img.onload = () => {
// image canvas
const canvas = imgToCanvas(img)
let resUrl = ''
// 0 ~ 1
let quality = 0.9
// maxSize0
while (size > maxSize && quality > 0) {
// canvasHTMLImageElementbase64
resUrl = canvas
.toDataURL('image/jpeg', quality)
.replace(/^data:image\/\w+;base64,/, '')
const resLength = resUrl.length
// base64
const resFileLength = parseInt(resLength - (resLength / 8) * 2)
size = parseInt((resFileLength / 1024).toFixed(2))
//
quality = (quality - 0.1).toFixed(1)
}
resolve(resUrl)
}
img.onerror = () => {
resolve(baseImg)
}
})
}
// image canvas
export function imgToCanvas(image) {
let canvas = document.createElement('canvas')
canvas.width = image.width
canvas.height = image.height
canvas.getContext('2d').drawImage(image, 0, 0)
return canvas
}

View File

@ -2,6 +2,7 @@
* @Description: 封装GPT响应内容流式输出
* @Author: 不见水星记P1kaj1uu
*/
import Vue from 'vue'
import { toBottom } from './messageToBottom'
export const resolveStreamResponse = async (
@ -26,15 +27,36 @@ export const resolveStreamResponse = async (
const utf8Decoder = new TextDecoder('utf-8')
let data = value ? utf8Decoder.decode(value, { stream: true }) : ''
console.log(data)
const ids = data.replaceAll(`data: `, '')
.replaceAll('[DONE]', '')
.split('\n')
.filter(item => item !== '')
.filter(item => item !== undefined)[1]
if (Boolean(!localStorage.getItem('newChatId')) && Boolean(ids) && Boolean(JSON.parse(ids).newChatId)) {
localStorage.setItem('newChatId', JSON.parse(ids).newChatId)
}
// "data: ""[DONE]"使splitJSON
// 使mapJSONJS使onStreaming
try {
data = data
/* data = data
.replaceAll(`data: `, '')
.replaceAll('[DONE]', '')
.split('\n')
.filter((_) => _ !== '')
.map((_) => JSON.parse(_))
data.forEach((_) => onStreaming(_)) */
data = data
.replaceAll(`data: `, '')
.replaceAll('[DONE]', '')
.split('\n')
.filter(item => item !== '')
.map(item => {
if (item.indexOf('"content":') !== -1) {
const stringify = JSON.stringify(item)
return JSON.parse(stringify)
}
})
.filter(item => item !== undefined)
data.forEach((_) => onStreaming(_))
} catch (e) {
onFailed(e)
@ -46,7 +68,7 @@ export const resolveStreamResponse = async (
button1.disabled = false
button2.disabled = false
toBottom()
onFinished()
onFinished(response)
break
} else {
button1.disabled = true

View File

@ -17,7 +17,7 @@
<div class="aboutMe">关于-声明</div>
<h2>关于</h2>
<ol>
<li>1&nbsp;.&nbsp;算机科学与技术专业正在美团前端实习的大四学生</li>
<li>1&nbsp;.&nbsp;科专业应届生三段专业相关实习经历在美团前端实习过参加过字节跳动青训营</li>
<li>2&nbsp;.&nbsp;个人博客https://cnblogs.com/P1kaj1uu</li>
<li>3&nbsp;.&nbsp;项目地址https://github.com/P1kaj1uu/VIP-Video-Parsing</li>
<li>
@ -27,7 +27,7 @@
</ol>
<h2 style="margin-top: 40px;">声明</h2>
<ol>
<li>1&nbsp;.&nbsp;该项目准备开源部署服务器</li>
<li>1&nbsp;.&nbsp;该项目已开源同时部署服务器</li>
<li>2&nbsp;.&nbsp;以后可能会尝试网站备案</li>
<li style="font-weight: 600;">3&nbsp;.&nbsp;本站只提供音乐影视解析和ChatGPT服务请勿用于任何商业用途如有侵权请联系我</li>
<li style="font-weight: 600;">4&nbsp;.&nbsp;请不要黑我服务器</li>
@ -42,7 +42,7 @@
<script>
export default {
name: "AboutView",
name: "About",
created() {
if (document.querySelector('.el-notification')) {
document.querySelector('.el-notification').style.display = 'none'

View File

@ -55,7 +55,9 @@
>
<img src="@/assets/images/gpt/trumpet.png" @click="playSoundFn" class="trumpetImg" alt="播放">
</el-tooltip>
<div class="ai chat" v-html="markdown(item.content)"></div>
<div class="ai chat ai-content">
<div v-html="markdown(item.content)" id="chat-markdown"></div>
</div>
<div class="infoAI-time">
<img src="@/assets/images/gpt/chatgpt.jpg" />
<span class="gptName">ChatGPT</span>
@ -114,6 +116,7 @@
</template>
<script>
import CopyGPTIcon from '@/assets/images/gpt/icon-copy-gpt.png'
import VuePuzzleVcode from 'vue-puzzle-vcode'
import Role from '@/components/Role'
import { sleep } from '@/utils/sleep'
@ -134,7 +137,7 @@ const initSession = [
]
export default {
name: 'GPTView',
name: 'GPT',
data() {
return {
gptValue: '',
@ -165,6 +168,42 @@ export default {
this.$message.warning('发送的消息不能为空哦~')
return
}
localStorage.getItem('GPTToken') ? this.gptSuccessVerify() : this.gptCheckModal()
},
// GPT
gptCheckModal() {
this.$prompt('当前状态为未验证请您输入本网站的ChatGPT验证码详情可联系我wxDveiklokk添加好友时请注明来意', '验证身份', {
type: 'warning',
center: true,
confirmButtonText: '确定',
cancelButtonText: '取消',
inputPattern: /[\w!#$%&'*+/=?^_`{|}~-]+(?:\.[\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\w](?:[\w-]*[\w])?\.)+[\w](?:[\w-]*[\w])?/,
inputErrorMessage: '格式不正确'
})
.then(({ value }) => {
if (value !== '891523233@qq.com') {
this.$message({
type: 'error',
message: '验证码错误'
})
} else {
localStorage.setItem('GPTToken', value)
this.$message({
type: 'success',
message: '验证成功'
})
this.gptSuccessVerify()
}
})
.catch(() => {
this.$message({
type: 'info',
message: '取消验证'
})
})
},
// GPT
gptSuccessVerify() {
++this.times
if (localStorage.getItem('session_times') >= 12) {
this.$message.warning('系统检测到当前环境异常,请先验证!')
@ -203,23 +242,17 @@ export default {
async getGPTResponse (content) {
// GPT3.5
const fetchPromise = fetch(
`GPT.URL`,
`URL`,
{
method: 'POST',
headers: {
'content-type': 'application/json'
'content-type': 'application/json',
'Authorization': 'Bearer ziyu-ystf3oih4jkfwkiljzt6n8bx-64b8a44109959843bc8945cb',
},
body: JSON.stringify({
frequency_penalty: 0,
max_tokens: 1000,
messages: this.messages,
model: 'gpt-3.5-turbo',
n: 1,
presence_penalty: 0,
stop: '',
chatId: localStorage.getItem('newChatId') || '',
stream: true,
temperature: 1,
top_p: 1
messages: [{"content": content, "role": "user"}]
})
}
).catch(() => {
@ -238,15 +271,21 @@ export default {
resolveStreamResponse(
fetchPromise,
(data) => {
message.content += data.choices.map((_) => _.delta.content).join('')
message.content += JSON.parse(data).choices[0].delta.content
this.toMessageBottom()
//message.content += data.choices.map((_) => _.delta.content).join('')
},
(err) => {
message.content += '宝,我出错啦,这个问题我也不知道该怎么回答你呢,要不你慢一点,容我再想一想~(建议:清空会话记录试试...'
this.$message.error('出错啦~建议刷新页面后,再重新尝试')
this.$message.error('服务器出错啦~')
console.log('错误!', err)
},
() => {
(res) => {
localStorage.setItem('session_cached', JSON.stringify(this.messages))
if (res.status && res.status === 500) {
message.content += 'APIKey余额不足~请联系我wxDveiklokk进行充值'
this.$message.warning('APIKey余额不足')
}
},
document.querySelector('.sendImg'),
document.querySelector('.clears')
@ -268,6 +307,7 @@ export default {
type: 'success',
message: '清空成功'
})
localStorage.removeItem('newChatId')
this.messages = this.backupMessage
this.setSessionCache()
})
@ -285,28 +325,34 @@ export default {
return JSON.parse(localStorage.getItem('session_cached'))
},
// markdown
markdown (content) {
markdown(content) {
const md = new MarkdownIt({
highlight: function (str, lang) {
highlight: function(str, lang) {
if (lang && hljs.getLanguage(lang)) {
try {
return (
'<pre class="hljs"><button class="CodesBlock" @click="copyCodeBlock">复制代码</button><code>' +
'<pre class="hljs"><div class="code-header"><div class="lang">' +
lang +
'</div><div class="copy"><img src="' +
CopyGPTIcon +
'" /><p>复制</p></div></div><code>' +
hljs.highlight(lang, str, true).value +
'</code></pre>'
)
} catch (__) {}
}
return (
'<pre class="hljs"><button class="CodesBlock" @click="copyCodeBlock">复制代码</button><code>' +
'<pre class="hljs"><div class="code-header"><div class="lang"></div><div class="copy" ><img src="' +
CopyGPTIcon +
'" /><p>复制</p></div></div><code>' +
md.utils.escapeHtml(str) +
'</code></pre>'
)
}
},
})
const result = md.render(content)
this.$nextTick(() => {
let elements = document.querySelectorAll('.CodesBlock')
let elements = document.querySelectorAll('.copy')
elements.forEach(item => {
item.addEventListener('click', this.copyCodeBlock)
})
@ -324,7 +370,6 @@ export default {
input.forEach(item => {
textarea.value += item.innerText || item.textContent
})
textarea.value = textarea.value.replaceAll('复制代码', '')
// <textarea>
document.body.appendChild(textarea)
textarea.select()
@ -348,7 +393,7 @@ export default {
},
//
copyCodeBlock (e) {
const codes = e.target.nextElementSibling
const codes = e.target.parentNode.parentNode.nextElementSibling
const text = codes.innerText || codes.textContent
const textarea = document.createElement('textarea')
textarea.value = text
@ -431,23 +476,6 @@ export default {
</script>
<style lang="less" scoped>
/deep/ .hljs {
position: relative;
padding: 10px;
background-color: #f6f8fa;
}
/deep/ .CodesBlock {
position: absolute;
top: 5px;
right: 5px;
cursor: pointer;
font-size: 15px;
background-color: #f6f8fa;
}
/deep/ .CodesBlock:hover {
color: pink;
}
.gptContainer {
position: relative;
}
@ -669,6 +697,14 @@ export default {
}
}
.ai-content {
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #292a2d;
line-height: 24px;
}
.loadEffect {
display: none;
width: 100px;

View File

@ -3,113 +3,145 @@
* @Author: 不见水星记P1kaj1uu
-->
<template>
<div>
<!-- 面包屑导航区域 -->
<el-breadcrumb separator-class="el-icon-arrow-right">
<el-breadcrumb-item>首页</el-breadcrumb-item>
<el-breadcrumb-item>帮助</el-breadcrumb-item>
</el-breadcrumb>
<!-- 卡片视图区域 -->
<el-card>
<el-row style="text-align: center;">
<el-col>
<div class="steps">第一步进入官方视频网站界面搜索需要会员的电视剧或者电影</div>
</el-col>
<el-col>
<img class="helpImgs" src="@/assets/images/help/help1.png">
</el-col>
</el-row>
</el-card>
<div>
<!-- 面包屑导航区域 -->
<el-breadcrumb separator-class="el-icon-arrow-right">
<el-breadcrumb-item>首页</el-breadcrumb-item>
<el-breadcrumb-item>帮助</el-breadcrumb-item>
</el-breadcrumb>
<el-card>
<el-row style="text-align: center;">
<el-col>
<div class="steps">第二步选择你喜欢的电视剧电影之后复制对应地址栏的地址</div>
</el-col>
<el-col>
<img class="helpImgs" src="@/assets/images/help/help2.png">
</el-col>
</el-row>
</el-card>
<!-- 卡片视图区域 -->
<el-card>
<el-row style="text-align: center">
<el-col>
<div class="steps">
第一步进入官方视频网站界面搜索需要会员的电视剧或者电影
</div>
</el-col>
<el-col>
<img class="helpImgs" src="@/assets/images/help/help1.png" />
</el-col>
</el-row>
</el-card>
<el-card>
<el-row style="text-align: center;">
<el-col>
<div class="steps">第三步返回观看页面粘贴复制的地址选择解析接口点击立即播放按钮</div>
</el-col>
<el-col>
<img class="helpImgs" src="@/assets/images/help/help3.png">
</el-col>
</el-row>
</el-card>
<el-card>
<el-row style="text-align: center">
<el-col>
<div class="steps">
第二步选择你喜欢的电视剧电影之后复制对应地址栏的地址
</div>
</el-col>
<el-col>
<img class="helpImgs" src="@/assets/images/help/help2.png" />
</el-col>
</el-row>
</el-card>
<el-card>
<el-row style="text-align: center;">
<el-col>
<div class="steps">备注1若出现如下情况请看下面的备注2-备注4</div>
</el-col>
<el-col>
<img class="helpImgs" src="@/assets/images/help/help4.png">
</el-col>
</el-row>
</el-card>
<el-card>
<el-row style="text-align: center">
<el-col>
<div class="steps">
第三步返回观看页面粘贴复制的地址选择解析接口点击立即播放按钮
</div>
</el-col>
<el-col>
<img class="helpImgs" src="@/assets/images/help/help3.png" />
</el-col>
</el-row>
</el-card>
<el-card>
<el-row style="text-align: center;">
<el-col>
<div class="steps">备注2若出现备注1的情况则先在视频输入框中输入完整片名然后点击搜索按钮</div>
</el-col>
<el-col>
<img class="helpImgs" src="@/assets/images/help/help5.png">
</el-col>
</el-row>
</el-card>
<el-card>
<el-row style="text-align: center">
<el-col>
<div class="steps">备注1若出现如下情况请看下面的备注2-备注4</div>
</el-col>
<el-col>
<img class="helpImgs" src="@/assets/images/help/help4.png" />
</el-col>
</el-row>
</el-card>
<el-card>
<el-row style="text-align: center;">
<el-col>
<div class="steps">备注3若出现备注1的情况再然后点击图示该处</div>
</el-col>
<el-col>
<img class="helpImgs" src="@/assets/images/help/help6.png">
</el-col>
</el-row>
</el-card>
<el-card>
<el-row style="text-align: center">
<el-col>
<div class="steps">
备注2若出现备注1的情况则先在视频输入框中输入完整片名然后点击搜索按钮
</div>
</el-col>
<el-col>
<img class="helpImgs" src="@/assets/images/help/help5.png" />
</el-col>
</el-row>
</el-card>
<el-card>
<el-row style="text-align: center;">
<el-col>
<div class="steps">备注4若出现备注1的情况最后可点击图示按钮选择对应的集数</div>
</el-col>
<el-col>
<img class="helpImgs" src="@/assets/images/help/help7.png">
</el-col>
</el-row>
</el-card>
</div>
<el-card>
<el-row style="text-align: center">
<el-col>
<div class="steps">备注3若出现备注1的情况再然后点击图示该处</div>
</el-col>
<el-col>
<img class="helpImgs" src="@/assets/images/help/help6.png" />
</el-col>
</el-row>
</el-card>
<el-card>
<el-row style="text-align: center">
<el-col>
<div class="steps">
备注4若出现备注1的情况最后可点击图示按钮选择对应的集数
</div>
</el-col>
<el-col>
<img class="helpImgs" src="@/assets/images/help/help7.png" />
</el-col>
</el-row>
</el-card>
<el-backtop target=".el-main" :bottom="50">
<div
style="
{
height: 40px;
width: 100%;
background-color: #f2f5f6;
box-shadow: 0 0 6px rgba(0, 0, 0, 0.12);
text-align: center;
line-height: 50px;
color: #1989fa;
border-radius: 50%;
font-size: 30px;
font-weight: 700;
}
"
>
</div>
</el-backtop>
</div>
</template>
<script>
export default {
name: 'HelpView',
created() {
if (document.querySelector('.el-notification')) {
document.querySelector('.el-notification').style.display = 'none'
}
name: 'Help',
created() {
if (document.querySelector('.el-notification')) {
document.querySelector('.el-notification').style.display = 'none'
}
}
}
</script>
<style lang="less" scoped>
.steps {
font-weight: 600;
font-size: 18px;
font-weight: 600;
font-size: 18px;
}
.helpImgs {
margin-top: 15px;
width: 750px;
height: 500px;
margin-top: 15px;
width: 100%;
height: 500px;
}
</style>
</style>

View File

@ -7,63 +7,71 @@
<!-- 头部区域 -->
<el-header>
<div>
<img src="@/assets/images/home/logo.png" class="webLogo" alt="logo">
<img src="@/assets/images/home/logo.png" class="webLogo" alt="logo" />
<h3 style="user-select: none; cursor: pointer">ChattyPlay</h3>
</div>
<a href="#" class="button button--bird" @click="ContactMeFn">
<div class="button__wrapper">
<span class="button__text">联系我</span>
</div>
<div class="birdBox">
<div class="bird wakeup">
<div class="bird__face"></div>
</div>
<div class="bird wakeup">
<div class="bird__face"></div>
</div>
<div class="bird">
<div class="bird__face"></div>
</div>
</div>
</a>
</el-header>
<!-- 页面主体区域 -->
<el-container>
<!-- 侧边栏 -->
<el-aside width="200px">
<el-menu
default-active="1"
@select="selectMenu"
:default-active="currentMenu"
class="el-menu-vertical-demo"
background-color="#333744"
text-color="#fff"
active-text-color="#409eff"
router
>
<el-menu-item index="1" :index="'/home/music'">
<el-menu-item :index="'/home/music'">
<i class="el-icon-headset"></i>
<span slot="title">音乐</span>
</el-menu-item>
<el-menu-item index="2" :index="'/home/video'">
<el-menu-item :index="'/home/video'">
<i class="el-icon-video-camera-solid"></i>
<span slot="title">观看</span>
</el-menu-item>
<el-menu-item index="3" :index="'/home/trans'">
<el-menu-item :index="'/home/trans'">
<i class="el-icon-reading"></i>
<span slot="title">降重</span>
</el-menu-item>
<el-menu-item index="4" :index="'/home/chatgpt'">
<el-menu-item :index="'/home/chatgpt'">
<i class="el-icon-s-promotion"></i>
<span slot="title">GPT</span>
</el-menu-item>
<el-menu-item index="5" :index="'/home/help'">
<el-menu-item :index="'/home/textToImg'">
<i class="el-icon-picture"></i>
<span slot="title">文图</span>
</el-menu-item>
<el-menu-item :index="'/home/help'">
<i class="el-icon-question"></i>
<span slot="title">帮助</span>
</el-menu-item>
<el-menu-item index="6" :index="'/home/about'">
<el-menu-item :index="'/home/about'">
<i class="el-icon-user-solid"></i>
<span slot="title">关于</span>
</el-menu-item>
</el-menu>
<el-tooltip effect="dark" :content="tooltipContent" placement="right">
<div class="aside-fold" @click="asideFoldHandle">{{ foldText }}</div>
</el-tooltip>
<a href="#" class="button button--bird" @click="ContactMeFn">
<div class="button__wrapper">
<span class="button__text">联系我</span>
</div>
<div class="birdBox">
<div class="bird wakeup">
<div class="bird__face"></div>
</div>
<div class="bird wakeup">
<div class="bird__face"></div>
</div>
<div class="bird">
<div class="bird__face"></div>
</div>
</div>
</a>
</el-aside>
<el-container>
<!-- 右侧内容主体 -->
@ -71,15 +79,19 @@
<!-- 路由占位符 -->
<router-view></router-view>
</el-main>
<el-footer style="font-family: 'Long Cang',cursive;" v-show="$route.path === '/' || $route.path === '/home/music'">
<div style="display: flex; justify-content: center;">
<el-footer
style="font-family: 'Long Cang', cursive"
v-show="$route.path === '/' || $route.path === '/home/music'"
>
<div style="display: flex; justify-content: center">
<div>[ 来日方长</div>
<div class="animated-icon">💗</div>
<div>未来可期 ]</div>
</div>
<div>
<span id="busuanzi_container_site_pv" style="color: #f2ffff;">
您是第&nbsp;<span id="busuanzi_value_site_pv">***</span>&nbsp;位访问本网站的友友~
<span id="busuanzi_container_site_pv" style="color: #f2ffff">
您是第&nbsp;<span id="busuanzi_value_site_pv">***</span
>&nbsp;位访问本网站的友友~
</span>
</div>
<div>© Copyright 2023 P1Kaj1uu. All Rights Reserved.</div>
@ -101,12 +113,16 @@
</div>
<div style="text-align: center">
<img
style="width: 65%; height: 55%; text-align: center; margin: 10px 0;"
style="width: 65%; height: 55%; text-align: center; margin: 10px 0"
src="@/assets/images/home/wx.jpg"
/>
</div>
<div style="text-align: center">
<a href="https://githubfast.com/P1kaj1uu/VIP-Video-Parsing" style="font-size: 12px;" target="_blank">
<a
href="https://githubfast.com/P1kaj1uu/VIP-Video-Parsing"
style="font-size: 12px"
target="_blank"
>
点击此处前往该项目的Github仓库希望您可以给一个小小的star
</a>
</div>
@ -116,39 +132,73 @@
</template>
<script>
import axios from "axios";
import axios from 'axios'
import { mapState, mapMutations } from 'vuex'
import { Address6 } from 'ip-address'
export default {
name: 'HomeView',
name: 'Home',
data() {
return {
dialogVisible: false
dialogVisible: false,
tooltipContent: '收起侧边栏',
foldText: '<'
}
},
computed: {
...mapState('slide', ['currentMenu'])
},
methods: {
...mapMutations('slide', ['setCurrentMenu']),
//
ContactMeFn() {
this.dialogVisible = true
},
handleClose() {
handleClose () {
this.dialogVisible = false
}
this.$router.push(this.currentMenu)
},
selectMenu(index) {
this.setCurrentMenu(index)
},
asideFoldHandle() {
const foldDOM = document.querySelector('.aside-fold')
const mainDOM = document.querySelector('.el-main')
const footerDOM = document.querySelector('.el-footer')
if (this.foldText === '<') {
foldDOM.style.left = '0'
mainDOM.style.left = '0'
footerDOM.style.left = '0'
} else {
foldDOM.style.left = '200px'
mainDOM.style.left = '200px'
footerDOM.style.left = '200px'
}
this.foldText = this.foldText === '<' ? '>' : '<'
this.tooltipContent = this.foldText === '<' ? '收起侧边栏' : '展开侧边栏'
},
},
created () {
axios.get('https://ipapi.co/json/').then(res => {
console.log(res.data)
const { ip } = res.data
this.$message({
message: `欢迎您访问本网站当前访问IP地址${ip} `,
type: 'success'
created() {
axios
.get('https://ipapi.co/json/')
.then((res) => {
console.log(res.data)
let { ip, version } = res.data
// Address6
const address6 = new Address6(ip)
ip = version === 'IPv6' ? address6.to4().address : ip
this.$message({
message: `欢迎您访问本网站当前访问IP地址${ip} `,
type: 'success'
})
})
}).catch(error => {
console.log(error)
this.$message({
message: `欢迎您访问本网站!`,
type: 'success'
.catch((error) => {
console.log(error)
this.$message({
message: `欢迎您访问本网站!`,
type: 'success'
})
})
})
if (document.querySelector('.el-notification')) {
document.querySelector('.el-notification').style.display = 'none'
}
@ -195,7 +245,27 @@ export default {
right: 0;
top: 60px;
bottom: 0;
overflow-y: scroll;
}
.aside-fold {
position: absolute;
top: 50%;
left: 200px;
z-index: 999;
width: 30px;
height: 60px;
text-align: center;
line-height: 60px;
cursor: pointer;
border-radius: 0 50% 50% 0;
font-weight: 700;
font-size: 20px;
color: #fff;
background: #333744;
border: 1px solid #333744;
user-select: none;
}
.aside-fold:hover {
background: blueviolet;
}
.el-footer {
@ -233,13 +303,20 @@ export default {
}
@keyframes iconAnimate {
0%, 100% {
0%,
100% {
transform: scale(1);
}
10%, 30% {
transform: scale(.9);
10%,
30% {
transform: scale(0.9);
}
20%, 40%, 50%, 60%, 70%, 80% {
20%,
40%,
50%,
60%,
70%,
80% {
transform: scale(1.1);
}
}
@ -286,7 +363,7 @@ export default {
border-radius: 40px;
background: var(--main_color);
position: relative;
margin-bottom: -30px;
margin-top: 100%;
}
.button__wrapper {

View File

@ -32,11 +32,7 @@
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item
label="验证码"
prop="code"
style="border-bottom: 1px solid black; padding-bottom: 30px"
>
<el-form-item label="验证码" prop="code" style="padding-bottom: 30px">
<el-input
style="width: 55%"
placeholder="请输入右侧的验证码"
@ -53,6 +49,11 @@
<VerifyCode ref="codeRef" :identifyCode="randomCode" />
</div>
</el-form-item>
<div class="loginOperate">
<div @click="retrieveHandle">忘记密码</div>
<span>&nbsp;&nbsp;&nbsp;</span>
<div @click="registerHandle">立即注册</div>
</div>
<div class="loginExact">
<div style="display: flex">
<input ref="agreeRef" id="agree" type="checkbox" checked />
@ -78,12 +79,8 @@
</div>
</div>
<el-form-item class="login_btn">
<el-button type="success" @click="loginFn">登录</el-button>
<el-button
type="primary"
@click="$router.push('/home/music')"
>游客</el-button
>
<el-button type="success" @click="loginUserFn">登录</el-button>
<el-button type="primary" @click="loginPlayerFn">游客</el-button>
<el-button type="info" @click="resetForm">重置</el-button>
</el-form-item>
</el-form>
@ -92,25 +89,74 @@
<div class="loginFooter">
© Copyright 2023 P1Kaj1uu. All Rights Reserved.
</div>
<el-dialog
width="35%"
title="找回密码"
:visible.sync="dialogForgetVisible"
:close-on-click-modal="false"
@close="closeForgetDialog"
>
<el-form :model="forgetForm" ref="forgetFormRef">
<el-form-item label="手机号" label-width="100">
<el-input
v-model="forgetForm.telephoneNumber"
placeholder="请输入注册时的手机号"
clearable
maxlength="11"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item label="验证码" label-width="100">
<el-input
v-model="forgetForm.checkCode"
maxlength="4"
placeholder="请输入短信手机验证码"
clearable
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item label="新密码" label-width="100">
<el-input
v-model="forgetForm.newPassword"
autocomplete="off"
clearable
placeholder="请输入您的新密码6-11位"
></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="dialogForgetVisible = false"
>确认重置密码</el-button
>
</div>
</el-dialog>
</div>
</template>
<script>
import { mapState } from 'vuex'
import VerifyCode from '@/components/VerifyCode.vue'
import { setToken } from '@/utils/token'
import { Heart } from '@/utils/model'
import { sleep } from '@/utils/sleep'
export default {
name: 'login',
name: 'Login',
data() {
return {
loginForm: {
username: 'P1Kaj1uu',
password: 'OWaGDragon',
password: 'OwaGDragon',
code: '',
randomCode: ''
},
dialogForgetVisible: false,
forgetForm: {
telephoneNumber: '',
checkCode: '',
newPassword: ''
},
//
loginFormRules: {
username: [
@ -119,7 +165,6 @@ export default {
message: '请输入您的ChattyPlay账号',
trigger: 'blur'
},
{ min: 3, max: 10, message: '长度在 3 到 10 个字符', trigger: 'blur' }
],
password: [
{
@ -127,7 +172,7 @@ export default {
message: '请输入您的ChattyPlay密码',
trigger: 'blur'
},
{ min: 6, max: 15, message: '长度在 6 到 15 个字符', trigger: 'blur' }
{ min: 6, max: 11, message: '长度在 6 到 11 个字符', trigger: 'blur' }
],
code: [
{ required: true, message: '请输入正确的验证码', trigger: 'blur' }
@ -135,6 +180,9 @@ export default {
}
}
},
computed: {
...mapState('slide', ['currentMenu'])
},
components: {
VerifyCode
},
@ -220,8 +268,34 @@ export default {
})
})
},
//
loginFn() {
//
loginPlayerFn() {
const urlMap = new Map([
['/home/music', '/home/music'],
['/home/video', '/home/video'],
['/home/trans', '/home/trans'],
['/home/chatgpt', '/home/chatgpt'],
['/home/textToImg', '/home/textToImg'],
['/home/help', '/home/help'],
['/home/about', '/home/about']
])
const urlItem = urlMap.get(this.currentMenu)
this.$router.push(urlItem)
},
//
retrieveHandle() {
this.dialogForgetVisible = true
},
closeForgetDialog() {
this.forgetForm.telephoneNumber = ''
this.forgetForm.checkCode = ''
this.forgetForm.newPassword = ''
this.dialogForgetVisible = false
},
//
registerHandle() {},
//
loginUserFn() {
const isAgree = this.$refs.agreeRef.checked
const isVerify =
this.randomCode.toLowerCase() === this.loginForm.code.toLowerCase()
@ -240,7 +314,7 @@ export default {
return false
} else {
this.heartBeat()
this.$router.push('/home/music')
this.loginPlayerFn()
setToken('Dveiklokk')
}
}
@ -278,7 +352,7 @@ export default {
);
border-radius: 5px;
opacity: 1.5;
position: absolute;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
@ -329,19 +403,39 @@ export default {
user-select: none;
overflow: hidden;
white-space: nowrap;
letter-spacing: .15em;
animation: typing 4s steps(30, end) infinite,
blink-caret 2s step-end infinite;
letter-spacing: 0.15em;
animation: typing 4s steps(30, end) infinite, blink-caret 2s step-end infinite;
}
@keyframes typing {
from { width: 0 }
to { width: 100% }
from {
width: 0;
}
to {
width: 100%;
}
}
@keyframes blink-caret {
from, to { border-color: transparent }
50% { border-color: #666 }
from,
to {
border-color: transparent;
}
50% {
border-color: #666;
}
}
.loginOperate {
display: flex;
position: absolute;
top: 68%;
cursor: pointer;
font-size: 12px;
font-weight: 700;
color: rgb(238, 238, 238);
}
.loginOperate div:hover {
color: blue;
}
.loginExact {
@ -349,6 +443,7 @@ export default {
justify-content: space-between;
align-items: center;
margin-top: -15px;
border-top: 1px solid black;
}
/deep/ .el-form-item__label {
width: 80px !important;

View File

@ -103,7 +103,7 @@
import axios from 'axios'
export default {
name: 'WelcomeView',
name: 'Music',
data() {
return {
//
@ -220,13 +220,12 @@ export default {
<style lang="less" scoped>
.play_wrap {
width: 800px;
height: 544px;
position: fixed;
position: absolute;
left: 50%;
top: 50%;
margin-left: -320px;
margin-top: -272px;
transform: translate(-50%, -55%);
cursor: pointer;
}
.search_bar {

369
src/views/TextToPhoto.vue Normal file
View File

@ -0,0 +1,369 @@
<!--
* @Description: 文生图页面
* @Author: 不见水星记P1kaj1uu
-->
<template>
<div class="TextToPhoto-Container">
<!-- 面包屑导航区域 -->
<el-breadcrumb separator-class="el-icon-arrow-right">
<el-breadcrumb-item>首页</el-breadcrumb-item>
<el-breadcrumb-item>文生图</el-breadcrumb-item>
</el-breadcrumb>
<div class="card-list">
<el-card class="box-card">
<div slot="header" class="card-title clearfix">
<span>注意事项🎓</span>
</div>
<div v-for="(item, index) in noticeList" :key="index" class="text item">
{{ item }}
</div>
</el-card>
<el-card class="box-card">
<div slot="header" class="card-title clearfix">
<span>调教指南👩💻</span>
</div>
<div v-for="(item, index) in guideList" :key="index" class="text item">
{{ item }}
</div>
</el-card>
</div>
<div class="card-list-generate">
<el-card class="box-card-preview">
<div slot="header" class="card-title clearfix">
<span>图片预览</span>
</div>
<div class="text item">
<el-image
style="width: 150px; height: 150px; border: 1px solid black"
:src="url"
:preview-src-list="srcList"
>
</el-image>
</div>
</el-card>
<el-card class="box-card-text">
<div slot="header" class="card-title clearfix">
<span>AI绘画 - 文生图</span>
</div>
<div class="text item ai-box">
<div class="ai-option">
<div class="ai-option-item ai-option-style">
<div>图片风格</div>
<el-select
v-model="photoStyleValue"
size="small"
clearable
placeholder="请选择图片风格"
>
<el-option
v-for="item in photoStyleList"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</div>
<div class="ai-option-item">
<div>图片宽度(范围为256-512之间)</div>
<el-slider
v-model="photoWidth"
:min="256"
:max="512"
show-input
>
</el-slider>
</div>
<div class="ai-option-item">
<div>图片高度(范围为256-512之间)</div>
<el-slider
v-model="photoHeight"
:min="256"
:max="512"
show-input
>
</el-slider>
</div>
</div>
<el-input
type="textarea"
placeholder="在此输入您想生成图片的提示词同时希望您在生成图片前花1分钟查阅上面的注意事项和调教指南~"
v-model="textToImgVal"
>
</el-input>
</div>
</el-card>
</div>
<el-card class="btn-list">
<el-button @click="photoGenerate" type="primary" round
>开始生成图片</el-button
>
</el-card>
</div>
</template>
<script>
import axios from 'axios'
import { mapState } from 'vuex'
export default {
name: 'TextToPhoto',
data() {
return {
textToImgVal: '',
//
noticeList: [
'1.禁止生成色情、暴力、血腥等不良图片,以及其他可能会引起社会不良影响的内容。',
'2.使用者对使用模型的任何行为和生成的图片负全部责任。',
'3.【点击图片】可以放大和下载。',
'4.本功能仍然在测试,若生成【全黑图】,请重新生成或者修改图片描述。另外,本网站暂时不保存图片,在点击`生成图片`前用户需要手动保存图片。',
'5.生成人物的效果较差(特别是画手和脚,有点恐怖!)~勿喷。'
],
//
guideList: [
'🎈目前【普通描述模式】已经支持任何语言描述。当然,如果你想生成的效果更好,建议用英文。',
'🎈尽可能让你的描述内容更加详细。',
'🎈一些有意思的实例:【阳光洒在长发女生的身上,双眼深邃望着前方,画面整体暖色调】【黑色跑车行驶在街道上,天空闪过一道黄色闪电】【暗黑风格的未来街道】'
],
url: 'https://pic.baike.soso.com/p/20140611/20140611145529-1600143101.jpg',
srcList: [
'https://pic.baike.soso.com/p/20140611/20140611145529-1600143101.jpg'
],
photoStyleValue: 'realism',
photoStyleList: [
{
value: 'realism',
label: '写实'
},
{
value: 'Ultra clear photograph',
label: '照片'
},
{
value: 'ancient customs',
label: '古风'
},
{
value: 'oil painting',
label: '油画'
},
{
value: 'watercolor painting',
label: '水彩画'
},
{
value: 'ink painting',
label: '油墨画'
},
{
value: 'black and white painting',
label: '黑白画'
},
{
value: '3D',
label: '3D'
},
{
value: 'free-hand sketch',
label: '手绘草图'
},
{
value: 'charcoal painting',
label: '炭笔画'
},
{
value: 'minimalist line drawing',
label: '极简线条画'
},
{
value: 'ukiyoe',
label: '浮世绘'
},
{
value: 'medieval style painting',
label: '中世纪风'
},
{
value: 'paper-cut art',
label: '剪纸艺术'
},
{
value: 'film texture style',
label: '电影质感'
},
{
value: 'mechanical style',
label: '机械风'
},
{
value: 'hi-tech style',
label: '科技风'
},
{
value: 'anime CG',
label: '二次元CG'
},
{
value: 'thick coated CG',
label: '厚涂CG'
},
{
value: 'aestheticism CG',
label: '唯美CG'
},
{
value: 'Chinese style',
label: '中国风'
},
{
value: 'Korean style',
label: '韩式风'
},
{
value: 'Japanese style',
label: '日本风'
},
{
value: ',American style',
label: '美国风'
},
],
photoWidth: 512,
photoHeight: 512,
sampler: ['DPM++ 2M Karras', 'Euler a'][Math.floor(Math.random() * 2)], //
lora: ['<lora:koreanDollLikeness_v15:1>', '<lora:GuoFeng3.2_Lora_light:1>', '<lora:taiwanDollLikeness_v10:1>'][Math.floor(Math.random() * 3)] //
}
},
computed: {
...mapState('funAi', ['token', 'userId'])
},
methods: {
photoGenerateRequest() {
const loading = this.$loading({
lock: true,
text: '正在拼命生成图片中...',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
})
axios({
url: '/api/img/text2Img/SD/base64',
method: 'POST',
headers: {
token: this.token
},
data: {
cfg_scale: Math.floor(Math.random() * 15) + 1,
height: this.photoHeight,
width: this.photoWidth,
img_style: this.photoStyleValue,
lora_style: this.lora,
prompt: this.textToImgVal.trim(),
sampler_index: this.sampler,
sampler_name: this.sampler,
seed: Math.floor(Math.random() * 100000) + 1,
steps: Math.floor(Math.random() * 11) + 20,
user_id: this.userId
}
})
.then((res) => {
if (res.data.code === 30002) {
this.$message.warning('当日AI绘画次数已达到上限请明日再试~')
return
}
if (res.data.code === 20001) {
this.$message.warning(res.data.message)
return
}
if (res.data.code === 20000) {
console.log(res.data.data.base64Img)
this.url = res.data.data.base64Img
this.srcList = [this.url]
this.$message.success('文生图生成成功')
}
})
.catch((error) => {
console.log(error)
})
.finally(() => {
loading.close()
})
},
photoGenerate() {
if (!this.textToImgVal.trim().length) {
this.$message.warning('文生图提示词不能为空哦~')
this.textToImgVal = ''
return
}
this.photoGenerateRequest()
}
}
}
</script>
<style lang="less" scoped>
/deep/ .el-textarea {
flex: 7;
padding: 0 20px;
}
/deep/ .el-textarea__inner {
height: 150px;
resize: none;
}
.card-list {
display: flex;
justify-content: center;
.card-title {
font-size: 16px;
}
.text {
font-size: 13px;
}
}
.card-list-generate {
display: flex;
justify-content: center;
.card-title {
font-size: 16px;
}
.text {
display: flex;
justify-content: center;
align-items: center;
font-size: 13px;
}
.box-card-preview {
flex: 2;
}
.box-card-text {
flex: 8;
.ai-box {
display: flex;
justify-content: center;
align-items: center;
.ai-option {
flex: 5;
padding: 0 20px;
border-right: 1px solid #eee;
.ai-option-style {
display: flex;
align-items: center;
}
.ai-option-item {
padding: 5px;
}
}
}
}
}
.btn-list {
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 0;
}
</style>

View File

@ -104,7 +104,7 @@ import md5 from 'js-md5'
import axios from 'axios'
export default {
name: 'TransView',
name: 'Trans',
data() {
return {
flag: false,
@ -160,7 +160,7 @@ export default {
let methodTypes = this.transTypeList[this.num].method
for (let i = 0; i < methodTypes.length; i++) {
let mode = methodTypes[i].split(' ')
await axios.get('/api/trans/vip/translate', {
await axios.get('/trans/vip/translate', {
params: {
q: this.transText,
from: mode[0],

View File

@ -11,13 +11,13 @@
</el-breadcrumb>
<div class="layui-container wrap">
<div class="layui-row">
<div class="layui-row video-top">
<div class="layui-input-inline layui-form">
<select id="api" name="api">
<option value="">请选择解析接口</option>
</select>
</div>
<div class="layui-input-inline layui-show-sm-inline-block">
<div class="layui-input-inline layui-show-sm-inline-block video-url">
<input type="text" lay-verify="required|phone|number" class="layui-input url" name=""
placeholder="输入视频地址" />
</div>
@ -30,7 +30,7 @@
</fieldset>
<div class="layui-row">
<div class="layui-col-md3">
<div class="layui-col-md6">
<div class="layui-card">
<div class="layui-card-header">爱奇艺可用-超推荐</div>
<div class="layui-card-body">
@ -41,7 +41,7 @@
</div>
</div>
<div class="layui-col-md3">
<div class="layui-col-md6">
<div class="layui-card">
<div class="layui-card-header">优酷可用-超推荐</div>
<div class="layui-card-body">
@ -52,7 +52,7 @@
</div>
</div>
<div class="layui-col-md3">
<div class="layui-col-md6">
<div class="layui-card">
<div class="layui-card-header">腾讯视频可用-超推荐</div>
<div class="layui-card-body">
@ -63,7 +63,7 @@
</div>
</div>
<div class="layui-col-md3">
<div class="layui-col-md6">
<div class="layui-card">
<div class="layui-card-header">芒果TV可用-超推荐</div>
<div class="layui-card-body">
@ -77,7 +77,7 @@
<div class="layui-row">
<div class="layui-col-md3">
<div class="layui-col-md6">
<div class="layui-card">
<div class="layui-card-header">哔哩哔哩可用-超推荐</div>
<div class="layui-card-body">
@ -88,7 +88,7 @@
</div>
</div>
<div class="layui-col-md3">
<div class="layui-col-md6">
<div class="layui-card">
<div class="layui-card-header">韩剧TV可能不得行</div>
<div class="layui-card-body">
@ -99,7 +99,7 @@
</div>
</div>
<div class="layui-col-md3">
<div class="layui-col-md6">
<div class="layui-card">
<div class="layui-card-header">OmoFun可能不得行</div>
<div class="layui-card-body">
@ -110,7 +110,7 @@
</div>
</div>
<div class="layui-col-md3">
<div class="layui-col-md6">
<div class="layui-card">
<div class="layui-card-header">乐视TV</div>
<div class="layui-card-body">
@ -123,7 +123,7 @@
</div>
<div class="layui-row">
<div class="layui-col-md3">
<div class="layui-col-md6">
<div class="layui-card">
<div class="layui-card-header">土豆视频</div>
<div class="layui-card-body">
@ -134,7 +134,7 @@
</div>
</div>
<div class="layui-col-md3">
<div class="layui-col-md6">
<div class="layui-card">
<div class="layui-card-header">1905</div>
<div class="layui-card-body">
@ -145,7 +145,7 @@
</div>
</div>
<div class="layui-col-md3">
<div class="layui-col-md6">
<div class="layui-card">
<div class="layui-card-header">搜狐视频</div>
<div class="layui-card-body">
@ -156,7 +156,7 @@
</div>
</div>
<div class="layui-col-md3">
<div class="layui-col-md6">
<div class="layui-card">
<div class="layui-card-header">PPTV聚力</div>
<div class="layui-card-body">
@ -177,7 +177,7 @@ import { sleep } from '@/utils/sleep'
import { getData } from '@/api/request'
export default {
name: 'VideoView',
name: 'Video',
created () {
let isDisPlay = document.querySelector('.model')?.style.display === 'none'
let notifyMessage = {
@ -209,8 +209,11 @@ body {
.wrap {
margin: 50px auto 50px;
}
.url {
width: 820px;
.video-top {
display: flex;
}
.video-url {
flex: 1;
}
.video-website {
padding: 10px;
@ -225,6 +228,6 @@ img {
}
.OtherImg {
width: 80px;
height: 50px;
height: 50px;
}
</style>

View File

@ -4,13 +4,20 @@ const packageJson = require('./package.json')
module.exports = {
devServer: {
proxy: {
'/trans': {
target: 'https://api.fanyi.baidu.com/api',
changeOrigin: true,
pathRewrite: {
'^/trans': '/trans'
}
},
'/api': {
target: 'https://api.fanyi.baidu.com',
target: 'https://xxxxx',
changeOrigin: true,
pathRewrite: {
'^/api': '/api'
}
}
},
}
},
}