Compare commits
3 Commits
master
...
feature/de
Author | SHA1 | Date |
---|---|---|
|
689cd88aec | |
|
24c9ff4a7e | |
|
6ecfe7fa5c |
21
README.md
|
@ -27,4 +27,23 @@ npm run build:stage
|
|||
|
||||
# 构建生产环境
|
||||
npm run build:prod
|
||||
```
|
||||
```
|
||||
|
||||
在js出发login
|
||||
import Vue from "vue";
|
||||
Vue.prototype.$eventBus.$emit("showLogin");
|
||||
|
||||
<!-- [
|
||||
{},
|
||||
[
|
||||
{
|
||||
id:'1',
|
||||
name:'',
|
||||
imgsur:''
|
||||
},
|
||||
{
|
||||
id:'',
|
||||
delflag:'2',
|
||||
}
|
||||
]
|
||||
] -->
|
16
package.json
|
@ -37,6 +37,9 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@riophae/vue-treeselect": "0.4.0",
|
||||
"@tailwindcss/postcss7-compat": "^2.2.17",
|
||||
"@wangeditor/editor": "^5.1.23",
|
||||
"autoprefixer": "^9.8.8",
|
||||
"axios": "0.28.1",
|
||||
"clipboard": "2.0.8",
|
||||
"core-js": "3.37.1",
|
||||
|
@ -48,16 +51,21 @@
|
|||
"js-beautify": "1.13.0",
|
||||
"js-cookie": "3.0.1",
|
||||
"jsencrypt": "3.0.0-rc.1",
|
||||
"lodash": "^4.17.21",
|
||||
"nprogress": "0.2.0",
|
||||
"quill": "2.0.2",
|
||||
"postcss": "^7.0.39",
|
||||
"qrcode": "^1.5.4",
|
||||
"screenfull": "5.0.2",
|
||||
"sortablejs": "1.10.2",
|
||||
"splitpanes": "2.4.1",
|
||||
"vue": "2.6.12",
|
||||
"tailwindcss": "npm:@tailwindcss/postcss7-compat",
|
||||
"vue": "^2.7.16",
|
||||
"vue-count-to": "1.0.13",
|
||||
"vue-cropper": "0.5.5",
|
||||
"vue-meta": "2.4.0",
|
||||
"vue-qr": "^4.0.9",
|
||||
"vue-router": "3.4.9",
|
||||
"vue2-editor": "^2.10.3",
|
||||
"vuedraggable": "2.24.3",
|
||||
"vuex": "3.6.0"
|
||||
},
|
||||
|
@ -65,6 +73,7 @@
|
|||
"@vue/cli-plugin-babel": "4.4.6",
|
||||
"@vue/cli-plugin-eslint": "4.4.6",
|
||||
"@vue/cli-service": "4.4.6",
|
||||
"autoprefixer": "latest",
|
||||
"babel-eslint": "10.1.0",
|
||||
"babel-plugin-dynamic-import-node": "2.3.3",
|
||||
"chalk": "4.1.0",
|
||||
|
@ -73,11 +82,14 @@
|
|||
"eslint": "7.15.0",
|
||||
"eslint-plugin-vue": "7.2.0",
|
||||
"lint-staged": "10.5.3",
|
||||
"postcss": "latest",
|
||||
"runjs": "4.4.2",
|
||||
"sass": "1.32.13",
|
||||
"sass-loader": "10.1.1",
|
||||
"script-ext-html-webpack-plugin": "2.1.5",
|
||||
"svg-sprite-loader": "5.1.1",
|
||||
"tailwindcss": "latest",
|
||||
"ts-node": "latest",
|
||||
"vue-template-compiler": "2.6.12"
|
||||
},
|
||||
"engines": {
|
||||
|
|
17
src/App.vue
|
@ -1,16 +1,16 @@
|
|||
<template>
|
||||
<div id="app">
|
||||
<router-view />
|
||||
<theme-picker />
|
||||
<McLogin ref="McLogin"></McLogin>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ThemePicker from "@/components/ThemePicker";
|
||||
|
||||
import McLogin from '@/components/McLogin'
|
||||
export default {
|
||||
name: "App",
|
||||
components: { ThemePicker },
|
||||
components: { ThemePicker,McLogin },
|
||||
metaInfo() {
|
||||
return {
|
||||
title: this.$store.state.settings.dynamicTitle && this.$store.state.settings.title,
|
||||
|
@ -18,7 +18,16 @@ export default {
|
|||
return title ? `${title} - ${process.env.VUE_APP_TITLE}` : process.env.VUE_APP_TITLE
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.$eventBus.$on("showLogin", () => {
|
||||
this.$refs.McLogin.showLogin();
|
||||
});
|
||||
},
|
||||
beforeDestroy() {
|
||||
// 移除监听器
|
||||
this.$eventBus.$off("showLogin");
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style scoped>
|
||||
|
|
|
@ -34,7 +34,7 @@ export function register(data) {
|
|||
// 获取用户详细信息
|
||||
export function getInfo() {
|
||||
return request({
|
||||
url: '/getInfo',
|
||||
url: '/system/user/selectUserById',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
import request from '@/utils/request'
|
||||
// 发送验证码
|
||||
export function getCode(query) {
|
||||
return request({
|
||||
url: '/getCode',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 手机号登陆
|
||||
export function phoneLogin(data) {
|
||||
return request({
|
||||
url: '/phoneLogin',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 登录方法
|
||||
export function login(phone,code) {
|
||||
const data = {
|
||||
phone,
|
||||
code,
|
||||
}
|
||||
return request({
|
||||
url: '/phoneLogin',
|
||||
headers: {
|
||||
isToken: false,
|
||||
repeatSubmit: false
|
||||
},
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
//微信扫描
|
||||
// 获取uuid
|
||||
export function getUUid(query) {
|
||||
return request({
|
||||
params:query,
|
||||
url: '/wx/uuid/get',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// uuid登录
|
||||
export function uuidLogin(query) {
|
||||
return request({
|
||||
params:query,
|
||||
url: '/wx/uuid/login',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// 用户信息编辑
|
||||
export function updateUserInfo(data) {
|
||||
return request({
|
||||
url: '/system/user/updateUserInfo',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
import request from '@/utils/request'
|
||||
|
||||
// 查询商品
|
||||
export function getMallProductList(query) {
|
||||
return request({
|
||||
url: '/MallProduct/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 获取详情
|
||||
export function getMallProduct(query) {
|
||||
return request({
|
||||
url: '/MallProduct/{id}',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 上传图片
|
||||
// export function getFile(data) {
|
||||
// return request({
|
||||
// url: '/MallProduct/file',
|
||||
// method: 'post',
|
||||
// data: data
|
||||
// })
|
||||
// }
|
||||
// 上传zip
|
||||
export function getZipUrlFile(data) {
|
||||
return request({
|
||||
url: '/MallProduct/zipUrlFile',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
// 上传文件
|
||||
export function uploadFile(data) {
|
||||
return request({
|
||||
headers: {
|
||||
"Content-Type": "multipart/form-data", // 浏览器会自动添加 boundary
|
||||
},
|
||||
url: '/WorkFlow/file',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
//下载zip
|
||||
export function getZipUrl(data) {
|
||||
return request({
|
||||
url: '/MallProduct/zipUrl',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
//上传图片
|
||||
export function modelImagePublish(data) {
|
||||
return request({
|
||||
url: '/modelImage/publish',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
import request from '@/utils/request'
|
||||
|
||||
// 获取个人关注、粉丝、下载次数和点赞数
|
||||
export function getSelectUserInfo(query) {
|
||||
return request({
|
||||
url: '/attention/selectUserInfo',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
//获取数据字典
|
||||
export function dictType(query) {
|
||||
return request({
|
||||
url: `/system/dict/data/type/${query.type}`,
|
||||
method: 'get',
|
||||
// params: query
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// 查看用户发布的作品
|
||||
export function mallProduct(data) {
|
||||
return request({
|
||||
url: '/MallProduct/selectByUserId',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
// 查看查看点赞商品
|
||||
export function selectByUserLike(data) {
|
||||
return request({
|
||||
url: '/like/selectByUserLike',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
import request from '@/utils/request'
|
||||
// 上传图片
|
||||
export function mallProductFile(data) {
|
||||
return request({
|
||||
headers: {
|
||||
"Content-Type": "multipart/form-data", // 浏览器会自动添加 boundary
|
||||
},
|
||||
url: '/MallProduct/file',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
//实名认证
|
||||
export function updateIdCard(data) {
|
||||
return request({
|
||||
url: '/system/user/updateIdCard',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1735892107667" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1046" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16"><path d="M945.93 130.759c-7.638-15.276-26.279-21.619-41.684-13.981L92.312 520.027c-15.276 7.638-21.619 26.279-13.981 41.684 1.683 3.365 3.884 6.343 6.473 8.803 3.365 3.237 7.378 5.696 12.169 7.249l273.148 85.828 41.943-52.041-222.919-70.035 611.539-303.957-327.131 395.999a22.868 22.868 0 0 0-2.071 2.848l-37.801 46.991v194.957c0 17.218 13.852 31.069 31.069 31.069s31.069-13.852 31.069-31.069v-175.54l297.097 93.206c3.495 1.036 6.991 1.553 10.485 1.423 15.017 0.388 28.609-10.227 31.457-25.502l113.79-621.507c0.388-2.071 0.517-4.272 0.517-6.343-0.13-4.402-1.036-9.062-3.237-13.333zM779.969 726.893l-240.396-75.472L866.314 255.81l-86.346 471.082z" p-id="1047"></path></svg>
|
After Width: | Height: | Size: 994 B |
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1735892143936" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1686" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16"><path d="M480 384h320a96.11 96.11 0 0 0 96-96V160a96.11 96.11 0 0 0-96-96H480a96.11 96.11 0 0 0-96 96v32H224a96.11 96.11 0 0 0-96 96v160a96.11 96.11 0 0 0 96 96h576a32 32 0 0 1 32 32v160a32 32 0 0 1-32 32H640v-32a96.11 96.11 0 0 0-96-96H224a96.11 96.11 0 0 0-96 96v128a96.11 96.11 0 0 0 96 96h320a96.11 96.11 0 0 0 96-96v-32h160a96.11 96.11 0 0 0 96-96V576a96.11 96.11 0 0 0-96-96H224a32 32 0 0 1-32-32V288a32 32 0 0 1 32-32h160v32a96.11 96.11 0 0 0 96 96z m96 480a32 32 0 0 1-32 32H224a32 32 0 0 1-32-32V736a32 32 0 0 1 32-32h320a32 32 0 0 1 32 32zM448 160a32 32 0 0 1 32-32h320a32 32 0 0 1 32 32v128a32 32 0 0 1-32 32H480a32 32 0 0 1-32-32z" p-id="1687"></path></svg>
|
After Width: | Height: | Size: 991 B |
|
@ -0,0 +1 @@
|
|||
<svg t="1735889157703" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="959" width="16" height="16"><path d="M512.064974 0a511.740759 511.740759 0 0 0 0 1024c83.345823 0 141.674937-19.443038 178.098228-59.625316 50.681519-55.866329 43.033924-134.156962 36.941772-197.152406-6.481013-67.143291-6.092152-96.826329 13.739747-107.455189a79.716456 79.716456 0 0 1 38.108355-9.98076c25.924051 0 53.014684 12.962025 78.549873 26.831393s48.737215 25.146329 75.179747 25.146329c90.734177 0 90.734177-118.602532 90.734177-189.50481A512.259241 512.259241 0 0 0 512.064974 0z m420.617722 650.17519c-33.701266 0-86.97519-51.848101-153.72962-51.848101a129.620253 129.620253 0 0 0-62.217722 16.072911C584.522696 684.524557 819.135354 972.151899 512.064974 972.151899A460.540759 460.540759 0 1 1 972.476114 511.740759c0 107.844051-14.128608 138.43443-39.793418 138.434431z" p-id="960"></path><path d="M526.063962 656.785823a102.4 102.4 0 1 0 102.270379 102.4 102.52962 102.52962 0 0 0-102.270379-102.4z m0 153.6a51.848101 51.848101 0 1 1 51.070379-51.848101 51.848101 51.848101 0 0 1-51.070379 51.848101z" p-id="961"></path><path d="M275.378392 572.921519a114.584304 114.584304 0 0 0-103.696203 71.80962 65.717468 65.717468 0 0 0 22.035444 76.216709c11.665823 9.203038 14.517468 22.165063 17.887594 42.515443 3.888608 22.813165 10.888101 64.810127 63.513925 64.810127 58.069873 0 71.420759-41.996962 82.17924-75.698228a225.28 225.28 0 0 1 15.55443-40.182279 87.752911 87.752911 0 0 0-1.814683-88.271392 111.343797 111.343797 0 0 0-95.659747-51.2z m52.496203 115.880506a298.126582 298.126582 0 0 0-19.183798 48.866836c-11.406582 35.77519-14.776709 40.052658-33.312405 40.052658a17.239494 17.239494 0 0 1-7.517975-1.036962 69.087595 69.087595 0 0 1-5.44405-21.516962c-3.758987-22.035443-8.684557-51.848101-36.812152-74.272405A15.035949 15.035949 0 0 1 220.678645 661.063291a63.254684 63.254684 0 0 1 55.088608-37.330633 60.791899 60.791899 0 0 1 51.848101 26.961013 36.423291 36.423291 0 0 1 0.259241 38.108354z" p-id="962"></path><path d="M379.852316 401.822785c0-52.625823-38.886076-95.400506-86.586329-95.400507a83.086582 83.086582 0 0 0-59.366076 25.924051c-10.24 10.24-23.072405 11.276962-42.904304 11.795443-21.776203 0-67.013671 1.685063-67.013671 57.551393a127.93519 127.93519 0 0 0 255.87038 0z m-204.67038 0v-5.18481a107.973671 107.973671 0 0 1 16.980253-1.166583 105.770127 105.770127 0 0 0 77.772152-26.831392c23.331646-23.331646 58.847595-5.703291 58.717975 33.182785a76.73519 76.73519 0 0 1-153.47038 0z" p-id="963"></path><path d="M471.623455 108.103291c-31.627342 0-127.93519 0-127.93519 92.678481a128.06481 128.06481 0 0 0 127.93519 127.93519c71.031899 0 156.710886-57.032911 156.710886-127.93519 0-34.608608-20.35038-92.678481-156.710886-92.678481z m0 169.413671a76.86481 76.86481 0 0 1-76.73519-76.73519c0-22.683544 5.703291-41.608101 76.73519-41.608101 31.756962 0 105.510886 4.147848 105.510886 41.608101s-60.403038 76.73519-105.510886 76.73519z" p-id="964"></path><path d="M755.232569 206.614684c-28.775696 0-46.663291 22.424304-65.458228 46.27443-5.05519 6.351392-10.499241 12.962025-16.461772 20.091139-19.961519 23.072405-36.812152 43.941266-42.774683 67.143291-7.129114 28.127595 3.240506 54.310886 30.590379 77.772152a116.658228 116.658228 0 0 0 75.438988 32.793924c28.775696 0 55.607089-14.258228 79.846076-42.385823a128.06481 128.06481 0 0 0-12.962026-180.431392 73.883544 73.883544 0 0 0-48.218734-21.257721z m22.424304 168.506329c-27.479494 31.756962-50.551899 32.405063-83.086582 4.407088-17.369114-15.16557-15.42481-22.683544-14.387848-26.701772a150.100253 150.100253 0 0 1 31.886582-46.404051c6.481013-7.517975 12.962025-14.906329 17.757975-21.776202 8.166076-10.36962 20.60962-25.924051 25.92405-26.831392 0 0 4.277468 0 14.517469 9.073417a75.568608 75.568608 0 0 1 25.92405 51.848102 76.346329 76.346329 0 0 1-18.146835 56.38481z" p-id="965"></path></svg>
|
After Width: | Height: | Size: 3.8 KiB |
|
@ -0,0 +1 @@
|
|||
<svg t="1735797429104" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="992" width="16" height="16"><path d="M332.3904 813.4656h545.1776c17.8176 0 31.3344-13.312 31.3344-31.3344s-13.312-31.3344-31.3344-31.3344H332.3904c-17.8176 0-31.3344 13.312-31.3344 31.3344 0 13.312 13.5168 31.3344 31.3344 31.3344z m0-268.288h545.1776c22.3232 0 35.84-13.312 35.84-31.3344s-13.312-31.3344-31.3344-31.3344H332.3904c-17.8176-4.5056-31.3344 9.0112-31.3344 31.3344 0 18.0224 13.5168 31.3344 31.3344 31.3344z m0-263.5776h545.1776c22.3232 0 35.84-17.8176 35.84-35.84 0-17.8176-13.312-31.3344-31.3344-31.3344H332.3904c-17.8176 0-31.3344 13.312-31.3344 31.3344 0 17.8176 13.5168 35.84 31.3344 35.84zM158.1056 826.7776c26.8288 0 49.152-22.3232 49.152-49.152s-22.3232-49.152-49.152-49.152-49.152 22.3232-49.152 49.152 22.3232 49.152 49.152 49.152z m49.152-312.9344c0-26.8288-22.3232-49.152-49.152-49.152-26.8288-4.5056-49.152 17.8176-49.152 49.152 0 26.8288 22.3232 49.152 49.152 49.152s49.152-22.3232 49.152-49.152zM158.1056 294.912c26.8288 0 49.152-22.3232 49.152-49.152s-22.3232-49.152-49.152-49.152-49.152 22.3232-49.152 49.152 22.3232 49.152 49.152 49.152z m0 0" p-id="993"></path></svg>
|
After Width: | Height: | Size: 1.2 KiB |
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1735892132852" class="icon" viewBox="0 0 1061 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1525" xmlns:xlink="http://www.w3.org/1999/xlink" width="16.578125" height="16"><path d="M447.122465 467.332105L49.240301 268.161564A33.501036 33.501036 0 0 0 0.136043 300.744763v441.020484a33.042117 33.042117 0 0 0 16.06214 27.994016L413.162511 1018.034062a33.959954 33.959954 0 0 0 17.438895 5.50702 33.042117 33.042117 0 0 0 33.042117-33.042118V497.161795a33.042117 33.042117 0 0 0-17.438895-29.82969zM398.018207 931.298504l-331.339011-208.348907v-367.134638l331.339011 162.915996zM1046.010843 263.572381a33.042117 33.042117 0 0 0-31.665363 0L550.838 467.332105a33.042117 33.042117 0 0 0-19.733487 30.288608v493.33717a33.042117 33.042117 0 0 0 49.563176 28.452934l463.048562-265.254776a33.042117 33.042117 0 0 0 16.521059-28.452934V291.566398a33.042117 33.042117 0 0 0-14.685386-27.994017z m-50.939931 441.020484L596.72983 931.298504v-413.026468l397.882163-176.224626zM991.399565 178.672496a33.042117 33.042117 0 0 0-22.486996-29.829689L550.838 1.530034a32.583199 32.583199 0 0 0-19.733487 0L83.659173 158.021173a33.042117 33.042117 0 0 0-4.130264 61.036134l397.882163 199.170541a33.042117 33.042117 0 0 0 14.685386 3.212428 33.959954 33.959954 0 0 0 13.30863 0l463.966399-205.595398a33.042117 33.042117 0 0 0 22.028078-37.172382zM494.391049 349.849021L180.490934 195.193555l358.874108-125.743613 328.126583 112.434982z m0 0" p-id="1526"></path></svg>
|
After Width: | Height: | Size: 1.6 KiB |
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1735889652636" class="icon" viewBox="0 0 1128 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1085" xmlns:xlink="http://www.w3.org/1999/xlink" width="17.625" height="16"><path d="M1065.795918 0H62.693878C27.167347 0 0 27.167347 0 62.693878v668.734693c0 35.526531 27.167347 62.693878 62.693878 62.693878h1003.10204c35.526531 0 62.693878-27.167347 62.693878-62.693878V62.693878c0-35.526531-27.167347-62.693878-62.693878-62.693878z m0 731.428571H62.693878V62.693878h1003.10204v668.734693z" p-id="1086"></path><path d="M522.44898 773.22449v208.979592h62.693877V773.22449h-62.693877z" p-id="1087"></path><path d="M815.020408 961.306122H313.469388v62.693878h501.55102v-62.693878zM777.404082 234.057143c-6.269388-8.359184-16.718367-12.538776-25.077551-12.538776-8.359184 0-16.718367 0-25.077551 2.089796-16.718367 4.179592-35.526531 12.538776-56.42449 25.077551l-12.538776 6.269388c-27.167347-14.628571-58.514286-25.077551-94.040816-25.077551-104.489796 0-188.081633 83.591837-188.081633 188.081633 0 20.897959 4.179592 43.885714 10.44898 62.693877l-2.089796 2.089796c-14.628571 18.808163-27.167347 35.526531-35.526531 50.155102-4.179592 8.359184-6.269388 14.628571-8.359183 22.987755 0 8.359184 0 18.808163 6.269387 27.167347 12.538776 14.628571 33.436735 14.628571 48.065307 12.538776 16.718367-4.179592 35.526531-12.538776 58.514285-22.987755 31.346939 20.897959 68.963265 33.436735 110.759184 33.436734 81.502041 0 152.555102-52.244898 177.632653-125.387755l-39.706122-14.628571C681.273469 524.538776 626.938776 564.244898 564.244898 564.244898c-54.334694 0-104.489796-31.346939-127.477551-75.232653 27.167347-31.346939 64.783673-66.873469 108.669388-102.4 39.706122-33.436735 79.412245-60.604082 112.848979-81.502041 22.987755 18.808163 37.616327 41.795918 45.97551 71.053061H585.142857v41.795919h167.183674c0-27.167347-6.269388-54.334694-16.718368-77.322449 12.538776-12.538776 25.077551-27.167347 33.436735-39.706123 6.269388-10.44898 12.538776-20.897959 14.628571-31.346939 2.089796-8.359184 4.179592-22.987755-6.269387-35.52653zM388.702041 553.795918s-2.089796 0 0 0c-2.089796 0 0-2.089796 0-2.089796 4.179592-8.359184 10.44898-18.808163 18.808163-29.257142 4.179592 6.269388 10.44898 12.538776 14.628572 18.808163-14.628571 6.269388-25.077551 10.44898-33.436735 12.538775z m129.567347-200.620408c-37.616327 31.346939-71.053061 60.604082-98.220408 89.861225-2.089796-8.359184-2.089796-16.718367-2.089796-25.077551 0-81.502041 64.783673-146.285714 146.285714-146.285715 18.808163 0 35.526531 4.179592 52.244898 10.44898-29.257143 18.808163-62.693878 43.885714-98.220408 71.053061z m215.248979-75.232653c-4.179592 8.359184-12.538776 16.718367-18.808163 25.077551-6.269388-6.269388-12.538776-14.628571-18.808163-20.897959 18.808163-8.359184 33.436735-14.628571 43.885714-18.808163h2.089796c-4.179592 6.269388-6.269388 10.44898-8.359184 14.628571z" p-id="1088"></path></svg>
|
After Width: | Height: | Size: 3.0 KiB |
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1735892115074" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1207" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16"><path d="M938.666667 553.92V768c0 64.8-52.533333 117.333333-117.333334 117.333333H202.666667c-64.8 0-117.333333-52.533333-117.333334-117.333333V256c0-64.8 52.533333-117.333333 117.333334-117.333333h618.666666c64.8 0 117.333333 52.533333 117.333334 117.333333v297.92z m-64-74.624V256a53.333333 53.333333 0 0 0-53.333334-53.333333H202.666667a53.333333 53.333333 0 0 0-53.333334 53.333333v344.48A290.090667 290.090667 0 0 1 192 597.333333a286.88 286.88 0 0 1 183.296 65.845334C427.029333 528.384 556.906667 437.333333 704 437.333333c65.706667 0 126.997333 16.778667 170.666667 41.962667z m0 82.24c-5.333333-8.32-21.130667-21.653333-43.648-32.917333C796.768 511.488 753.045333 501.333333 704 501.333333c-121.770667 0-229.130667 76.266667-270.432 188.693334-2.730667 7.445333-7.402667 20.32-13.994667 38.581333-7.68 21.301333-34.453333 28.106667-51.370666 13.056-16.437333-14.634667-28.554667-25.066667-36.138667-31.146667A222.890667 222.890667 0 0 0 192 661.333333c-14.464 0-28.725333 1.365333-42.666667 4.053334V768a53.333333 53.333333 0 0 0 53.333334 53.333333h618.666666a53.333333 53.333333 0 0 0 53.333334-53.333333V561.525333zM320 480a96 96 0 1 1 0-192 96 96 0 0 1 0 192z m0-64a32 32 0 1 0 0-64 32 32 0 0 0 0 64z" p-id="1208"></path></svg>
|
After Width: | Height: | Size: 1.5 KiB |
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1736651367860" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1267" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16"><path d="M662.62186 561.268406c68.523788-46.884193 113.609197-126.232559 113.609197-216.401253 0-146.068057-119.020424-265.088481-265.088481-265.088481-146.072307 0-263.289697 119.020424-263.289697 263.284384 0 90.169757 45.08541 169.51706 113.61026 216.401253C206.375662 620.778086 98.177692 770.454336 98.177692 945.37731l0 0 73.936077 0 0 0c0-173.118878 131.641661-317.383901 299.353562-337.221524 1.804096 0 46.885256-3.60713 84.755343 0l3.60713 0 0 0c164.104771 23.441566 290.33733 164.101583 290.33733 335.417427l0 0 75.739111 0 0 0C924.101085 770.454336 815.903115 620.778086 662.62186 561.268406L662.62186 561.268406zM511.142576 541.431845c-110.006317 0-198.367727-88.363535-198.367727-198.36879 0-110.002067 88.362473-198.363477 198.367727-198.363477 110.001004 0 198.363477 88.36141 198.363477 198.363477C709.506053 453.069373 621.14358 541.431845 511.142576 541.431845L511.142576 541.431845zM511.142576 541.431845" fill="#272636" p-id="1268"></path></svg>
|
After Width: | Height: | Size: 1.3 KiB |
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1736651375254" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1428" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16"><path d="M700.667 128a96.001 96.001 0 0 1 78.505 40.746l2.733 4.104 135.997 215.994c22.525 35.776 18.916 81.878-8.384 113.667l-3.255 3.603-355.596 374.312c-20.288 21.355-54.045 22.22-75.4 1.933l-1.934-1.933-355.596-374.312c-29.119-30.651-34.641-76.563-14.122-113.098l2.483-4.172L242.095 172.85a96.001 96.001 0 0 1 76.309-44.724l4.929-0.126h377.334z m0 64H323.333a32.001 32.001 0 0 0-25.194 12.27l-1.885 2.68-135.997 215.994c-7.24 11.5-6.38 26.2 1.85 36.736l2.03 2.354L512 828.18l347.863-366.147c8.64-9.094 11.048-22.22 6.649-33.582l-1.242-2.8-1.527-2.708L727.746 206.95a32.001 32.001 0 0 0-23.807-14.783l-3.272-0.167z m-60.445 233.373l45.255 45.254L512 644.104 338.523 470.627l45.255-45.254L512 553.6l128.222-128.227z" fill="#000000" p-id="1429"></path></svg>
|
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 827 B |
After Width: | Height: | Size: 860 B |
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 2.4 MiB |
After Width: | Height: | Size: 5.5 KiB |
|
@ -0,0 +1,425 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-form
|
||||
class="form-content"
|
||||
:model="formData"
|
||||
:rules="rules"
|
||||
ref="formFef"
|
||||
label-width="120px"
|
||||
label-position="top"
|
||||
>
|
||||
<el-form-item prop="modelName">
|
||||
<div class="form-title">模型名称<span class="form-required">*</span></div>
|
||||
<div class="input-group">
|
||||
<el-input
|
||||
v-model="formData.name1"
|
||||
placeholder="宣传语,可填写模型系列、作者标识"
|
||||
></el-input>
|
||||
<span class="separator">-</span>
|
||||
<el-input
|
||||
v-model="formData.name2"
|
||||
placeholder="模型描述,例如:精致逼人人像摄影"
|
||||
></el-input>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 模型类型 -->
|
||||
<el-form-item prop="type">
|
||||
<div class="form-title">模型类型<span class="form-required">*</span></div>
|
||||
<el-select
|
||||
class="formWidth"
|
||||
v-model="formData.type"
|
||||
placeholder="请选择模型类型"
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in model_category"
|
||||
:key="item.dictValue"
|
||||
:label="item.dictLabel"
|
||||
:value="item.dictValue"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 内容类别 -->
|
||||
<el-form-item prop="category">
|
||||
<div class="form-title">内容类别</div>
|
||||
<div class="form-desc">
|
||||
填写类别可让模型获得更精准的流量, 平台也有权基于标准修改你的类别标签
|
||||
</div>
|
||||
<!-- <el-select
|
||||
class="formWidth"
|
||||
v-model="formData.category"
|
||||
placeholder="垂类"
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in categoryList"
|
||||
:key="item.dictCode"
|
||||
:label="item.dictLabel"
|
||||
:value="item.dictCode"
|
||||
></el-option>
|
||||
</el-select> -->
|
||||
<el-cascader
|
||||
class="formWidth"
|
||||
:props="{
|
||||
label: 'dictLabel', // 指定 label 对应的属性名
|
||||
value: 'dictValue', // 指定 value 对应的属性名
|
||||
children: 'children', // 如果有子选项,指定 children 对应的属性名
|
||||
}"
|
||||
v-model="formData.category"
|
||||
:options="categoryList"
|
||||
:show-all-levels="true"
|
||||
></el-cascader>
|
||||
<el-select
|
||||
style="margin-top: 4px"
|
||||
class="formWidth"
|
||||
v-model="formData.work_flow_functions"
|
||||
placeholder="功能"
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in work_flow_functions"
|
||||
:key="item.dictValue"
|
||||
:label="item.dictLabel"
|
||||
:value="item.dictValue"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 标签 -->
|
||||
<el-form-item prop="tags">
|
||||
<div class="form-title">标签</div>
|
||||
<div class="form-desc">添加标签将自动推荐给感兴趣的人</div>
|
||||
<!-- <el-select
|
||||
class="formWidth"
|
||||
v-model="form1.tags"
|
||||
multiple
|
||||
filterable
|
||||
allow-create
|
||||
placeholder="选择或输入后按回车键添加标签"
|
||||
:clearable="true"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in tags"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
></el-option>
|
||||
</el-select> -->
|
||||
|
||||
<el-select
|
||||
class="formWidth"
|
||||
v-model="formData.tags"
|
||||
multiple
|
||||
filterable
|
||||
allow-create
|
||||
default-first-option
|
||||
placeholder="选择或输入后按回车键添加标签"
|
||||
>
|
||||
<el-option v-for="item in tags" :key="item" :label="item.label" :value="item">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 参与活动 -->
|
||||
<el-form-item prop="activity">
|
||||
<div class="form-title">参与活动</div>
|
||||
<div class="form-desc">参加特定活动或比赛, 下拉选择</div>
|
||||
<el-select
|
||||
class="formWidth"
|
||||
v-model="formData.activity"
|
||||
placeholder="请选择参与活动"
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in activities"
|
||||
:key="item.dictValue"
|
||||
:label="item.dictLabel"
|
||||
:value="item.dictValue"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- reprint -->
|
||||
<!-- 原创内容 -->
|
||||
<el-form-item prop="content">
|
||||
<div class="form-title">原创内容<span class="form-required">*</span></div>
|
||||
<div class="FormField_content">
|
||||
<div class="ant-segmented-group">
|
||||
<div
|
||||
class="ant-segmented-group-item"
|
||||
v-for="(item, index) in originalBtnList"
|
||||
:key="index"
|
||||
@click="changeIsOriginal(item)"
|
||||
:style="{
|
||||
backgroundColor:
|
||||
formData.content === item.value ? 'rgba(49, 98, 255, 0.1)' : '#fff',
|
||||
color: formData.content === item.value ? '#3162ff' : '#000',
|
||||
}"
|
||||
>
|
||||
{{ item.label }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item prop="name" v-if="formData.content === 'reprint'">
|
||||
<el-input v-model="formData.name" placeholder="请输入原创作者名"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div class="step-group">
|
||||
<div class="step1-group">
|
||||
<div class="step-btn step1" @click="onStepNext()">下一步</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { dictType } from "@/api/mcwl/personalCenter";
|
||||
export default {
|
||||
name: "CreateModels",
|
||||
data() {
|
||||
return {
|
||||
categoryList:[],
|
||||
options1: [
|
||||
{
|
||||
dictValue: "zhinan",
|
||||
dictLabel: "指南",
|
||||
children: [
|
||||
{
|
||||
dictValue: "yizhi",
|
||||
dictLabel: "一致",
|
||||
},
|
||||
{
|
||||
dictValue: "fankui",
|
||||
dictLabel: "反馈",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
model_category: [], //模型类型
|
||||
model_part_category: [], //垂类一级
|
||||
model_child_category: [], //垂类二级
|
||||
chuilei: [], //模型类型
|
||||
work_flow_functions: [], //工能
|
||||
modelTypes: [
|
||||
{ label: "类型1", value: "type1" },
|
||||
{ label: "类型2", value: "type2" },
|
||||
{ label: "类型3", value: "type3" },
|
||||
],
|
||||
tags: [],
|
||||
activities: [],
|
||||
originalBtnList: [
|
||||
{ label: "原创", value: "original" },
|
||||
{ label: "转载", value: "reprint" },
|
||||
],
|
||||
// 表单验证规则
|
||||
rules: {
|
||||
modelName: [
|
||||
{
|
||||
validator: (rule, value, callback) => {
|
||||
// 如果两个部分都为空,校验失败
|
||||
if (!this.formData.name1 && !this.formData.name2) {
|
||||
callback(new Error("至少填写一个输入框内容"));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
},
|
||||
trigger: "blur", // 校验触发时机,可改为 'change'
|
||||
},
|
||||
],
|
||||
type: [{ required: true, message: "请输入内容", trigger: "change" }],
|
||||
},
|
||||
formData: {
|
||||
work_flow_functions: "",
|
||||
name: "",
|
||||
category: "",
|
||||
tags: [],
|
||||
activity: "",
|
||||
content: "original",
|
||||
},
|
||||
// categories: [],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
changeIsOriginal(item) {
|
||||
this.formData.content = item.value;
|
||||
},
|
||||
setdata(data1, data2) {},
|
||||
onStepNext() {
|
||||
this.$refs.formFef.validate((valid) => {
|
||||
if (valid) {
|
||||
this.$emit("changeCreateModelInfo", this.formData);
|
||||
this.$emit("stepNext", 2);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
},
|
||||
// 重置表单
|
||||
resetForm1() {
|
||||
this.$refs.form1.resetFields();
|
||||
},
|
||||
async getDictType() {
|
||||
// model_category:[], //模型类型
|
||||
// model_part_category:[], //垂类一级
|
||||
// model_child_category:[], //垂类二级
|
||||
// chuilei:[], //模型类型
|
||||
// work_flow_functions:[], //工能
|
||||
try {
|
||||
// const res = await dictType({ type: "model_category" });
|
||||
// const res2 = await dictType({ type: "model_part_category" });
|
||||
// const res3 = await dictType({ type: "model_child_category" });
|
||||
// const res4 = await dictType({ type: "work_flow_functions" });
|
||||
|
||||
const [res, res2, res3, res4] = await Promise.all([
|
||||
dictType({ type: "model_category" }),
|
||||
dictType({ type: "model_part_category" }),
|
||||
dictType({ type: "model_child_category" }),
|
||||
dictType({ type: "work_flow_functions" }),
|
||||
]);
|
||||
|
||||
this.model_category = res.data;
|
||||
this.model_part_category = res2.data;
|
||||
this.model_child_category = res3.data;
|
||||
this.work_flow_functions = res4.data;
|
||||
let categoryList = this.model_part_category;
|
||||
// 遍历第一个数据数组,检查是否有子项
|
||||
categoryList.forEach((item) => {
|
||||
// 给每个对象添加一个children属性,初始化为空数组
|
||||
item.children = [];
|
||||
|
||||
// 遍历第二个数据数组
|
||||
this.model_child_category.forEach((child) => {
|
||||
// 检查parentId是否与dictValue相等
|
||||
if (child.partId === item.dictCode) {
|
||||
// 将符合条件的子项放入children数组中
|
||||
item.children.push(child);
|
||||
}
|
||||
});
|
||||
});
|
||||
this.categoryList = categoryList;
|
||||
console.log(res2, res3);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.getDictType();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.form-content {
|
||||
.form-required{
|
||||
color: red;
|
||||
}
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
background-color: #f4f5f9;
|
||||
font-size: 14px;
|
||||
.step-group {
|
||||
margin-top: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.step-btn {
|
||||
width: 200px;
|
||||
height: 40px;
|
||||
margin-right: 20px;
|
||||
text-align: center;
|
||||
line-height: 40px;
|
||||
}
|
||||
.step1-group {
|
||||
display: flex;
|
||||
background-color: blue;
|
||||
border-radius: 4px;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.form-wrapper {
|
||||
position: relative;
|
||||
.version-form-group {
|
||||
position: absolute;
|
||||
right: -50px;
|
||||
top: 0;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
}
|
||||
.form2-upload-img {
|
||||
.upload-img-container {
|
||||
width: 100%;
|
||||
height: 150px;
|
||||
border: 1px dashed #ccc;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
background-color: #fff;
|
||||
border-radius: 10px;
|
||||
.upload-img-btn {
|
||||
padding: 4px 20px;
|
||||
text-align: center;
|
||||
background-color: rgb(45, 40, 255);
|
||||
color: #fff;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.upload-img-tips {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.nextStep {
|
||||
width: 300px;
|
||||
}
|
||||
.input-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.separator {
|
||||
margin: 0 8px;
|
||||
color: #ccc;
|
||||
}
|
||||
.formWidth {
|
||||
width: 100%;
|
||||
}
|
||||
.el-form--label-top .el-form-item__label {
|
||||
padding-bottom: 0 !important;
|
||||
}
|
||||
.el-form-item {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.el-button {
|
||||
margin-right: 10px;
|
||||
}
|
||||
.FormField_content {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
background-color: #fff;
|
||||
border-radius: 4px;
|
||||
.ant-segmented-group {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.ant-segmented-group-item {
|
||||
width: 50%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,467 @@
|
|||
<template>
|
||||
<div class="container">
|
||||
<div class="add-form">
|
||||
<el-button type="primary" @click="addForm">添加表单</el-button>
|
||||
</div>
|
||||
<input
|
||||
type="file"
|
||||
ref="fileInput"
|
||||
@change="handleFileChange"
|
||||
style="display: none"
|
||||
accept=".safetensors,.ckpt,.pt,.bin,.pth,.gguf,.sft"
|
||||
/>
|
||||
<div v-for="(form, index) in forms" :key="index" class="form-wrapper">
|
||||
<div class="version-form-group">
|
||||
<div class="">
|
||||
<i @click="removeForm(index)" class="el-icon-delete" :size="28"></i>
|
||||
</div>
|
||||
<!-- <div>上</div>
|
||||
<div>下</div> -->
|
||||
</div>
|
||||
<el-form
|
||||
:model="form"
|
||||
:ref="`form${index}`"
|
||||
:rules="rules"
|
||||
label-width="120px"
|
||||
label-position="top"
|
||||
>
|
||||
<el-form-item prop="name1">
|
||||
<div class="form-title">版本名称<span class="form-required">*</span></div>
|
||||
<el-input v-model="form.name1" placeholder="请输入名称"></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item prop="type1">
|
||||
<div class="form-title">基础类型<span class="form-required">*</span></div>
|
||||
<el-select v-model="form.type1" placeholder="请选择基础类型" class="formWidth">
|
||||
<el-option label="类型一" value="type1"></el-option>
|
||||
<el-option label="类型二" value="type2"></el-option>
|
||||
<el-option label="类型三" value="type3"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item prop="type">
|
||||
<div class="form2-upload-img">
|
||||
<div class="form-title">上传文件<span class="form-required">*</span></div>
|
||||
<div v-if="form.file"><span>100%</span>这是一个文件名</div>
|
||||
<div v-else class="upload-img-container">
|
||||
<div class="upload-img-btn" @click="onUploadFile(index)">上传文件</div>
|
||||
<!-- <div>拖拽文件</div> -->
|
||||
<div class="upload-img-tips">
|
||||
支持格式:.safetensors/.ckpt/.pt/.bin/.path/.gguf/.sft
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item prop="type">
|
||||
<div class="form2-upload-img">
|
||||
<div class="form-title">版本介绍<span class="form-required">*</span></div>
|
||||
<!-- <rich-text-editor v-model="form.editorContent" /> -->
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item prop="name">
|
||||
<div class="form-title">出发关键词</div>
|
||||
<div class="form-desc">
|
||||
填写类别可让模型获得更精准的流量, 平台也有权基于标准修改你的类别标签
|
||||
</div>
|
||||
<el-input v-model="form.name" placeholder="例如: 1boy"></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<div class="form-title">权限设置</div>
|
||||
<div class="form-desc">可见范围</div>
|
||||
<el-radio-group v-model="form.resource">
|
||||
<el-radio label="公开"></el-radio>
|
||||
<el-radio label="仅自己可见"></el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item prop="content">
|
||||
<div class="form-desc">付费设置</div>
|
||||
<div class="FormField_content">
|
||||
<div class="ant-segmented-group">
|
||||
<div
|
||||
class="ant-segmented-group-item"
|
||||
v-for="(item, index) in originalBtnList"
|
||||
:key="index"
|
||||
@click="form.content = item.value"
|
||||
:style="{
|
||||
backgroundColor:
|
||||
form.content === item.value ? 'rgba(49, 98, 255, 0.1)' : '#fff',
|
||||
color: form.content === item.value ? '#3162ff' : '#000',
|
||||
}"
|
||||
>
|
||||
{{ item.label }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<div style="margin-bottom: 10px">
|
||||
选择会员专属或会员下载视为你已经阅读
|
||||
<span style="color: blue"><<会员模型许可协议>></span> 并同意其中条款
|
||||
</div>
|
||||
|
||||
<el-form-item>
|
||||
<div class="form-desc">创作许可范围</div>
|
||||
<el-checkbox-group v-model="form.type">
|
||||
<el-checkbox label="允许在魔创未来在线使用" name="type"></el-checkbox>
|
||||
<el-checkbox label="允许下载生图" name="type"></el-checkbox>
|
||||
<el-checkbox
|
||||
label="允许在魔创未来旗下其他产品在线使用"
|
||||
name="type"
|
||||
></el-checkbox>
|
||||
<el-checkbox label="允许进行融合" name="type"></el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<div class="form-desc">商用权限</div>
|
||||
<el-checkbox-group v-model="form.type">
|
||||
<el-checkbox label="生成图片可售或者用于商业目的" name="type"></el-checkbox>
|
||||
<el-checkbox label="允许模型模型转售或融合后出售" name="type"></el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<div class="form-desc">独家设置</div>
|
||||
<el-checkbox-group v-model="form.type">
|
||||
<el-checkbox label="" name="type">
|
||||
此版本为魔创未来独家模型*获取更多流量* 独家模型规则
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item prop="description" style="margin-top: 20px;">
|
||||
<div class="form-title">上传文件<span class="form-required">*</span></div>
|
||||
<rich-text-editor />
|
||||
</el-form-item> -->
|
||||
|
||||
<!-- <el-button type="danger" @click="removeForm(index)">删除表单</el-button> -->
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="step-group">
|
||||
<div class="step1-group">
|
||||
<div
|
||||
class="step-btn step1"
|
||||
style="background-color: #f1f2f7; color: #000; margin-right: 20px"
|
||||
@click="onStep1Next(1)"
|
||||
>
|
||||
上一步
|
||||
</div>
|
||||
<div class="step-btn step1" @click="onStep1Next(3)">下一步</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { uploadImagesInBatches } from "@/utils/uploadImages.js";
|
||||
// import RichTextEditor from "@/components/WangEditor";
|
||||
import { dictType } from "@/api/mcwl/personalCenter";
|
||||
import { getZipUrlFile, uploadFile } from "@/api/mcwl/mallProduct";
|
||||
export default {
|
||||
name: "editVersion",
|
||||
data() {
|
||||
return {
|
||||
allowedExtensions: [
|
||||
".safetensors",
|
||||
".ckpt",
|
||||
".pt",
|
||||
".bin",
|
||||
".pth",
|
||||
".gguf",
|
||||
".sft",
|
||||
],
|
||||
currentUploadIndex: 0,
|
||||
rules: {
|
||||
name1: [{ required: true, message: "请输入内容", trigger: "blur" }],
|
||||
type1: [{ required: true, message: "请选择选项", trigger: "change" }],
|
||||
},
|
||||
originalBtnList: [
|
||||
{
|
||||
label: "原创",
|
||||
value: "original",
|
||||
},
|
||||
{
|
||||
label: "转载",
|
||||
value: "reprint",
|
||||
},
|
||||
],
|
||||
forms: [
|
||||
{
|
||||
name1: "",
|
||||
type1: "",
|
||||
type: "",
|
||||
file: "",
|
||||
content: "original",
|
||||
description: "",
|
||||
},
|
||||
],
|
||||
|
||||
// 模型类型选项
|
||||
modelTypes: [
|
||||
{ label: "类型1", value: "type1" },
|
||||
{ label: "类型2", value: "type2" },
|
||||
{ label: "类型3", value: "type3" },
|
||||
],
|
||||
// 内容类别选项
|
||||
categories: [
|
||||
{ label: "垂类", value: "vertical" },
|
||||
{ label: "功能", value: "function" },
|
||||
],
|
||||
// 标签选项
|
||||
tags: ["标签1", "标签2", "标签3"],
|
||||
// 参与活动选项
|
||||
activities: [
|
||||
{ label: "活动1", value: "activity1" },
|
||||
{ label: "活动2", value: "activity2" },
|
||||
{ label: "活动3", value: "activity3" },
|
||||
],
|
||||
};
|
||||
},
|
||||
components: {
|
||||
// RichTextEditor,
|
||||
},
|
||||
methods: {
|
||||
// 检查文件后缀名是否合法
|
||||
isFileExtensionValid(file) {
|
||||
const fileName = file.name;
|
||||
const fileExtension = fileName.slice(fileName.lastIndexOf(".")).toLowerCase();
|
||||
return this.allowedExtensions.includes(fileExtension);
|
||||
},
|
||||
async handleFileChange(event) {
|
||||
const files = event.target.files;
|
||||
if (files.length > 1) {
|
||||
alert("只能选择 1 张图片");
|
||||
return;
|
||||
}
|
||||
|
||||
let imageFiles = [];
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
const file = files[i];
|
||||
if (this.isFileExtensionValid(file)) {
|
||||
imageFiles.push(file);
|
||||
} else {
|
||||
this.$message.error(
|
||||
"文件类型不支持,请上传 .safetensors、.ckpt、.pt、.bin、。gguf、.sft 或 .pth 文件"
|
||||
);
|
||||
}
|
||||
}
|
||||
const formData = new FormData();
|
||||
formData.append("file", imageFiles[0]); // 'file' 是后端要求的字段名
|
||||
formData.append("fileName", imageFiles[0].name);
|
||||
const pictureResultList = await uploadFile(formData);
|
||||
},
|
||||
|
||||
onUploadFile(index) {
|
||||
this.currentUploadIndex = index;
|
||||
this.$refs.fileInput.click();
|
||||
},
|
||||
|
||||
// 添加表单form
|
||||
addForm() {
|
||||
this.forms.push({
|
||||
name: "",
|
||||
type: "",
|
||||
image: "",
|
||||
description: "",
|
||||
});
|
||||
},
|
||||
// 下一步
|
||||
onStep1Next(index) {
|
||||
if (index == 3) {
|
||||
let allValid = true;
|
||||
this.forms.forEach((form, index) => {
|
||||
this.$refs[`form${index}`][0].validate((valid) => {
|
||||
if (!valid) {
|
||||
allValid = false;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (allValid) {
|
||||
this.$emit("stepNext", index);
|
||||
this.$emit("changeEditVersionInfo", this.forms);
|
||||
// 在这里处理提交逻辑
|
||||
} else {
|
||||
console.log("表单验证未通过");
|
||||
}
|
||||
} else if (index == 1) {
|
||||
this.$emit("stepNext", index);
|
||||
}
|
||||
},
|
||||
//删除表单
|
||||
removeForm(index) {
|
||||
if (this.forms.length == 1) {
|
||||
return;
|
||||
}
|
||||
this.forms.splice(index, 1);
|
||||
},
|
||||
async getDictType() {
|
||||
try {
|
||||
const res = await dictType({ type: "mall_product_status" });
|
||||
const res2 = await dictType({ type: "mall_product_order" });
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.container {
|
||||
.add-form {
|
||||
margin-top: -20px;
|
||||
margin-bottom: 20px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
margin: 20px;
|
||||
.step-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.step-btn {
|
||||
width: 200px;
|
||||
height: 40px;
|
||||
text-align: center;
|
||||
line-height: 40px;
|
||||
}
|
||||
.step1-group {
|
||||
display: flex;
|
||||
background-color: blue;
|
||||
border-radius: 4px;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.steps {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 11px;
|
||||
margin-bottom: 20px;
|
||||
|
||||
.step {
|
||||
width: 60%;
|
||||
}
|
||||
.el-steps {
|
||||
padding: 11px;
|
||||
.el-step {
|
||||
padding: 11px;
|
||||
|
||||
.el-step__head.is-finish {
|
||||
padding: 11px;
|
||||
|
||||
.el-step__icon {
|
||||
z-index: 0 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.form-title {
|
||||
line-height: 26px;
|
||||
font-weight: 600;
|
||||
.form-required {
|
||||
margin-left: 4px;
|
||||
color: #ff0000;
|
||||
}
|
||||
}
|
||||
.FormField_content {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
background-color: #fff;
|
||||
border-radius: 4px;
|
||||
.ant-segmented-group {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.ant-segmented-group-item {
|
||||
width: 50%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.form-desc {
|
||||
font-size: 12px;
|
||||
line-height: 12px;
|
||||
text-align: left;
|
||||
color: #999;
|
||||
margin: 4px 0;
|
||||
}
|
||||
.form-content {
|
||||
.form-wrapper {
|
||||
padding: 20px;
|
||||
border-radius: 10px;
|
||||
background-color: #f4f5f9;
|
||||
font-size: 14px;
|
||||
margin-bottom: 20px;
|
||||
position: relative;
|
||||
.version-form-group {
|
||||
position: absolute;
|
||||
right: -50px;
|
||||
top: 0;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
}
|
||||
.form2-upload-img {
|
||||
.upload-img-container {
|
||||
width: 100%;
|
||||
height: 150px;
|
||||
border: 1px dashed #ccc;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
background-color: #fff;
|
||||
border-radius: 10px;
|
||||
.upload-img-btn {
|
||||
padding: 4px 20px;
|
||||
text-align: center;
|
||||
background-color: rgb(45, 40, 255);
|
||||
color: #fff;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.upload-img-tips {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.nextStep {
|
||||
width: 300px;
|
||||
}
|
||||
.input-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.separator {
|
||||
margin: 0 8px;
|
||||
color: #ccc;
|
||||
}
|
||||
}
|
||||
.formWidth {
|
||||
width: 100%;
|
||||
}
|
||||
.el-form--label-top .el-form-item__label {
|
||||
padding-bottom: 0 !important;
|
||||
}
|
||||
.el-form-item {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.el-button {
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,223 @@
|
|||
<template>
|
||||
<div class="product-list" ref="listContainer" @scroll="handleScroll">
|
||||
<div class="image-grid-container">
|
||||
<!-- 商品卡片网格 -->
|
||||
<div class="image-grid">
|
||||
<div
|
||||
class="image-card"
|
||||
v-for="item in products"
|
||||
:key="item.id"
|
||||
>
|
||||
<div class="image-wrapper">
|
||||
<img src="http://img2.baidu.com/it/u=705459853,1015457524&fm=253&app=138&f=JPEG?w=800&h=1422" :alt="item.title" />
|
||||
</div>
|
||||
<div class="image-info">
|
||||
<h3 class="title">{{ item.title }}</h3>
|
||||
<p class="details">{{ item.details }}</p>
|
||||
<div class="stats">
|
||||
<span><i class="icon icon-view"></i>{{ item.views }}</span>
|
||||
<span><i class="icon icon-like"></i>{{ item.likes }}</span>
|
||||
<span><i class="icon icon-comment"></i>{{ item.comments }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="loading" class="loading">加载中...</div>
|
||||
<div v-if="noMore" class="no-more">没有更多商品了</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { selectByUserLike} from "@/api/mcwl/personalCenter";
|
||||
import _ from 'lodash';
|
||||
export default {
|
||||
props: {
|
||||
order: {
|
||||
type: String,
|
||||
default: 0, // 默认值为 0
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
order: {
|
||||
// immediate: true,
|
||||
handler() {
|
||||
this.resetAndFetchProducts();
|
||||
},
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.fetchProducts();
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
products: [], // 商品列表数据
|
||||
pageNumber: 1, // 当前页码
|
||||
pageSize: 12, // 每页商品数量
|
||||
loading: false, // 是否正在加载
|
||||
noMore: false, // 是否没有更多数据
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
// 节流函数
|
||||
throttle(func, delay) {
|
||||
let lastTime = 0;
|
||||
return function (...args) {
|
||||
const now = new Date().getTime();
|
||||
if (now - lastTime >= delay) {
|
||||
lastTime = now;
|
||||
func.apply(this, args);
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
// 重置数据并重新获取商品
|
||||
resetAndFetchProducts() {
|
||||
this.products = [];
|
||||
this.pageNumber = 1;
|
||||
this.noMore = false;
|
||||
this.fetchProducts();
|
||||
},
|
||||
// 获取商品数据
|
||||
async fetchProducts() {
|
||||
if (this.loading || this.noMore) return;
|
||||
this.loading = true;
|
||||
try {
|
||||
let params = {
|
||||
pageNumber: this.pageNumber,
|
||||
pageSize: this.pageSize,
|
||||
order: this.order, //
|
||||
}
|
||||
selectByUserLike(params).then((res)=>{
|
||||
const newProducts = res.data.records;
|
||||
if (newProducts.length < this.pageSize) {
|
||||
this.noMore = true; // 数据不足一页,标记为无更多数据
|
||||
}
|
||||
this.products = [...this.products, ...newProducts];
|
||||
this.pageNumber += 1; // 下一页
|
||||
})
|
||||
} catch (error) {
|
||||
console.error("加载商品数据失败:", error);
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
handleScroll() {
|
||||
const container = this.$refs.listContainer;
|
||||
if (!container) return;
|
||||
|
||||
const scrollTop = container.scrollTop; // 滚动条距离顶部的高度
|
||||
const scrollHeight = container.scrollHeight; // 滚动内容的总高度
|
||||
const clientHeight = container.clientHeight; // 容器的可见高度
|
||||
|
||||
// 如果滚动到底部,触发加载更多
|
||||
if (scrollTop + clientHeight >= scrollHeight - 10) {
|
||||
this.fetchProducts();
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.product-list {
|
||||
height: 400px;
|
||||
overflow-y: auto;
|
||||
// border: 1px solid #ccc;
|
||||
padding: 10px;
|
||||
/* SCSS 样式 */
|
||||
|
||||
/* 变量定义 */
|
||||
$background-color: #f5f5f5;
|
||||
$card-bg-color: #fff;
|
||||
$text-color: #333;
|
||||
$sub-text-color: #555;
|
||||
$icon-color: #999;
|
||||
$box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
|
||||
/* 容器样式 */
|
||||
.image-grid-container {
|
||||
// height: 100px;
|
||||
padding: 20px;
|
||||
background-color: $background-color;
|
||||
|
||||
.image-grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 16px;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.image-card {
|
||||
height: 300px;
|
||||
background: $card-bg-color;
|
||||
border-radius: 8px;
|
||||
// box-shadow: $box-shadow;
|
||||
overflow: hidden;
|
||||
width: calc(25% - 16px); // 每行显示 4 个卡片
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.image-wrapper {
|
||||
img {
|
||||
width: 100%;
|
||||
height: 300px;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.image-info {
|
||||
padding: 10px;
|
||||
font-size: 14px;
|
||||
color: $text-color;
|
||||
|
||||
.title {
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
margin-bottom: 8px;
|
||||
color: darken($text-color, 10%);
|
||||
}
|
||||
|
||||
.details {
|
||||
margin-bottom: 8px;
|
||||
color: $sub-text-color;
|
||||
}
|
||||
|
||||
.stats {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 12px;
|
||||
color: $icon-color;
|
||||
|
||||
span {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
|
||||
.icon {
|
||||
font-size: 14px;
|
||||
color: $icon-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.product-item {
|
||||
margin-bottom: 15px;
|
||||
padding: 10px;
|
||||
// border: 1px solid #481212;
|
||||
border-radius: 5px;
|
||||
color: #481212;
|
||||
}
|
||||
|
||||
.loading,
|
||||
.no-more {
|
||||
text-align: center;
|
||||
padding: 10px;
|
||||
color: #999;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,289 @@
|
|||
<template>
|
||||
<div class="container">
|
||||
<div class="profile-container">
|
||||
<div class="profile-header">
|
||||
<div class="profile-avatar" @click="handlePictureInput">
|
||||
<img :src="ruleForm.avatar" class="avatar" alt="头像" />
|
||||
</div>
|
||||
<input
|
||||
type="file"
|
||||
@change="handlePictureChange"
|
||||
accept="image/*"
|
||||
ref="pictureInput"
|
||||
style="display: none"
|
||||
/>
|
||||
<!-- <el-upload
|
||||
class="upload-demo"
|
||||
action="#"
|
||||
@change="handlePictureChange"
|
||||
:on-preview="handlePreview"
|
||||
:on-remove="handleRemove"
|
||||
:limit="1"
|
||||
:file-list="fileList">
|
||||
<el-button size="small" type="primary">点击上传</el-button>
|
||||
</el-upload> -->
|
||||
</div>
|
||||
<div class="profile-form">
|
||||
<!-- <div class="form-group">
|
||||
<label for="username">用户名 *</label>
|
||||
<div class="input-wrapper">
|
||||
<input v-model="nickName" type="text" id="username" maxlength="10" placeholder="请输入用户名" value="微信用户a98592" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="bio">简介</label>
|
||||
<textarea v-model="brief" id="bio" placeholder="请输入简介"></textarea>
|
||||
</div> -->
|
||||
|
||||
<el-form
|
||||
label-width="70px"
|
||||
:model="ruleForm"
|
||||
:rules="rules"
|
||||
ref="ruleForm"
|
||||
class="demo-ruleForm"
|
||||
>
|
||||
<el-form-item label="用户名" prop="nickName">
|
||||
<el-input v-model="ruleForm.nickName"></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="简介" prop="brief">
|
||||
<el-input type="textarea" :rows="5" v-model="ruleForm.brief"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<div class="form-buttons">
|
||||
<button type="button" class="cancel-button" @click="closeEditInfo">
|
||||
暂不修改
|
||||
</button>
|
||||
<button type="submit" class="submit-button" @click="onUpdate">确认修改</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { updateUserInfo } from "@/api/mcwl/login";
|
||||
import { uploadImagesInBatches } from "@/utils/uploadImages.js";
|
||||
import { mapGetters } from "vuex";
|
||||
export default {
|
||||
name: "McEdit",
|
||||
methods: {},
|
||||
data() {
|
||||
return {
|
||||
fileList: [],
|
||||
ruleForm: {
|
||||
nickName: "",
|
||||
avatar: "",
|
||||
brief: "",
|
||||
userId: "",
|
||||
},
|
||||
rules: {
|
||||
nickName: [
|
||||
{ required: true, message: "请输入用户名", trigger: "change" },
|
||||
{ min: 3, max: 12, message: "长度在 3 到 10 个字符", trigger: "change" },
|
||||
],
|
||||
brief: [{ required: false, message: "请填写简介", trigger: "blur" }],
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(["nickName", "avatar", "brief", "userId"]),
|
||||
},
|
||||
props: {},
|
||||
methods: {
|
||||
handlePictureInput() {
|
||||
this.$refs.pictureInput.click();
|
||||
},
|
||||
|
||||
handleRemove(file, fileList) {
|
||||
console.log(file, fileList);
|
||||
},
|
||||
handlePreview(file) {},
|
||||
|
||||
async handlePictureChange(event) {
|
||||
console.log("object", event);
|
||||
const files = event.target.files;
|
||||
if (files.length > 1) {
|
||||
alert("只能选择 1 张图片");
|
||||
return;
|
||||
}
|
||||
|
||||
let imageFiles = [];
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
const file = files[i];
|
||||
if (file.type.startsWith("image/")) {
|
||||
imageFiles.push(file);
|
||||
// this.imageUrls.push(URL.createObjectURL(file)); // 生成预览 URL
|
||||
} else {
|
||||
alert("请选择有效的图片文件");
|
||||
}
|
||||
}
|
||||
|
||||
const pictureResultList = await uploadImagesInBatches(imageFiles);
|
||||
this.ruleForm.avatar = pictureResultList[0];
|
||||
},
|
||||
onUpdate() {
|
||||
updateUserInfo(this.ruleForm).then((res) => {
|
||||
if (res.code == 200) {
|
||||
this.$message.success("修改成功");
|
||||
this.closeEditInfo();
|
||||
}
|
||||
});
|
||||
},
|
||||
closeEditInfo() {
|
||||
this.$emit("closeEditInfo", false);
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.ruleForm.nickName = this.nickName;
|
||||
this.ruleForm.avatar = this.avatar;
|
||||
this.ruleForm.brief = this.brief;
|
||||
this.ruleForm.userId = this.userId;
|
||||
console.log("ruleForm", this.userId, this.ruleForm);
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
background-color: #f7f9fc;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.profile-container {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
width: 400px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.profile-header {
|
||||
margin-bottom: 20px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.profile-avatar {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.change-avatar-button {
|
||||
position: absolute;
|
||||
bottom: -10px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
background-color: #f0f0f0;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
font-size: 12px;
|
||||
padding: 5px 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.profile-form .form-group {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.profile-form label {
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.input-wrapper {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.input-wrapper input {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
border: 1px solid #d8d8d8;
|
||||
border-radius: 5px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.input-wrapper .char-count {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
font-size: 12px;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
textarea {
|
||||
width: 100%;
|
||||
height: 80px;
|
||||
padding: 10px;
|
||||
border: 1px solid #d8d8d8;
|
||||
border-radius: 5px;
|
||||
font-size: 14px;
|
||||
resize: none;
|
||||
}
|
||||
|
||||
.social-links {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.social-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.social-link span {
|
||||
white-space: nowrap;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.social-link input {
|
||||
flex: 1;
|
||||
padding: 10px;
|
||||
border: 1px solid #d8d8d8;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.form-buttons {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.cancel-button,
|
||||
.submit-button {
|
||||
flex: 1;
|
||||
padding: 10px;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
margin: 0 5px;
|
||||
}
|
||||
|
||||
.cancel-button {
|
||||
background-color: #e0e0e0;
|
||||
}
|
||||
|
||||
.submit-button {
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,296 @@
|
|||
<template>
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<div class="header-left">
|
||||
<a
|
||||
class="header-iconLogo"
|
||||
style="
|
||||
background-image: url('https://liblibai-web-static.liblib.cloud/liblibai_v4_online/static/_next/static/images/icon-logo.e3ce24f316fb81dbde1cafc3bf956080.svg');
|
||||
"
|
||||
></a>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<!-- <div>PC客户端</div> -->
|
||||
<div class="header-right-btn pc-client">
|
||||
<svg-icon icon-class="mc-pckehuduan"></svg-icon>
|
||||
PC客户端
|
||||
</div>
|
||||
<div class="header-right-btn">
|
||||
<svg-icon icon-class="mc-jiaochengzhuanqu"></svg-icon>
|
||||
教程专区
|
||||
</div>
|
||||
<div class="header-right-btn publish">
|
||||
<svg-icon icon-class="mc-fabu"></svg-icon>
|
||||
发布
|
||||
<div class="publish-menu">
|
||||
<div class="publish-menu-inner">
|
||||
<div class="publish-menu-item">
|
||||
<svg-icon icon-class="mc-moxing"></svg-icon>
|
||||
模型
|
||||
</div>
|
||||
<div class="publish-menu-item" @click="onShowPublishPicture">
|
||||
<svg-icon icon-class="mc-tupian"></svg-icon>
|
||||
图片
|
||||
</div>
|
||||
<div class="publish-menu-item">
|
||||
<svg-icon icon-class="mc-gongzuoliu"></svg-icon>
|
||||
工作流
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mc-avatar" v-if="avatar">
|
||||
<img :src="avatar" alt="" class="mcwl-avatar-img" />
|
||||
<div class="avatar-menu">
|
||||
<div class="avatar-menu-inner">
|
||||
<div class="avatar-menu-item">
|
||||
<svg-icon icon-class="mc-moxing"></svg-icon>
|
||||
我的模型
|
||||
</div>
|
||||
<div class="avatar-menu-item">
|
||||
<svg-icon icon-class="mc-tupian"></svg-icon>
|
||||
我的作品
|
||||
</div>
|
||||
<div class="avatar-menu-item">
|
||||
<svg-icon icon-class="mc-gongzuoliu"></svg-icon>
|
||||
我点赞的
|
||||
</div>
|
||||
<div class="avatar-menu-item" @click="logout">
|
||||
<svg-icon icon-class="mc-gongzuoliu"></svg-icon>
|
||||
退出登录
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="header-right-btn header-login" v-else @click="onShowLogin">
|
||||
登录/注册
|
||||
</div>
|
||||
<!-- <div><el-button class="pc-client"><svg-icon icon-class="404" @click="click" />PC客户端</el-button></div>
|
||||
<div><el-button><svg-icon icon-class="404" @click="click" />教程专区</el-button></div>
|
||||
<div><el-button><svg-icon icon-class="404" @click="click" />发布</el-button></div>
|
||||
<div><el-button><svg-icon icon-class="404" @click="click" />登录/注册</el-button></div> -->
|
||||
</div>
|
||||
</div>
|
||||
<PublishWorks
|
||||
@closePublishWorks="closePublishPicture"
|
||||
v-if="visiblePostPicture"
|
||||
></PublishWorks>
|
||||
<!-- <div class="login-content">
|
||||
<McLogin @onCloseLogin="onCloseLogin" @success="loginSuccess" v-if="showLogin"></McLogin>
|
||||
</div> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { downloadImage } from "@/utils/downloadImage";
|
||||
import PublishWorks from "@/components/PublishWorks";
|
||||
import { mapGetters } from "vuex";
|
||||
export default {
|
||||
name: "McHeader",
|
||||
data() {
|
||||
return {
|
||||
visiblePostPicture: false,
|
||||
// showLogin:false
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(["nickName", "avatar"]),
|
||||
},
|
||||
methods: {
|
||||
async logout() {
|
||||
this.$confirm("确定注销并退出系统吗?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning",
|
||||
})
|
||||
.then(() => {
|
||||
this.$store.dispatch("LogOut").then(() => {
|
||||
location.href = "/";
|
||||
});
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
onShowPublishPicture() {
|
||||
this.visiblePostPicture = true;
|
||||
},
|
||||
closePublishPicture() {
|
||||
this.visiblePostPicture = false;
|
||||
},
|
||||
onShowLogin() {
|
||||
this.$eventBus.$emit("showLogin");
|
||||
},
|
||||
handleDownload() {
|
||||
const imageUrl =
|
||||
"https://img0.baidu.com/it/u=2191392668,814349101&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=1399";
|
||||
const fileName = "downloaded_image.jpg"; // 可自定义文件名
|
||||
downloadImage(imageUrl, fileName);
|
||||
},
|
||||
},
|
||||
|
||||
beforeMount() {
|
||||
console.log(this.nickName, "name");
|
||||
// this.onGetCode()
|
||||
},
|
||||
mounted() {
|
||||
const parent = document.querySelector(".mc-avatar");
|
||||
const child = document.querySelector(".avatar-menu");
|
||||
if (parent && child) {
|
||||
parent.addEventListener("mouseenter", () => {
|
||||
const rect = child.getBoundingClientRect();
|
||||
if (rect.right > window.innerWidth) {
|
||||
child.style.left = "auto"; // 取消左定位
|
||||
child.style.right = "-10px"; // 右对齐
|
||||
}
|
||||
});
|
||||
|
||||
parent.addEventListener("mouseleave", () => {
|
||||
child.style.left = "50%"; // 重置为默认值
|
||||
child.style.right = "auto"; // 重置右对齐
|
||||
});
|
||||
}
|
||||
},
|
||||
components: {
|
||||
PublishWorks,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.header-btn {
|
||||
color: #1890ff;
|
||||
// border-color: #badeff;
|
||||
}
|
||||
.container {
|
||||
// position: absolute;
|
||||
// top: 0;
|
||||
// left: 0;
|
||||
// width: 100%;
|
||||
// padding:0 20px;
|
||||
.login-content {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
flex: 1;
|
||||
z-index: 999;
|
||||
}
|
||||
.header {
|
||||
padding: 10px 20px;
|
||||
border-bottom: 1px solid #e5e7eb;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
.header-left {
|
||||
.header-iconLogo {
|
||||
display: block;
|
||||
background-repeat: no-repeat;
|
||||
width: 100px;
|
||||
height: 40px;
|
||||
}
|
||||
}
|
||||
.header-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.header-right-btn {
|
||||
position: relative;
|
||||
padding: 6px 10px;
|
||||
border-radius: 6px;
|
||||
margin-right: 10px;
|
||||
color: rgb(51, 51, 51);
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
background-color: rgb(241, 242, 248);
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
color: #1890ff;
|
||||
// border: 1px solid #1890ff;
|
||||
// background-color: #fff;
|
||||
border-color: #badeff;
|
||||
}
|
||||
}
|
||||
.mc-avatar {
|
||||
// overflow: hidden;
|
||||
margin-right: 10px;
|
||||
cursor: pointer;
|
||||
img {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
position: relative;
|
||||
&:hover {
|
||||
.avatar-menu {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
.avatar-menu {
|
||||
display: none;
|
||||
position: absolute;
|
||||
z-index: 999;
|
||||
left: -20px;
|
||||
top: 40px;
|
||||
background-color: #fff;
|
||||
font-size: 14px;
|
||||
color: rgb(51, 51, 51);
|
||||
font-weight: 500;
|
||||
.avatar-menu-inner {
|
||||
border-radius: 10px;
|
||||
margin-top: 10px;
|
||||
width: 120px;
|
||||
padding: 10px 20px;
|
||||
border: 1px solid #e5e7eb;
|
||||
.avatar-menu-item {
|
||||
&:hover {
|
||||
color: #1890ff;
|
||||
}
|
||||
color: #2d2d2e;
|
||||
padding: 8px 0;
|
||||
> svg {
|
||||
margin-right: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.publish {
|
||||
position: relative;
|
||||
&:hover {
|
||||
.publish-menu,
|
||||
publish-menu:hover {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
.publish-menu {
|
||||
display: none;
|
||||
position: absolute;
|
||||
z-index: 999;
|
||||
left: -20px;
|
||||
top: 30px;
|
||||
background-color: #fff;
|
||||
.publish-menu-inner {
|
||||
border-radius: 10px;
|
||||
margin-top: 10px;
|
||||
width: 110px;
|
||||
padding: 10px 20px;
|
||||
border: 1px solid #e5e7eb;
|
||||
.publish-menu-item {
|
||||
&:hover {
|
||||
color: #1890ff;
|
||||
}
|
||||
color: #2d2d2e;
|
||||
padding: 8px 0;
|
||||
> svg {
|
||||
margin-right: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.pc-client {
|
||||
color: #1890ff;
|
||||
border: 1px solid #1890ff;
|
||||
background-color: #fff;
|
||||
border-color: #badeff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,333 @@
|
|||
<template>
|
||||
<div v-if="isVisible" class="login-container">
|
||||
<div class="login-box">
|
||||
<i class="el-icon-close close-login" @click="onCloseLogin(false)"></i>
|
||||
<div class="login-form">
|
||||
<h2 class="title">{{ loginModeDescriptions[currentLoginMode].title }}</h2>
|
||||
<p class="subtitle">{{ loginModeDescriptions[currentLoginMode].des }}</p>
|
||||
<el-form
|
||||
v-if="currentLoginMode === 'phone'"
|
||||
ref="ruleFormRef"
|
||||
:model="ruleForm"
|
||||
:rules="rules"
|
||||
label-width="0"
|
||||
>
|
||||
<el-form-item prop="phone">
|
||||
<el-input
|
||||
v-model="ruleForm.phone"
|
||||
placeholder="请输入手机号"
|
||||
>
|
||||
<!-- <template #prepend>
|
||||
+86
|
||||
</template> -->
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="code">
|
||||
<el-input v-model="ruleForm.code" placeholder="请输入验证码">
|
||||
<template #suffix>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="small"
|
||||
class="code-button"
|
||||
:disabled="codeButtonDisabled"
|
||||
@click="onGetCode"
|
||||
>
|
||||
{{ codeButtonText }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<!-- <el-checkbox v-model="form.agree">
|
||||
点击【登录】代表同意
|
||||
<a href="#/user-agreement">《用户协议》</a>
|
||||
<a href="#/privacy-policy">《隐私政策》</a>
|
||||
</el-checkbox> -->
|
||||
<div class="agreement-text">
|
||||
<div>点击【登录】代表同意</div>
|
||||
<div class="agreement-link">《用户协议》《隐私政策》</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<div class="login-button" @click="submitForm(ruleFormRef)">登录</div>
|
||||
</el-form>
|
||||
<div v-if="currentLoginMode === 'wechat'" class="wechat-qs">
|
||||
<div class="qr-code">
|
||||
<McWechatLoginQr />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="other-login-methods">
|
||||
<div>
|
||||
<span>其他登录方式</span>
|
||||
</div>
|
||||
<div class="icons-container">
|
||||
<div class="icon-item" @click="setCurrentLoginMode(currentLoginMode)">
|
||||
<img :src="loginModeDescriptions[currentLoginMode].src" alt="" />
|
||||
</div>
|
||||
<!-- <div class="icon-item">
|
||||
<img src="../../assets/images/icon/icon-qq.png" alt="" />
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getCode } from "@/api/mcwl/login";
|
||||
import McWechatLoginQr from "@/components/McWechatLoginQr";
|
||||
export default {
|
||||
name: "McLogin",
|
||||
data(){
|
||||
return{
|
||||
isVisible: false, // 默认隐藏弹窗
|
||||
rules:{
|
||||
phone: [
|
||||
{ required: true, message: '请输入手机号', trigger: 'change' },
|
||||
{ pattern: /^1[3-9]\d{9}$/, message: '手机号格式不正确', trigger: 'blur' }
|
||||
],
|
||||
code: [
|
||||
{ required: true, message: '请输入验证码', trigger: 'change' },
|
||||
{ len: 4, message: '验证码长度为4位', trigger: 'blur' }
|
||||
]
|
||||
},
|
||||
codeButtonText:'获取验证码',
|
||||
codeButtonDisabled:false,
|
||||
timerCode:null,
|
||||
ruleForm:{
|
||||
phone: '15888888888',
|
||||
code: ''
|
||||
},
|
||||
ruleFormRef:null,
|
||||
currentLoginMode:'phone',
|
||||
loginModeDescriptions:{
|
||||
phone: {
|
||||
title: '登录',
|
||||
des: '如未注册,验证后自动登录',
|
||||
src: require('@/assets/images/phone.png')
|
||||
},
|
||||
wechat: {
|
||||
title: '微信一键登录',
|
||||
des: '关注后自动登录',
|
||||
src: require('@/assets/images/wechat.png')
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
components:{
|
||||
McWechatLoginQr
|
||||
},
|
||||
methods: {
|
||||
closeLogin() {
|
||||
this.isVisible = false;
|
||||
},
|
||||
showLogin() {
|
||||
if (this.isVisible) return;
|
||||
this.isVisible = true; // 显示弹窗
|
||||
},
|
||||
onCloseLogin(ag){
|
||||
this.isVisible =false
|
||||
this.$emit('onCloseLogin', ag)
|
||||
},
|
||||
toggleMode(mode){
|
||||
return mode === 'phone' ? 'wechat' : mode === 'wechat' ? 'phone' : mode
|
||||
},
|
||||
setCurrentLoginMode(mode){
|
||||
this.currentLoginMode = this.toggleMode(mode)
|
||||
},
|
||||
async submitForm (){
|
||||
// const res = await phoneLogin({...this.ruleForm})
|
||||
this.$refs.ruleFormRef.validate(valid => {
|
||||
if (valid) {
|
||||
// this.loading = true;
|
||||
// if (this.loginForm.rememberMe) {
|
||||
// Cookies.set("username", this.loginForm.username, { expires: 30 });
|
||||
// Cookies.set("password", encrypt(this.loginForm.password), { expires: 30 });
|
||||
// Cookies.set('rememberMe', this.loginForm.rememberMe, { expires: 30 });
|
||||
// } else {
|
||||
// Cookies.remove("username");
|
||||
// Cookies.remove("password");
|
||||
// Cookies.remove('rememberMe');
|
||||
// }
|
||||
this.$store.dispatch("Login", this.ruleForm).then(() => {
|
||||
this.onCloseLogin()
|
||||
// this.$router.push({ path: this.redirect || "/" }).catch(()=>{});
|
||||
location.href = "/";
|
||||
}).catch(() => {
|
||||
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
async onGetCode () {
|
||||
if (!this.ruleForm.phone || !/^1[3-9]\d{9}$/.test(this.ruleForm.phone)) {
|
||||
// ElMessage.error('请输入有效的手机号')
|
||||
return
|
||||
}
|
||||
try{
|
||||
const res = await getCode({phone:this.ruleForm.phone})
|
||||
console.log(res);
|
||||
this.codeButtonDisabled = true
|
||||
let countdown = 60
|
||||
this.codeButtonText = `${countdown}秒后重试`
|
||||
this.timerCode = window.setInterval(() => {
|
||||
countdown--
|
||||
if (countdown <= 0) {
|
||||
clearInterval(this.timerCode)
|
||||
this.codeButtonDisabled = false
|
||||
this.codeButtonText = '获取验证码'
|
||||
} else {
|
||||
this.codeButtonText = `${countdown}秒后重试`
|
||||
}
|
||||
}, 1000)
|
||||
// ElMessage.success('验证码已发送')
|
||||
}catch(err){
|
||||
console.log(err);
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.el-input--medium .el-input__inner{
|
||||
height: 42px !important;
|
||||
line-height: 42px !important;
|
||||
}
|
||||
.login-container {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 9999;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background-color: rgba($color: #000000, $alpha: 0.7);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: calc(100vh - $titleBarHeight);
|
||||
|
||||
.login-box {
|
||||
position: relative;
|
||||
width: 360px;
|
||||
padding: 40px;
|
||||
background: #fff;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||
.close-login{
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
right: -30px;
|
||||
color: #fff;
|
||||
font-size: 24px;
|
||||
top: 0;
|
||||
&:hover{
|
||||
transform: scale(1.2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.wechat-qs {
|
||||
text-align: center;
|
||||
}
|
||||
.agreement-text {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
display: flex;
|
||||
.agreement-link {
|
||||
color: #409eff;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.login-button {
|
||||
background-color: rgb(45, 85, 255);
|
||||
text-align: center;
|
||||
border-radius: 10px;
|
||||
cursor: pointer;
|
||||
color: #fff;
|
||||
font-size: 20px;
|
||||
width: 100%;
|
||||
line-height: 50px;
|
||||
}
|
||||
.code-button {
|
||||
background-color: rgba($color: #fff, $alpha: 0);
|
||||
border: none;
|
||||
color: #409eff;
|
||||
}
|
||||
.title {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
margin-bottom: 10px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
text-align: center;
|
||||
color: #666;
|
||||
margin-bottom: 14px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
// 统一表单项高度
|
||||
.el-form-item {
|
||||
margin-bottom: 20px;
|
||||
|
||||
.el-input,
|
||||
.el-select {
|
||||
height: 40px; // 统一高度
|
||||
line-height: 40px;
|
||||
box-sizing: border-box; // 包括内外边距
|
||||
}
|
||||
|
||||
// 处理选择器的高度一致
|
||||
.region-select {
|
||||
.el-input {
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
.el-button {
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
padding: 0 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.el-checkbox {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
|
||||
a {
|
||||
color: #409eff;
|
||||
text-decoration: none;
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.other-login-methods {
|
||||
margin-top: 20px;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
.icons-container {
|
||||
margin-top: 20px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.icon-item {
|
||||
height: 48px;
|
||||
padding: 0px 20px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,301 @@
|
|||
<template>
|
||||
<div class="container">
|
||||
<div class="mcwl-siderbar" v-for="(item,index) in sideBarList">
|
||||
<div class="mcwl-siderbar-title">
|
||||
探索
|
||||
</div>
|
||||
<!-- <div class="siderbar-item" :style="{border:item.dashed ? '1px dashed rgb(208 208 208)' : ''}" v-for="(subItem,subIndex) in item.list" :key="subIndex" @click="handleRoute(subItem)">
|
||||
<div class="siderbar-icon">
|
||||
<svg-icon icon-class="pdf"></svg-icon>
|
||||
</div>
|
||||
<div class="siderbar-menu">
|
||||
<div class="siderbar-menu-text">
|
||||
{{ subItem.text }}
|
||||
</div>
|
||||
<div class="siderbar-menu-des">
|
||||
{{ subItem.desc }}
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<div class="siderbar-item" @click="handleRoute()">
|
||||
<div class="siderbar-icon">
|
||||
<svg-icon icon-class="userCenter"></svg-icon>
|
||||
</div>
|
||||
<div class="siderbar-menu">
|
||||
<div class="siderbar-menu-text">
|
||||
模型广场
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mcwl-siderbar" v-for="(item,index) in sideBarList" :key="index">
|
||||
<div class="mcwl-siderbar-title">
|
||||
{{ item.title }}
|
||||
</div>
|
||||
<!-- <div class="siderbar-item" :style="{border:item.dashed ? '1px dashed rgb(208 208 208)' : ''}" v-for="(subItem,subIndex) in item.list" :key="subIndex" @click="handleRoute(subItem)">
|
||||
<div class="siderbar-icon">
|
||||
<svg-icon icon-class="pdf"></svg-icon>
|
||||
</div>
|
||||
<div class="siderbar-menu">
|
||||
<div class="siderbar-menu-text">
|
||||
{{ subItem.text }}
|
||||
</div>
|
||||
<div class="siderbar-menu-des">
|
||||
{{ subItem.desc }}
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<div class="siderbar-item" @click="handleRoute()">
|
||||
<div class="siderbar-icon">
|
||||
<svg-icon icon-class="userCenter"></svg-icon>
|
||||
</div>
|
||||
<div class="siderbar-menu">
|
||||
<div class="siderbar-menu-text">
|
||||
个人中心
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="siderbar-item" @click="handleRoute()">
|
||||
<div class="siderbar-icon">
|
||||
<svg-icon icon-class="vipCenter"></svg-icon>
|
||||
</div>
|
||||
<div class="siderbar-menu">
|
||||
<div class="siderbar-menu-text">
|
||||
会员中心
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="footer-content">
|
||||
<div class="join-us">
|
||||
<svg-icon icon-class="pdf"></svg-icon>
|
||||
加入我们
|
||||
</div>
|
||||
<div class="platform-content">
|
||||
<div class="platform-item">
|
||||
微信公众号
|
||||
</div>
|
||||
<div class="platform-item">
|
||||
小红书
|
||||
</div>
|
||||
<div class="platform-item">
|
||||
抖音
|
||||
</div>
|
||||
<div class="platform-item">
|
||||
B站
|
||||
</div>
|
||||
</div>
|
||||
<div class="platform-content">
|
||||
<div>
|
||||
用户协议
|
||||
</div>
|
||||
<div>
|
||||
隐私政策
|
||||
</div>
|
||||
<div>
|
||||
关于我们
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer-text">
|
||||
<div>
|
||||
上海辰风互娱网络科技有限公司
|
||||
</div>
|
||||
<div>
|
||||
京IPC备234324324号
|
||||
</div>
|
||||
<div>
|
||||
网信算备
|
||||
</div>
|
||||
<div>
|
||||
23423432432432423号
|
||||
</div>
|
||||
<div>
|
||||
生成式人工智能服务管理暂行办法
|
||||
</div>
|
||||
<div>
|
||||
备案号shanghai-sefef-23434
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "McSideBar",
|
||||
data(){
|
||||
return{
|
||||
sideBarList:[
|
||||
// {
|
||||
// id:1,
|
||||
// title:'探索',
|
||||
// dashed:false,
|
||||
// list:[
|
||||
// {
|
||||
// id:11,
|
||||
// icon:'',
|
||||
// text:'模型广场',
|
||||
// desc:''
|
||||
// },
|
||||
// {
|
||||
// id:12,
|
||||
// icon:'',
|
||||
// text:'作品灵感',
|
||||
// desc:''
|
||||
// },
|
||||
// {
|
||||
// id:13,
|
||||
// icon:'',
|
||||
// text:'工作流',
|
||||
// desc:''
|
||||
// },
|
||||
// ]
|
||||
// },
|
||||
// {
|
||||
// id:2,
|
||||
// title:'创作',
|
||||
// dashed:true,
|
||||
// list:[
|
||||
// {
|
||||
// id:21,
|
||||
// icon:'',
|
||||
// text:'在线生图',
|
||||
// desc:'Web UI'
|
||||
// },
|
||||
// {
|
||||
// id:22,
|
||||
// icon:'',
|
||||
// text:'在线工作流',
|
||||
// desc:'Comfy UI'
|
||||
// },
|
||||
// {
|
||||
// id:23,
|
||||
// icon:'',
|
||||
// text:'训练LoRA'
|
||||
// },
|
||||
// {
|
||||
// id:24,
|
||||
// icon:'',
|
||||
// text:'高级版生图'
|
||||
// },
|
||||
// ]
|
||||
// },
|
||||
{
|
||||
id:3,
|
||||
title:'其他',
|
||||
dashed:false,
|
||||
list:[
|
||||
// {
|
||||
// id:31,
|
||||
// icon:'',
|
||||
// text:'API开放平台',
|
||||
// },
|
||||
// {
|
||||
// id:32,
|
||||
// icon:'',
|
||||
// text:'创作中心',
|
||||
// },
|
||||
{
|
||||
path: 'personalCenter',
|
||||
id:33,
|
||||
icon:'',
|
||||
text:'个人中心',
|
||||
|
||||
},
|
||||
{
|
||||
id:34,
|
||||
icon:'',
|
||||
text:'会员中心',
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleRoute(){
|
||||
this.$emit('handleRoute','/publishModel')
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.container{
|
||||
overflow: auto; /* 内容可滚动 */
|
||||
scrollbar-width: none; /* 仅适用于 Firefox,隐藏滚动条 */
|
||||
-ms-overflow-style: none; /* 仅适用于 IE 和 Edge */
|
||||
color: #4e4e4e;
|
||||
width: 220px;
|
||||
height: calc(100vh - 61px);
|
||||
border-right:1px solid #e7e7e7;
|
||||
.mcwl-siderbar{
|
||||
font-size: 14px;
|
||||
padding:10px 20px;
|
||||
.mcwl-siderbar-title{
|
||||
color: rgb(156, 163, 175);
|
||||
font-size: 12px;
|
||||
}
|
||||
.siderbar-item-dashed{
|
||||
border: 1px dashed #818080;
|
||||
}
|
||||
.siderbar-item{
|
||||
border-radius: 10px;
|
||||
padding: 10px 8px;
|
||||
margin-top: 8px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
.siderbar-icon{
|
||||
line-height: 20px;
|
||||
margin-right: 4px;
|
||||
> svg{
|
||||
font-size: 14px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
.siderbar-menu{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
|
||||
.siderbar-menu-des{
|
||||
margin-top: 4px;
|
||||
color: #8e8e8e;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.footer-content{
|
||||
padding: 20px;
|
||||
.join-us{
|
||||
width: auto;
|
||||
line-height: 30px;
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
border: 1px dashed #818080;
|
||||
border-radius: 6px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.platform-content{
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
font-size: 12px;
|
||||
.platform-item{
|
||||
padding: 4px 6px;
|
||||
}
|
||||
}
|
||||
.footer-text{
|
||||
font-size:12px;
|
||||
color:#8e8e8e;
|
||||
>div{
|
||||
margin-top: 6px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,130 @@
|
|||
<template>
|
||||
<div class="container">
|
||||
<div class="wechat-login-container">
|
||||
<div v-if="bindTimeout" class="tipTimeout" @click="onGetUUid">
|
||||
刷新二维码
|
||||
<el-icon :size="30"><Refresh /></el-icon>
|
||||
<!-- <i class="el-icon-refresh" @click="onGetUUid"></i> 刷新 -->
|
||||
</div>
|
||||
<div class="qrcode-wrapper" v-if="qrUrl">
|
||||
<!-- <canvas ref="qrcodeCanvas"></canvas> -->
|
||||
<VueQr id="vueQr" :text="qrUrl" :size="200" style="margin: 0 auto;display: block;"></VueQr>
|
||||
<!-- <qrcode-vue :value="qrUrl" :size="200" level="M" /> -->
|
||||
|
||||
<!-- <qrcode-vue :value="qrUrl" :size="200" level="M" /> -->
|
||||
<!-- <div class="refresh-tip" v-if="needRefresh">
|
||||
二维码已过期,点击刷新
|
||||
<button @click="generateQrCode">刷新二维码</button>
|
||||
</div> -->
|
||||
</div>
|
||||
<div v-else class="loading">
|
||||
加载中...
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import VueQr from 'vue-qr'
|
||||
import { getUUid, uuidLogin } from "@/api/mcwl/login";
|
||||
export default {
|
||||
name: "McWechatLoginQr",
|
||||
data(){
|
||||
return{
|
||||
qrUrl:'',
|
||||
bindTimeout:null,
|
||||
pollingTimer:null,
|
||||
}
|
||||
},
|
||||
components: {
|
||||
VueQr
|
||||
},
|
||||
methods: {
|
||||
async onGetUUid(){
|
||||
try {
|
||||
const res = await getUUid({})
|
||||
if (res.code === 200) {
|
||||
const localIP = 'http://p7sjuc.natappfree.cc'
|
||||
const appid = 'wx82d4c3c96f0ffa5b'
|
||||
if (localIP) {
|
||||
const { uuid } = res
|
||||
const redirect_uri = `http://p7sjuc.natappfree.cc/wx/uuid/bind/openid?uuid=${uuid}`
|
||||
const codeUrl = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri=${encodeURIComponent(redirect_uri)}&response_type=code&scope=snsapi_userinfo&state=123456#wechat_redirect`
|
||||
this.qrUrl = codeUrl
|
||||
let counter = 1
|
||||
this.pollingTimer && clearTimeout(this.pollingTimer)
|
||||
this.pollingTimer = setInterval(function () {
|
||||
uuidLogin({
|
||||
uuid: uuid
|
||||
})
|
||||
.then((res) => {
|
||||
counter++
|
||||
if (counter === 59) {
|
||||
clearTimeout(this.pollingTimer)
|
||||
this.bindTimeout = true
|
||||
}
|
||||
if (res.status === 1) {
|
||||
clearTimeout(this.pollingTimer)
|
||||
// store.userInfo = res.data
|
||||
// router.push('./home')
|
||||
|
||||
// store.dispatch("uuidLogin", res)
|
||||
// that.$store.dispatch("uuidLogin", res)
|
||||
// setTimeout(() => {
|
||||
// that.$router.push({
|
||||
// path: that.redirect || "/"
|
||||
// }).catch(() => {});
|
||||
// }, 1500)
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
clearTimeout(this.pollingTimer)
|
||||
})
|
||||
}, 1000)
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.onGetUUid()
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
|
||||
.wechat-login-container {
|
||||
width: 280px;
|
||||
padding:0 20px;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
.tipTimeout{
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 9999;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
height: 100%;
|
||||
color: #fff;
|
||||
background-color: rgba($color: #000000, $alpha: 0.5);
|
||||
.qrcode-wrapper {
|
||||
position: relative;
|
||||
}
|
||||
.loading {
|
||||
padding: 20px;
|
||||
color: #999;
|
||||
}
|
||||
// opacity:0.3
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
|
@ -0,0 +1,212 @@
|
|||
<template>
|
||||
<div class="container ">
|
||||
<div class="profile-container">
|
||||
<div class="tip">一天只能认证三次</div>
|
||||
<div class="profile-form">
|
||||
<el-form label-width="84px" :model="ruleForm" :rules="rules" ref="formRef" class="demo-ruleForm">
|
||||
<el-form-item label="姓名" prop="name">
|
||||
<el-input v-model="ruleForm.name"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="身份证号" prop="idCard">
|
||||
<el-input v-model="ruleForm.idCard"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div class="form-buttons">
|
||||
<button type="button" class="cancel-button" @click="closeEditInfo">取消</button>
|
||||
<button type="submit" class="submit-button" @click="onUpdate">确认实名</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
|
||||
import {updateIdCard} from '@/api/mcwl/utils'
|
||||
export default {
|
||||
name: "McNameAuth",
|
||||
computed: {
|
||||
...mapGetters(['userId']),
|
||||
},
|
||||
data() {
|
||||
const idCardPattern = /^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[1-2]\d|3[0-1])\d{3}(\d|X|x)$/
|
||||
const zhNamePattern = /^(?:[\u4e00-\u9fa5·]{2,16})$/
|
||||
return {
|
||||
zhName:'/^(?:[\u4e00-\u9fa5·]{2,16})$/',
|
||||
pattern:'/(^\d{8}(0\d|10|11|12)([0-2]\d|30|31)\d{3}$)|(^\d{6}(18|19|20)\d{2}(0\d|10|11|12)([0-2]\d|30|31)\d{3}(\d|X|x)$)/',
|
||||
ruleForm:{
|
||||
idCard: '',
|
||||
name: '',
|
||||
userId: ''
|
||||
},
|
||||
rules: {
|
||||
name: [
|
||||
{ pattern: zhNamePattern,trigger: 'blur', required: true, message: '请输入正确的姓名' },
|
||||
],
|
||||
idCard: [
|
||||
{pattern: idCardPattern, message: '请输入正确的身份证号', required: true, trigger: 'blur' },
|
||||
],
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods:{
|
||||
onUpdate(){
|
||||
this.$refs.formRef.validate((valid) => {
|
||||
if (valid) {
|
||||
updateIdCard(this.ruleForm).then(res=>{
|
||||
if(res.code==200){
|
||||
this.$message.success('认证成功')
|
||||
this.closeEditInfo()
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
},
|
||||
closeEditInfo(){
|
||||
this.$emit('closeNameAuth',false)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.ruleForm.userId = this.userId
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
background-color: #f7f9fc;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
}
|
||||
.container{
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background-color: rgba($color: #000000, $alpha: 0.7);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: calc(100vh - $titleBarHeight);
|
||||
}
|
||||
|
||||
.profile-container {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
width: 400px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||
padding: 20px;
|
||||
position: relative;
|
||||
.tip{
|
||||
margin-bottom: 20px;
|
||||
font-size: 12px;
|
||||
color: #ff0000;
|
||||
}
|
||||
// width: 360px;
|
||||
// padding: 40px;
|
||||
// background: #fff;
|
||||
// border-radius: 10px;
|
||||
// box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.profile-form .form-group {
|
||||
margin-bottom: 15px;
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
.profile-form label {
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.input-wrapper {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.input-wrapper input {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
border: 1px solid #d8d8d8;
|
||||
border-radius: 5px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.input-wrapper .char-count {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
font-size: 12px;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
textarea {
|
||||
width: 100%;
|
||||
height: 80px;
|
||||
padding: 10px;
|
||||
border: 1px solid #d8d8d8;
|
||||
border-radius: 5px;
|
||||
font-size: 14px;
|
||||
resize: none;
|
||||
}
|
||||
|
||||
.social-links {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.social-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.social-link span {
|
||||
white-space: nowrap;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.social-link input {
|
||||
flex: 1;
|
||||
padding: 10px;
|
||||
border: 1px solid #d8d8d8;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.form-buttons {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.cancel-button,
|
||||
.submit-button {
|
||||
flex: 1;
|
||||
padding: 10px;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
margin: 0 5px;
|
||||
}
|
||||
|
||||
.cancel-button {
|
||||
background-color: #e0e0e0;
|
||||
}
|
||||
|
||||
.submit-button {
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
@ -0,0 +1,288 @@
|
|||
<template>
|
||||
<div class="container">
|
||||
<i class="el-icon-close close-btn" @click="onCloseLogin(false)"></i>
|
||||
<div class="upload-container">
|
||||
<h2>上传我的作品</h2>
|
||||
<!-- 上传按钮 -->
|
||||
<div>
|
||||
<!-- <p class="upload-tip">
|
||||
建议用图库上传的图片作为封面图,获得更多推荐流量和试用用户~<br />
|
||||
最多支持添加8张图片
|
||||
</p> -->
|
||||
<div class="upload-buttons">
|
||||
<button class="upload-btn" @click="selectPictureFromGallery">
|
||||
本地上传
|
||||
<input
|
||||
type="file"
|
||||
@change="handlePictureChange"
|
||||
accept="image/*"
|
||||
ref="pictureInput"
|
||||
multiple
|
||||
style="display: none"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<!-- <img v-for="(item) in params.pictureResultList" :src="item" alt=""> -->
|
||||
</div>
|
||||
<div class="publish-img-content">
|
||||
<img
|
||||
class="publish-img"
|
||||
v-for="item in imageFiles"
|
||||
:src="item"
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
|
||||
<el-form
|
||||
:model="ruleForm"
|
||||
ref="ruleForm"
|
||||
label-width="100px"
|
||||
class="demo-ruleForm"
|
||||
>
|
||||
<el-form-item label="图片标题" prop="name">
|
||||
<el-input v-model="ruleForm.title"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="图片标签" prop="name">
|
||||
<el-select
|
||||
v-model="ruleForm.tags"
|
||||
multiple
|
||||
filterable
|
||||
style="width: 100%;"
|
||||
allow-create
|
||||
default-first-option
|
||||
placeholder="请选择文章标签"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in options"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="描述信息" prop="desc">
|
||||
<el-input :row="8" type="textarea" v-model="ruleForm.desc"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<!-- 发布按钮 -->
|
||||
<button class="submit-button" @click="submitForm">发布</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { uploadImagesInBatches } from "@/utils/uploadImages.js";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
imageFiles:[],
|
||||
options:[],
|
||||
ruleForm: {
|
||||
imagePaths: [],
|
||||
title: "",
|
||||
tags: "",
|
||||
description: "",
|
||||
},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
async handlePictureChange(event) {
|
||||
const files = event.target.files;
|
||||
if (files.length > 3) {
|
||||
alert("最多只能选择 3 张图片");
|
||||
return;
|
||||
}
|
||||
|
||||
this.imageFiles = [];
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
const file = files[i];
|
||||
if (file.type.startsWith("image/")) {
|
||||
this.imageFiles.push(file);
|
||||
} else {
|
||||
alert("请选择有效的图片文件");
|
||||
}
|
||||
}
|
||||
|
||||
const pictureResultList = await uploadImagesInBatches(this.imageFiles);
|
||||
this.ruleForm.imagePaths = pictureResultList;
|
||||
},
|
||||
onCloseLogin() {
|
||||
this.$emit("closePublishWorks", false);
|
||||
},
|
||||
selectPictureFromGallery() {
|
||||
this.$refs.pictureInput.click();
|
||||
},
|
||||
|
||||
submitForm() {
|
||||
if (!this.imagePaths) {
|
||||
this.$message({
|
||||
message: '必须上传一张图片!',
|
||||
type: 'warning'
|
||||
});
|
||||
} else {
|
||||
alert("发布成功!");
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$primary-color: #007bff;
|
||||
$text-color: #333;
|
||||
$border-color: #e6e6e6;
|
||||
$placeholder-color: #999;
|
||||
.container {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 999;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background-color: rgba($color: #000000, $alpha: 0.7);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.publish-img-content {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 10px;
|
||||
.publish-img {
|
||||
padding: 4px;
|
||||
width: 33.33%;
|
||||
height: 160px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
}
|
||||
.close-btn {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
right: 10px;
|
||||
top: 10px;
|
||||
color: #fff;
|
||||
font-size: 30px;
|
||||
z-index: 999;
|
||||
}
|
||||
::-webkit-scrollbar {
|
||||
display: none; /* 对于 WebKit 浏览器(Chrome, Safari) */
|
||||
}
|
||||
.upload-container {
|
||||
width: 600px;
|
||||
padding: 20px;
|
||||
background: #fff;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||
max-height: 90%;
|
||||
overflow: auto;
|
||||
|
||||
h2 {
|
||||
font-size: 20px;
|
||||
color: $text-color;
|
||||
margin-bottom: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.upload-buttons {
|
||||
border: 1px solid $border-color;
|
||||
height: 120px;
|
||||
background-color: #f3f5f9;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-bottom: 15px;
|
||||
align-items: center;
|
||||
border-radius: 10px;
|
||||
.upload-btn {
|
||||
background: $primary-color;
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
padding: 10px 15px;
|
||||
font-size: 16px;
|
||||
margin: 0 5px;
|
||||
height: 40px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s;
|
||||
|
||||
&:hover {
|
||||
background-color: darken($primary-color, 10%);
|
||||
}
|
||||
|
||||
i {
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.upload-tip {
|
||||
font-size: 12px;
|
||||
color: $placeholder-color;
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 20px;
|
||||
|
||||
label {
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
color: $text-color;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
input,
|
||||
select,
|
||||
textarea {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
border: 1px solid $border-color;
|
||||
border-radius: 5px;
|
||||
font-size: 14px;
|
||||
color: $text-color;
|
||||
outline: none;
|
||||
|
||||
&:focus {
|
||||
border-color: $primary-color;
|
||||
box-shadow: 0 0 5px rgba(0, 123, 255, 0.3);
|
||||
}
|
||||
|
||||
&::placeholder {
|
||||
color: $placeholder-color;
|
||||
}
|
||||
}
|
||||
|
||||
textarea {
|
||||
height: 80px;
|
||||
resize: none;
|
||||
}
|
||||
|
||||
.char-counter {
|
||||
font-size: 12px;
|
||||
color: $placeholder-color;
|
||||
text-align: right;
|
||||
margin-top: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.submit-button {
|
||||
width: 100%;
|
||||
background: $primary-color;
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
padding: 10px 15px;
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s;
|
||||
|
||||
&:hover {
|
||||
background-color: darken($primary-color, 10%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,330 @@
|
|||
<template>
|
||||
<div class="product-list" ref="listContainer" @scroll="handleScroll">
|
||||
<div class="image-grid-container">
|
||||
<!-- 商品卡片网格 -->
|
||||
<div class="image-grid">
|
||||
<div class="image-card" v-for="item in products1" :key="item.id">
|
||||
<div class="image-wrapper">
|
||||
<img
|
||||
src="http://img2.baidu.com/it/u=705459853,1015457524&fm=253&app=138&f=JPEG?w=800&h=1422"
|
||||
:alt="item.title"
|
||||
/>
|
||||
</div>
|
||||
<div class="drop-down">
|
||||
<i class="el-icon-more">
|
||||
<div class="drop-down-group">
|
||||
<div class="drop-down-item" @click="handleEdit(item)">编辑</div>
|
||||
<div class="drop-down-item delete" @click="handleDelete(item)">删除</div>
|
||||
<div class="drop-down-item" @click="handleTop(item)">置顶</div>
|
||||
</div>
|
||||
</i>
|
||||
</div>
|
||||
<!-- <div class="image-info">
|
||||
<h3 class="title">{{ item.title }}</h3>
|
||||
<p class="details">{{ item.details }}</p>
|
||||
<div class="stats">
|
||||
<span><i class="icon icon-view"></i>{{ item.views }}</span>
|
||||
<span><i class="icon icon-like"></i>{{ item.likes }}</span>
|
||||
<span><i class="icon icon-comment"></i>{{ item.comments }}</span>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="loading" class="loading">加载中...</div>
|
||||
<div v-if="noMore" class="no-more">没有更多商品了</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mallProduct } from "@/api/mcwl/personalCenter";
|
||||
import _ from "lodash";
|
||||
export default {
|
||||
props: {
|
||||
order: {
|
||||
type: String,
|
||||
default: 0, // 默认值为 0
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
default: 0, // 默认值为 0
|
||||
},
|
||||
date: {
|
||||
type: Array | null,
|
||||
default: [], // 默认值为 []
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
// 监听 status 变化,当其更新时重新加载商品
|
||||
status: {
|
||||
// immediate: true,
|
||||
handler() {
|
||||
this.resetAndFetchProducts();
|
||||
},
|
||||
},
|
||||
date: {
|
||||
// immediate: true,
|
||||
handler() {
|
||||
this.resetAndFetchProducts();
|
||||
},
|
||||
},
|
||||
order: {
|
||||
// immediate: true,
|
||||
handler() {
|
||||
this.resetAndFetchProducts();
|
||||
},
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.fetchProducts();
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
products1: [{ title: "wewre" }, {}, {},{},{}], // 商品列表数据,
|
||||
|
||||
products: [], // 商品列表数据
|
||||
pageNumber: 1, // 当前页码
|
||||
pageSize: 12, // 每页商品数量
|
||||
loading: false, // 是否正在加载
|
||||
noMore: false, // 是否没有更多数据
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
// 节流函数
|
||||
throttle(func, delay) {
|
||||
let lastTime = 0;
|
||||
return function (...args) {
|
||||
const now = new Date().getTime();
|
||||
if (now - lastTime >= delay) {
|
||||
lastTime = now;
|
||||
func.apply(this, args);
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
// 重置数据并重新获取商品
|
||||
resetAndFetchProducts() {
|
||||
this.products = [];
|
||||
this.pageNumber = 1;
|
||||
this.noMore = false;
|
||||
this.fetchProducts();
|
||||
},
|
||||
// 获取商品数据
|
||||
async fetchProducts() {
|
||||
if (this.loading || this.noMore) return;
|
||||
this.loading = true;
|
||||
try {
|
||||
let params = {
|
||||
pageNumber: this.pageNumber,
|
||||
pageSize: this.pageSize,
|
||||
status: this.status, // 将 status 参数传递给商品接口
|
||||
order: this.order, // 将 status 参数传递给商品接口
|
||||
// startTime: this.date[0], // 将 status 参数传递给商品接口
|
||||
// endTime: this.date[1], // 将 status 参数传递给商品接口
|
||||
};
|
||||
if (this.date && this.date.length > 0) {
|
||||
params.startTime = `${this.date[0]} 00:00:00`;
|
||||
params.endTime = `${this.date[1]} 23:59:59`;
|
||||
}
|
||||
mallProduct(params).then((res) => {
|
||||
if (res.data.records && res.data.records.length > 0) {
|
||||
const newProducts = res.data.records;
|
||||
if (newProducts.length < this.pageSize) {
|
||||
this.noMore = true; // 数据不足一页,标记为无更多数据
|
||||
}
|
||||
this.products = [...this.products, ...newProducts];
|
||||
this.pageNumber += 1; // 下一页
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("加载商品数据失败:", error);
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
|
||||
// fetchProducts:throttle(()=>{
|
||||
// if (this.loading || this.noMore) return;
|
||||
// this.loading = true;
|
||||
// try {
|
||||
// let params = {
|
||||
// pageNumber: this.pageNumber,
|
||||
// pageSize: this.pageSize,
|
||||
// status: this.status, // 将 status 参数传递给商品接口
|
||||
// order: this.order, // 将 status 参数传递给商品接口
|
||||
// }
|
||||
// mallProduct(params).then((res)=>{
|
||||
// const newProducts = res.data.records;
|
||||
// if (newProducts.length < this.pageSize) {
|
||||
// this.noMore = true; // 数据不足一页,标记为无更多数据
|
||||
// }
|
||||
// this.products = [...this.products, ...newProducts];
|
||||
// this.pageNumber += 1; // 下一页
|
||||
// })
|
||||
// } catch (error) {
|
||||
// console.error("加载商品数据失败:", error);
|
||||
// } finally {
|
||||
// this.loading = false;
|
||||
// }
|
||||
// },1000),
|
||||
// 处理滚动事件
|
||||
// handleScroll:throttle(()=>{
|
||||
// const container = this.$refs.listContainer;
|
||||
// if (!container) return;
|
||||
|
||||
// const scrollTop = container.scrollTop; // 滚动条距离顶部的高度
|
||||
// const scrollHeight = container.scrollHeight; // 滚动内容的总高度
|
||||
// const clientHeight = container.clientHeight; // 容器的可见高度
|
||||
|
||||
// // 如果滚动到底部,触发加载更多
|
||||
// if (scrollTop + clientHeight >= scrollHeight - 10) {
|
||||
// this.fetchProducts();
|
||||
// }
|
||||
// }, 1000),
|
||||
handleScroll() {
|
||||
const container = this.$refs.listContainer;
|
||||
if (!container) return;
|
||||
|
||||
const scrollTop = container.scrollTop; // 滚动条距离顶部的高度
|
||||
const scrollHeight = container.scrollHeight; // 滚动内容的总高度
|
||||
const clientHeight = container.clientHeight; // 容器的可见高度
|
||||
|
||||
// 如果滚动到底部,触发加载更多
|
||||
if (scrollTop + clientHeight >= scrollHeight - 10) {
|
||||
this.fetchProducts();
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.product-list {
|
||||
height: 400px;
|
||||
overflow-y: auto;
|
||||
// border: 1px solid #ccc;
|
||||
padding: 10px;
|
||||
/* SCSS 样式 */
|
||||
|
||||
/* 变量定义 */
|
||||
$background-color: #f5f5f5;
|
||||
$card-bg-color: #fff;
|
||||
$text-color: #333;
|
||||
$sub-text-color: #555;
|
||||
$icon-color: #999;
|
||||
$box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
|
||||
/* 容器样式 */
|
||||
.image-grid-container {
|
||||
// height: 100px;
|
||||
padding: 20px;
|
||||
.image-grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 16px;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.image-card {
|
||||
border-radius: 10px;
|
||||
position: relative;
|
||||
height: 300px;
|
||||
background: $card-bg-color;
|
||||
// box-shadow: $box-shadow;
|
||||
overflow: hidden;
|
||||
width: calc(25% - 16px); // 每行显示 4 个卡片
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.drop-down {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
.el-icon-more {
|
||||
&:hover {
|
||||
.drop-down-group{
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
.drop-down-group {
|
||||
position: absolute;
|
||||
top: 14px;
|
||||
right: -10px;
|
||||
background-color: #fff;
|
||||
border-radius: 10px;
|
||||
display: none;
|
||||
.drop-down-item {
|
||||
width: 100px;
|
||||
text-align: center;
|
||||
line-height: 40px;
|
||||
color: #2f2f2f;
|
||||
}
|
||||
.delete{
|
||||
color: #ff0000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.image-wrapper {
|
||||
img {
|
||||
width: 100%;
|
||||
height: 300px;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.image-info {
|
||||
padding: 10px;
|
||||
font-size: 14px;
|
||||
color: $text-color;
|
||||
|
||||
.title {
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
margin-bottom: 8px;
|
||||
color: darken($text-color, 10%);
|
||||
}
|
||||
|
||||
.details {
|
||||
margin-bottom: 8px;
|
||||
color: $sub-text-color;
|
||||
}
|
||||
|
||||
.stats {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 12px;
|
||||
color: $icon-color;
|
||||
|
||||
span {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
|
||||
.icon {
|
||||
font-size: 14px;
|
||||
color: $icon-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.product-item {
|
||||
margin-bottom: 15px;
|
||||
padding: 10px;
|
||||
// border: 1px solid #481212;
|
||||
border-radius: 5px;
|
||||
color: #481212;
|
||||
}
|
||||
|
||||
.loading,
|
||||
.no-more {
|
||||
text-align: center;
|
||||
padding: 10px;
|
||||
color: #999;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,125 @@
|
|||
<template>
|
||||
<div class="container">
|
||||
<!-- Quill 富文本编辑器 -->
|
||||
<quill-editor
|
||||
v-model="content"
|
||||
ref="myQuillEditor"
|
||||
style="height: 100px"
|
||||
@input="onInput"
|
||||
:options="editorOption"
|
||||
@change="onEditorChange"
|
||||
/>
|
||||
<!-- 隐藏的文件上传输入框 -->
|
||||
<input
|
||||
type="file"
|
||||
ref="imageInput"
|
||||
multiple
|
||||
style="display: none"
|
||||
@change="handleImageUpload"
|
||||
accept="image/*"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { quillEditor } from "vue-quill-editor";
|
||||
import "quill/dist/quill.core.css";
|
||||
import "quill/dist/quill.snow.css";
|
||||
import "quill/dist/quill.bubble.css";
|
||||
import { uploadImagesInBatches } from "@/utils/uploadImages.js";
|
||||
export default {
|
||||
components: {
|
||||
quillEditor,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
content: "", // 编辑器内容
|
||||
editorOption: {
|
||||
modules: {
|
||||
toolbar: {
|
||||
container: [
|
||||
["bold", "italic", "underline", "strike"], // 加粗、斜体、下划线、删除线
|
||||
["blockquote", "code-block"], // 引用、代码块
|
||||
[{ header: 1 }, { header: 2 }], // 标题
|
||||
[{ list: "ordered" }, { list: "bullet" }], // 有序列表、无序列表
|
||||
[{ script: "sub" }, { script: "super" }], // 上标、下标
|
||||
[{ indent: "-1" }, { indent: "+1" }], // 缩进
|
||||
[{ direction: "rtl" }], // 文字方向
|
||||
[{ size: ["small", false, "large", "huge"] }], // 字体大小
|
||||
[{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题级别
|
||||
[{ color: [] }, { background: [] }], // 字体颜色、背景颜色
|
||||
[{ font: [] }], // 字体
|
||||
[{ align: [] }], // 对齐方式
|
||||
["clean"], // 清除格式
|
||||
["link", "image", "video"], // 链接、图片、视频
|
||||
],
|
||||
handlers: {
|
||||
image: this.handleImageClick, // 自定义图片上传处理
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onInput(value) {
|
||||
this.$emit("input", value);
|
||||
},
|
||||
// 编辑器内容变化时触发
|
||||
onEditorChange({ quill, html, text }) {
|
||||
this.$emit("input", html);
|
||||
console.log("编辑器内容:", html);
|
||||
},
|
||||
// 点击图片按钮时触发
|
||||
handleImageClick() {
|
||||
this.$refs.imageInput.click(); // 触发文件选择对话框
|
||||
},
|
||||
// 处理图片上传
|
||||
async handleImageUpload(event) {
|
||||
const files = event.target.files;
|
||||
let imageFiles = [];
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
const file = files[i];
|
||||
if (file.type.startsWith("image/")) {
|
||||
imageFiles.push(file);
|
||||
// this.imageUrls.push(URL.createObjectURL(file)); // 生成预览 URL
|
||||
} else {
|
||||
alert("请选择有效的图片文件");
|
||||
}
|
||||
}
|
||||
|
||||
const res = await uploadImagesInBatches(imageFiles);
|
||||
// const quill = this.$refs.myQuillEditor.quill;
|
||||
// const range = quill.getSelection();
|
||||
// quill.insertEmbed(range.index, "image", res[0]); // 插入图片
|
||||
// if (file) {
|
||||
// const formData = new FormData();
|
||||
// formData.append("image", file);
|
||||
|
||||
// // 替换为你的图片上传接口
|
||||
// fetch("https://your-image-upload-api.com/upload", {
|
||||
// method: "POST",
|
||||
// body: formData,
|
||||
// })
|
||||
// .then((response) => response.json())
|
||||
// .then((data) => {
|
||||
// const quill = this.$refs.myQuillEditor.quill;
|
||||
// const range = quill.getSelection();
|
||||
// quill.insertEmbed(range.index, "image", data.imageUrl); // 插入图片
|
||||
// })
|
||||
// .catch((error) => {
|
||||
// console.error("图片上传失败:", error);
|
||||
// });
|
||||
// }
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.container {
|
||||
background-color: #fff;
|
||||
height: 166px;
|
||||
}
|
||||
/* 自定义样式 */
|
||||
</style>
|
|
@ -0,0 +1,352 @@
|
|||
<template>
|
||||
<div class="container">
|
||||
<div class="content">
|
||||
<div class="left-content">
|
||||
<el-form
|
||||
class="form-content"
|
||||
:model="formData"
|
||||
:rules="rules"
|
||||
ref="formFef"
|
||||
label-width="120px"
|
||||
label-position="top"
|
||||
>
|
||||
<el-form-item prop="modelName">
|
||||
<div class="form-title">工作流名称<span class="form-required">*</span></div>
|
||||
<el-input v-model="formData.name1" placeholder="请输入工作流名称"></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 内容类别 -->
|
||||
<el-form-item prop="category">
|
||||
<div class="form-title">内容类别</div>
|
||||
<div class="form-desc">
|
||||
填写类别可让模型获得更精准的流量, 平台也有权基于标准修改你的类别标签
|
||||
</div>
|
||||
<el-cascader
|
||||
class="formWidth"
|
||||
placeholder="垂类"
|
||||
:props="{
|
||||
label: 'dictLabel', // 指定 label 对应的属性名
|
||||
value: 'dictValue', // 指定 value 对应的属性名
|
||||
children: 'children', // 如果有子选项,指定 children 对应的属性名
|
||||
}"
|
||||
v-model="formData.category"
|
||||
:options="options1"
|
||||
:show-all-levels="true"
|
||||
></el-cascader>
|
||||
|
||||
<el-select
|
||||
style="margin-top: 4px"
|
||||
class="formWidth"
|
||||
v-model="formData.work_flow_functions"
|
||||
placeholder="主体"
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in work_flow_functions"
|
||||
:key="item.dictValue"
|
||||
:label="item.dictLabel"
|
||||
:value="item.dictValue"
|
||||
></el-option>
|
||||
</el-select>
|
||||
|
||||
<el-select
|
||||
style="margin-top: 4px"
|
||||
class="formWidth"
|
||||
v-model="formData.work_flow_functions"
|
||||
placeholder="风格"
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in work_flow_functions"
|
||||
:key="item.dictValue"
|
||||
:label="item.dictLabel"
|
||||
:value="item.dictValue"
|
||||
></el-option>
|
||||
</el-select>
|
||||
|
||||
<el-select
|
||||
style="margin-top: 4px"
|
||||
class="formWidth"
|
||||
v-model="formData.work_flow_functions"
|
||||
placeholder="功能"
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in work_flow_functions"
|
||||
:key="item.dictValue"
|
||||
:label="item.dictLabel"
|
||||
:value="item.dictValue"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 参与活动 -->
|
||||
<el-form-item prop="activity">
|
||||
<div class="form-title">参与活动</div>
|
||||
<div class="form-desc">参加特定活动或比赛, 下拉选择</div>
|
||||
<el-select
|
||||
class="formWidth"
|
||||
v-model="formData.activity"
|
||||
placeholder="请选择参与活动"
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in activities"
|
||||
:key="item.dictValue"
|
||||
:label="item.dictLabel"
|
||||
:value="item.dictValue"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<div class="right-content">
|
||||
<div class="form-wrapper">
|
||||
<el-form
|
||||
:model="formData"
|
||||
:rules="rules"
|
||||
label-width="120px"
|
||||
label-position="top"
|
||||
>
|
||||
<div class="mcwl-stack-root stepOne">
|
||||
<div>
|
||||
<div class="form-desc">是否公开</div>
|
||||
<div class="FormField_content">
|
||||
<div class="ant-segmented-group">
|
||||
<div
|
||||
class="ant-segmented-group-item"
|
||||
v-for="(item, index) in originalBtnList"
|
||||
:key="index"
|
||||
@click="formData.content = item.value"
|
||||
:style="{
|
||||
backgroundColor:
|
||||
formData.content === item.value
|
||||
? 'rgba(49, 98, 255, 0.1)'
|
||||
: '#fff',
|
||||
color: formData.content === item.value ? '#3162ff' : '#000',
|
||||
}"
|
||||
>
|
||||
{{ item.label }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="form-title">是否原创</div>
|
||||
<div class="FormField_content">
|
||||
<div class="ant-segmented-group">
|
||||
<div
|
||||
class="ant-segmented-group-item"
|
||||
v-for="(item, index) in originalBtnList"
|
||||
:key="index"
|
||||
@click="formData.content = item.value"
|
||||
:style="{
|
||||
backgroundColor:
|
||||
formData.content === item.value
|
||||
? 'rgba(49, 98, 255, 0.1)'
|
||||
: '#fff',
|
||||
color: formData.content === item.value ? '#3162ff' : '#000',
|
||||
}"
|
||||
>
|
||||
{{ item.label }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mcwl-stack-root stepTwo">
|
||||
<div>
|
||||
<div style="color: #3162ff; margin-bottom: 10px">
|
||||
用户使用时, 我授予用户以下权限:
|
||||
</div>
|
||||
<el-checkbox-group v-model="formData.type">
|
||||
<el-checkbox label="允许在线使用" name="type"></el-checkbox>
|
||||
</el-checkbox-group>
|
||||
<div
|
||||
style="
|
||||
color: #999999;
|
||||
margin: 4px 0 10px 0;
|
||||
padding-left: 24px;
|
||||
font-size: 12px;
|
||||
"
|
||||
>
|
||||
您的工作流为公开状态时, 默认同意此条款, 他人不能随意转载
|
||||
</div>
|
||||
<el-checkbox-group v-model="formData.type">
|
||||
<el-checkbox label="允许下载工作流" name="type"></el-checkbox>
|
||||
</el-checkbox-group>
|
||||
<div
|
||||
style="
|
||||
color: #999999;
|
||||
margin: 4px 0 10px 0;
|
||||
padding-left: 24px;
|
||||
font-size: 12px;
|
||||
"
|
||||
>
|
||||
允许下载后, 您的工作流可能会被 他人转载, 我们无法控制该行为
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div style="color: #3162ff; margin-bottom: 10px">
|
||||
用户使用时, 我授予用户以下商业用途权限:
|
||||
</div>
|
||||
<el-checkbox-group v-model="formData.type">
|
||||
<el-checkbox label="" name="type">
|
||||
生成图片可出售或者用于商业目的
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</div>
|
||||
<div>
|
||||
<div style="margin: 20px 0 10px 0">声明</div>
|
||||
<div class="explain" style="font-size: 12px">
|
||||
<div>请勿转载境外模型</div>
|
||||
<div>请勿上传色情、暴力等违法内容</div>
|
||||
<div>不得侵害他人依法享有的知识产权</div>
|
||||
<div>您所上传的内容需要使用具有合法来源的数据</div>
|
||||
<div>魔创未来将会对上传的所有内容进行安全审查</div>
|
||||
<div>许可范围为创作者本人设置, 使用者需要按规范使用</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mcwl-stack-footer">
|
||||
<div class="next-step" @click="onNextStep">下一步</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
originalBtnList: [
|
||||
{
|
||||
label: "原创",
|
||||
value: "original",
|
||||
},
|
||||
{
|
||||
label: "非原创",
|
||||
value: "notOriginal",
|
||||
},
|
||||
],
|
||||
rules: {},
|
||||
activities: [],
|
||||
work_flow_functions: [],
|
||||
options1: [],
|
||||
formData: {
|
||||
name: "",
|
||||
content: "original",
|
||||
type: "",
|
||||
tags: "",
|
||||
name1: "",
|
||||
},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onNextStep(){
|
||||
this.$emit('changeWorkFlowInfo',this.formData)
|
||||
this.$emit('nextStep',2)
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.container {
|
||||
.content {
|
||||
display: flex;
|
||||
.left-content {
|
||||
.form-title {
|
||||
// font-weight: 600;
|
||||
color: #000;
|
||||
.form-required {
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
.form-desc {
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
line-height: 10px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.formWidth {
|
||||
width: 100%;
|
||||
}
|
||||
width: 66%;
|
||||
background: #f4f5f9;
|
||||
padding: 20px;
|
||||
border-radius: 10px;
|
||||
margin-right: 20px;
|
||||
}
|
||||
.right-content {
|
||||
width: 33%;
|
||||
.form-wrapper {
|
||||
.mcwl-stack-root {
|
||||
margin-bottom: 10px;
|
||||
background: #f4f5f9;
|
||||
padding: 20px;
|
||||
border-radius: 10px;
|
||||
.explain {
|
||||
> div {
|
||||
padding: 4px 0;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
.stepTwo {
|
||||
font-size: 14px;
|
||||
}
|
||||
.FormField_content {
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
margin: 10px 0;
|
||||
background-color: #fff;
|
||||
border-radius: 4px;
|
||||
.form-title {
|
||||
color: #000;
|
||||
}
|
||||
.ant-segmented-group {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.ant-segmented-group-item {
|
||||
width: 50%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
width: 34%;
|
||||
// background: #f4f5f9;
|
||||
// padding: 20px;
|
||||
// border-radius: 10px;
|
||||
}
|
||||
}
|
||||
.mcwl-stack-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
.next-step {
|
||||
width: 100px;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
text-align: center;
|
||||
background: #3162ff;
|
||||
color: #fff;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,243 @@
|
|||
<template>
|
||||
<div class="container">
|
||||
<input
|
||||
type="file"
|
||||
@change="handleFileChange"
|
||||
accept="image/*"
|
||||
ref="pictureInput"
|
||||
style="display: none"
|
||||
/>
|
||||
<div class="header">
|
||||
<div class="header-group">
|
||||
<div class="add-version" @click="addForm">添加版本</div>
|
||||
<!-- <div>收起版本信息</div> -->
|
||||
</div>
|
||||
<div class="header-tips">小提醒: 版本在当前页面展示顺序为线上用户实际看到顺序</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div v-for="(form, index) in forms" :key="index" class="form-wrapper">
|
||||
<div class="version-form-group">
|
||||
<div class="">
|
||||
<i @click="removeForm(index)" class="el-icon-delete" :size="28"></i>
|
||||
</div>
|
||||
</div>
|
||||
<el-form
|
||||
:model="form"
|
||||
:ref="`form${index}`"
|
||||
:rules="rules"
|
||||
label-width="120px"
|
||||
label-position="top"
|
||||
>
|
||||
<el-form-item prop="name">
|
||||
<div class="form-title">版本名称<span class="form-required">*</span></div>
|
||||
<el-input v-model="form.name" placeholder="请输入名称"></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item prop="type">
|
||||
<div class="form-upload-img">
|
||||
<div class="form-title">上传工作流文件<span class="form-required">*</span></div>
|
||||
<div v-if="form.file"><span>100%</span>这是一个文件名</div>
|
||||
<div v-else class="upload-img-container">
|
||||
<div class="upload-img-btn" @click="onUploadFile(index)">上传文件</div>
|
||||
<!-- <div>拖拽文件</div> -->
|
||||
<div class="upload-img-tips">支持格式:.json/.zip</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="step-group">
|
||||
<div class="step1-group">
|
||||
<div
|
||||
class="step-btn step1"
|
||||
style="background-color: #f1f2f7; color: #000; margin-right: 20px"
|
||||
@click="onStepNext(1)"
|
||||
>
|
||||
上一步
|
||||
</div>
|
||||
<div class="step-btn step1" @click="onStepNext(3)">下一步</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { uploadImagesInBatches } from "@/utils/uploadImages.js";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
currentUploadIndex:null,
|
||||
forms: [
|
||||
{
|
||||
name: "",
|
||||
type: "",
|
||||
file: "",
|
||||
editorContent: "",
|
||||
},
|
||||
],
|
||||
rules: {
|
||||
name: [{ required: true, message: "请输入名称", trigger: "blur" }],
|
||||
},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
addForm() {
|
||||
this.forms.push({
|
||||
name1: "",
|
||||
type: "",
|
||||
file: "",
|
||||
editorContent: "",
|
||||
});
|
||||
},
|
||||
removeForm(index) {
|
||||
if(this.forms.length === 1) return
|
||||
this.forms.splice(index, 1);
|
||||
},
|
||||
// 下一步
|
||||
onStepNext(index) {
|
||||
if (index == 3) {
|
||||
let allValid = true;
|
||||
this.forms.forEach((form, index) => {
|
||||
this.$refs[`form${index}`][0].validate((valid) => {
|
||||
if (!valid) {
|
||||
allValid = false;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (allValid) {
|
||||
this.$emit("stepNext", index);
|
||||
this.$emit("changeEditVersionWorkFlowInfo", this.forms);
|
||||
// 在这里处理提交逻辑
|
||||
} else {
|
||||
console.log("表单验证未通过");
|
||||
}
|
||||
} else if (index == 1) {
|
||||
this.$emit("stepNext", index);
|
||||
}
|
||||
},
|
||||
onUploadFile(index) {
|
||||
this.currentUploadIndex = index;
|
||||
this.$refs.pictureInput.click();
|
||||
},
|
||||
//上传图片
|
||||
async handleFileChange(event) {
|
||||
console.log("object", event);
|
||||
const files = event.target.files;
|
||||
if (files.length > 1) {
|
||||
alert("只能选择 1 张图片");
|
||||
return;
|
||||
}
|
||||
|
||||
let imageFiles = [];
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
const file = files[i];
|
||||
if (file.type.startsWith("image/")) {
|
||||
imageFiles.push(file);
|
||||
// this.imageUrls.push(URL.createObjectURL(file)); // 生成预览 URL
|
||||
} else {
|
||||
alert("请选择有效的图片文件");
|
||||
}
|
||||
}
|
||||
|
||||
const pictureResultList = await uploadImagesInBatches(imageFiles);
|
||||
let imgUrl = pictureResultList.join(',')
|
||||
this.forms[this.currentUploadIndex].file = imgUrl
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.container {
|
||||
font-size: 14px;
|
||||
.header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.header-tips {
|
||||
color: #b1b1b1;
|
||||
font-size: 12px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
.header-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
.add-version {
|
||||
cursor: pointer;
|
||||
width: 200px;
|
||||
line-height: 40px;
|
||||
font-weight: 600;
|
||||
border-radius: 30px;
|
||||
border: 1px solid #b1b1b1;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
.form-group {
|
||||
.form-wrapper {
|
||||
background-color: #f4f5f9;
|
||||
padding: 20px;
|
||||
border-radius: 10px;
|
||||
position: relative;
|
||||
margin-bottom: 20px;
|
||||
.version-form-group {
|
||||
position: absolute;
|
||||
right: -20px;
|
||||
cursor: pointer;
|
||||
top: 0px;
|
||||
}
|
||||
.form-title{
|
||||
.form-required{
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
.upload-img-container {
|
||||
width: 100%;
|
||||
height: 150px;
|
||||
border: 1px dashed #ccc;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
background-color: #fff;
|
||||
border-radius: 10px;
|
||||
.upload-img-btn {
|
||||
padding: 4px 20px;
|
||||
text-align: center;
|
||||
background-color: rgb(45, 40, 255);
|
||||
color: #fff;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.upload-img-tips {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.step-group {
|
||||
margin-top: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.step-btn {
|
||||
width: 200px;
|
||||
height: 40px;
|
||||
text-align: center;
|
||||
line-height: 40px;
|
||||
}
|
||||
.step1-group {
|
||||
display: flex;
|
||||
background-color: blue;
|
||||
border-radius: 4px;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,261 @@
|
|||
<template>
|
||||
<div class="container">
|
||||
<div class="pay-content">
|
||||
<div class="header-user-info">
|
||||
<div class="user-info">
|
||||
<div class="user-avatar">
|
||||
<img src="../../assets/images/wechat.png" alt="" />
|
||||
</div>
|
||||
<div class="user-group">
|
||||
<div class="user-name">微信用户a932432</div>
|
||||
<div class="user-level">
|
||||
<div class="user-level-icon">
|
||||
<svg-icon icon-class="userCenter"></svg-icon>
|
||||
</div>
|
||||
<div class="user-level-name">您还不是魔创未来的会员</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="close-icon" @click="closeVipPay">X</div>
|
||||
</div>
|
||||
<div class="vip-card">
|
||||
<div class="vip-card-item">
|
||||
<div class="vip-card-item-title">
|
||||
<svg-icon icon-class="userCenter"></svg-icon>
|
||||
基础版VIP连续包月
|
||||
</div>
|
||||
<div class="price">
|
||||
<div class="price-symbol">¥</div>
|
||||
<div class="price-number">9.9</div>
|
||||
<div class="original-price">¥19.9</div>
|
||||
</div>
|
||||
<div class="price-desc">次月续费¥39元</div>
|
||||
</div>
|
||||
<div class="vip-card-item">
|
||||
<div class="vip-card-item-title">
|
||||
<svg-icon icon-class="userCenter"></svg-icon>
|
||||
基础版VIP连续包月
|
||||
</div>
|
||||
<div class="price">
|
||||
<div class="price-symbol">¥</div>
|
||||
<div class="price-number">9.9</div>
|
||||
<div class="original-price">¥19.9</div>
|
||||
</div>
|
||||
<div class="price-desc">次月续费¥39元</div>
|
||||
</div>
|
||||
<div class="vip-card-item">
|
||||
<div class="vip-card-item-title">
|
||||
<svg-icon icon-class="userCenter"></svg-icon>
|
||||
基础版VIP连续包月
|
||||
</div>
|
||||
<div class="price">
|
||||
<div class="price-symbol">¥</div>
|
||||
<div class="price-number">9.9</div>
|
||||
<div class="original-price">¥19.9</div>
|
||||
</div>
|
||||
<div class="price-desc">次月续费¥39元</div>
|
||||
</div>
|
||||
<div class="vip-card-item">
|
||||
<div class="vip-card-item-title">
|
||||
<svg-icon icon-class="userCenter"></svg-icon>
|
||||
基础版VIP连续包月
|
||||
</div>
|
||||
<div class="price">
|
||||
<div class="price-symbol">¥</div>
|
||||
<div class="price-number">9.9</div>
|
||||
<div class="original-price">¥19.9</div>
|
||||
</div>
|
||||
<div class="price-desc">次月续费¥39元</div>
|
||||
</div>
|
||||
<!-- <div class="vip-card-item">
|
||||
<div class="vip-card-item-title">
|
||||
<svg-icon icon-class="userCenter"></svg-icon>
|
||||
基础版VIP连续包月
|
||||
</div>
|
||||
<div class="price">
|
||||
<div class="price-symbol">¥</div>
|
||||
<div class="price-number">9.9</div>
|
||||
<div class="original-price">¥19.9</div>
|
||||
</div>
|
||||
<div class="price-desc">次月续费¥39元</div>
|
||||
</div> -->
|
||||
|
||||
</div>
|
||||
<div class="vip-list-container">
|
||||
<div class="vip-list-item">
|
||||
<div class="vip-list-subitem">
|
||||
<svg-icon icon-class="userCenter"></svg-icon>
|
||||
基础版VIP权益
|
||||
</div>
|
||||
<div class="vip-list-subitem">每月15000点算力</div>
|
||||
<div class="vip-list-subitem">每月20GB存储空间</div>
|
||||
<div class="vip-list-subitem">每月800次生图加速</div>
|
||||
<div class="vip-list-subitem">2个生图任务并行</div>
|
||||
<div class="vip-list-subitem">-</div>
|
||||
</div>
|
||||
<div class="vip-list-item">
|
||||
<div class="vip-list-subitem">
|
||||
<svg-icon icon-class="userCenter"></svg-icon>
|
||||
专业版VIP权益
|
||||
</div>
|
||||
<div class="vip-list-subitem">每月35000点算力</div>
|
||||
<div class="vip-list-subitem">每月50GB存储空间</div>
|
||||
<div class="vip-list-subitem">每月5000次生图加速</div>
|
||||
<div class="vip-list-subitem">3个生图任务并行</div>
|
||||
<div class="vip-list-subitem">可训练XL模型</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="vip-list-desc">
|
||||
会员每月算力和加速特权按下月下发, 有效期31天, 到期重置
|
||||
</div>
|
||||
<div class="pay-container">
|
||||
<div class="pay-qrcode">
|
||||
|
||||
</div>
|
||||
<div class="pay-info">
|
||||
<div class="pay-info-title">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'vipPay',
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
methods: {
|
||||
closeVipPay(){
|
||||
this.$emit('closeVipPay')
|
||||
}
|
||||
},
|
||||
mounted() {},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.container {
|
||||
color: #333;
|
||||
position: fixed;
|
||||
background-color: rgba($color: #000000, $alpha: 0.5);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 9999;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.pay-content {
|
||||
background-color: #fff;
|
||||
border-radius: 20px;
|
||||
.header-user-info {
|
||||
padding:10px 20px;
|
||||
border-radius: 20px 20px 0 0;
|
||||
background-color: #ffda96;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
.user-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.user-avatar {
|
||||
margin-right: 20px;
|
||||
border-radius: 50%;
|
||||
background-color: #ccc;
|
||||
}
|
||||
.user-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
.user-name {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
.user-level {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.user-level-name {
|
||||
color: #333;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.close-icon {
|
||||
}
|
||||
}
|
||||
.vip-card {
|
||||
padding: 10px 30px;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
.vip-card-item {
|
||||
width: 170px;
|
||||
height: 152px;
|
||||
background: linear-gradient(90deg, #fffaf1, #ffeccf);
|
||||
border-radius: 10px;
|
||||
border: 1px solid #f7b252;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
.vip-card-item-title{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 12px;
|
||||
color: #814600;
|
||||
}
|
||||
.price{
|
||||
display: flex;
|
||||
.price-symbol{
|
||||
color: #814600;
|
||||
font-size: 14px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
.price-number{
|
||||
color: #814600;
|
||||
font-size: 20px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
.original-price{
|
||||
text-decoration: line-through;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.vip-list-container {
|
||||
padding: 10px 30px;
|
||||
.vip-list-item {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
.vip-list-subitem {
|
||||
// white-space: nowrap;
|
||||
width: 140px;
|
||||
border: 1px solid #eeeeee;
|
||||
flex: 1;
|
||||
line-height: 30px;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
color: #333;
|
||||
padding: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.vip-list-desc{
|
||||
padding:0 30px;
|
||||
color: #9d8c75;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
margin-top: 6px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
|
@ -0,0 +1,223 @@
|
|||
<template>
|
||||
<div class="membership-table">
|
||||
<h2 class="title">会员权益</h2>
|
||||
|
||||
<div class="plans-container">
|
||||
<!-- 会员等级列 -->
|
||||
<div class="plan-column features">
|
||||
<div class="plan-header">会员权益</div>
|
||||
<div class="feature-item" v-for="feature in features" :key="feature">
|
||||
{{ feature }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 免费用户列 -->
|
||||
<div class="plan-column free">
|
||||
<div class="plan-header">免费用户</div>
|
||||
<div class="plan-details">
|
||||
<div class="feature-item">每天300点</div>
|
||||
<div class="feature-item">3GB</div>
|
||||
<div class="feature-item">
|
||||
<span class="cross">✕</span>
|
||||
</div>
|
||||
<div class="feature-item">
|
||||
<span class="cross">✕</span>
|
||||
</div>
|
||||
<div class="feature-item">
|
||||
<span class="cross">✕</span>
|
||||
</div>
|
||||
<div class="feature-item">
|
||||
<span class="cross">✕</span>
|
||||
</div>
|
||||
<div class="feature-item">
|
||||
<span class="cross">✕</span>
|
||||
</div>
|
||||
<div class="feature-item">
|
||||
<span class="cross">✕</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 基础版VIP列 -->
|
||||
<div class="plan-column basic">
|
||||
<div class="plan-header">
|
||||
<span class="vip-icon">💎</span>
|
||||
基础版VIP
|
||||
</div>
|
||||
<div class="plan-details">
|
||||
<div class="feature-item">每月15000点</div>
|
||||
<div class="feature-item">20GB</div>
|
||||
<div class="feature-item">每月800次</div>
|
||||
<div class="feature-item">
|
||||
<span class="check">✓</span>
|
||||
</div>
|
||||
<div class="feature-item">
|
||||
<span class="check">✓</span>
|
||||
</div>
|
||||
<div class="feature-item">
|
||||
<span class="cross">✕</span>
|
||||
</div>
|
||||
<div class="feature-item">
|
||||
<span class="check">✓</span>
|
||||
</div>
|
||||
<div class="feature-item">2个</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 专业版VIP列 -->
|
||||
<div class="plan-column pro">
|
||||
<div class="plan-header">
|
||||
<span class="vip-icon">💝</span>
|
||||
专业版VIP
|
||||
</div>
|
||||
<div class="plan-details">
|
||||
<div class="feature-item">每月35000点</div>
|
||||
<div class="feature-item">50GB</div>
|
||||
<div class="feature-item">每月5000次</div>
|
||||
<div class="feature-item">
|
||||
<span class="check">✓</span>
|
||||
</div>
|
||||
<div class="feature-item">
|
||||
<span class="check">✓</span>
|
||||
</div>
|
||||
<div class="feature-item">
|
||||
<span class="check">✓</span>
|
||||
</div>
|
||||
<div class="feature-item">
|
||||
<span class="check">✓</span>
|
||||
</div>
|
||||
<div class="feature-item">3个</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'MembershipTable',
|
||||
data() {
|
||||
return {
|
||||
features: [
|
||||
'算力',
|
||||
'云端存储空间',
|
||||
'生图加速特权',
|
||||
'会员专属模型',
|
||||
'生图高级功能',
|
||||
'训练XL模型',
|
||||
'图片去水印下载',
|
||||
'多任务并行生图'
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.membership-table {
|
||||
padding: 20px;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
color: #6b6a6a;
|
||||
.title {
|
||||
text-align: center;
|
||||
color: #333;
|
||||
margin-bottom: 30px;
|
||||
font-size: 24px;
|
||||
position: relative;
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
content: '+';
|
||||
color: #ffa500;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
&::before {
|
||||
left: calc(50% - 100px);
|
||||
}
|
||||
|
||||
&::after {
|
||||
right: calc(50% - 100px);
|
||||
}
|
||||
}
|
||||
|
||||
.plans-container {
|
||||
display: flex;
|
||||
gap: 2px;
|
||||
background: #f5f5f5;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.plan-column {
|
||||
flex: 1;
|
||||
background: white;
|
||||
|
||||
&.features {
|
||||
background: #f8f8f8;
|
||||
}
|
||||
|
||||
&.pro {
|
||||
background: #fff9f0;
|
||||
}
|
||||
}
|
||||
|
||||
.plan-header {
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
background: #fbfbfb;
|
||||
border-bottom: 1px solid #eee;
|
||||
|
||||
.vip-icon {
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.feature-item {
|
||||
padding: 15px 20px;
|
||||
border-bottom: 1px solid #eee;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 52px;
|
||||
|
||||
.check {
|
||||
color: #4CAF50;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.cross {
|
||||
color: #ff4444;
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.basic {
|
||||
.plan-header {
|
||||
color: #ffa500;
|
||||
}
|
||||
}
|
||||
|
||||
.pro {
|
||||
.plan-header {
|
||||
color: #ff6b6b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.membership-table {
|
||||
.plans-container {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.feature-item {
|
||||
padding: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,5 @@
|
|||
import Vue from 'vue';
|
||||
|
||||
const eventBus = new Vue();
|
||||
|
||||
export default eventBus;
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div :class="classObj" class="app-wrapper" :style="{'--current-color': theme}">
|
||||
<!-- <div :class="classObj" class="app-wrapper" :style="{'--current-color': theme}">
|
||||
<div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside"/>
|
||||
<sidebar v-if="!sidebar.hide" class="sidebar-container"/>
|
||||
<div :class="{hasTagsView:needTagsView,sidebarHide:sidebar.hide}" class="main-container">
|
||||
|
@ -12,27 +12,54 @@
|
|||
<settings/>
|
||||
</right-panel>
|
||||
</div>
|
||||
</div> -->
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<McHeader></McHeader>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="sidebar-content">
|
||||
<McSidebar @handleRoute="handleRoute"></McSidebar>
|
||||
</div>
|
||||
<div class="main-content">
|
||||
<router-view />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import RightPanel from '@/components/RightPanel'
|
||||
import { AppMain, Navbar, Settings, Sidebar, TagsView } from './components'
|
||||
import ResizeMixin from './mixin/ResizeHandler'
|
||||
// import { isRelogin } from '../../utils/request'
|
||||
import { getToken } from '@/utils/auth'
|
||||
// import RightPanel from '@/components/RightPanel'
|
||||
import McHeader from '@/components/McHeader'
|
||||
import McSidebar from '@/components/McSideBar'
|
||||
import McLogin from '@/components/McLogin'
|
||||
import McPersonalCenter from '@/views/McPersonalCenter'
|
||||
// import { AppMain, Navbar, Settings, Sidebar, TagsView } from './components'
|
||||
// import ResizeMixin from './mixin/ResizeHandler'
|
||||
import { mapState } from 'vuex'
|
||||
import variables from '@/assets/styles/variables.scss'
|
||||
|
||||
export default {
|
||||
name: 'Layout',
|
||||
components: {
|
||||
AppMain,
|
||||
Navbar,
|
||||
RightPanel,
|
||||
Settings,
|
||||
Sidebar,
|
||||
TagsView
|
||||
data() {
|
||||
return {
|
||||
isShowLogin:false,
|
||||
}
|
||||
},
|
||||
mixins: [ResizeMixin],
|
||||
components: {
|
||||
// AppMain,
|
||||
// Navbar,
|
||||
// RightPanel,
|
||||
// Settings,
|
||||
// Sidebar,
|
||||
// TagsView,
|
||||
McHeader,
|
||||
McSidebar,
|
||||
McLogin,
|
||||
McPersonalCenter
|
||||
},
|
||||
// mixins: [ResizeMixin],
|
||||
computed: {
|
||||
...mapState({
|
||||
theme: state => state.settings.theme,
|
||||
|
@ -55,57 +82,101 @@ export default {
|
|||
}
|
||||
},
|
||||
methods: {
|
||||
handleClickOutside() {
|
||||
this.$store.dispatch('app/closeSideBar', { withoutAnimation: false })
|
||||
}
|
||||
}
|
||||
handleRoute(route){
|
||||
this.$router.push(route)
|
||||
},
|
||||
// import Vue from "vue";
|
||||
// Vue.prototype.$eventBus.$emit("showLogin");
|
||||
// onCloseLogin(ag){
|
||||
// this.isShowLogin = ag
|
||||
// },
|
||||
// handleClickOutside() {
|
||||
// this.$store.dispatch('app/closeSideBar', { withoutAnimation: false })
|
||||
// }
|
||||
},
|
||||
mounted() {
|
||||
// this.isShowLogin = isRelogin.show
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "~@/assets/styles/mixin.scss";
|
||||
@import "~@/assets/styles/variables.scss";
|
||||
.container{
|
||||
.header{
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
}
|
||||
.content{
|
||||
position: relative;
|
||||
display: flex;
|
||||
// padding-top: 61px;
|
||||
.main-content{
|
||||
flex: 1;
|
||||
overflow: auto; /* 内容可滚动 */
|
||||
scrollbar-width: none; /* 仅适用于 Firefox,隐藏滚动条 */
|
||||
-ms-overflow-style: none; /* 仅适用于 IE 和 Edge */
|
||||
color: #4e4e4e;
|
||||
// width: 220px;
|
||||
height: calc(100vh - 61px);
|
||||
// border-right:1px solid #e7e7e7;
|
||||
}
|
||||
.sidebar-content{
|
||||
|
||||
.app-wrapper {
|
||||
@include clearfix;
|
||||
position: relative;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
&.mobile.openSidebar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
}
|
||||
.login-content{
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// .main-content{
|
||||
// display: flex;
|
||||
// padding-top: 61px
|
||||
// }
|
||||
// .app-wrapper {
|
||||
// @include clearfix;
|
||||
// position: relative;
|
||||
// height: 100%;
|
||||
// width: 100%;
|
||||
|
||||
.drawer-bg {
|
||||
background: #000;
|
||||
opacity: 0.3;
|
||||
width: 100%;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
z-index: 999;
|
||||
}
|
||||
// &.mobile.openSidebar {
|
||||
// position: fixed;
|
||||
// top: 0;
|
||||
// }
|
||||
// }
|
||||
|
||||
.fixed-header {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: 9;
|
||||
width: calc(100% - #{$base-sidebar-width});
|
||||
transition: width 0.28s;
|
||||
}
|
||||
// .drawer-bg {
|
||||
// background: #000;
|
||||
// opacity: 0.3;
|
||||
// width: 100%;
|
||||
// top: 0;
|
||||
// height: 100%;
|
||||
// position: absolute;
|
||||
// z-index: 999;
|
||||
// }
|
||||
|
||||
.hideSidebar .fixed-header {
|
||||
width: calc(100% - 54px);
|
||||
}
|
||||
// .fixed-header {
|
||||
// position: fixed;
|
||||
// top: 0;
|
||||
// right: 0;
|
||||
// z-index: 9;
|
||||
// // width: calc(100% - #{$base-sidebar-width});
|
||||
// transition: width 0.28s;
|
||||
// }
|
||||
|
||||
.sidebarHide .fixed-header {
|
||||
width: 100%;
|
||||
}
|
||||
// .hideSidebar .fixed-header {
|
||||
// width: calc(100% - 54px);
|
||||
// }
|
||||
|
||||
.mobile .fixed-header {
|
||||
width: 100%;
|
||||
}
|
||||
// .sidebarHide .fixed-header {
|
||||
// width: 100%;
|
||||
// }
|
||||
|
||||
// .mobile .fixed-header {
|
||||
// width: 100%;
|
||||
// }
|
||||
</style>
|
||||
|
|
12
src/main.js
|
@ -1,5 +1,5 @@
|
|||
import Vue from 'vue'
|
||||
|
||||
// import App from "./App.vue";
|
||||
import Cookies from 'js-cookie'
|
||||
|
||||
import Element from 'element-ui'
|
||||
|
@ -24,7 +24,7 @@ import Pagination from "@/components/Pagination";
|
|||
// 自定义表格工具组件
|
||||
import RightToolbar from "@/components/RightToolbar"
|
||||
// 富文本组件
|
||||
import Editor from "@/components/Editor"
|
||||
// import Editor from "@/components/Editor"
|
||||
// 文件上传组件
|
||||
import FileUpload from "@/components/FileUpload"
|
||||
// 图片上传组件
|
||||
|
@ -53,7 +53,7 @@ Vue.prototype.handleTree = handleTree
|
|||
Vue.component('DictTag', DictTag)
|
||||
Vue.component('Pagination', Pagination)
|
||||
Vue.component('RightToolbar', RightToolbar)
|
||||
Vue.component('Editor', Editor)
|
||||
// Vue.component('Editor', Editor)
|
||||
Vue.component('FileUpload', FileUpload)
|
||||
Vue.component('ImageUpload', ImageUpload)
|
||||
Vue.component('ImagePreview', ImagePreview)
|
||||
|
@ -77,7 +77,11 @@ Vue.use(Element, {
|
|||
})
|
||||
|
||||
Vue.config.productionTip = false
|
||||
|
||||
// 创建全局事件总线
|
||||
Vue.prototype.$eventBus = new Vue();
|
||||
// new Vue({
|
||||
// render: (h) => h(App),
|
||||
// }).$mount("#app");
|
||||
new Vue({
|
||||
el: '#app',
|
||||
router,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import router from './router'
|
||||
import eventBus from './eventBus';
|
||||
import store from './store'
|
||||
import { Message } from 'element-ui'
|
||||
import NProgress from 'nprogress'
|
||||
|
@ -26,35 +27,64 @@ router.beforeEach((to, from, next) => {
|
|||
} else if (isWhiteList(to.path)) {
|
||||
next()
|
||||
} else {
|
||||
if (store.getters.roles.length === 0) {
|
||||
isRelogin.show = true
|
||||
// 判断当前用户是否已拉取完user_info信息
|
||||
// next()
|
||||
store.dispatch('GetInfo').then(() => {
|
||||
isRelogin.show = false
|
||||
// isRelogin.show = false
|
||||
store.dispatch('GenerateRoutes').then(accessRoutes => {
|
||||
// 根据roles权限生成可访问的路由表
|
||||
router.addRoutes(accessRoutes) // 动态添加可访问路由表
|
||||
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
|
||||
// router.addRoutes(accessRoutes) // 动态添加可访问路由表
|
||||
next() // hack方法 确保addRoutes已完成
|
||||
})
|
||||
}).catch(err => {
|
||||
store.dispatch('LogOut').then(() => {
|
||||
Message.error(err)
|
||||
next({ path: '/' })
|
||||
})
|
||||
})
|
||||
} else {
|
||||
// store.dispatch('LogOut').then(() => {
|
||||
// Message.error(err)
|
||||
// next({ path: '/' })
|
||||
// })
|
||||
next()
|
||||
}
|
||||
|
||||
})
|
||||
// if (store.getters.roles.length === 0) {
|
||||
// isRelogin.show = true
|
||||
// // 判断当前用户是否已拉取完user_info信息
|
||||
// store.dispatch('GetInfo').then(() => {
|
||||
// isRelogin.show = false
|
||||
// store.dispatch('GenerateRoutes').then(accessRoutes => {
|
||||
// // 根据roles权限生成可访问的路由表
|
||||
// router.addRoutes(accessRoutes) // 动态添加可访问路由表
|
||||
// next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
|
||||
// })
|
||||
// }).catch(err => {
|
||||
// store.dispatch('LogOut').then(() => {
|
||||
// Message.error(err)
|
||||
// next({ path: '/' })
|
||||
// })
|
||||
// })
|
||||
// } else {
|
||||
// next()
|
||||
// }
|
||||
}
|
||||
} else {
|
||||
// 没有token
|
||||
if (isWhiteList(to.path)) {
|
||||
// 在免登录白名单,直接进入
|
||||
store.dispatch('LogOut').then(() => {
|
||||
|
||||
// Message.error(err)
|
||||
next()
|
||||
} else {
|
||||
next(`/login?redirect=${encodeURIComponent(to.fullPath)}`) // 否则全部重定向到登录页
|
||||
NProgress.done()
|
||||
}
|
||||
})
|
||||
// eventBus.$eventBus.$emit("showLogin");
|
||||
// const app = Vue
|
||||
// setTimeout(() => {
|
||||
// if(app.$eventBus){
|
||||
// app.$eventBus.$emit("showLogin");
|
||||
// }
|
||||
// }, 500);
|
||||
|
||||
// 没有token
|
||||
// if (isWhiteList(to.path)) {
|
||||
// // 在免登录白名单,直接进入
|
||||
// next()
|
||||
// } else {
|
||||
// next(`/login?redirect=${encodeURIComponent(to.fullPath)}`) // 否则全部重定向到登录页
|
||||
// NProgress.done()
|
||||
// }
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
@ -62,16 +62,47 @@ export const constantRoutes = [
|
|||
hidden: true
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
path: '/',
|
||||
component: Layout,
|
||||
redirect: 'index',
|
||||
name: 'Layout',
|
||||
redirect: 'home',
|
||||
children: [
|
||||
{
|
||||
path: 'index',
|
||||
path: '/personalCenter',
|
||||
component: () => import('@/views/McPersonalCenter/index'),
|
||||
name: 'PersonalCenter',
|
||||
meta: { title: '个人中心', icon: 'dashboard', affix: true }
|
||||
},
|
||||
{
|
||||
path: '/home',
|
||||
component: () => import('@/views/home/index'),
|
||||
name: 'Home',
|
||||
meta: { title: '首页', icon: 'dashboard', affix: true }
|
||||
},
|
||||
{
|
||||
path: '/workFlow',
|
||||
component: () => import('@/views/workFlow/index'),
|
||||
name: 'WorkFlow',
|
||||
meta: { title: '工作流', icon: 'dashboard', affix: true }
|
||||
},
|
||||
{
|
||||
path: '/publishModel',
|
||||
component: () => import('@/views/publishModel/index'),
|
||||
name: 'PublishModel',
|
||||
meta: { title: '首页', icon: 'dashboard', affix: true }
|
||||
},
|
||||
{
|
||||
path: '/index',
|
||||
component: () => import('@/views/index'),
|
||||
name: 'Index',
|
||||
meta: { title: '首页', icon: 'dashboard', affix: true }
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/vipCenter',
|
||||
component: () => import('@/views/vipCenter/index'),
|
||||
name: 'VipCenter',
|
||||
meta: { title: '首页', icon: 'dashboard', affix: true }
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
|
@ -5,9 +5,15 @@ const getters = {
|
|||
dict: state => state.dict.dict,
|
||||
visitedViews: state => state.tagsView.visitedViews,
|
||||
cachedViews: state => state.tagsView.cachedViews,
|
||||
userInfo: state => state.userInfo,
|
||||
token: state => state.user.token,
|
||||
idName: state => state.user.idName,
|
||||
avatar: state => state.user.avatar,
|
||||
userId: state => state.user.userId,
|
||||
brief: state => state.user.brief,
|
||||
userInfo: state => state.user.userInfo,
|
||||
name: state => state.user.name,
|
||||
nickName: state => state.user.nickName,
|
||||
introduction: state => state.user.introduction,
|
||||
roles: state => state.user.roles,
|
||||
permissions: state => state.user.permissions,
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
import { login, logout, getInfo } from '@/api/login'
|
||||
// import { login, logout, getInfo } from '@/api/login'
|
||||
import { logout, getInfo } from '@/api/login'
|
||||
import { login } from '@/api/mcwl/login'
|
||||
import { getToken, setToken, removeToken } from '@/utils/auth'
|
||||
import { isHttp, isEmpty } from "@/utils/validate"
|
||||
import defAva from '@/assets/images/profile.jpg'
|
||||
|
@ -6,10 +8,15 @@ import defAva from '@/assets/images/profile.jpg'
|
|||
const user = {
|
||||
state: {
|
||||
token: getToken(),
|
||||
user:{},
|
||||
nickName:'',
|
||||
id: '',
|
||||
userId: '',
|
||||
brief: '',
|
||||
name: '',
|
||||
avatar: '',
|
||||
roles: [],
|
||||
idName:'',
|
||||
permissions: []
|
||||
},
|
||||
|
||||
|
@ -17,15 +24,30 @@ const user = {
|
|||
SET_TOKEN: (state, token) => {
|
||||
state.token = token
|
||||
},
|
||||
SET_USER_INFO: (state, user) => {
|
||||
state.user = user
|
||||
},
|
||||
SET_ID: (state, id) => {
|
||||
state.id = id
|
||||
},
|
||||
SET_USERID: (state, userId) => {
|
||||
state.userId = userId
|
||||
},
|
||||
SET_NAME: (state, name) => {
|
||||
state.name = name
|
||||
},
|
||||
SET_ID_NAME: (state, idName) => {
|
||||
state.idName = idName
|
||||
},
|
||||
SET_NICK_NAME: (state, name) => {
|
||||
state.nickName = name
|
||||
},
|
||||
SET_AVATAR: (state, avatar) => {
|
||||
state.avatar = avatar
|
||||
},
|
||||
SET_BRIEF: (state, brief) => {
|
||||
state.brief = brief
|
||||
},
|
||||
SET_ROLES: (state, roles) => {
|
||||
state.roles = roles
|
||||
},
|
||||
|
@ -37,15 +59,19 @@ const user = {
|
|||
actions: {
|
||||
// 登录
|
||||
Login({ commit }, userInfo) {
|
||||
const username = userInfo.username.trim()
|
||||
const password = userInfo.password
|
||||
// const username = userInfo.username.trim()
|
||||
// const password = userInfo.password
|
||||
const code = userInfo.code
|
||||
const uuid = userInfo.uuid
|
||||
const phone = userInfo.phone.trim()
|
||||
// const uuid = userInfo.uuid
|
||||
return new Promise((resolve, reject) => {
|
||||
login(username, password, code, uuid).then(res => {
|
||||
// username, password, code, uuid
|
||||
login(phone,code).then(res => {
|
||||
console.log('object', res);
|
||||
setToken(res.token)
|
||||
commit('SET_TOKEN', res.token)
|
||||
resolve()
|
||||
this.GetInfo()
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
})
|
||||
|
@ -56,19 +82,24 @@ const user = {
|
|||
GetInfo({ commit, state }) {
|
||||
return new Promise((resolve, reject) => {
|
||||
getInfo().then(res => {
|
||||
const user = res.user
|
||||
const user = res.data
|
||||
let avatar = user.avatar || ""
|
||||
if (!isHttp(avatar)) {
|
||||
avatar = (isEmpty(avatar)) ? defAva : process.env.VUE_APP_BASE_API + avatar
|
||||
}
|
||||
if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组
|
||||
commit('SET_ROLES', res.roles)
|
||||
commit('SET_PERMISSIONS', res.permissions)
|
||||
} else {
|
||||
commit('SET_ROLES', ['ROLE_DEFAULT'])
|
||||
}
|
||||
commit('SET_ID', user.userId)
|
||||
// if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组
|
||||
// commit('SET_ROLES', res.roles)
|
||||
// commit('SET_PERMISSIONS', res.permissions)
|
||||
// } else {
|
||||
// commit('SET_ROLES', ['ROLE_DEFAULT'])
|
||||
// }
|
||||
commit('SET_USER_INFO', user)
|
||||
commit('SET_ID', user.id)
|
||||
commit('SET_USERID', user.userId)
|
||||
commit('SET_BRIEF', user.brief)
|
||||
commit('SET_NAME', user.userName)
|
||||
commit('SET_NICK_NAME', user.nickName)
|
||||
commit('SET_ID_NAME', user.name)
|
||||
commit('SET_AVATAR', avatar)
|
||||
resolve(res)
|
||||
}).catch(error => {
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
// src/utils/downloadImage.js
|
||||
|
||||
export async function downloadImage(imageUrl, fileName = 'downloaded_image.jpg') {
|
||||
try {
|
||||
// 使用 fetch 获取图片数据
|
||||
const response = await fetch(imageUrl);
|
||||
const blob = await response.blob(); // 将响应转为 Blob
|
||||
|
||||
// 创建一个 URL 对象
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
|
||||
// 创建一个 <a> 标签并设置其下载属性
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = fileName; // 指定下载的文件名
|
||||
a.click(); // 触发下载
|
||||
|
||||
// 释放对象 URL
|
||||
window.URL.revokeObjectURL(url);
|
||||
} catch (error) {
|
||||
console.error('下载图片失败:', error);
|
||||
}
|
||||
}
|
||||
|
|
@ -45,7 +45,7 @@ service.interceptors.request.use(config => {
|
|||
const requestSize = Object.keys(JSON.stringify(requestObj)).length; // 请求数据大小
|
||||
const limitSize = 5 * 1024 * 1024; // 限制存放数据5M
|
||||
if (requestSize >= limitSize) {
|
||||
console.warn(`[${config.url}]: ` + '请求数据大小超出允许的5M限制,无法进行防重复提交验证。')
|
||||
console.warn(`[${config.url}]: ` + '请求数据大小超出允许的5M限制, 无法进行防重复提交验证。')
|
||||
return config;
|
||||
}
|
||||
const sessionObj = cache.session.getJSON('sessionObj')
|
||||
|
@ -55,7 +55,8 @@ service.interceptors.request.use(config => {
|
|||
const s_url = sessionObj.url; // 请求地址
|
||||
const s_data = sessionObj.data; // 请求数据
|
||||
const s_time = sessionObj.time; // 请求时间
|
||||
const interval = 1000; // 间隔时间(ms),小于此时间视为重复提交
|
||||
const interval = 0; // 间隔时间(ms),小于此时间视为重复提交
|
||||
// const interval = 1000; // 间隔时间(ms),小于此时间视为重复提交
|
||||
if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) {
|
||||
const message = '数据正在处理,请勿重复提交';
|
||||
console.warn(`[${s_url}]: ` + message)
|
||||
|
@ -82,18 +83,22 @@ service.interceptors.response.use(res => {
|
|||
return res.data
|
||||
}
|
||||
if (code === 401) {
|
||||
if (!isRelogin.show) {
|
||||
isRelogin.show = true;
|
||||
MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => {
|
||||
isRelogin.show = false;
|
||||
store.dispatch('LogOut').then(() => {
|
||||
location.href = '/index';
|
||||
})
|
||||
}).catch(() => {
|
||||
isRelogin.show = false;
|
||||
});
|
||||
}
|
||||
return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
|
||||
store.dispatch('LogOut').then(() => {
|
||||
// location.href = '/index';
|
||||
})
|
||||
// this.$eventBus.$emit("showLogin");
|
||||
// if (!isRelogin.show) {
|
||||
// isRelogin.show = true;
|
||||
// MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => {
|
||||
// isRelogin.show = false;
|
||||
// store.dispatch('LogOut').then(() => {
|
||||
// location.href = '/index';
|
||||
// })
|
||||
// }).catch(() => {
|
||||
// isRelogin.show = false;
|
||||
// });
|
||||
// }
|
||||
// return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
|
||||
} else if (code === 500) {
|
||||
Message({ message: msg, type: 'error' })
|
||||
return Promise.reject(new Error(msg))
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
import { mallProductFile } from "@/api/mcwl/utils";
|
||||
|
||||
/**
|
||||
* 分批次上传图片
|
||||
* @param {File[]} files - 需要上传的图片文件数组
|
||||
* @param {string} url - 上传接口的 URL
|
||||
* @param {number} batchSize - 每批次上传的文件数量(默认为 3)
|
||||
* @returns {Promise<{ success: boolean, message: string, data: any[] }>} - 返回上传结果
|
||||
*/
|
||||
|
||||
export const uploadImagesInBatches = async (files, batchSize = 3) => {
|
||||
const uploadResults = [];
|
||||
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
const file = files[i];
|
||||
|
||||
// 创建 FormData 对象
|
||||
const formData = new FormData();
|
||||
formData.append('file', file); // 假设后端接收字段是 `file`
|
||||
|
||||
// 上传当前图片
|
||||
try {
|
||||
console.log('object', formData);
|
||||
const res = await mallProductFile(formData)
|
||||
uploadResults.push(res.msg);
|
||||
} catch (error) {
|
||||
console.error(`图片上传失败: ${file.name}`, error);
|
||||
uploadResults.push({ success: false, error });
|
||||
}
|
||||
}
|
||||
return uploadResults;
|
||||
}
|
|
@ -0,0 +1,439 @@
|
|||
<template>
|
||||
<div class="container">
|
||||
<div class="banner-content"></div>
|
||||
<div class="info-content">
|
||||
<div class="edit-info-content">
|
||||
<div class="mc-head">
|
||||
<div class="mc-head-inner">
|
||||
<img class="head-img" :src="avatar" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="edit-info" @click="onEditInfo(true)">编辑资料</div>
|
||||
|
||||
<div v-if="idName" class="edit-info">已经实名</div>
|
||||
<div v-else class="edit-info" @click="onShowId(true)">去实名</div>
|
||||
</div>
|
||||
|
||||
<div class="user-info">
|
||||
<div class="nickname">
|
||||
{{ nickName }}
|
||||
</div>
|
||||
<div class="info-desc">
|
||||
{{ userInfo.brief }}
|
||||
</div>
|
||||
<div class="production-state">
|
||||
<div class="production-state-item">
|
||||
<span class="production-state-number">{{ selectUserInfo.bean }}</span
|
||||
>粉丝
|
||||
</div>
|
||||
<div class="production-state-item">
|
||||
<span class="production-state-number">{{ selectUserInfo.attention }}</span
|
||||
>关注
|
||||
</div>
|
||||
<div class="production-state-item">
|
||||
<span class="production-state-number">{{ selectUserInfo.download }}</span
|
||||
>作品被使用次数
|
||||
</div>
|
||||
<div class="production-state-item">
|
||||
<span class="production-state-number">{{ selectUserInfo.likeCount }}</span
|
||||
>作品被点赞次数
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mc-tabs">
|
||||
<div
|
||||
class="mc-tabs-btn"
|
||||
v-for="(item, index) in stateList"
|
||||
:key="index"
|
||||
:style="{
|
||||
background: currentState === item.id ? '#000' : '#fff',
|
||||
color: currentState === item.id ? '#fff' : '#000',
|
||||
}"
|
||||
@click="changeTabs(item.id)"
|
||||
>
|
||||
{{ item.title }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="select-content">
|
||||
<div class="mc-felx select-type">
|
||||
<div
|
||||
v-for="(item, index) in typeList"
|
||||
@click="changeType(item.id)"
|
||||
:key="index"
|
||||
class="select-type-item"
|
||||
:style="{ background: item.id === publishParams.type ? '#fff' : '#f4f5f9' }"
|
||||
>
|
||||
{{ item.title }}
|
||||
</div>
|
||||
<!-- <div class="select-type-item">工作流</div>
|
||||
<div class="select-type-item">图片</div> -->
|
||||
</div>
|
||||
|
||||
<!-- 发布的form -->
|
||||
<div class="mc-felx" v-if="currentState === 'mallProduct'">
|
||||
<div class="custom-select">
|
||||
<!-- //状态 -->
|
||||
<el-select size="small" v-model="publishParams.status" placeholder="请选择">
|
||||
<el-option
|
||||
v-for="item in statusOptions"
|
||||
:key="item.dictValue"
|
||||
@change="changeStatus"
|
||||
:label="item.dictLabel"
|
||||
:value="item.dictValue"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
<!-- 最新/热度 -->
|
||||
<div class="custom-select">
|
||||
<el-select size="small" v-model="publishParams.order" placeholder="请选择">
|
||||
<el-option
|
||||
v-for="item in orderOptions"
|
||||
:key="item.dictValue"
|
||||
@change="changeOrder"
|
||||
:label="item.dictLabel"
|
||||
:value="item.dictValue"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
|
||||
<!-- //时间 -->
|
||||
<div class="custom-select">
|
||||
<el-date-picker
|
||||
size="small"
|
||||
@change="changeDate"
|
||||
v-model="publishParams.date"
|
||||
type="daterange"
|
||||
value-format="yyyy-MM-dd"
|
||||
range-separator="至"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
>
|
||||
</el-date-picker>
|
||||
</div>
|
||||
</div>
|
||||
<!-- //点赞的form -->
|
||||
<div class="mc-felx" v-if="currentState === 'like'">
|
||||
<!-- 最新/热度 -->
|
||||
<div class="custom-select">
|
||||
<el-select size="small" v-model="likesParams.order" placeholder="请选择">
|
||||
<el-option
|
||||
v-for="item in orderOptions"
|
||||
:key="item.dictValue"
|
||||
@change="changeLikeOrder"
|
||||
:label="item.dictLabel"
|
||||
:value="item.dictValue"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="edit-info-dialog" v-if="isShowEditInfo">
|
||||
<McEditInfo :userInfo="userInfo" @closeEditInfo="onEditInfo"></McEditInfo>
|
||||
</div>
|
||||
<div class="login-content">
|
||||
<LikeWorks v-show="currentState === 'like'" :order="likesParams.order"></LikeWorks>
|
||||
<PublishedWorks
|
||||
v-show="currentState === 'mallProduct'"
|
||||
:status="publishParams.status"
|
||||
:order="publishParams.order"
|
||||
:date="publishParams.date"
|
||||
></PublishedWorks>
|
||||
</div>
|
||||
<NameAuth v-if="isShowId" @closeNameAuth="onCloseNameAuth"></NameAuth>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getSelectUserInfo, dictType, userInfo } from "@/api/mcwl/personalCenter";
|
||||
import McEditInfo from "@/components/McEditInfo";
|
||||
import McLogin from "@/components/McLogin";
|
||||
import { mapGetters } from "vuex";
|
||||
import PublishedWorks from "@/components/PublishedWorks";
|
||||
import LikeWorks from "@/components/LikeWorks";
|
||||
import NameAuth from "@/components/NameAuth";
|
||||
|
||||
export default {
|
||||
name: "McPersonalCenter",
|
||||
data() {
|
||||
return {
|
||||
isShowId: false,
|
||||
selectUserInfo: {},
|
||||
// currentSelect:'mallProduct', //MallProductf发布, like点赞
|
||||
orderOptions: [],
|
||||
statusOptions: [],
|
||||
userInfo: {},
|
||||
isShowEditInfo: false,
|
||||
currentState: "mallProduct",
|
||||
stateList: [
|
||||
{
|
||||
id: "mallProduct",
|
||||
title: "发布",
|
||||
},
|
||||
{
|
||||
id: "like",
|
||||
title: "点赞",
|
||||
},
|
||||
],
|
||||
typeList: [
|
||||
{
|
||||
id: "0",
|
||||
title: "模型",
|
||||
},
|
||||
{
|
||||
id: "1",
|
||||
title: "工作流",
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
title: "图片",
|
||||
},
|
||||
],
|
||||
likesParams: {
|
||||
order: "0", //排序 值为1(最新)其他值(热度)
|
||||
},
|
||||
publishParams: {
|
||||
type: "0", //类型(0全部 1模型 2工作流 3图片)
|
||||
status: "0", //状态(0全部 1未审核 2公开 3隐私 4未通过)
|
||||
order: "0", //排序 值为1(最新)其他值(热度)
|
||||
startTime: "", //开始时间 时间格式为yyyy-MM-dd HH:mm:ss
|
||||
endTime: "", //结束时间 时间格式为yyyy-MM-dd HH:mm:ss
|
||||
date: [],
|
||||
},
|
||||
};
|
||||
},
|
||||
components: {
|
||||
McEditInfo,
|
||||
McLogin,
|
||||
PublishedWorks,
|
||||
LikeWorks,
|
||||
NameAuth,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(["user", "nickName", "avatar", "idName"]),
|
||||
},
|
||||
methods: {
|
||||
changeType(id) {
|
||||
this.publishParams.type = id;
|
||||
},
|
||||
onCloseNameAuth() {
|
||||
this.isShowId = false;
|
||||
},
|
||||
onShowId() {
|
||||
this.isShowId = true;
|
||||
},
|
||||
changeDate(data) {
|
||||
if (!data) {
|
||||
this.publishParams.date = [];
|
||||
console.log("11", this.publishParams.date);
|
||||
} else {
|
||||
this.publishParams.date = data;
|
||||
console.log("22", this.publishParams.date);
|
||||
}
|
||||
},
|
||||
changeStatus(ag) {
|
||||
this.publishParams.status = ag;
|
||||
},
|
||||
changeOrder(ag) {
|
||||
this.publishParams.order = ag;
|
||||
},
|
||||
changeLikeOrder(id) {
|
||||
this.likesParams.order = id;
|
||||
},
|
||||
// 切换发布/点赞
|
||||
changeTabs(id) {
|
||||
this.currentState = id;
|
||||
console.log("currentState", this.currentState);
|
||||
},
|
||||
onEditInfo(ag) {
|
||||
this.isShowEditInfo = ag;
|
||||
},
|
||||
|
||||
//个人关注、粉丝、下载次数和点赞数
|
||||
onGetSelectUserInfo() {
|
||||
getSelectUserInfo()
|
||||
.then((res) => {
|
||||
this.selectUserInfo = res.data;
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log("err-----", err);
|
||||
});
|
||||
},
|
||||
// //数据字典
|
||||
async getDictType() {
|
||||
try {
|
||||
const res = await dictType({ type: "mall_product_status" });
|
||||
const res2 = await dictType({ type: "mall_product_order" });
|
||||
this.orderOptions = res2.data;
|
||||
this.statusOptions = res.data;
|
||||
// this.publishParams.status = res.data[0].dictValue
|
||||
// this.publishParams.order = res2.data[0].dictValue
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
},
|
||||
|
||||
// //查看用户信息
|
||||
getUserInfo() {
|
||||
userInfo({}).then((res) => {
|
||||
this.userInfo = res.data;
|
||||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.getDictType();
|
||||
this.onGetSelectUserInfo();
|
||||
// this.getUserInfo()
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.header-btn {
|
||||
color: #1890ff;
|
||||
}
|
||||
.edit-info-dialog {
|
||||
background-color: rgba($color: #000000, $alpha: 0.5);
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.mc-felx {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.custom-select {
|
||||
margin-right: 10px;
|
||||
}
|
||||
.el-select {
|
||||
width: 120px;
|
||||
}
|
||||
}
|
||||
.container {
|
||||
.banner-content {
|
||||
width: 100%;
|
||||
height: 120px;
|
||||
// background-image: url(../../assets//images/bg.png);
|
||||
background-image: url(https://liblibai-web-static.liblib.cloud/liblibai_v4_online/static/_next/static/images/defaultBgImg.381282c0f2b01780c83d8fe6dc0aa90a.png);
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 150px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
padding-right: 40px;
|
||||
> img {
|
||||
width: 100px;
|
||||
height: 50px;
|
||||
}
|
||||
}
|
||||
.info-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
padding: 20px;
|
||||
margin-top: -50px;
|
||||
.edit-info-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.mc-head {
|
||||
border-radius: 50px;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
margin-right: 20px;
|
||||
background-color: #fff;
|
||||
margin-right: 20px;
|
||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.2);
|
||||
.mc-head-inner {
|
||||
background-color: #a6d4ff;
|
||||
margin: 3px;
|
||||
width: 74px;
|
||||
height: 74px;
|
||||
border-radius: 50%;
|
||||
.head-img {
|
||||
background-color: #fff;
|
||||
margin: 2px;
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
.edit-info {
|
||||
margin-right: 10px;
|
||||
cursor: pointer;
|
||||
padding: 4px 20px;
|
||||
line-height: 30px;
|
||||
background-color: #fff;
|
||||
border-radius: 20px;
|
||||
box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.2);
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
.user-info {
|
||||
margin-top: 10px;
|
||||
.nickname {
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.info-desc {
|
||||
margin: 4px 0 10px 0;
|
||||
color: #2c2b2b;
|
||||
font-size: 14px;
|
||||
}
|
||||
.production-state {
|
||||
display: flex;
|
||||
color: #2c2b2b;
|
||||
font-size: 14px;
|
||||
.production-state-item {
|
||||
margin-right: 20px;
|
||||
.production-state-number {
|
||||
color: #000000;
|
||||
font-weight: 600;
|
||||
margin-right: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.mc-tabs {
|
||||
border-bottom: 1px solid #dcdcdc;
|
||||
padding: 0 20px;
|
||||
display: flex;
|
||||
.mc-tabs-btn {
|
||||
margin-bottom: 10px;
|
||||
padding: 4px 20px;
|
||||
border-radius: 20px;
|
||||
margin-right: 10px;
|
||||
color: #272727;
|
||||
text-align: center;
|
||||
line-height: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.select-content {
|
||||
margin-top: 10px;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
padding: 0 20px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
.select-type {
|
||||
background-color: #f4f5f9;
|
||||
border-radius: 20px;
|
||||
.select-type-item {
|
||||
margin: 4px;
|
||||
border-radius: 20px;
|
||||
padding: 4px 18px;
|
||||
font-size: 12px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,168 @@
|
|||
<template>
|
||||
<div class="container">
|
||||
<div class="search-container">
|
||||
<!-- 输入框 -->
|
||||
<input
|
||||
type="text"
|
||||
v-model="searchText"
|
||||
placeholder="搜索模型/图片/作者寻找灵感"
|
||||
/>
|
||||
<!-- 按钮 -->
|
||||
<button @click="performSearch">搜索</button>
|
||||
</div>
|
||||
<div class="select-content">
|
||||
<div class="mc-felx select-type">
|
||||
|
||||
</div>
|
||||
<!-- 发布的form -->
|
||||
<div class="mc-felx">
|
||||
<div class="custom-select">
|
||||
<!-- //状态 -->
|
||||
<el-select size="small" v-model="publishParams.status" placeholder="请选择">
|
||||
<el-option
|
||||
v-for="item in statusOptions"
|
||||
:key="item.dictValue"
|
||||
@change="changeStatus"
|
||||
:label="item.dictLabel"
|
||||
:value="item.dictValue">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
<!-- 最新/热度 -->
|
||||
<div class="custom-select">
|
||||
<el-select size="small" v-model="publishParams.order" placeholder="请选择">
|
||||
<el-option
|
||||
v-for="item in orderOptions"
|
||||
:key="item.dictValue"
|
||||
@change="changeOrder"
|
||||
:label="item.dictLabel"
|
||||
:value="item.dictValue">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
<!-- //时间 -->
|
||||
<div class="custom-select">
|
||||
<el-date-picker
|
||||
size="small"
|
||||
@change="changeDate"
|
||||
v-model="publishParams.date"
|
||||
type="daterange"
|
||||
value-format="yyyy-MM-dd"
|
||||
range-separator="至"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期">
|
||||
</el-date-picker>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getMallProductList } from "@/api/mcwl/mallProduct";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
publishParams:{},
|
||||
statusOptions:[],
|
||||
orderOptions:[],
|
||||
searchText: "",
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
changeDate(){},
|
||||
changeOrder(){},
|
||||
changeStatus(){},
|
||||
performSearch() {
|
||||
if (this.searchText.trim() === "") {
|
||||
alert("请输入搜索内容!");
|
||||
return;
|
||||
}
|
||||
alert(`搜索内容为:${this.searchText}`);
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
// _variables.scss
|
||||
$primary-color: #007bff;
|
||||
$text-color: #6c757d;
|
||||
$placeholder-color: #adb5bd;
|
||||
$icon-color: #adb5bd;
|
||||
.container{
|
||||
padding: 20px;
|
||||
.search-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: 2px solid $primary-color;
|
||||
border-radius: 25px;
|
||||
padding: 5px 10px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
width: 400px;
|
||||
|
||||
input {
|
||||
border: none;
|
||||
outline: none;
|
||||
font-size: 16px;
|
||||
padding: 8px;
|
||||
flex: 1;
|
||||
border-radius: 20px;
|
||||
color: $text-color;
|
||||
background-color: transparent;
|
||||
|
||||
&::placeholder {
|
||||
color: $placeholder-color;
|
||||
}
|
||||
}
|
||||
|
||||
.icon {
|
||||
margin-right: 10px;
|
||||
color: $icon-color;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: $primary-color;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 20px;
|
||||
padding: 8px 16px;
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s;
|
||||
|
||||
&:hover {
|
||||
background-color: darken($primary-color, 10%);
|
||||
}
|
||||
}
|
||||
}
|
||||
.select-content{
|
||||
margin-top: 10px;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
padding: 0 20px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
.select-type{
|
||||
background-color: #f1f1f1;
|
||||
border-radius: 20px;
|
||||
.select-type-item{
|
||||
padding: 4px 18px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.mc-felx{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.custom-select{
|
||||
margin-right: 10px;
|
||||
}
|
||||
.el-select{
|
||||
width: 120px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,219 @@
|
|||
<template>
|
||||
<div class="create-model">
|
||||
<!-- 步骤条 -->
|
||||
<div class="steps">
|
||||
<div class="step">
|
||||
<el-steps :active="currentStep" align-center>
|
||||
<el-step title="创建模型"></el-step>
|
||||
<el-step title="编辑版本"></el-step>
|
||||
<el-step title="上传图片"></el-step>
|
||||
</el-steps>
|
||||
</div>
|
||||
</div>
|
||||
<input
|
||||
type="file"
|
||||
@change="handlePictureChange"
|
||||
accept="image/*"
|
||||
ref="pictureInput"
|
||||
style="display: none"
|
||||
/>
|
||||
<!-- 表单区域 1-->
|
||||
<div class="form-content" v-show="currentStep === 1">
|
||||
<CreateModel
|
||||
@stepNext="stepNext"
|
||||
@changeCreateModelInfo="changeCreateModelInfo"
|
||||
></CreateModel>
|
||||
</div>
|
||||
|
||||
<!-- 表单区域 2-->
|
||||
<div class="form-content" v-show="currentStep === 2">
|
||||
<EditVersion
|
||||
@stepNext="stepNext"
|
||||
@changeEditVersionInfo="changeEditVersionInfo"
|
||||
></EditVersion>
|
||||
</div>
|
||||
|
||||
<div class="form-content" v-show="currentStep === 3">
|
||||
<div class="uploadImg">
|
||||
<div class="version-item" v-for="(item, index) in editVersionInfo" :key="index">
|
||||
<div>版本名字: {{ item.name }}</div>
|
||||
<div class="version-desc">
|
||||
添加版本实例图片 <span class="required-icon">*</span>
|
||||
</div>
|
||||
<div class="upload-img-container">
|
||||
<div class="upload-img-btn" @click="onUploadImg(index)">上传文件</div>
|
||||
<!-- <div
|
||||
style="
|
||||
font-size: 14px;
|
||||
margin-top: 10px;
|
||||
font-weight: 600;
|
||||
color: rgb(94 94 94);
|
||||
"
|
||||
>
|
||||
建议从图库上传,便于用户画不同款来适用模型效果
|
||||
</div> -->
|
||||
<div class="upload-img-tips">
|
||||
支持格式:.safetensors/.ckpt/.pt/.bin/.path/.gguf/.sft
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="step-group">
|
||||
<div class="step1-group">
|
||||
<div
|
||||
class="step-btn step1"
|
||||
style="background-color: #f1f2f7; color: #000;"
|
||||
@click="stepNext(2)"
|
||||
>
|
||||
上一步
|
||||
</div>
|
||||
<div class="step-btn step1" @click="onPublish(3)">发布</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { uploadImagesInBatches } from "@/utils/uploadImages.js";
|
||||
// import RichTextEditor from "@/components/WangEditor";
|
||||
import CreateModel from "@/components/CreateModels";
|
||||
import EditVersion from "@/components/EditVersion";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
editVersionInfo: [{ name: "1.1" }, { name: "1.2" }],
|
||||
currentStep: 3,
|
||||
CreateModelInfo: {},
|
||||
// 原创转载选项
|
||||
};
|
||||
},
|
||||
|
||||
components: {
|
||||
// RichTextEditor,
|
||||
CreateModel,
|
||||
EditVersion,
|
||||
currentUploadImg: null,
|
||||
},
|
||||
methods: {
|
||||
// 上传图片
|
||||
async handlePictureChange(event) {
|
||||
console.log("object", event);
|
||||
const files = event.target.files;
|
||||
if (files.length > 1) {
|
||||
alert("只能选择 1 张图片");
|
||||
return;
|
||||
}
|
||||
|
||||
let imageFiles = [];
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
const file = files[i];
|
||||
if (file.type.startsWith("image/")) {
|
||||
imageFiles.push(file);
|
||||
// this.imageUrls.push(URL.createObjectURL(file)); // 生成预览 URL
|
||||
} else {
|
||||
alert("请选择有效的图片文件");
|
||||
}
|
||||
}
|
||||
|
||||
const pictureResultList = await uploadImagesInBatches(imageFiles);
|
||||
this.ruleForm.avatar = pictureResultList[0];
|
||||
},
|
||||
// 触发上传事件
|
||||
onUploadImg(index) {
|
||||
this.$refs.pictureInput.click();
|
||||
this.currentUploadImg = index;
|
||||
},
|
||||
// 创建模型步骤的的数据
|
||||
changeCreateModelInfo(info) {
|
||||
this.CreateModelInfo = info;
|
||||
},
|
||||
stepNext(index) {
|
||||
this.currentStep = index;
|
||||
},
|
||||
|
||||
//编辑表单中的数据
|
||||
changeEditVersionInfo(info) {
|
||||
// this.editVersionInfo = info;
|
||||
},
|
||||
// 发布
|
||||
onPublish() {},
|
||||
},
|
||||
created() {
|
||||
// this.getDictType();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.create-model {
|
||||
padding: 20px 0;
|
||||
.form-content {
|
||||
margin: 10px 80px;
|
||||
padding: 20px 10px;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
.uploadImg {
|
||||
font-size: 16px;
|
||||
padding: 20px;
|
||||
.version-item {
|
||||
background-color: #f4f5f9;
|
||||
padding: 20px;
|
||||
margin: 20px 0;
|
||||
border-radius: 10px;
|
||||
.version-desc {
|
||||
font-size: 14px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.required-icon {
|
||||
color: red;
|
||||
}
|
||||
.upload-img-container {
|
||||
margin-top: 10px;
|
||||
width: 100%;
|
||||
height: 150px;
|
||||
border: 1px dashed #ccc;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
background-color: #fff;
|
||||
border-radius: 10px;
|
||||
.upload-img-btn {
|
||||
padding: 4px 20px;
|
||||
text-align: center;
|
||||
background-color: rgb(45, 40, 255);
|
||||
color: #fff;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.upload-img-tips {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.step-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.step-btn {
|
||||
width: 200px;
|
||||
height: 40px;
|
||||
margin-right: 20px;
|
||||
text-align: center;
|
||||
line-height: 40px;
|
||||
}
|
||||
.step1-group {
|
||||
display: flex;
|
||||
background-color: blue;
|
||||
border-radius: 4px;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,177 @@
|
|||
<template>
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<div class="user-info">
|
||||
<div class="user-name">用户名</div>
|
||||
<div class="model-info">
|
||||
<div>下载0</div>
|
||||
<div>不可下载</div>
|
||||
<div>图片0</div>
|
||||
<div>心0</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tags-group">
|
||||
<div class="tags">标签1</div>
|
||||
<div class="tags">标签2</div>
|
||||
<div class="tags">标签3</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="content-left">
|
||||
<el-tabs v-model="activeName" @tab-click="handleClick">
|
||||
<el-tab-pane v-for="(item, index) in contentList" :key="index" :label="item.title" :name="item.id">
|
||||
<!-- {{ item.title }} -->
|
||||
<div class="reprint-originator">
|
||||
转载自作者:魔创未来
|
||||
</div>
|
||||
<div class="versions-info">
|
||||
<div class="versions-title">
|
||||
版本介绍
|
||||
</div>
|
||||
<div class="versions-img">
|
||||
<img src="">
|
||||
</div>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
<div class="content-right">
|
||||
<div class="content-right-user-info">
|
||||
<div class="user-avatar">
|
||||
|
||||
</div>
|
||||
<div class="model-info">
|
||||
<div class="user-name">用户名</div>
|
||||
<div class="user-tags">
|
||||
<div>下载0</div>
|
||||
<div>不可下载</div>
|
||||
<div>图片0</div>
|
||||
<div>心0</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<div>
|
||||
立即生图
|
||||
</div>
|
||||
<div>
|
||||
<div>加入模型库</div>
|
||||
<div>不可下载</div>
|
||||
</div>
|
||||
<div>
|
||||
已验证 2026/01/01
|
||||
</div>
|
||||
</div>
|
||||
<div class="right-version-info">
|
||||
<div class="version-info-title">版本详情</div>
|
||||
<div class="">
|
||||
<div>类型</div>
|
||||
<div>ESFPSPFDF</div>
|
||||
</div>
|
||||
<div class="">
|
||||
<div>在线生成数</div>
|
||||
<div>暂无</div>
|
||||
</div>
|
||||
<div class="">
|
||||
<div>下载量</div>
|
||||
<div>作者设置不可下载</div>
|
||||
</div>
|
||||
<div class="">
|
||||
<div>基础算法</div>
|
||||
<div>基础模型F1</div>
|
||||
</div>
|
||||
<div class="">
|
||||
<div>触发词</div>
|
||||
<div>触发词2</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="right-version-info">
|
||||
<div class="version-info-title">推荐参数</div>
|
||||
<div class="">
|
||||
<div>采样方法</div>
|
||||
<div>EULER, DOOPP</div>
|
||||
</div>
|
||||
<div class="">
|
||||
<div>CFG</div>
|
||||
<div>3.5</div>
|
||||
</div>
|
||||
<div class="">
|
||||
<div>VAE</div>
|
||||
<div>无</div>
|
||||
</div>
|
||||
<div class="">
|
||||
<div>高清放大算法</div>
|
||||
<div>LASDF</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
data(){
|
||||
return {
|
||||
currentVersion: {
|
||||
id:'1',
|
||||
title: '用户管理',
|
||||
version: '1.0.0',
|
||||
xiazailiang: '0',
|
||||
bukexiazai: '0',
|
||||
tupian: '0',
|
||||
xin: '0'
|
||||
},
|
||||
contentList: [
|
||||
{
|
||||
id:'1',
|
||||
title: '用户管理',
|
||||
version: '1.0.0',
|
||||
xiazailiang: '0',
|
||||
bukexiazai: '0',
|
||||
tupian: '0',
|
||||
xin: '0'
|
||||
},
|
||||
{
|
||||
id:'2',
|
||||
title: '配置管理',
|
||||
id:'1',
|
||||
title: '用户管理',
|
||||
version: '1.0.0',
|
||||
xiazailiang: '0',
|
||||
bukexiazai: '0',
|
||||
tupian: '0',
|
||||
xin: '0'
|
||||
}
|
||||
],
|
||||
activeName: '1'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleClick(tab, event) {
|
||||
console.log(tab, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.container{
|
||||
.header{
|
||||
.user-info{
|
||||
display: flex;
|
||||
.user-name{
|
||||
font-size: 20px;
|
||||
}
|
||||
.model-info{
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
.tags-group{
|
||||
display: flex;
|
||||
.tags{
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -156,7 +156,7 @@
|
|||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="内容">
|
||||
<editor v-model="form.noticeContent" :min-height="192"/>
|
||||
<!-- <editor v-model="form.noticeContent" :min-height="192"/> -->
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
|
|
@ -0,0 +1,414 @@
|
|||
<template>
|
||||
<div class="membership-page bg-[#1C1C1C]">
|
||||
<!-- 左侧用户信息卡片 -->
|
||||
<div class="user-info-card">
|
||||
<div class="user-card">
|
||||
<div class="user-profile">
|
||||
<div class="avatar">
|
||||
<img src="default-avatar.png" alt="头像" />
|
||||
</div>
|
||||
<div class="user-id">微信用户a98592</div>
|
||||
<div class="member-status">
|
||||
<span class="diamond-icon">♢</span>
|
||||
您还不是魔创未来会员
|
||||
</div>
|
||||
<button class="activate-btn" @click="openMembership(0)">开通会员</button>
|
||||
<div class="free-trial">兑换会员</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="vip-privileges">
|
||||
<!-- 顶部余额信息 -->
|
||||
<div class="balance-info">
|
||||
<div class="balance-item">
|
||||
<div class="title">算力余额</div>
|
||||
<div class="value">
|
||||
300点
|
||||
<span class="recharge">充值 ></span>
|
||||
</div>
|
||||
<div class="sub-text">算力明细 ></div>
|
||||
</div>
|
||||
<div class="balance-item">
|
||||
<div class="title">生图加速余额</div>
|
||||
<div class="value">
|
||||
0次
|
||||
<span class="recharge">充值 ></span>
|
||||
</div>
|
||||
<div class="sub-text">加速明细 ></div>
|
||||
</div>
|
||||
<div class="balance-item">
|
||||
<div class="title">训练加速余额</div>
|
||||
<div class="value">0次</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 空间使用信息 -->
|
||||
<div class="storage-info">
|
||||
<div class="tabs">
|
||||
<div class="tab">我的存储空间</div>
|
||||
<div class="tab">管理图库</div>
|
||||
<div class="tab">管理训练</div>
|
||||
</div>
|
||||
<div class="usage">
|
||||
<span class="blue-dot"></span>生图 <span class="green-dot"></span>训练
|
||||
<span class="space-usage">0G/3G</span>
|
||||
</div>
|
||||
<div class="usage-bar"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 右侧内容区域 -->
|
||||
<div class="main-content">
|
||||
<!-- 会员类型选项卡 -->
|
||||
<!-- <div class="membership-tabs">
|
||||
<div class="tab active">LiblibAI-会员</div>
|
||||
<div class="tab">
|
||||
LiblibAI-训练会员
|
||||
<span class="trial-tag">可与LiblibAI会员叠加</span>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<!-- 会员套餐卡片 -->
|
||||
<div class="plans-container">
|
||||
<div class="plan-card" v-for="(plan, index) in plans" :key="index">
|
||||
<div class="discount-tag" v-if="plan.discount">立减{{ plan.discount }}元</div>
|
||||
<div class="plan-header">
|
||||
<span class="plan-icon">{{ plan.icon }}</span>
|
||||
<span class="plan-name">{{ plan.name }}</span>
|
||||
</div>
|
||||
<div class="price">
|
||||
<span class="currency">¥</span>
|
||||
<span class="amount">{{ plan.price }}</span>
|
||||
<span class="original-price">¥{{ plan.originalPrice }}</span>
|
||||
</div>
|
||||
<div class="price-detail">{{ plan.detail }}</div>
|
||||
<div class="subscribe-btn" @click="openMembership(plan.price)">立即开通</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<vipRights></vipRights>
|
||||
</div>
|
||||
</div>
|
||||
<vipPay v-if="isPay" @closeVipPay="closeVipPay"></vipPay>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import vipRights from '@/components/vipRights'
|
||||
import vipPay from '@/components/vipPay'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
isPay:true,
|
||||
plans: [
|
||||
{
|
||||
discount: 264,
|
||||
icon: "🏆",
|
||||
name: "基础版VIP连续包月",
|
||||
price: 39,
|
||||
originalPrice: 50,
|
||||
detail: "低至¥28.00元/月",
|
||||
},
|
||||
{
|
||||
icon: "🏆",
|
||||
name: "基础版VIP 12个月",
|
||||
price: 336,
|
||||
originalPrice: 600,
|
||||
detail: "低至¥28.00元/月",
|
||||
},
|
||||
{
|
||||
icon: "🏆",
|
||||
name: "基础版VIP 12个月",
|
||||
price: 336,
|
||||
originalPrice: 600,
|
||||
detail: "到期按¥70/月续费可随时取消",
|
||||
},
|
||||
// ... 其他套餐
|
||||
],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
openMembership(){
|
||||
this.isPay = true
|
||||
},
|
||||
closeVipPay(){
|
||||
this.isPay = false
|
||||
}
|
||||
},
|
||||
components: {
|
||||
vipRights,
|
||||
vipPay
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.membership-page {
|
||||
// display: flex;
|
||||
min-height: 100vh;
|
||||
padding: 20px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.user-info-card {
|
||||
background-color: #1e1915; // 深棕色背景
|
||||
|
||||
display: flex;
|
||||
.user-card {
|
||||
width: 300px;
|
||||
background: rgba(40, 35, 30, 0.95); // 稍微偏褐色的深色
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
margin-right: 20px;
|
||||
height: fit-content;
|
||||
|
||||
.user-profile {
|
||||
text-align: center;
|
||||
|
||||
.avatar {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
border-radius: 50%;
|
||||
margin: 0 auto 12px;
|
||||
overflow: hidden;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
}
|
||||
|
||||
.user-id {
|
||||
font-size: 16px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.member-status {
|
||||
color: #999;
|
||||
font-size: 14px;
|
||||
|
||||
.diamond-icon {
|
||||
color: #ccc;
|
||||
margin-right: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.activate-btn {
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
background: #ffe7ba;
|
||||
color: #8b4513;
|
||||
padding: 12px;
|
||||
border-radius: 24px;
|
||||
margin: 20px 0 12px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.free-trial {
|
||||
text-align: center;
|
||||
color: #999;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.vip-privileges{
|
||||
.balance-info {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 20px;
|
||||
margin-bottom: 20px;
|
||||
|
||||
.balance-item {
|
||||
background: rgba(40, 35, 30, 0.95); // 与用户卡片相同的背景色
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
|
||||
.title {
|
||||
color: #999;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.value {
|
||||
font-size: 18px;
|
||||
margin-bottom: 8px;
|
||||
|
||||
.recharge {
|
||||
color: #999;
|
||||
font-size: 14px;
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.sub-text {
|
||||
color: #999;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.storage-info {
|
||||
background: rgba(40, 35, 30, 0.95);
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
|
||||
.tabs {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
margin-bottom: 12px;
|
||||
|
||||
.tab {
|
||||
color: #999;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.usage {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin-bottom: 8px;
|
||||
|
||||
.blue-dot,
|
||||
.green-dot {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.blue-dot {
|
||||
background: #007aff;
|
||||
}
|
||||
|
||||
.green-dot {
|
||||
background: #34c759;
|
||||
}
|
||||
|
||||
.space-usage {
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.usage-bar {
|
||||
height: 4px;
|
||||
background: #3a3a3a;
|
||||
border-radius: 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.main-content {
|
||||
background: #fff5e2;
|
||||
padding-top: 20px;
|
||||
.membership-tabs {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
margin-bottom: 20px;
|
||||
|
||||
.tab {
|
||||
padding: 12px 24px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
|
||||
&.active {
|
||||
color: #f5a623;
|
||||
border-bottom: 2px solid #f5a623;
|
||||
}
|
||||
|
||||
.trial-tag {
|
||||
position: absolute;
|
||||
top: -8px;
|
||||
right: -8px;
|
||||
background: #f5a623;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
padding: 2px 8px;
|
||||
border-radius: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.plans-container {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
// overflow-x: auto;
|
||||
padding-bottom: 20px;
|
||||
|
||||
.plan-card {
|
||||
min-width: 280px;
|
||||
background: #ffefd9;
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
border: 1px solid #ffffff;
|
||||
.discount-tag {
|
||||
position: absolute;
|
||||
top: -12px;
|
||||
left: 0px;
|
||||
background: #ff3b30;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
padding: 2px 8px;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.plan-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-bottom: 16px;
|
||||
.plan-name{
|
||||
color: #e08909;
|
||||
}
|
||||
}
|
||||
|
||||
.price {
|
||||
margin-bottom: 12px;
|
||||
|
||||
.currency {
|
||||
font-size: 20px;
|
||||
color: #814600;
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
.amount {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
color: #814600;
|
||||
}
|
||||
|
||||
.original-price {
|
||||
color: #999;
|
||||
text-decoration: line-through;
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.price-detail {
|
||||
color: #d27f08;
|
||||
font-size: 14px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.subscribe-btn {
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
background: #ffe7ba;
|
||||
color: #8b4513;
|
||||
padding: 12px;
|
||||
border-radius: 24px;
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,163 @@
|
|||
<template>
|
||||
<div class="container">
|
||||
<div class="steps">
|
||||
<div class="step">
|
||||
<el-steps :active="currentStep" align-center>
|
||||
<el-step title="编辑工作流"></el-step>
|
||||
<el-step title="编辑版本"></el-step>
|
||||
<el-step title="上传图片"></el-step>
|
||||
</el-steps>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="edit-workflow" v-show="currentStep===1">
|
||||
<EditWorkFlow @changeWorkFlowInfo="changeWorkFlowInfo" @nextStep="onNextStep"></EditWorkFlow>
|
||||
</div>
|
||||
<div class="edit-workflow" v-show="currentStep===2">
|
||||
<EditWorkFlowVersion @changeEditVersionWorkFlowInfo="changeEditVersionWorkFlowInfo" @stepNext="onNextStep"></EditWorkFlowVersion>
|
||||
</div>
|
||||
<div class="form-content" v-show="currentStep === 3">
|
||||
<div class="uploadImg">
|
||||
<div class="version-item" v-for="(item, index) in editVersionInfo" :key="index">
|
||||
<div>版本名字: {{ item.name }}</div>
|
||||
<div class="version-desc">
|
||||
添加版本实例图片 <span class="required-icon">*</span>
|
||||
</div>
|
||||
<div class="upload-img-container">
|
||||
<div class="upload-img-btn" @click="onUploadImg(index)">上传文件</div>
|
||||
<!-- <div
|
||||
style="
|
||||
font-size: 14px;
|
||||
margin-top: 10px;
|
||||
font-weight: 600;
|
||||
color: rgb(94 94 94);
|
||||
"
|
||||
>
|
||||
建议从图库上传,便于用户画不同款来适用模型效果
|
||||
</div> -->
|
||||
<div class="upload-img-tips">
|
||||
支持格式:.safetensors/.ckpt/.pt/.bin/.path/.gguf/.sft
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="step-group">
|
||||
<div class="step1-group">
|
||||
<div
|
||||
class="step-btn step1"
|
||||
style="background-color: #f1f2f7; color: #000;"
|
||||
@click="onNextStep(2)"
|
||||
>
|
||||
上一步
|
||||
</div>
|
||||
<div class="step-btn step1" @click="onPublish()">发布</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import EditWorkFlow from "@/components/editWorkFlow";
|
||||
import EditWorkFlowVersion from "@/components/editWorkFlowVersion";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
currentStep: 2,
|
||||
editWorkFlowInfo: {},
|
||||
editVersionWorkFlowInfo:{},
|
||||
editVersionInfo: [{ name: "1.1" }, { name: "1.2" }],
|
||||
};
|
||||
},
|
||||
components: {
|
||||
EditWorkFlow,
|
||||
EditWorkFlowVersion
|
||||
},
|
||||
methods: {
|
||||
changeEditVersionWorkFlowInfo(info){
|
||||
this.editVersionWorkFlowInfo = info;
|
||||
|
||||
},
|
||||
changeWorkFlowInfo(info) {
|
||||
this.editWorkFlowInfo = info;
|
||||
},
|
||||
onNextStep(index) {
|
||||
this.currentStep = index;
|
||||
},
|
||||
onPublish(){}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.container {
|
||||
padding: 20px;
|
||||
.edit-workflow{
|
||||
margin: 0 80px
|
||||
}
|
||||
.form-content {
|
||||
margin: 10px 80px;
|
||||
padding: 20px 10px;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
.uploadImg {
|
||||
font-size: 16px;
|
||||
.version-item {
|
||||
background-color: #f4f5f9;
|
||||
padding: 20px;
|
||||
margin: 20px 0;
|
||||
border-radius: 10px;
|
||||
.version-desc {
|
||||
font-size: 14px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.required-icon {
|
||||
color: red;
|
||||
}
|
||||
.upload-img-container {
|
||||
margin-top: 10px;
|
||||
width: 100%;
|
||||
height: 150px;
|
||||
border: 1px dashed #ccc;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
background-color: #fff;
|
||||
border-radius: 10px;
|
||||
.upload-img-btn {
|
||||
padding: 4px 20px;
|
||||
text-align: center;
|
||||
background-color: rgb(45, 40, 255);
|
||||
color: #fff;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.upload-img-tips {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.step-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.step-btn {
|
||||
width: 200px;
|
||||
height: 40px;
|
||||
margin-right: 20px;
|
||||
text-align: center;
|
||||
line-height: 40px;
|
||||
}
|
||||
.step1-group {
|
||||
display: flex;
|
||||
background-color: blue;
|
||||
border-radius: 4px;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -36,7 +36,10 @@ module.exports = {
|
|||
proxy: {
|
||||
// detail: https://cli.vuejs.org/config/#devserver-proxy
|
||||
[process.env.VUE_APP_BASE_API]: {
|
||||
target: `http://1.13.246.108:8080`,
|
||||
// target: `https://702bc39c.r27.cpolar.top`,
|
||||
// 192.168.1.69 海洋
|
||||
//192.168.2.22 代
|
||||
target: `http://192.168.2.22:8080`,
|
||||
changeOrigin: true,
|
||||
pathRewrite: {
|
||||
['^' + process.env.VUE_APP_BASE_API]: ''
|
||||
|
@ -59,6 +62,15 @@ module.exports = {
|
|||
'@': resolve('src')
|
||||
}
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.js$/,
|
||||
loader: 'babel-loader',
|
||||
exclude: /node_modules\/(?!quill)/, // 排除 node_modules,但包含 quill
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
// http://doc.ruoyi.vip/ruoyi-vue/other/faq.html#使用gzip解压缩静态文件
|
||||
new CompressionPlugin({
|
||||
|
|