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 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)

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