mirror of
https://github.com/yangjian102621/geekai.git
synced 2025-09-18 01:06:39 +08:00
feat: change theme for mobile site is ready
This commit is contained in:
parent
51a8f42d89
commit
1ba08bbfa6
@ -7,8 +7,12 @@
|
|||||||
* 功能优化:优化首页登录注册页面的 UI
|
* 功能优化:优化首页登录注册页面的 UI
|
||||||
* BUG修复:修复License验证的逻辑漏洞
|
* BUG修复:修复License验证的逻辑漏洞
|
||||||
* Bug修复:后台添加用户的时候密码规则限制跟前台注册保持一致
|
* Bug修复:后台添加用户的时候密码规则限制跟前台注册保持一致
|
||||||
* 功能新增:管理后台支持切换主题,支持 light 和 dark 模式
|
* 功能新增:管理后台支持切换主题,支持 light 和 dark 两种主题
|
||||||
* 功能新增:移动端新增 DALL-E 绘画功能
|
* 功能新增:移动端新增 DALL-E 绘画功能
|
||||||
|
* 功能新增:新增移动端首页功能,移动端支持 light 和 dark 两种主题
|
||||||
|
* 功能新增:移动支持免登录预览功能
|
||||||
|
* Bug修复:解决在同一个浏览器开启多个对话时候对话内容会相互乱串的问题
|
||||||
|
* Bug修复:修复部分中转 API 模型会出现第一输出的字符被淹没的Bug
|
||||||
|
|
||||||
## v4.0.4
|
## v4.0.4
|
||||||
|
|
||||||
|
@ -5,7 +5,6 @@ const LoginUserCache = "LOGIN_USER_CACHE"
|
|||||||
|
|
||||||
const UserAuthHeader = "Authorization"
|
const UserAuthHeader = "Authorization"
|
||||||
const AdminAuthHeader = "Admin-Authorization"
|
const AdminAuthHeader = "Admin-Authorization"
|
||||||
const ChatTokenHeader = "Chat-Token"
|
|
||||||
|
|
||||||
// Session configs struct
|
// Session configs struct
|
||||||
type Session struct {
|
type Session struct {
|
||||||
|
@ -139,6 +139,7 @@ func (h *ChatHandler) ChatHandle(c *gin.Context) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
client.Close()
|
client.Close()
|
||||||
h.App.ChatClients.Delete(sessionId)
|
h.App.ChatClients.Delete(sessionId)
|
||||||
|
h.App.ChatSession.Delete(sessionId)
|
||||||
cancelFunc := h.App.ReqCancelFunc.Get(sessionId)
|
cancelFunc := h.App.ReqCancelFunc.Get(sessionId)
|
||||||
if cancelFunc != nil {
|
if cancelFunc != nil {
|
||||||
cancelFunc()
|
cancelFunc()
|
||||||
|
@ -115,11 +115,8 @@ func (h *ChatHandler) sendOpenAiMessage(
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
// 初始化 role
|
// output stopped
|
||||||
if responseBody.Choices[0].Delta.Role != "" && message.Role == "" {
|
if responseBody.Choices[0].FinishReason != "" {
|
||||||
message.Role = responseBody.Choices[0].Delta.Role
|
|
||||||
continue
|
|
||||||
} else if responseBody.Choices[0].FinishReason != "" {
|
|
||||||
break // 输出完成或者输出中断了
|
break // 输出完成或者输出中断了
|
||||||
} else {
|
} else {
|
||||||
content := responseBody.Choices[0].Delta.Content
|
content := responseBody.Choices[0].Delta.Content
|
||||||
|
@ -232,18 +232,10 @@ func (h *UserHandler) Login(c *gin.Context) {
|
|||||||
|
|
||||||
// Logout 注 销
|
// Logout 注 销
|
||||||
func (h *UserHandler) Logout(c *gin.Context) {
|
func (h *UserHandler) Logout(c *gin.Context) {
|
||||||
sessionId := c.GetHeader(types.ChatTokenHeader)
|
|
||||||
key := h.GetUserKey(c)
|
key := h.GetUserKey(c)
|
||||||
if _, err := h.redis.Del(c, key).Result(); err != nil {
|
if _, err := h.redis.Del(c, key).Result(); err != nil {
|
||||||
logger.Error("error with delete session: ", err)
|
logger.Error("error with delete session: ", err)
|
||||||
}
|
}
|
||||||
// 删除 websocket 会话列表
|
|
||||||
h.App.ChatSession.Delete(sessionId)
|
|
||||||
// 关闭 socket 连接
|
|
||||||
client := h.App.ChatClients.Get(sessionId)
|
|
||||||
if client != nil {
|
|
||||||
client.Close()
|
|
||||||
}
|
|
||||||
resp.SUCCESS(c)
|
resp.SUCCESS(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
"markmap-lib": "^0.16.1",
|
"markmap-lib": "^0.16.1",
|
||||||
"markmap-view": "^0.16.0",
|
"markmap-view": "^0.16.0",
|
||||||
"md-editor-v3": "^2.2.1",
|
"md-editor-v3": "^2.2.1",
|
||||||
|
"mitt": "^3.0.1",
|
||||||
"pinia": "^2.1.4",
|
"pinia": "^2.1.4",
|
||||||
"qrcode": "^1.5.3",
|
"qrcode": "^1.5.3",
|
||||||
"qs": "^6.11.1",
|
"qs": "^6.11.1",
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
.rate {
|
.rate {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content center
|
justify-content center
|
||||||
background-color #f5f5f5
|
background-color var(--van-background-3)
|
||||||
padding 5px 10px
|
padding 5px 10px
|
||||||
margin 5px 0
|
margin 5px 0
|
||||||
border-radius 5px
|
border-radius 5px
|
||||||
@ -24,14 +24,14 @@
|
|||||||
|
|
||||||
.text {
|
.text {
|
||||||
text-align center
|
text-align center
|
||||||
color #555555
|
color var(--van-text-color)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.model {
|
.model {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content center
|
justify-content center
|
||||||
background-color #f5f5f5
|
background-color var(--van-background-3)
|
||||||
padding 6px
|
padding 6px
|
||||||
margin 5px 0
|
margin 5px 0
|
||||||
border-radius 5px
|
border-radius 5px
|
||||||
@ -48,12 +48,12 @@
|
|||||||
|
|
||||||
.text {
|
.text {
|
||||||
text-align center
|
text-align center
|
||||||
color #555555
|
color var(--van-text-color)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.active {
|
.active {
|
||||||
background-color #e5e5e5
|
background-color var(--van-text-color-3)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import 'vant/lib/index.css';
|
|||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
import {createPinia} from "pinia";
|
import {createPinia} from "pinia";
|
||||||
import {
|
import {
|
||||||
|
ActionSheet,
|
||||||
Badge,
|
Badge,
|
||||||
Button,
|
Button,
|
||||||
Cell,
|
Cell,
|
||||||
@ -14,7 +15,8 @@ import {
|
|||||||
Collapse,
|
Collapse,
|
||||||
CollapseItem,
|
CollapseItem,
|
||||||
ConfigProvider,
|
ConfigProvider,
|
||||||
Dialog, Divider,
|
Dialog,
|
||||||
|
Divider,
|
||||||
DropdownItem,
|
DropdownItem,
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
Empty,
|
Empty,
|
||||||
@ -28,7 +30,8 @@ import {
|
|||||||
Lazyload,
|
Lazyload,
|
||||||
List,
|
List,
|
||||||
Loading,
|
Loading,
|
||||||
NavBar, NoticeBar,
|
NavBar,
|
||||||
|
NoticeBar,
|
||||||
Notify,
|
Notify,
|
||||||
Overlay,
|
Overlay,
|
||||||
Picker,
|
Picker,
|
||||||
@ -52,8 +55,8 @@ import {router} from "@/router";
|
|||||||
import 'v3-waterfall/dist/style.css'
|
import 'v3-waterfall/dist/style.css'
|
||||||
import V3waterfall from "v3-waterfall";
|
import V3waterfall from "v3-waterfall";
|
||||||
|
|
||||||
const app = createApp(App)
|
const app = createApp(App);
|
||||||
app.use(createPinia())
|
app.use(createPinia());
|
||||||
app.use(ConfigProvider);
|
app.use(ConfigProvider);
|
||||||
app.use(Tabbar);
|
app.use(Tabbar);
|
||||||
app.use(TabbarItem);
|
app.use(TabbarItem);
|
||||||
@ -99,6 +102,7 @@ app.use(Tab);
|
|||||||
app.use(Tabs);
|
app.use(Tabs);
|
||||||
app.use(Divider);
|
app.use(Divider);
|
||||||
app.use(NoticeBar);
|
app.use(NoticeBar);
|
||||||
|
app.use(ActionSheet);
|
||||||
app.use(router).use(ElementPlus).mount('#app')
|
app.use(router).use(ElementPlus).mount('#app')
|
||||||
|
|
||||||
|
|
||||||
|
6
web/src/store/eventbus.js
Normal file
6
web/src/store/eventbus.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
// 导入mitt包
|
||||||
|
import mitt from 'mitt'
|
||||||
|
// 创建EventBus实例对象
|
||||||
|
const bus = mitt()
|
||||||
|
// 共享出eventbus的实例对象
|
||||||
|
export default bus
|
@ -5,25 +5,11 @@ import Storage from "good-storage";
|
|||||||
* storage handler
|
* storage handler
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const SessionIDKey = process.env.VUE_APP_KEY_PREFIX + 'SESSION_ID';
|
|
||||||
const UserTokenKey = process.env.VUE_APP_KEY_PREFIX + "Authorization";
|
const UserTokenKey = process.env.VUE_APP_KEY_PREFIX + "Authorization";
|
||||||
const AdminTokenKey = process.env.VUE_APP_KEY_PREFIX + "Admin-Authorization"
|
const AdminTokenKey = process.env.VUE_APP_KEY_PREFIX + "Admin-Authorization"
|
||||||
|
|
||||||
export function getSessionId() {
|
export function getSessionId() {
|
||||||
let sessionId = Storage.get(SessionIDKey)
|
return randString(42)
|
||||||
if (!sessionId) {
|
|
||||||
sessionId = randString(42)
|
|
||||||
setSessionId(sessionId)
|
|
||||||
}
|
|
||||||
return sessionId
|
|
||||||
}
|
|
||||||
|
|
||||||
export function removeSessionId() {
|
|
||||||
Storage.remove(SessionIDKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setSessionId(sessionId) {
|
|
||||||
Storage.set(SessionIDKey, sessionId)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getUserToken() {
|
export function getUserToken() {
|
||||||
|
@ -286,7 +286,7 @@ const notice = ref("")
|
|||||||
const noticeKey = ref("SYSTEM_NOTICE")
|
const noticeKey = ref("SYSTEM_NOTICE")
|
||||||
|
|
||||||
if (isMobile()) {
|
if (isMobile()) {
|
||||||
router.replace("/mobile")
|
router.replace("/mobile/chat")
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取系统配置
|
// 获取系统配置
|
||||||
|
@ -760,6 +760,7 @@ onMounted(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
|
clipboard.value.destroy()
|
||||||
socket.value = null
|
socket.value = null
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<van-config-provider :theme="getMobileTheme()">
|
<van-config-provider :theme="theme">
|
||||||
<div class="mobile-home">
|
<div class="mobile-home">
|
||||||
<router-view/>
|
<router-view/>
|
||||||
|
|
||||||
<van-tabbar route v-model="active" @change="onChange">
|
<van-tabbar route v-model="active">
|
||||||
<van-tabbar-item to="/mobile/index" name="home" icon="home-o">首页</van-tabbar-item>
|
<van-tabbar-item to="/mobile/index" name="home" icon="home-o">首页</van-tabbar-item>
|
||||||
<van-tabbar-item to="/mobile/chat" name="chat" icon="chat-o">对话</van-tabbar-item>
|
<van-tabbar-item to="/mobile/chat" name="chat" icon="chat-o">对话</van-tabbar-item>
|
||||||
<van-tabbar-item to="/mobile/image" name="image" icon="photo-o">绘图</van-tabbar-item>
|
<van-tabbar-item to="/mobile/image" name="image" icon="photo-o">绘图</van-tabbar-item>
|
||||||
<van-tabbar-item to="/mobile/profile" name="profile" icon="user-o">我的</van-tabbar-item>
|
<van-tabbar-item to="/mobile/profile" name="profile" icon="user-o">我的
|
||||||
|
</van-tabbar-item>
|
||||||
</van-tabbar>
|
</van-tabbar>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -17,9 +18,10 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import {ref} from "vue";
|
import {ref} from "vue";
|
||||||
import {getMobileTheme} from "@/store/system";
|
import {getMobileTheme, setMobileTheme} from "@/store/system";
|
||||||
import {useRouter} from "vue-router";
|
import {useRouter} from "vue-router";
|
||||||
import {isMobile} from "@/utils/libs";
|
import {isMobile} from "@/utils/libs";
|
||||||
|
import bus from '@/store/eventbus'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
if (!isMobile()) {
|
if (!isMobile()) {
|
||||||
@ -27,9 +29,12 @@ if (!isMobile()) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const active = ref('home')
|
const active = ref('home')
|
||||||
const onChange = (index) => {
|
const theme = ref(getMobileTheme())
|
||||||
console.log(index)
|
|
||||||
}
|
bus.on('changeTheme', (value) => {
|
||||||
|
theme.value = value
|
||||||
|
setMobileTheme(theme.value)
|
||||||
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
<van-field label="有效期" v-if="form.expired_time > 0">
|
<van-field label="有效期" v-if="form.expired_time > 0">
|
||||||
<template #input>
|
<template #input>
|
||||||
<van-tag type="warning">{{ dateFormat(form.expired_time) }}</van-tag>
|
{{ dateFormat(form.expired_time) }}
|
||||||
</template>
|
</template>
|
||||||
</van-field>
|
</van-field>
|
||||||
|
|
||||||
@ -39,11 +39,15 @@
|
|||||||
|
|
||||||
<div class="opt" v-if="isLogin">
|
<div class="opt" v-if="isLogin">
|
||||||
<van-row :gutter="10">
|
<van-row :gutter="10">
|
||||||
<van-col :span="12">
|
<van-col :span="8">
|
||||||
<van-button round block type="primary" @click="showPasswordDialog = true">修改密码</van-button>
|
<van-button round block @click="showPasswordDialog = true" size="small">修改密码</van-button>
|
||||||
</van-col>
|
</van-col>
|
||||||
<van-col :span="12">
|
<van-col :span="8">
|
||||||
<van-button round block @click="logout">退出登录</van-button>
|
<van-button round block @click="logout" size="small">退出登录</van-button>
|
||||||
|
</van-col>
|
||||||
|
|
||||||
|
<van-col :span="8">
|
||||||
|
<van-button round block @click="showSettings = true" icon="setting" size="small">设置</van-button>
|
||||||
</van-col>
|
</van-col>
|
||||||
</van-row>
|
</van-row>
|
||||||
</div>
|
</div>
|
||||||
@ -114,6 +118,34 @@
|
|||||||
</van-cell-group>
|
</van-cell-group>
|
||||||
</van-form>
|
</van-form>
|
||||||
</van-dialog>
|
</van-dialog>
|
||||||
|
|
||||||
|
<van-action-sheet v-model:show="showSettings" title="用户设置">
|
||||||
|
<div class="setting-content">
|
||||||
|
<van-form>
|
||||||
|
<van-cell-group inset>
|
||||||
|
<van-field name="switch" label="暗黑主题">
|
||||||
|
<template #input>
|
||||||
|
<van-switch v-model="dark" @change="changeTheme"/>
|
||||||
|
</template>
|
||||||
|
</van-field>
|
||||||
|
<!-- <van-field-->
|
||||||
|
<!-- v-model="password"-->
|
||||||
|
<!-- type="password"-->
|
||||||
|
<!-- name="密码"-->
|
||||||
|
<!-- label="密码"-->
|
||||||
|
<!-- placeholder="密码"-->
|
||||||
|
<!-- :rules="[{ required: true, message: '请填写密码' }]"-->
|
||||||
|
<!-- />-->
|
||||||
|
</van-cell-group>
|
||||||
|
<!-- <div style="margin: 16px;">-->
|
||||||
|
<!-- <van-button round block type="primary" native-type="submit">-->
|
||||||
|
<!-- 提交-->
|
||||||
|
<!-- </van-button>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
</van-form>
|
||||||
|
</div>
|
||||||
|
</van-action-sheet>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -127,6 +159,8 @@ import {ElMessage} from "element-plus";
|
|||||||
import {checkSession} from "@/action/session";
|
import {checkSession} from "@/action/session";
|
||||||
import {useRouter} from "vue-router";
|
import {useRouter} from "vue-router";
|
||||||
import {removeUserToken} from "@/store/session";
|
import {removeUserToken} from "@/store/session";
|
||||||
|
import bus from '@/store/eventbus'
|
||||||
|
import {getMobileTheme} from "@/store/system";
|
||||||
|
|
||||||
const form = ref({
|
const form = ref({
|
||||||
username: 'GeekMaster',
|
username: 'GeekMaster',
|
||||||
@ -148,6 +182,7 @@ const payWays = ref({})
|
|||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const userId = ref(0)
|
const userId = ref(0)
|
||||||
const isLogin = ref(false)
|
const isLogin = ref(false)
|
||||||
|
const showSettings = ref(false)
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
checkSession().then(user => {
|
checkSession().then(user => {
|
||||||
@ -276,6 +311,13 @@ const logout = function () {
|
|||||||
showFailToast('注销失败!');
|
showFailToast('注销失败!');
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const dark = ref(getMobileTheme() === 'dark')
|
||||||
|
|
||||||
|
const changeTheme = () => {
|
||||||
|
bus.emit('changeTheme', dark.value ? 'dark' : 'light')
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="stylus">
|
<style lang="stylus">
|
||||||
@ -305,8 +347,10 @@ const logout = function () {
|
|||||||
.product-list {
|
.product-list {
|
||||||
padding 0 15px
|
padding 0 15px
|
||||||
|
|
||||||
|
color var(--van-text-color)
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
border 1px solid #e5e5e5
|
border 1px solid var(--van-border-color)
|
||||||
border-radius 10px
|
border-radius 10px
|
||||||
margin-bottom 15px
|
margin-bottom 15px
|
||||||
overflow hidden
|
overflow hidden
|
||||||
@ -327,6 +371,10 @@ const logout = function () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.van-cell__value {
|
||||||
|
flex 2
|
||||||
|
}
|
||||||
|
|
||||||
.price {
|
.price {
|
||||||
font-size 18px
|
font-size 18px
|
||||||
color #f56c6c
|
color #f56c6c
|
||||||
@ -334,5 +382,9 @@ const logout = function () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.setting-content {
|
||||||
|
padding 16px
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
@ -270,6 +270,7 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<button style="display: none" class="copy-prompt" :data-clipboard-text="prompt" id="copy-btn">复制</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -280,7 +281,6 @@ import {
|
|||||||
showFailToast,
|
showFailToast,
|
||||||
showNotify,
|
showNotify,
|
||||||
showToast,
|
showToast,
|
||||||
showDialog,
|
|
||||||
showImagePreview,
|
showImagePreview,
|
||||||
showSuccessToast
|
showSuccessToast
|
||||||
} from "vant";
|
} from "vant";
|
||||||
@ -291,6 +291,7 @@ import {checkSession} from "@/action/session";
|
|||||||
import {useRouter} from "vue-router";
|
import {useRouter} from "vue-router";
|
||||||
import {Delete} from "@element-plus/icons-vue";
|
import {Delete} from "@element-plus/icons-vue";
|
||||||
import {showLoginDialog} from "@/utils/libs";
|
import {showLoginDialog} from "@/utils/libs";
|
||||||
|
import Clipboard from "clipboard";
|
||||||
|
|
||||||
const activeColspan = ref([""])
|
const activeColspan = ref([""])
|
||||||
|
|
||||||
@ -337,8 +338,18 @@ const socket = ref(null)
|
|||||||
const power = ref(0)
|
const power = ref(0)
|
||||||
const activeName = ref("txt2img")
|
const activeName = ref("txt2img")
|
||||||
const isLogin = ref(false)
|
const isLogin = ref(false)
|
||||||
|
const prompt = ref('')
|
||||||
|
const clipboard = ref(null)
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
clipboard.value = new Clipboard(".copy-prompt");
|
||||||
|
clipboard.value.on('success', () => {
|
||||||
|
showNotify({type: 'success', message: '复制成功', duration: 1000})
|
||||||
|
})
|
||||||
|
clipboard.value.on('error', () => {
|
||||||
|
showNotify({type: 'danger', message: '复制失败', duration: 2000})
|
||||||
|
})
|
||||||
|
|
||||||
checkSession().then(user => {
|
checkSession().then(user => {
|
||||||
power.value = user['power']
|
power.value = user['power']
|
||||||
userId.value = user.id
|
userId.value = user.id
|
||||||
@ -354,6 +365,7 @@ onMounted(() => {
|
|||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
socket.value = null
|
socket.value = null
|
||||||
|
clipboard.value.destroy()
|
||||||
})
|
})
|
||||||
|
|
||||||
const mjPower = ref(1)
|
const mjPower = ref(1)
|
||||||
@ -616,11 +628,15 @@ const publishImage = (item, action) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const showPrompt = (item) => {
|
const showPrompt = (item) => {
|
||||||
showDialog({
|
prompt.value = item.prompt
|
||||||
|
showConfirmDialog({
|
||||||
title: "绘画提示词",
|
title: "绘画提示词",
|
||||||
message: item.prompt,
|
message: item.prompt,
|
||||||
|
confirmButtonText: "复制",
|
||||||
|
cancelButtonText: "关闭",
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
// on close
|
document.querySelector('#copy-btn').click()
|
||||||
|
}).catch(() => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,7 +198,7 @@
|
|||||||
<el-button type="success" v-else @click="publishImage($event, item, true)" circle>
|
<el-button type="success" v-else @click="publishImage($event, item, true)" circle>
|
||||||
<i class="iconfont icon-share-bold"></i>
|
<i class="iconfont icon-share-bold"></i>
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button type="primary" @click="showTask(item)" circle>
|
<el-button type="primary" @click="showPrompt(item)" circle>
|
||||||
<i class="iconfont icon-prompt"></i>
|
<i class="iconfont icon-prompt"></i>
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
@ -208,7 +208,7 @@
|
|||||||
</van-list>
|
</van-list>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
<button style="display: none" class="copy-prompt-sd" :data-clipboard-text="prompt" id="copy-btn-sd">复制</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -232,7 +232,6 @@ import {showLoginDialog} from "@/utils/libs";
|
|||||||
|
|
||||||
const listBoxHeight = ref(window.innerHeight - 40)
|
const listBoxHeight = ref(window.innerHeight - 40)
|
||||||
const mjBoxHeight = ref(window.innerHeight - 150)
|
const mjBoxHeight = ref(window.innerHeight - 150)
|
||||||
const showTaskDialog = ref(false)
|
|
||||||
const item = ref({})
|
const item = ref({})
|
||||||
const isLogin = ref(false)
|
const isLogin = ref(false)
|
||||||
const activeColspan = ref([""])
|
const activeColspan = ref([""])
|
||||||
@ -338,15 +337,15 @@ const connect = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const clipboard = ref(null)
|
const clipboard = ref(null)
|
||||||
|
const prompt = ref('')
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
initData()
|
initData()
|
||||||
clipboard.value = new Clipboard('.copy-prompt-sd');
|
clipboard.value = new Clipboard(".copy-prompt-sd");
|
||||||
clipboard.value.on('success', () => {
|
clipboard.value.on('success', () => {
|
||||||
showNotify({type: "success", message: "复制成功!"});
|
showNotify({type: 'success', message: '复制成功', duration: 1000})
|
||||||
})
|
})
|
||||||
|
|
||||||
clipboard.value.on('error', () => {
|
clipboard.value.on('error', () => {
|
||||||
showNotify({type: "danger", message: '复制失败!'});
|
showNotify({type: 'danger', message: '复制失败', duration: 2000})
|
||||||
})
|
})
|
||||||
|
|
||||||
httpGet("/api/config/get?key=system").then(res => {
|
httpGet("/api/config/get?key=system").then(res => {
|
||||||
@ -438,7 +437,7 @@ const generate = () => {
|
|||||||
return showToast("请输入绘画提示词!")
|
return showToast("请输入绘画提示词!")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.value.seed === '') {
|
if (!params.value.seed) {
|
||||||
params.value.seed = -1
|
params.value.seed = -1
|
||||||
}
|
}
|
||||||
params.value.session_id = getSessionId()
|
params.value.session_id = getSessionId()
|
||||||
@ -450,14 +449,17 @@ const generate = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const showTask = (row) => {
|
const showPrompt = (item) => {
|
||||||
item.value = row
|
prompt.value = item.prompt
|
||||||
showTaskDialog.value = true
|
showConfirmDialog({
|
||||||
}
|
title: "绘画提示词",
|
||||||
|
message: item.prompt,
|
||||||
const copyParams = (row) => {
|
confirmButtonText: "复制",
|
||||||
params.value = row.params
|
cancelButtonText: "关闭",
|
||||||
showTaskDialog.value = false
|
}).then(() => {
|
||||||
|
document.querySelector('#copy-btn-sd').click()
|
||||||
|
}).catch(() => {
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const removeImage = (event, item) => {
|
const removeImage = (event, item) => {
|
||||||
|
@ -13,7 +13,13 @@
|
|||||||
style="height: 100%;width: 100%;"
|
style="height: 100%;width: 100%;"
|
||||||
>
|
>
|
||||||
<van-cell v-for="item in data['mj'].data" :key="item.id">
|
<van-cell v-for="item in data['mj'].data" :key="item.id">
|
||||||
<van-image :src="item['img_thumb']" @click="showPrompt(item)" fit="cover"/>
|
<van-image :src="item['img_thumb']" @click="imageView(item)" fit="cover"/>
|
||||||
|
|
||||||
|
<div class="opt-box">
|
||||||
|
<el-button type="primary" @click="showPrompt(item)" circle>
|
||||||
|
<i class="iconfont icon-prompt"></i>
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
</van-cell>
|
</van-cell>
|
||||||
</van-list>
|
</van-list>
|
||||||
</van-tab>
|
</van-tab>
|
||||||
@ -27,7 +33,13 @@
|
|||||||
@load="onLoad"
|
@load="onLoad"
|
||||||
>
|
>
|
||||||
<van-cell v-for="item in data['sd'].data" :key="item.id">
|
<van-cell v-for="item in data['sd'].data" :key="item.id">
|
||||||
<van-image :src="item['img_thumb']" @click="showPrompt(item)" fit="cover"/>
|
<van-image :src="item['img_thumb']" @click="imageView(item)" fit="cover"/>
|
||||||
|
|
||||||
|
<div class="opt-box">
|
||||||
|
<el-button type="primary" @click="showPrompt(item)" circle>
|
||||||
|
<i class="iconfont icon-prompt"></i>
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
</van-cell>
|
</van-cell>
|
||||||
</van-list>
|
</van-list>
|
||||||
</van-tab>
|
</van-tab>
|
||||||
@ -36,13 +48,19 @@
|
|||||||
</van-tab>
|
</van-tab>
|
||||||
</van-tabs>
|
</van-tabs>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<button style="display: none" class="copy-prompt-wall" :data-clipboard-text="prompt" id="copy-btn-wall">复制
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import {ref} from "vue";
|
import {onMounted, onUnmounted, ref} from "vue";
|
||||||
import {httpGet} from "@/utils/http";
|
import {httpGet} from "@/utils/http";
|
||||||
import {showDialog, showFailToast} from "vant";
|
import {showConfirmDialog, showDialog, showFailToast, showImagePreview, showNotify} from "vant";
|
||||||
|
import {Delete} from "@element-plus/icons-vue";
|
||||||
|
import Clipboard from "clipboard";
|
||||||
|
import {ElMessage} from "element-plus";
|
||||||
|
|
||||||
const activeName = ref("mj")
|
const activeName = ref("mj")
|
||||||
const data = ref({
|
const data = ref({
|
||||||
@ -52,7 +70,7 @@ const data = ref({
|
|||||||
error: false,
|
error: false,
|
||||||
page: 1,
|
page: 1,
|
||||||
pageSize: 12,
|
pageSize: 12,
|
||||||
url: "/api/mj/jobs",
|
url: "/api/mj/imgWall",
|
||||||
data: []
|
data: []
|
||||||
},
|
},
|
||||||
"sd": {
|
"sd": {
|
||||||
@ -61,7 +79,7 @@ const data = ref({
|
|||||||
error: false,
|
error: false,
|
||||||
page: 1,
|
page: 1,
|
||||||
pageSize: 12,
|
pageSize: 12,
|
||||||
url: "/api/sd/jobs",
|
url: "/api/sd/imgWall",
|
||||||
data: []
|
data: []
|
||||||
},
|
},
|
||||||
"dalle3": {
|
"dalle3": {
|
||||||
@ -70,11 +88,32 @@ const data = ref({
|
|||||||
error: false,
|
error: false,
|
||||||
page: 1,
|
page: 1,
|
||||||
pageSize: 12,
|
pageSize: 12,
|
||||||
url: "/api/dalle3/jobs",
|
url: "/api/dalle3/imgWall",
|
||||||
data: []
|
data: []
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const prompt = ref('')
|
||||||
|
const clipboard = ref(null)
|
||||||
|
onMounted(() => {
|
||||||
|
clipboard.value = new Clipboard(".copy-prompt-wall");
|
||||||
|
clipboard.value.on('success', () => {
|
||||||
|
showNotify({type: 'success', message: '复制成功', duration: 1000})
|
||||||
|
})
|
||||||
|
clipboard.value.on('error', () => {
|
||||||
|
showNotify({type: 'danger', message: '复制失败', duration: 2000})
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
clipboard.value.on('error', () => {
|
||||||
|
ElMessage.error('复制失败!');
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
clipboard.value.destroy()
|
||||||
|
})
|
||||||
|
|
||||||
const onLoad = () => {
|
const onLoad = () => {
|
||||||
const d = data.value[activeName.value]
|
const d = data.value[activeName.value]
|
||||||
httpGet(`${d.url}?status=1&page=${d.page}&page_size=${d.pageSize}&publish=true`).then(res => {
|
httpGet(`${d.url}?status=1&page=${d.page}&page_size=${d.pageSize}&publish=true`).then(res => {
|
||||||
@ -105,22 +144,39 @@ const onLoad = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const showPrompt = (item) => {
|
const showPrompt = (item) => {
|
||||||
showDialog({
|
prompt.value = item.prompt
|
||||||
|
showConfirmDialog({
|
||||||
title: "绘画提示词",
|
title: "绘画提示词",
|
||||||
message: item.prompt,
|
message: item.prompt,
|
||||||
|
confirmButtonText: "复制",
|
||||||
|
cancelButtonText: "关闭",
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
// on close
|
document.querySelector('#copy-btn-wall').click()
|
||||||
|
}).catch(() => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const imageView = (item) => {
|
||||||
|
showImagePreview([item['img_url']]);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="stylus">
|
<style lang="stylus">
|
||||||
.img-wall {
|
.img-wall {
|
||||||
.content {
|
.content {
|
||||||
.van-cell__value {
|
.van-cell__value {
|
||||||
|
min-height 80px
|
||||||
|
|
||||||
.van-image {
|
.van-image {
|
||||||
width 100%
|
width 100%
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.opt-box {
|
||||||
|
position absolute
|
||||||
|
right 0
|
||||||
|
top 0
|
||||||
|
padding 10px
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user