Skip to content

Commit c074712

Browse files
committed
feat: 用户模块
1 parent ebbe002 commit c074712

File tree

22 files changed

+563
-49
lines changed

22 files changed

+563
-49
lines changed

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@
1111
"dependencies": {
1212
"@vueuse/core": "^10.1.2",
1313
"clipboard": "^2.0.11",
14+
"crypto-js": "^4.1.1",
1415
"vue": "^3.2.47",
1516
"vue3-lazy": "^1.0.0-alpha.1"
1617
},
1718
"devDependencies": {
19+
"@types/node": "^20.3.0",
1820
"@types/uuid": "^9.0.1",
1921
"@vitejs/plugin-vue": "^4.1.0",
2022
"@vitejs/plugin-vue-jsx": "^3.0.1",

src/DrawPanel.vue

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script setup lang="ts">
2-
import { reactive, ref, onMounted } from 'vue';
2+
import { reactive, ref, onMounted, defineAsyncComponent } from 'vue';
33
import { Message, MessageStatus } from './interfaces/message'
44
import MessageItem from './Message.vue'
55
import { getMessagesAPI, createMessageAPI, upscaleMessageAPI } from './api/midjourney'
@@ -9,15 +9,19 @@ 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 } from './utils/index'
13-
12+
import { drawStyles, randomPrompt, getJointPrompt, showLoginModal } from './utils/index'
13+
import { useLimitHook } from '@/hooks/use-limit-hook';
1414
1515
const showUseModal = () => {
16-
showModal(UseModal)
16+
showModal(UseModal, {
17+
title: "使用说明"
18+
})
1719
}
1820
1921
const showSettingsModal = () => {
20-
showModal(SettingsModal)
22+
showModal(SettingsModal, {
23+
title: "设置"
24+
})
2125
}
2226
createWebsocket({
2327
onMessage(data) {
@@ -64,12 +68,6 @@ const onClickSend = () => {
6468
}
6569
6670
const onKeyDown = useDebounceFn((event: Event) => {
67-
if (!data.prompt) {
68-
Toast({
69-
value: '描述不能为空'
70-
})
71-
return
72-
}
7371
event.stopPropagation()
7472
event.preventDefault()
7573
sendPrompt()
@@ -95,7 +93,21 @@ const getList = (params: any) => {
9593
9694
const sendPrompt = async () => {
9795
data.prompt = data.prompt.trim()
98-
if (!data.prompt) return
96+
if (!data.prompt) {
97+
Toast({
98+
value: '描述不能为空'
99+
})
100+
return
101+
}
102+
103+
const { isExceedFreeTimesByDay, recordTimeUse } = useLimitHook()
104+
if (isExceedFreeTimesByDay()) {
105+
Toast({ value: "今日免费次数已用尽,请先登录" })
106+
setTimeout(() => {
107+
showLoginModal()
108+
}, 2000)
109+
return
110+
}
99111
const newPmt = getJointPrompt(data.prompt)
100112
const msgId = await createMessageAPI(newPmt) as any;
101113
console.log("msgId: ", msgId)
@@ -107,9 +119,9 @@ const sendPrompt = async () => {
107119
status: MessageStatus.INIT
108120
}
109121
110-
// data.messages.push(msgObj)
111122
data.messages.unshift(msgObj)
112123
data.prompt = ''
124+
recordTimeUse()
113125
scrollToBottom()
114126
}
115127
@@ -174,6 +186,7 @@ onMounted(() => {
174186
</script>
175187

176188
<template>
189+
<!-- <div class="h-full w-full max-sm:py-0 bg-gray-600" v-loading:[title]="true"> -->
177190
<div class="h-full w-full max-sm:py-0 bg-gray-600">
178191
<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">
179192
<div id="contentWrap" ref="contentWrap" class="h-[calc(100%-150px)] overflow-auto m-auto flex flex-col-reverse">

src/api/midjourney.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,19 @@ interface IUpscaleAPI {
77
}
88

99
export const getMessagesAPI = (params?: any) => {
10-
return $http.get('/list', {
10+
return $http.get('/messages', {
1111
params
1212
})
1313
}
1414

1515
export const createMessageAPI = (prompt: string) => {
16-
return $http.post('/imagine', {
16+
return $http.post('/mj/imagine', {
1717
prompt
1818
})
1919
}
2020

2121
export const upscaleMessageAPI = (body: IUpscaleAPI) => {
22-
return $http.post('/upscale', body)
22+
return $http.post('/mj/upscale', body)
2323
}
2424

2525

src/api/user.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { $http } from '../utils/axios'
2+
3+
interface IUser {
4+
username: string;
5+
password?: string;
6+
rePassword?: string;
7+
}
8+
9+
export const registerUserAPI = (data: IUser) => {
10+
return $http.post('/user/register', data)
11+
}
12+
13+
export const loginUserAPI = (data: IUser) => {
14+
return $http.post('/user/login', data)
15+
}

src/assets/coffee.png

1.09 KB
Loading

src/components/Loading/index.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import Loading from './index.vue'
2+
import { ComponentPublicInstance, createApp } from 'vue'
3+
4+
type LoadingElementType = HTMLElement & {
5+
instance: ComponentPublicInstance
6+
}
7+
8+
const append = (el: LoadingElementType) => {
9+
const style = getComputedStyle(el)
10+
if (['absolute', 'relative', 'fixed'].indexOf(style.position) === -1) {
11+
el.classList.add('relative')
12+
}
13+
el.appendChild(el.instance.$el)
14+
}
15+
const remove = (el: LoadingElementType) => {
16+
el.removeChild(el.instance.$el)
17+
el.classList.remove('relative')
18+
}
19+
20+
export const loadingDirective = {
21+
mounted(el: any, binding: any) {
22+
const app = createApp(Loading)
23+
const container = document.createElement('div')
24+
const instance = app.mount(container);
25+
instance.$el
26+
27+
el.instance = instance
28+
29+
if (binding.value) {
30+
append(el)
31+
}
32+
if (binding.arg !== 'undefined') {
33+
el.instance.setTitle(binding.arg)
34+
}
35+
},
36+
updated(el: any, binding: any) {
37+
38+
if (binding.arg !== 'undefined') {
39+
// setTitle 使我们在loading组件中定义的⽅法
40+
el.instance.setTitle(binding.arg)
41+
}
42+
43+
if (binding.value !== binding.oldValue) {
44+
// 三元表达式 true 插入 false 移除
45+
binding.value ? append(el) : remove(el)
46+
}
47+
}
48+
}
49+
50+
export const useLoading = () => {
51+
return { ...loadingDirective }
52+
}

src/components/Loading/index.vue

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
<template>
2+
<div class="loading-mask">
3+
<div class="loading-loader">
4+
<div>
5+
<div class="loading-dot"></div>
6+
<div class="loading-dot"></div>
7+
<div class="loading-dot"></div>
8+
<div class="loading-dot"></div>
9+
<div class="loading-dot"></div>
10+
</div>
11+
<div class="loading-tip-text">{{ title }}</div>
12+
</div>
13+
</div>
14+
</template>
15+
16+
<script setup lang="ts">
17+
import { ref } from 'vue'
18+
19+
let title = ref('') // 加载提示文字
20+
// 更改加载提示文字
21+
const setTitle = (val) => {
22+
title.value = val
23+
}
24+
25+
// 暴露出去
26+
defineExpose({
27+
title,
28+
setTitle
29+
})
30+
</script>
31+
32+
<style scoped>
33+
.loading-mask {
34+
width: 100%;
35+
height: 100%;
36+
position: absolute;
37+
top: 0;
38+
left: 0;
39+
/* background-color: rgba(0, 0, 0, 0.3); */
40+
z-index: 99;
41+
cursor: wait;
42+
}
43+
44+
.loading-mask .loading-loader {
45+
position: absolute;
46+
top: 50%;
47+
left: 40%;
48+
margin-left: 10%;
49+
transform: translate3d(-50%, -50%, 0);
50+
display: flex;
51+
flex-direction: column;
52+
align-items: center;
53+
}
54+
55+
.loading-tip-text {
56+
color: #3793ff;
57+
padding-top: 10px;
58+
}
59+
60+
.loading-dot {
61+
width: 18px;
62+
height: 18px;
63+
border-radius: 100%;
64+
display: inline-block;
65+
animation: slide 1s infinite;
66+
}
67+
68+
.loading-dot:nth-child(1) {
69+
animation-delay: 0.1s;
70+
background: #1fbfff;
71+
}
72+
.loading-dot:nth-child(2) {
73+
animation-delay: 0.2s;
74+
background: #2ea4ff;
75+
}
76+
.loading-dot:nth-child(3) {
77+
animation-delay: 0.3s;
78+
background: #3793ff;
79+
}
80+
.loading-dot:nth-child(4) {
81+
animation-delay: 0.4s;
82+
background: #3b89ff;
83+
}
84+
.loading-dot:nth-child(5) {
85+
animation-delay: 0.5s;
86+
background: #4577ff;
87+
}
88+
89+
@-moz-keyframes slide {
90+
0% {
91+
transform: scale(1);
92+
}
93+
94+
50% {
95+
opacity: 0.3;
96+
transform: scale(2);
97+
}
98+
99+
100% {
100+
transform: scale(1);
101+
}
102+
}
103+
104+
@-webkit-keyframes slide {
105+
0% {
106+
transform: scale(1);
107+
}
108+
109+
50% {
110+
opacity: 0.3;
111+
transform: scale(2);
112+
}
113+
114+
100% {
115+
transform: scale(1);
116+
}
117+
}
118+
119+
@-o-keyframes slide {
120+
0% {
121+
transform: scale(1);
122+
}
123+
124+
50% {
125+
opacity: 0.3;
126+
transform: scale(2);
127+
}
128+
129+
100% {
130+
transform: scale(1);
131+
}
132+
}
133+
134+
@keyframes slide {
135+
0% {
136+
transform: scale(1);
137+
}
138+
139+
50% {
140+
opacity: 0.3;
141+
transform: scale(2);
142+
}
143+
144+
100% {
145+
transform: scale(1);
146+
}
147+
}
148+
</style>
149+

0 commit comments

Comments
 (0)