micro fixs, update database SQL file

This commit is contained in:
RockYang
2024-12-27 17:02:27 +08:00
parent 2ba3c52e6e
commit 488169683f
25 changed files with 1190 additions and 329 deletions

View File

@@ -29,12 +29,11 @@
color:var(--text-theme-color)
}
img{
width 40px
height: 40px
height: 44px
object-fit: cover
border-radius: 50%
padding: 4px
border: 2px solid #754ff6;
background: #fff
}
.marr{
margin-right: 4px;
@@ -119,6 +118,7 @@
// margin-bottom: 10px;
margin: 0 8px 8px;
cursor: pointer;
font-weight: 550;
&:hover{
.el-icon{
background: rgba(79, 89, 102, .122);
@@ -140,7 +140,7 @@
}
&.active{
color: var(--text-color);
font-weight: 600;
font-weight: 700;
filter: none !important;
.el-icon{
background: rgba(79, 89, 102, .122);

View File

@@ -71,9 +71,9 @@
.logo {
height 60px
width 60px
border-radius 50%
background: var(--theme-bg)
background: #fff
border: 2px solid #754ff6
}
.el-button {

View File

@@ -1,4 +1,3 @@
.loginPage{
background: var(--card-bg) !important
background-color: var(---card-bg) !important
@@ -54,9 +53,10 @@
width: 306px;
margin-right: 9px;
}
:deep(.el-tabs__item.is-active, .el-tabs__item:hover){
color: var(--common-text-color) !important;
}
.el-tabs__item{
color:var( --text-theme-color)
}
:deep(.el-tabs__item.is-active), :deep(.el-tabs__item:hover) {
color: var(--common-text-color) !important
}
:deep(.el-tabs__item) {
color: var(--text-theme-color)
}

View File

@@ -3,20 +3,8 @@
<a class="file-upload-img" @click="fetchFiles(1)">
<i class="iconfont icon-attachment-st"></i>
</a>
<el-dialog
class="file-list-dialog"
v-model="show"
:close-on-click-modal="true"
:show-close="true"
:width="800"
title="文件管理"
>
<el-scrollbar
ref="scrollbarRef"
max-height="80vh"
style="height: 100%"
@scroll="onScroll"
>
<el-dialog class="file-list-dialog" v-model="show" :close-on-click-modal="true" :show-close="true" :width="800" title="文件管理">
<el-scrollbar ref="scrollbarRef" max-height="80vh" style="height: 100%" @scroll="onScroll">
<div class="file-list">
<el-row :gutter="20">
<el-col :span="3">
@@ -36,43 +24,18 @@
</el-col>
<el-col :span="3" v-for="file in fileData.items" :key="file.url">
<div class="grid-content">
<el-tooltip
class="box-item"
effect="dark"
:content="file.name"
placement="top"
>
<el-image
:src="file.url"
fit="cover"
v-if="isImage(file.ext)"
@click="insertURL(file)"
/>
<el-image
:src="GetFileIcon(file.ext)"
fit="cover"
v-else
@click="insertURL(file)"
/>
<el-tooltip class="box-item" effect="dark" :content="file.name" placement="top">
<el-image :src="file.url" fit="cover" v-if="isImage(file.ext)" @click="insertURL(file)" />
<el-image :src="GetFileIcon(file.ext)" fit="cover" v-else @click="insertURL(file)" />
</el-tooltip>
<div class="opt">
<el-button
type="danger"
size="small"
:icon="Delete"
@click="removeFile(file)"
circle
/>
<el-button type="danger" size="small" :icon="Delete" @click="removeFile(file)" circle />
</div>
</div>
</el-col>
</el-row>
<el-row
justify="center"
v-if="!fileData.isLastPage"
@click="fetchFiles(fileData.page)"
>
<el-row justify="center" v-if="!fileData.isLastPage" @click="fetchFiles(fileData.page)">
<el-link>加载更多</el-link>
</el-row>
</div>
@@ -88,9 +51,10 @@ import { httpGet, httpPost } from "@/utils/http";
import { Delete, Plus } from "@element-plus/icons-vue";
import { isImage, removeArrayItem } from "@/utils/libs";
import { GetFileIcon } from "@/store/system";
import { checkSession } from "@/store/cache";
import { useSharedStore } from "@/store/sharedata";
const props = defineProps({
userId: Number
userId: Number,
});
const emits = defineEmits(["selected"]);
const show = ref(false);
@@ -98,28 +62,37 @@ const scrollbarRef = ref(null);
const fileData = reactive({
items: [],
page: 1,
isLastPage: true
isLastPage: true,
});
const store = useSharedStore();
const fetchFiles = (pageNo) => {
if (pageNo === 1) show.value = true;
httpPost("/api/upload/list", { page: pageNo || 1, page_size: 30 })
.then((res) => {
const { items, page, total_page } = res.data;
checkSession()
.then(() => {
show.value = true;
httpPost("/api/upload/list", { page: pageNo || 1, page_size: 30 })
.then((res) => {
const { items, page, total_page } = res.data;
if (page === 1) {
fileData.items = items;
} else {
fileData.items = [...fileData.items, ...items];
}
if (page === 1) {
fileData.items = items;
} else {
fileData.items = [...fileData.items, ...items];
}
fileData.isLastPage = page === total_page;
fileData.isLastPage = page === total_page;
if (!fileData.isLastPage) {
fileData.page = page + 1;
}
if (!fileData.isLastPage) {
fileData.page = page + 1;
}
})
.catch((e) => {
showMessageError("获取文件列表失败:" + e.message);
});
})
.catch(() => {});
.catch(() => {
store.setShowLoginDialog(true);
});
};
// el-scrollbar 滚动回调

View File

@@ -1,5 +1,5 @@
<template>
<div class="login-dialog w-full p-8">
<div class="login-dialog w-full">
<div class="login-box" v-if="login">
<el-form :model="data" class="form">
<div class="block">
@@ -292,10 +292,10 @@ const submit = (verifyData) => {
// 登录操作
const submitLogin = () => {
if (data.value.username === "") {
if (!data.value.username) {
return ElMessage.error("请输入用户名");
}
if (data.value.password === "") {
if (!data.value.password) {
return ElMessage.error("请输入密码");
}
if (enableVerify.value) {

View File

@@ -1,66 +1,29 @@
<template>
<el-dialog
class="config-dialog"
v-model="showDialog"
:close-on-click-modal="true"
:before-close="close"
style="max-width: 600px"
title="账户信息"
>
<div class="user-info" id="user-info">
<el-form v-if="user.id" :model="user" label-width="150px">
<el-form-item label="账户">
<span>{{ user.username }}</span>
</el-form-item>
<el-form-item label="剩余算力">
<el-tag>{{ user['power'] }}</el-tag>
</el-form-item>
<el-form-item label="会员到期时间" v-if="user['expired_time'] > 0">
<el-tag type="danger">{{ dateFormat(user['expired_time']) }}</el-tag>
</el-form-item>
</el-form>
<el-dialog class="config-dialog" v-model="showDialog" :close-on-click-modal="true" :before-close="close" style="max-width: 400px" title="账户信息">
<div class="flex-center-col p-4 pt-0" id="user-info">
<user-profile @hide="close" />
</div>
</el-dialog>
</template>
<script setup>
import {computed, onMounted, ref} from "vue"
import {httpGet} from "@/utils/http";
import {ElMessage} from "element-plus";
import {dateFormat} from "@/utils/libs";
import { computed } from "vue";
import UserProfile from "@/components/UserProfile.vue";
// eslint-disable-next-line no-undef
const props = defineProps({
show: Boolean,
user: Object,
models: Array,
});
const showDialog = computed(() => {
return props.show
})
const user = ref({
username: '',
nickname: '',
avatar: '',
calls: 0,
tokens: 0,
})
onMounted(() => {
// 获取最新用户信息
httpGet('/api/user/profile').then(res => {
user.value = res.data
}).catch(e => {
ElMessage.error("获取用户信息失败:" + e.message)
});
})
return props.show;
});
// eslint-disable-next-line no-undef
const emits = defineEmits(['hide']);
const emits = defineEmits(["hide"]);
const close = function () {
emits('hide', false);
}
emits("hide", false);
};
</script>
<style lang="stylus">
@@ -68,23 +31,6 @@ const close = function () {
.el-dialog {
--el-dialog-width 90%;
max-width 800px;
.el-dialog__body {
overflow-y auto;
.user-info {
position relative;
.el-message {
position: absolute;
}
}
.tip {
color #c1c1c1
font-size 12px;
}
}
}
}
</style>
</style>

View File

@@ -1,20 +1,11 @@
<template>
<div class="user-info" id="user-info">
<el-form :model="user" label-width="100px">
<div class="user-info flex-center-col" id="user-info">
<el-form :model="user" label-width="80px" label-position="left">
<el-row>
<el-upload
class="avatar-uploader"
:auto-upload="true"
:show-file-list="false"
:http-request="afterRead"
accept=".png,.jpg,.jpeg,.bmp"
>
<el-avatar
v-if="user.avatar"
:src="user.avatar"
shape="circle"
:size="100"
/>
<el-upload class="avatar-uploader" :auto-upload="true" :show-file-list="false" :http-request="afterRead" accept=".png,.jpg,.jpeg,.bmp">
<el-tooltip content="点击上传头像" placement="top" v-if="user.avatar">
<el-avatar :src="user.avatar" shape="circle" :size="100" />
</el-tooltip>
<el-icon v-else class="avatar-uploader-icon">
<Plus />
</el-icon>
@@ -26,22 +17,14 @@
<el-form-item label="账号">
<div class="flex">
<span>{{ user.username }}</span>
<el-tooltip
class="box-item"
content="您已经是 VIP 会员"
placement="right"
>
<span class="vip-icon"
><el-image
v-if="user.vip"
:src="vipImg"
style="height: 25px; margin-left: 10px"
/></span>
<el-tooltip class="box-item" content="您已经是 VIP 会员" placement="right">
<span class="vip-icon"><el-image v-if="user.vip" :src="vipImg" class="rounded-full ml-1 size-5" /></span>
</el-tooltip>
</div>
</el-form-item>
<el-form-item label="剩余算力">
<el-text type="warning">{{ user["power"] }}</el-text>
<el-tag type="info" size="small" class="ml-2 cursor-pointer" @click="gotoLog">算力日志</el-tag>
</el-form-item>
<el-form-item label="会员到期时间" v-if="user['expired_time'] > 0">
<el-tag type="danger">{{ dateFormat(user["expired_time"]) }}</el-tag>
@@ -62,17 +45,19 @@ import { Plus } from "@element-plus/icons-vue";
import Compressor from "compressorjs";
import { dateFormat } from "@/utils/libs";
import { checkSession } from "@/store/cache";
import { useRouter } from "vue-router";
const user = ref({
vip: false,
username: "演示数据",
nickname: "演示数据",
avatar: "/images/menu/member.png",
mobile: "演示数据",
power: 99999
power: 99999,
});
const vipImg = ref("/images/menu/member.png");
const vipImg = ref("/images/menu/member.png");
const router = useRouter();
const emits = defineEmits(["hide"]);
onMounted(() => {
checkSession()
.then(() => {
@@ -109,7 +94,7 @@ const afterRead = (file) => {
},
error(err) {
console.log(err.message);
}
},
});
};
@@ -122,11 +107,15 @@ const save = () => {
ElMessage.error("更新失败:" + e.message);
});
};
const gotoLog = () => {
router.push("/powerLog");
emits("hide", false);
};
</script>
<style lang="stylus" scoped>
.user-info {
padding 20px 0
.el-row {
justify-content center
@@ -139,7 +128,6 @@ const save = () => {
}
.opt-line {
padding-top 20px
.el-button {
width 100%

View File

@@ -1,7 +1,7 @@
<template>
<div :class="'sidebar ' + theme">
<a class="logo w-full flex items-center" href="/" target="_blank">
<img :src="logo" style="height: 36px" />
<img :src="logo" />
<span class="text" v-show="!sidebar.collapse">{{ title }}</span>
</a>
@@ -213,19 +213,17 @@ setMenuItems(items);
.logo {
display flex
background-color #324157
padding 6px 15px;
cursor pointer
background-color: #324157
.el-image {
width 36px;
img {
height 36px;
padding-top 5px;
border-radius 100%
.el-image__inner {
height 40px
}
background #fff
border 2px solid #754ff6
padding 2px
}
.text {

View File

@@ -128,30 +128,6 @@
<div class="input-box">
<div class="input-box-inner">
<!-- <span class="tool-item" @click="realtimeChat">
<el-tooltip
class="box-item"
effect="dark"
content="实时语音对话"
>
<i class="iconfont icon-mic-bold"></i>
</el-tooltip>
</span> -->
<!-- <span class="tool-item" v-if="isLogin">
<el-tooltip
class="box-item"
effect="dark"
content="上传附件"
>
<file-select
v-if="isLogin"
:user-id="loginUser.id"
@selected="insertFile"
/>
</el-tooltip>
</span> -->
<div class="input-body">
<div ref="textHeightRef" class="hide-div">{{ prompt }}</div>
<div class="input-border">
@@ -172,15 +148,6 @@
</textarea>
</div>
<div class="flex-between">
<!-- <div @click="_newChat" class="flex-center add-new">
<el-tooltip
class="box-item"
effect="dark"
content="新建会话"
>
<el-icon><CirclePlusFilled /></el-icon>
</el-tooltip>
</div> -->
<div class="flex little-btns">
<span class="tool-item-btn" @click="realtimeChat">
<el-tooltip class="box-item" effect="dark" :content="'实时语音对话,每次消耗' + config.advance_voice_power + '算力'">
@@ -188,9 +155,9 @@
</el-tooltip>
</span>
<span class="tool-item-btn" v-if="isLogin">
<span class="tool-item-btn">
<el-tooltip class="box-item" effect="dark" content="上传附件">
<file-select v-if="isLogin" :user-id="loginUser.id" @selected="insertFile" />
<file-select :user-id="loginUser?.id" @selected="insertFile" />
</el-tooltip>
</span>
</div>

View File

@@ -95,7 +95,7 @@
<el-button type="primary" :dark="false" round @click="generate"> 立即生成 </el-button>
</div>
</div>
<div class="task-list-box pl-6 pr-6 pb-4 pt-4">
<div class="task-list-box pl-6 pr-6 pb-4 pt-4 h-dvh">
<div class="task-list-inner" :style="{ height: listBoxHeight + 'px' }">
<div class="job-list-box">
<h2 class="text-xl">任务列表</h2>
@@ -318,6 +318,8 @@ onMounted(() => {
httpGet("/api/dall/models")
.then((res) => {
models.value = res.data;
selectedModel.value = models.value[0];
params.value.model_id = selectedModel.value.id;
})
.catch((e) => {
showMessageError("获取模型列表失败:" + e.message);
@@ -393,9 +395,6 @@ const fetchFinishJobs = () => {
// 创建绘图任务
const promptRef = ref(null);
const generate = () => {
if (!params.value.model_id) {
return ElMessage.error("请选择生图模型!");
}
if (params.value.prompt === "") {
promptRef.value.focus();
return ElMessage.error("请输入绘画提示词!");

View File

@@ -82,9 +82,6 @@
</template>
<template #default>
<ul class="more-menus setting-menus">
<li>
<img :src="loginUser.avatar ? loginUser.avatar : avatarImg" />
</li>
<li>
<div @click="showConfigDialog = true" class="flex">
<el-icon>
@@ -207,11 +204,11 @@ watch(
}
);
// 监听路由变化
// router.beforeEach((to, from, next) => {
// curPath.value = to.path;
// next();
// });
// 监听路由变化;
router.beforeEach((to, from, next) => {
curPath.value = to.path;
next();
});
if (curPath.value === "/external") {
curPath.value = router.currentRoute.value.query.url;

View File

@@ -151,7 +151,7 @@
</el-form>
</div>
</div>
<div class="task-list-box pl-6 pr-6 pb-4">
<div class="task-list-box pl-6 pr-6 pb-4 h-dvh">
<div class="task-list-inner" :style="{ height: listBoxHeight + 'px' }">
<div class="extra-params">
<el-form>

View File

@@ -235,7 +235,7 @@
<el-button type="primary" :dark="false" round @click="generate">立即生成</el-button>
</div>
</div>
<div class="task-list-box pl-6 pr-6 pb-4 pt-4">
<div class="task-list-box pl-6 pr-6 pb-4 pt-4 h-dvh">
<div class="task-list-inner" :style="{ height: listBoxHeight + 'px' }">
<div class="job-list-box">
<h2 class="text-xl">任务列表</h2>

View File

@@ -5,8 +5,7 @@
<div class="menu-box">
<el-menu mode="horizontal" :ellipsis="false">
<div class="menu-item">
<!-- <el-image :src="logo" class="logo" alt="Geek-AI" /> -->
<img :src="logo" class="logo" alt="" />
<img :src="logo" class="logo" alt="Geek-AI" />
</div>
<div class="menu-item">
<span v-if="!license.de_copy">

View File

@@ -54,8 +54,6 @@ import Captcha from "@/components/Captcha.vue";
const router = useRouter();
const title = ref("Geek-AI");
const username = ref(process.env.VUE_APP_USER);
const password = ref(process.env.VUE_APP_PASS);
const logo = ref("");
const licenseConfig = ref({});
@@ -132,8 +130,8 @@ const login = async function () {
const store = useSharedStore();
const doLogin = (verifyData) => {
httpPost("/api/user/login", {
username: username.value,
password: password.value,
username: ruleForm.username,
password: ruleForm.password,
key: verifyData.key,
dots: verifyData.dots,
x: verifyData.x,

View File

@@ -78,6 +78,10 @@
<div class="wechat-card">
<el-image :src="wxImg" />
</div>
<div class="mt-3">
<el-button type="primary" @click="router.push('/')"><i class="iconfont icon-home mr-1"></i> 返回首页</el-button>
</div>
</template>
</el-result>
</div>

View File

@@ -1,6 +1,5 @@
<template>
<!-- :style="{ height: winHeight + 'px' }" -->
<div class="page-suno" :style="{ height: winHeight + 'px' }">
<div class="page-suno">
<div class="left-bar">
<div class="bar-top">
<el-tooltip content="定义模式" placement="top">
@@ -135,7 +134,7 @@
</div>
</div>
</div>
<div class="right-box" v-loading="loading" element-loading-background="rgba(100,100,100,0.3)">
<div class="right-box h-dvh" v-loading="loading" element-loading-background="rgba(100,100,100,0.3)">
<div class="list-box" v-if="!noData">
<div v-for="item in list" :key="item.id">
<div class="item" v-if="item.progress === 100">
@@ -289,9 +288,6 @@ import Compressor from "compressorjs";
import Generating from "@/components/ui/Generating.vue";
import { useSharedStore } from "@/store/sharedata";
// const winHeight = ref(window.innerHeight - 50);
const winHeight = ref(window.innerHeight - 20);
const custom = ref(false);
const models = ref([
{ label: "v3.0", value: "chirp-v3-0" },

View File

@@ -209,7 +209,7 @@
签到赠送算力
<el-tooltip effect="dark" content="每日签到赠送算力" raw-content placement="right">
<el-icon>
<InfoFilled/>
<InfoFilled />
</el-icon>
</el-tooltip>
</div>
@@ -249,10 +249,9 @@
<template #label>
<div class="label-title">
MJ操作算力
<el-tooltip effect="dark" content="主要用户函数调用 DALL-E-3 进行绘画" raw-content
placement="right">
<el-tooltip effect="dark" content="主要用户函数调用 DALL-E-3 进行绘画" raw-content placement="right">
<el-icon>
<InfoFilled/>
<InfoFilled />
</el-icon>
</el-tooltip>
</div>
@@ -388,7 +387,9 @@
<!-- <el-text type="danger">请注意在修复数据前请先备份好数据库以免数据丢失</el-text>-->
<p><el-button type="primary" @click="fixData">立即修复</el-button></p>
<div class="mt-3">
<el-button type="primary" @click="fixData">立即修复</el-button>
</div>
</div>
</el-tab-pane>
</el-tabs>
@@ -396,17 +397,17 @@
</template>
<script setup>
import {onMounted, reactive, ref} from "vue";
import {httpGet, httpPost} from "@/utils/http";
import { onMounted, reactive, ref } from "vue";
import { httpGet, httpPost } from "@/utils/http";
import Compressor from "compressorjs";
import {ElMessage, ElMessageBox} from "element-plus";
import {CloseBold, InfoFilled, Select, UploadFilled} from "@element-plus/icons-vue";
import { ElMessage, ElMessageBox } from "element-plus";
import { CloseBold, InfoFilled, Select, UploadFilled } from "@element-plus/icons-vue";
import MdEditor from "md-editor-v3";
import "md-editor-v3/lib/style.css";
import Menu from "@/views/admin/Menu.vue";
import {copyObj, dateFormat} from "@/utils/libs";
import { copyObj, dateFormat } from "@/utils/libs";
import ItemsInput from "@/components/ui/ItemsInput.vue";
import {useSharedStore} from "@/store/sharedata";
import { useSharedStore } from "@/store/sharedata";
const activeName = ref("basic");
const system = ref({ models: [] });

View File

@@ -2,7 +2,9 @@
<div class="login flex w-full flex-col place-content-center h-lvh">
<el-image src="/images/logo.png" class="w-1/2 mx-auto logo" />
<div class="title text-center text-3xl font-bold mt-8">{{ title }}</div>
<login-dialog @success="loginSuccess" />
<div class="w-full p-8">
<login-dialog @success="loginSuccess" />
</div>
</div>
</template>

View File

@@ -152,11 +152,22 @@ const qualities = [
{ text: "标准", value: "standard" },
{ text: "高清", value: "hd" },
];
const sizes = [
const fluxSizes = [
{ text: "1024x1024", value: "1024x1024" },
{ text: "1024x768", value: "1024x768" },
{ text: "768x1024", value: "768x1024" },
{ text: "1280x960", value: "1280x960" },
{ text: "960x1280", value: "960x1280" },
{ text: "1366x768", value: "1366x768" },
{ text: "768x1366", value: "768x1366" },
];
const dalleSizes = [
{ text: "1024x1024", value: "1024x1024" },
{ text: "1792x1024", value: "1792x1024" },
{ text: "1024x1792", value: "1024x1792" },
];
let sizes = dalleSizes;
const styles = [
{ text: "生动", value: "vivid" },
{ text: "自然", value: "natural" },
@@ -223,7 +234,7 @@ onMounted(() => {
httpGet("/api/dall/models")
.then((res) => {
for (let i = 0; i < res.data.length; i++) {
models.value.push({ text: res.data[i].name, value: res.data[i].id });
models.value.push({ text: res.data[i].name, value: res.data[i].id, name: res.data[i].value });
}
selectedModel.value = models.value[0]?.text;
params.value.model_id = models.value[0]?.value;
@@ -415,6 +426,11 @@ const modelConfirm = (item) => {
params.value.model_id = item.selectedOptions[0].value;
selectedModel.value = item.selectedOptions[0].text;
showModelPicker.value = false;
if (item.selectedOptions[0].name.startsWith("dall")) {
sizes = dalleSizes;
} else {
sizes = fluxSizes;
}
};
</script>