Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit a59cfe7

Browse files
committed
feat: 优化排版
1 parent d7146ac commit a59cfe7

File tree

20 files changed

+612
-77
lines changed

20 files changed

+612
-77
lines changed

‎auto-imports.d.ts‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/* eslint-disable */
2+
/* prettier-ignore */
3+
// @ts-nocheck
4+
// Generated by unplugin-auto-import
5+
export {}
6+
declare global {
7+
8+
}

‎components.d.ts‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/* eslint-disable */
2+
/* prettier-ignore */
3+
// @ts-nocheck
4+
// Generated by unplugin-vue-components
5+
// Read more: https://github.com/vuejs/core/pull/3399
6+
export {}
7+
8+
declare module 'vue' {
9+
export interface GlobalComponents {
10+
copy: typeof import('./src/components/Image copy.vue')['default']
11+
ElImage: typeof import('element-plus/es')['ElImage']
12+
ElPopover: typeof import('element-plus/es')['ElPopover']
13+
GroupModal: typeof import('./src/components/Group-Modal/index.vue')['default']
14+
Image: typeof import('./src/components/Image.vue')['default']
15+
'Image copy': typeof import('./src/components/Image copy.vue')['default']
16+
Loading: typeof import('./src/components/Loading/index.vue')['default']
17+
LoginModal: typeof import('./src/components/Login-Modal/index.vue')['default']
18+
Modal: typeof import('./src/components/Modal/index.vue')['default']
19+
SettingsModal: typeof import('./src/components/Settings-Modal/index.vue')['default']
20+
Tag: typeof import('./src/components/Tag.vue')['default']
21+
Toast: typeof import('./src/components/Toast/index.vue')['default']
22+
UseModal: typeof import('./src/components/Use-Modal/index.vue')['default']
23+
}
24+
export interface ComponentCustomProperties {
25+
vLoading: typeof import('element-plus/es')['ElLoadingDirective']
26+
}
27+
}

‎package.json‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212
"@vueuse/core": "^10.1.2",
1313
"clipboard": "^2.0.11",
1414
"crypto-js": "^4.1.1",
15+
"element-plus": "^2.3.6",
1516
"socket.io-client": "^4.6.2",
16-
"vue": "^3.2.47",
17-
"vue3-lazy": "^1.0.0-alpha.1"
17+
"vue": "^3.2.47"
1818
},
1919
"devDependencies": {
2020
"@types/node": "^20.3.0",
@@ -26,6 +26,8 @@
2626
"postcss": "^8.4.24",
2727
"tailwindcss": "^3.3.2",
2828
"typescript": "^5.0.2",
29+
"unplugin-auto-import": "^0.16.4",
30+
"unplugin-vue-components": "^0.25.1",
2931
"vite": "^4.3.9",
3032
"vue-tsc": "^1.4.2"
3133
}

‎src/DrawPanel.vue‎

Lines changed: 79 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
11
<script setup lang="ts">
2-
import { reactive, ref, onMounted, defineAsyncComponent } from 'vue';
2+
import { reactive, ref, onMounted, createVNode } from 'vue';
33
import { Message, MessageStatus } from './interfaces/message'
44
import MessageItem from './Message.vue'
55
import { getMessagesAPI, createMessageAPI, upscaleMessageAPI } from './api/midjourney'
6-
import { sendMessage, createWebsocket } from './utils/websocket'
7-
import { useDebounceFn } from '@vueuse/core'
6+
import { createWebsocket } from './utils/websocket'
7+
import { useDebounceFn, } from '@vueuse/core'
88
import Toast from './components/Toast/index'
99
import UseModal from './components/Use-Modal/index.vue'
1010
import SettingsModal from './components/Settings-Modal/index.vue'
1111
import { showModal } from './components/Modal';
12-
import { drawStyles, randomPrompt, getJointPrompt, showLoginModal } from './utils/index'
12+
import { drawStyles, randomPrompt, getJointPrompt } from './utils/index'
1313
import { useLimitHook } from '@/hooks/use-limit-hook';
14+
import { userStorage } from '@/utils/storage';
15+
import { useUser } from '@/hooks/use-user'
16+
import GroupModal from '@/components/Group-Modal/index.vue'
1417
18+
19+
const { isLogin, showLoginModal, userLogout } = useUser()
1520
const showUseModal = () => {
1621
showModal(UseModal, {
1722
title: "使用说明"
@@ -20,17 +25,12 @@ const showUseModal = () => {
2025
2126
const showSettingsModal = () => {
2227
showModal(SettingsModal, {
23-
title: "设置"
28+
title: "设置",
29+
closeOnClickModal: true
2430
})
2531
}
32+
2633
createWebsocket({
27-
onMessage(data) {
28-
// console.log('message event: ', event)
29-
console.log('message event: ', data)
30-
},
31-
onOnLine(data) {
32-
console.log('online data: ', data)
33-
},
3434
onTaskUpdate(data: Message) {
3535
console.log('taskupdate data: ', data)
3636
const { id } = data
@@ -46,11 +46,13 @@ const data = reactive({
4646
messages: [],
4747
pageNum: 1,
4848
pageSize: 5,
49+
initLoading: true,
4950
loading: false,
5051
loaded: false,
5152
useModalVisible: false,
5253
styles: [...drawStyles],
53-
currentStyle: ''
54+
currentStyle: '',
55+
onlyCurrentUser: false
5456
})
5557
5658
const findOneAndUpdate = (id: number, msgData: Partial<Message>) => {
@@ -80,15 +82,12 @@ const getList = (params: any) => {
8082
return new Promise((resolve, reject) => {
8183
if (data.loading || data.loaded) return
8284
getMessagesAPI(params).then((resData) => {
83-
// data.messages = resData as any;
84-
// ((resData || [] as any) as []).reverse();
85-
// data.messages = [...resData as any, ...data.messages];
86-
8785
data.messages = data.messages.concat(resData)
8886
8987
data.loaded = !resData || !(resData as any).length
9088
}).finally(() => {
9189
data.loading = false
90+
data.initLoading = false
9291
resolve(undefined)
9392
})
9493
})
@@ -111,6 +110,9 @@ const sendPrompt = async () => {
111110
}, 2000)
112111
return
113112
}
113+
if (data.prompt.length > 500) {
114+
return Toast({ value: "描述过长,最多500个字符,包括标点符号" })
115+
}
114116
const newPmt = getJointPrompt(data.prompt)
115117
const msgId = await createMessageAPI(newPmt) as any;
116118
console.log("msgId: ", msgId)
@@ -121,11 +123,11 @@ const sendPrompt = async () => {
121123
id: msgId,
122124
status: MessageStatus.INIT
123125
}
124-
126+
125127
data.messages.unshift(msgObj)
126128
data.prompt = ''
127129
recordTimeUse()
128-
scrollToBottom()
130+
//scrollToBottom()
129131
}
130132
131133
const onUpscale = async (msg: Message) => {
@@ -155,7 +157,7 @@ const onUpscale = async (msg: Message) => {
155157
const scrollToBottom = () => {
156158
setTimeout(() => {
157159
if (contentWrap.value) {
158-
contentWrap.value.scrollTop = contentWrap.value.scrollHeight
160+
//contentWrap.value.scrollTop = contentWrap.value.scrollHeight
159161
}
160162
})
161163
}
@@ -173,8 +175,42 @@ const helpThink = () => {
173175
data.prompt = p
174176
}
175177
178+
const onlyForMe = () => {
179+
setTimeout(() => {
180+
const user = userStorage.get();
181+
const isForUser = data.onlyCurrentUser
182+
const queries: any = {
183+
pageNum: 1,
184+
pageSize: data.pageSize,
185+
}
186+
if (isForUser) {
187+
if (!user) {
188+
data.onlyCurrentUser = false;
189+
return showLoginModal()
190+
}
191+
if (user && user.username) {
192+
queries.username = user.username
193+
}
194+
}
195+
data.loaded = false
196+
data.initLoading = true;
197+
data.messages = []
198+
data.pageNum = 1
199+
getList(queries)
200+
data.loading = true
201+
})
202+
}
203+
204+
const showGroupModal = () => {
205+
showModal(GroupModal, {
206+
closeOnClickModal: true,
207+
closeOnPressEscape: true
208+
})
209+
}
210+
176211
onMounted(() => {
177212
getList({ pageNum: 1, pageSize: data.pageSize }).finally(() => {
213+
data.initLoading = false
178214
setTimeout(() => {
179215
contentWrap.value.addEventListener('scroll', onContentWrapScroll)
180216
scrollToBottom()
@@ -191,34 +227,37 @@ onMounted(() => {
191227
<template>
192228
<!-- <div class="h-full w-full max-sm:py-0 bg-gray-600" v-loading:[title]="true"> -->
193229
<div class="h-full w-full max-sm:py-0 bg-gray-600">
194-
<div class="relative h-full max-w-[980px] bg-gray-700 m-auto text-white px-10 py-4 sm:py-0 max-sm:py-2 max-sm:px-4 rounded-none">
195-
<div id="contentWrap" ref="contentWrap" class="h-[calc(100%-150px)] overflow-auto m-auto flex flex-col-reverse">
230+
<div
231+
class="relative h-full max-w-[980px] bg-gray-700 m-auto text-white px-10 py-4 sm:py-0 max-sm:py-2 max-sm:px-4 rounded-none">
232+
<div v-loading="data.initLoading" id="contentWrap" ref="contentWrap"
233+
class="h-[calc(100%-150px)] overflow-auto m-auto flex flex-col-reverse">
196234
<div class="border-b-2 border-purple-400" v-for="(item, index) in data.messages" :key="item.id">
197235
<MessageItem :key="item.id" :message="item" @on-upscale="onUpscale" />
198236
</div>
199237
</div>
200-
<div class="absolute left-10 right-10 max-sm:left-2 max-sm:right-2 bottom-4 max-sm:bottom-2 flex-row items-center justify-between px-2 py-2 bg-gray-100 border-gray-400 rounded-[4px]">
238+
<div
239+
class="absolute left-10 right-10 max-sm:left-2 max-sm:right-2 bottom-4 max-sm:bottom-2 flex-row items-center justify-between px-2 py-2 bg-gray-100 border-gray-400 rounded-[4px]">
201240
<!-- 快捷/帮助区域 -->
202-
<div class="flex w-full px-2 pb-2 pt-1 text-md select-none">
203-
<p class="underline text-orange-400 pr-4 cursor-pointer" @click.stop="helpThink">帮我想一个</p>
204-
<p class="underline text-orange-400 pr-4 cursor-pointer" @click.stop="showSettingsModal">设置参数</p>
205-
<p class="underline text-orange-400 pr-4 cursor-pointer" @click.stop="showSettingsModal">设置风格</p>
241+
<div class="flex w-full px-2 pb-2 pt-1 text-md select-none flex-wrap">
242+
<p class="underline text-orange-400 pr-4 cursor-pointer max-sm:text-sm" @click.stop="helpThink">想一个</p>
243+
<p class="underline text-orange-400 pr-4 cursor-pointer max-sm:text-sm" @click.stop="showSettingsModal">设置</p>
244+
<!-- <p class="underline text-orange-400 pr-4 cursor-pointer" @click.stop="showSettingsModal">设置风格</p> -->
245+
<p class="underline text-orange-400 cursor-pointer max-sm:text-sm" @click.stop="showUseModal">使用说明</p>
246+
<p class="underline text-orange-400 pr-4 ml-4 max-sm:text-sm" @click.stop="onlyForMe">
247+
<input id="onlyMe" v-model="data.onlyCurrentUser" type="checkbox" class="cursor-pointer">
248+
<label for="onlyMe" class="cursor-pointer">只看自己</label>
249+
</p>
206250
<p class="flex-1"></p>
207-
<p class="underline text-orange-400 pr-4 cursor-pointer font-bold" @click.stop="showLoginModal">登录/注册</p>
208-
<p class="underline text-orange-400 pr-4 cursor-pointer">微信交流群</p>
209-
<p class="underline text-orange-400 cursor-pointer" @click.stop="showUseModal">使用说明</p>
210-
</div>
251+
<p class="underline text-orange-400 pr-4 cursor-pointer max-sm:text-sm" @click="showGroupModal">交流群</p>
252+
<p v-if="!isLogin"class="underline text-orange-400 pr-4 cursor-pointer font-bold max-sm:text-sm"@click.stop="showLoginModal">登录/注册</p>
253+
<p v-if="isLogin"class="underline text-orange-400 pr-4 cursor-pointer max-sm:text-sm" @click.stop="userLogout">退出</p>
254+
</div>
211255
<!-- 输入框 -->
212256
<div class="w-full bg-white flex items-center">
213-
<textarea
214-
v-model="data.prompt"
215-
class="flex-1 px-4 py-2 resize-none rounded-[8px] outline-none max-sm:text-sm text-md text-gray-500"
216-
autofocus
217-
placeholder="输入图片描述,例如'可爱的橘黄色的猫咪, 迪士尼风格'、'海边,机器人,小女孩,吉卜力风格'等"
218-
type="textarea"
219-
:rows="2"
220-
@keydown.enter.prevent.stop="onKeyDown"
221-
/>
257+
<textarea v-model="data.prompt"
258+
class="flex-1 px-4 py-2 resize-none rounded-[8px] outline-none max-sm:text-sm text-md text-gray-500" autofocus
259+
placeholder="输入图片描述,例如'可爱的橘黄色的猫咪, 迪士尼风格'、'海边,机器人,小女孩,吉卜力风格'等" type="textarea" :rows="2"
260+
@keydown.enter.prevent.stop="onKeyDown" />
222261
<img @click="onClickSend" class="mx-4 w-[36px] h-[36px] cursor-pointer" src="/src/assets/send.png" alt="">
223262
</div>
224263
</div>

‎src/assets/group.jpg‎

179 KB
Loading[フレーム]

‎src/components/Group-Modal/index.vue‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<script setup lang="ts">
2+
const props = defineProps({
3+
close: {
4+
type: Function
5+
}
6+
})
7+
8+
const onClickCancel = () => {
9+
props.close?.()
10+
}
11+
12+
</script>
13+
14+
<template>
15+
<div class="">
16+
<img src="/src/assets/group.jpg" alt="">
17+
</div>
18+
</template>

‎src/components/Image copy.vue‎

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<script setup lang="ts">
2+
import { computed, reactive } from 'vue';
3+
4+
const props = defineProps({
5+
url: {
6+
type: String,
7+
default: ""
8+
},
9+
width: {
10+
type: [String, Number],
11+
default: '100%'
12+
},
13+
loadText: {
14+
type: String,
15+
default: "加载中"
16+
},
17+
errorText: String,
18+
})
19+
20+
const cdnHost = 'cdn.discordapp.com'
21+
const cdnHost2 = 'midjourney.cdn.zhishuyun.com'
22+
const trueUrl = computed(() => {
23+
if (props.url && props.url.indexOf(cdnHost) !== -1) {
24+
return props.url.replace(cdnHost, cdnHost2)
25+
}
26+
return props.url
27+
})
28+
29+
const data = reactive({
30+
loading: false,
31+
loaded: false,
32+
loadError: false
33+
})
34+
35+
const onLoadStart = (event: Event) => {
36+
console.log('load start: ', event)
37+
data.loading = true
38+
}
39+
const onLoadError = (event: Event) => {
40+
console.log('load eroor: ', event)
41+
data.loadError = true
42+
}
43+
const onLoad = () => {
44+
data.loading = false
45+
data.loaded = true
46+
}
47+
</script>
48+
49+
<template>
50+
<div class="relative w-full bg-gray-500 rounded my-2 h-0 pb-[100%]">
51+
<img v-if="trueUrl" v-lazy="trueUrl" class="absolute top-0 left-0 w-[100%] h-[100%] object-contain" loading="lazy" alt="" @loadstart="onLoadStart" @error="onLoadError" @load="onLoad">
52+
</div>
53+
</template>

‎src/components/Image.vue‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,15 @@ const onLoad = () => {
4848

4949
<template>
5050
<div class="relative w-full bg-gray-500 rounded my-2 h-0 pb-[100%]">
51-
<img v-if="trueUrl" v-lazy="trueUrl" class="absolute top-0 left-0 w-[100%] h-[100%] object-contain" loading="lazy" alt="" @loadstart="onLoadStart" @error="onLoadError" @load="onLoad">
51+
<el-image style="position: absolute !important;" class="absolute w-[100%] h-[100%] object-contain" v-if="trueUrl"
52+
fit="contain" :src="trueUrl" lazy :preview-src-list="[trueUrl]" hide-on-click-modal>
53+
<template #placeholder>
54+
<div class="w-full h-full" v-loading="true" element-loading-text="正在加载图片"></div>
55+
</template>
56+
<template #error>
57+
<div class="w-full h-full flex items-center justify-center" v-loading="false" element-loading-text="加载失败">加载失败</div>
58+
</template>
59+
</el-image>
60+
<!-- <img v-if="trueUrl" v-lazy="trueUrl" class="absolute top-0 left-0 w-[100%] h-[100%] object-contain" loading="lazy" alt="" @loadstart="onLoadStart" @error="onLoadError" @load="onLoad"> -->
5261
</div>
5362
</template>

‎src/components/Login-Modal/index.vue‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ const onClickCancel = () => {
8888
</script>
8989

9090
<template>
91-
<div class="max-w-[600px] px-8 py-4 min-w-[420px]" v-loading="form.loading">
91+
<div class="max-w-[600px] px-8 py-4 min-w-[420px]" todayUsed="form.loading">
9292
<img class="block m-auto pb-4" src="/src/assets/coffee.png" alt="">
9393
<p class="py-1 pb-4 text-center text-orange-100 font-bold">欢迎使用</p>
9494
<div class="flex justify-between items-center py-2 text-sm mb-2" >

‎src/components/Modal/index.tsx‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ interface IShowModal {
66
visible?: boolean;
77
showClose?: boolean;
88
onClose?: () => void;
9+
closeOnClickModal?: boolean;
10+
closeOnPressEscape?: boolean
911
}
1012
export const showModal = (component: VNodeTypes, props: IShowModal = {}) => {
1113
return new Promise((resolve, reject) => {
@@ -15,6 +17,8 @@ export const showModal = (component: VNodeTypes, props: IShowModal = {}) => {
1517
title: props.title,
1618
modelValue: true,
1719
showClose: props.showClose,
20+
closeOnClickModal: props.closeOnClickModal || false,
21+
closeOnPressEscape: props.closeOnPressEscape || false,
1822
onClose: () => {
1923
document.body.removeChild(container)
2024
props?.onClose?.()

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /