手机端即梦页面功能完成

This commit is contained in:
RockYang
2025-08-09 23:25:47 +08:00
parent c0a89d6f32
commit 9a94d98725
14 changed files with 768 additions and 619 deletions

View File

@@ -118,6 +118,7 @@ import MarkdownIt from 'markdown-it'
import emoji from 'markdown-it-emoji'
import { onMounted, ref } from 'vue'
import { useRouter } from 'vue-router'
import { isMobile } from '@/utils/libs'
const router = useRouter()
@@ -146,6 +147,10 @@ const md = new MarkdownIt({
}).use(emoji)
onMounted(() => {
if (isMobile()) {
router.push('/mobile/index')
return
}
getSystemInfo()
.then((res) => {
title.value = res.data.title

View File

@@ -138,7 +138,7 @@
</div>
<div class="param-line">
<ImageUpload
v-model="store.imageEditParams.image_urls"
v-model="store.imageEditParams.image_input"
:max-count="1"
:multiple="false"
/>
@@ -171,7 +171,7 @@
</div>
<div class="param-line">
<ImageUpload
v-model="store.imageEffectsParams.image_input1"
v-model="store.imageEffectsParams.image_input"
:max-count="1"
:multiple="false"
/>
@@ -271,7 +271,7 @@
</div>
<div class="param-line">
<ImageUpload
v-model="store.imageToVideoParams.image_urls"
v-model="store.imageToVideoParams.image_input"
:max-count="2"
:multiple="true"
/>
@@ -387,7 +387,7 @@
preload="auto"
loop="loop"
muted="muted"
class="preview-video w-full h-full"
class="w-full h-full object-cover"
>
您的浏览器不支持视频播放
</video>
@@ -457,15 +457,6 @@
</el-tooltip>
</span>
<span class="ml-1">
<el-tooltip content="画同款" placement="top">
<i
class="iconfont icon-image-list cursor-pointer"
@click="store.drawSame(item)"
></i>
</el-tooltip>
</span>
<template v-if="item.status === 'failed'">
<span class="ml-1" v-if="item.status === 'failed'">
<el-tooltip content="重试" placement="top">
@@ -531,16 +522,19 @@
<!-- 视频预览对话框 -->
<el-dialog v-model="store.showDialog" title="视频预览" center>
<video
:src="store.currentVideoUrl"
autoplay="true"
controls
preload="auto"
loop="loop"
muted="muted"
>
您的浏览器不支持视频播放
</video>
<div class="flex justify-center items-center">
<video
:src="store.currentVideoUrl"
autoplay
controls
preload="auto"
loop
muted
style="max-height: calc(100vh - 100px); max-width: 100vw; object-fit: cover"
>
您的浏览器不支持视频播放
</video>
</div>
</el-dialog>
</div>
</template>

View File

@@ -55,149 +55,268 @@ onMounted(() => {
<style lang="scss" scoped>
.login-page {
min-height: 100vh;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
background: var(--theme-bg-all);
background-image: var(--panel-bg);
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
position: relative;
overflow: auto;
}
.back-home-btn {
.back-home-btn {
position: fixed;
top: 20px;
left: 20px;
z-index: 1000;
display: flex;
align-items: center;
justify-content: center;
width: 44px;
height: 44px;
background: var(--card-bg);
border: 1px solid var(--line-box);
border-radius: 12px;
color: var(--theme-text-color-primary);
text-decoration: none;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
backdrop-filter: blur(8px);
transition: all 0.3s ease;
&:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.15);
background: var(--hover-deep-color);
}
.iconfont {
font-size: 20px;
}
}
.login-container {
width: 100%;
max-width: 480px;
margin: 0 auto;
}
.login-card {
background: var(--card-bg);
border: 1px solid var(--line-box);
border-radius: 20px;
padding: 40px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
backdrop-filter: blur(10px);
position: relative;
overflow: hidden;
&::before {
content: '';
position: absolute;
top: 24px;
left: 24px;
z-index: 10;
font-size: 22px;
color: #fff;
background: rgba(0, 0, 0, 0.15);
border-radius: 50%;
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
transition: background 0.2s;
}
.back-home-btn:hover {
background: rgba(0, 0, 0, 0.25);
}
@media (max-width: 768px) {
.back-home-btn {
top: 12px;
left: 12px;
font-size: 20px;
width: 36px;
height: 36px;
}
}
:deep(.van-theme-dark) .back-home-btn {
color: #fff;
background: rgba(0, 0, 0, 0.35);
top: 0;
left: 0;
right: 0;
height: 4px;
background: var(--btnColor);
}
}
.login-container {
width: 100%;
max-width: 480px;
.login-header {
text-align: center;
margin-bottom: 32px;
}
.login-card {
background: var(--el-bg-color);
border-radius: 16px;
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
overflow: hidden;
.login-title {
font-size: 28px;
font-weight: 600;
color: var(--theme-text-color-primary);
margin: 0 0 8px 0;
letter-spacing: -0.5px;
}
.login-header {
background: linear-gradient(135deg, var(--el-color-primary), #8b5cf6);
color: white;
padding: 40px 30px;
text-align: center;
.login-subtitle {
font-size: 16px;
color: var(--theme-text-color-secondary);
margin: 0;
line-height: 1.5;
}
.login-title {
font-size: 28px;
font-weight: 600;
margin: 0 0 8px 0;
.login-content {
:deep(.login-dialog) {
.form {
.block {
margin-bottom: 20px;
.el-input {
.el-input__wrapper {
background: var(--el-fill-color-blank);
border: 1px solid var(--line-box);
border-radius: 12px;
box-shadow: none;
transition: all 0.3s ease;
&:hover,
&.is-focus {
border-color: var(--border-active);
box-shadow: 0 0 0 3px rgba(91, 98, 206, 0.1);
}
}
.el-input__inner {
color: var(--theme-text-color-primary);
font-size: 16px;
&::placeholder {
color: var(--theme-text-color-secondary);
opacity: 0.7;
}
}
.el-input__prefix {
color: var(--theme-text-color-secondary);
}
}
}
.login-subtitle {
.btn-row {
margin-top: 32px;
.login-btn {
width: 100%;
height: 48px;
border-radius: 12px;
background: var(--btnColor);
border: none;
font-size: 16px;
opacity: 0.9;
margin: 0;
font-weight: 500;
transition: all 0.3s ease;
box-shadow: 0 4px 16px rgba(91, 98, 206, 0.3);
&:hover {
transform: translateY(-2px);
box-shadow: 0 8px 24px rgba(91, 98, 206, 0.4);
}
&:active {
transform: translateY(0);
}
}
}
.login-content {
padding: 40px 30px;
.text {
margin-top: 24px;
color: var(--theme-text-color-secondary);
.el-button {
color: var(--text-color-primary);
background: transparent;
border: none;
padding: 0 8px;
font-size: 14px;
&:hover {
background: var(--btn-bg);
border-radius: 6px;
}
&.forget {
color: var(--theme-text-color-secondary);
&:hover {
color: var(--text-color-primary);
}
}
}
}
}
}
}
// 深色主题适配
:deep(.van-theme-dark) {
.login-page {
.login-card {
background: var(--el-bg-color-overlay);
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
}
}
}
// 移动端响应式设计
// 移动端适配
@media (max-width: 768px) {
.login-page {
padding: 16px;
background: var(--van-background);
}
.login-container {
max-width: 100%;
.back-home-btn {
top: 16px;
left: 16px;
width: 40px;
height: 40px;
.login-card {
border-radius: 20px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
.iconfont {
font-size: 18px;
}
}
.login-header {
padding: 30px 20px;
background: linear-gradient(135deg, var(--van-primary-color), #8b5cf6);
.login-card {
padding: 32px 24px;
border-radius: 16px;
margin-top: 60px;
}
.login-title {
font-size: 24px;
}
.login-title {
font-size: 24px;
}
.login-subtitle {
font-size: 14px;
.login-subtitle {
font-size: 15px;
}
.login-content {
:deep(.login-dialog) {
.form {
.block {
margin-bottom: 18px;
.el-input {
.el-input__wrapper {
border-radius: 10px;
}
.el-input__inner {
font-size: 16px;
}
}
}
.login-content {
padding: 30px 20px;
.btn-row {
margin-top: 28px;
.login-btn {
height: 46px;
border-radius: 10px;
font-size: 15px;
}
}
.text {
margin-top: 20px;
font-size: 13px;
.el-button {
font-size: 13px;
padding: 0 6px;
}
}
}
}
}
}
// 小屏幕移动端优化
@media (max-width: 375px) {
.login-page {
padding: 12px;
// 小屏幕手机适配
@media (max-width: 480px) {
.login-card {
padding: 24px 20px;
}
.login-container {
.login-card {
.login-header {
padding: 24px 16px;
.login-title {
font-size: 22px;
}
.login-title {
font-size: 22px;
}
.login-subtitle {
font-size: 13px;
}
}
.login-content {
padding: 24px 16px;
}
}
}
.login-subtitle {
font-size: 14px;
}
}
</style>

View File

@@ -58,158 +58,398 @@ onMounted(() => {
<style lang="scss" scoped>
.register-page {
min-height: 100vh;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
background: var(--theme-bg-all);
background-image: var(--panel-bg);
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
position: relative;
overflow: auto;
}
.back-home-btn {
.back-home-btn {
position: fixed;
top: 20px;
left: 20px;
z-index: 1000;
display: flex;
align-items: center;
justify-content: center;
width: 44px;
height: 44px;
background: var(--card-bg);
border: 1px solid var(--line-box);
border-radius: 12px;
color: var(--theme-text-color-primary);
text-decoration: none;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
backdrop-filter: blur(8px);
transition: all 0.3s ease;
&:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.15);
background: var(--hover-deep-color);
}
.iconfont {
font-size: 20px;
}
}
.register-container {
width: 100%;
max-width: 480px;
margin: 0 auto;
}
.register-card {
background: var(--card-bg);
border: 1px solid var(--line-box);
border-radius: 20px;
padding: 40px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
backdrop-filter: blur(10px);
position: relative;
overflow: hidden;
&::before {
content: '';
position: absolute;
top: 24px;
left: 24px;
z-index: 10;
font-size: 22px;
color: #fff;
background: rgba(0, 0, 0, 0.15);
border-radius: 50%;
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
transition: background 0.2s;
}
.back-home-btn:hover {
background: rgba(0, 0, 0, 0.25);
}
@media (max-width: 768px) {
.back-home-btn {
top: 12px;
left: 12px;
font-size: 20px;
width: 36px;
height: 36px;
}
}
:deep(.van-theme-dark) .back-home-btn {
color: #fff;
background: rgba(0, 0, 0, 0.35);
top: 0;
left: 0;
right: 0;
height: 4px;
background: var(--btnColor);
}
}
.register-container {
width: 100%;
max-width: 480px;
.register-header {
text-align: center;
margin-bottom: 32px;
}
.register-card {
background: var(--el-bg-color);
border-radius: 16px;
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
overflow: hidden;
.register-title {
font-size: 28px;
font-weight: 600;
color: var(--theme-text-color-primary);
margin: 0 0 8px 0;
letter-spacing: -0.5px;
}
.register-header {
background: linear-gradient(135deg, #10b981, #059669);
color: white;
padding: 40px 30px;
text-align: center;
.register-subtitle {
font-size: 16px;
color: var(--theme-text-color-secondary);
margin: 0;
line-height: 1.5;
}
.register-title {
font-size: 28px;
font-weight: 600;
margin: 0 0 8px 0;
}
.register-content {
:deep(.login-dialog) {
.form {
.block {
margin-bottom: 20px;
.register-subtitle {
font-size: 16px;
opacity: 0.9;
margin: 0;
.el-input {
.el-input__wrapper {
background: var(--el-fill-color-blank);
border: 1px solid var(--line-box);
border-radius: 12px;
box-shadow: none;
transition: all 0.3s ease;
&:hover,
&.is-focus {
border-color: var(--border-active);
box-shadow: 0 0 0 3px rgba(91, 98, 206, 0.1);
}
}
.el-input__inner {
color: var(--theme-text-color-primary);
font-size: 16px;
&::placeholder {
color: var(--theme-text-color-secondary);
opacity: 0.7;
}
}
.el-input__prefix,
.el-input__suffix {
color: var(--theme-text-color-secondary);
}
}
}
.register-content {
padding: 40px 30px;
.btn-row {
margin-top: 32px;
.el-button {
&[type="primary"],
&.register-btn {
width: 100%;
height: 48px;
border-radius: 12px;
background: var(--btnColor);
border: none;
font-size: 16px;
font-weight: 500;
transition: all 0.3s ease;
box-shadow: 0 4px 16px rgba(91, 98, 206, 0.3);
&:hover {
transform: translateY(-2px);
box-shadow: 0 8px 24px rgba(91, 98, 206, 0.4);
}
&:active {
transform: translateY(0);
}
}
}
}
.text {
margin-top: 24px;
color: var(--theme-text-color-secondary);
.el-button {
color: var(--text-color-primary);
background: transparent;
border: none;
padding: 0 8px;
font-size: 14px;
&:hover {
background: var(--btn-bg);
border-radius: 6px;
}
&.forget {
color: var(--theme-text-color-secondary);
&:hover {
color: var(--text-color-primary);
}
}
}
}
// 验证码输入框样式
.verify-code {
.el-row {
.el-col:first-child {
.el-input__wrapper {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
}
.el-col:last-child {
.el-button {
height: 40px;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
border-left: none;
background: var(--btn-bg);
color: var(--theme-text-color-primary);
border: 1px solid var(--line-box);
font-size: 14px;
&:hover {
background: var(--hover-deep-color);
color: var(--text-color-primary);
}
&:disabled {
opacity: 0.6;
cursor: not-allowed;
}
}
}
}
}
// 邀请码输入框样式
.invite-code {
.el-input__wrapper {
background: var(--quote-bg-color);
border-color: var(--border-active);
}
}
// 协议条款样式
.agreement {
display: flex;
align-items: flex-start;
margin-bottom: 20px;
font-size: 14px;
color: var(--theme-text-color-secondary);
line-height: 1.5;
.el-checkbox {
margin-right: 8px;
flex-shrink: 0;
:deep(.el-checkbox__inner) {
border-color: var(--line-box);
background: var(--el-fill-color-blank);
&:hover {
border-color: var(--border-active);
}
}
:deep(.el-checkbox__input.is-checked) {
.el-checkbox__inner {
background: var(--btnColor);
border-color: var(--border-active);
}
}
}
a {
color: var(--text-color-primary);
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
}
}
}
}
// 深色主题适配
:deep(.van-theme-dark) {
.register-page {
.register-card {
background: var(--el-bg-color-overlay);
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
}
}
}
// 移动端响应式设计
// 移动端适配
@media (max-width: 768px) {
.register-page {
padding: 16px;
background: var(--van-background);
}
.back-home-btn {
top: 16px;
left: 16px;
font-size: 20px;
.back-home-btn {
top: 16px;
left: 16px;
width: 40px;
height: 40px;
.iconfont {
font-size: 18px;
}
}
.register-container {
max-width: 100%;
.register-card {
padding: 32px 24px;
border-radius: 16px;
margin-top: 60px;
}
.register-card {
border-radius: 20px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
.register-title {
font-size: 24px;
}
.register-header {
padding: 30px 20px;
background: linear-gradient(135deg, #10b981, #059669);
.register-subtitle {
font-size: 15px;
}
.register-title {
font-size: 24px;
}
.register-content {
:deep(.login-dialog) {
.form {
.block {
margin-bottom: 18px;
.register-subtitle {
font-size: 14px;
.el-input {
.el-input__wrapper {
border-radius: 10px;
}
.el-input__inner {
font-size: 16px;
}
}
}
.register-content {
padding: 30px 20px;
.btn-row {
margin-top: 28px;
.el-button {
&[type="primary"],
&.register-btn {
height: 46px;
border-radius: 10px;
font-size: 15px;
}
}
}
.text {
margin-top: 20px;
font-size: 13px;
.el-button {
font-size: 13px;
padding: 0 6px;
}
}
.verify-code {
.el-row {
.el-col:last-child {
.el-button {
height: 38px;
font-size: 13px;
}
}
}
}
.agreement {
font-size: 13px;
}
}
}
}
}
// 小屏幕移动端优化
@media (max-width: 375px) {
.register-page {
padding: 12px;
// 小屏幕手机适配
@media (max-width: 480px) {
.register-card {
padding: 24px 20px;
}
.back-home-btn {
top: 12px;
left: 12px;
font-size: 18px;
}
.register-title {
font-size: 22px;
}
.register-container {
.register-card {
.register-header {
padding: 24px 16px;
.register-subtitle {
font-size: 14px;
}
.register-title {
font-size: 22px;
}
.register-subtitle {
font-size: 13px;
.register-content {
:deep(.login-dialog) {
.form {
.verify-code {
.el-row {
.el-col:first-child {
padding-right: 0;
}
.el-col:last-child {
padding-left: 0;
margin-top: 10px;
.el-button {
width: 100%;
border-radius: 10px;
border-left: 1px solid var(--line-box);
}
}
}
}
.register-content {
padding: 24px 16px;
.agreement {
font-size: 12px;
}
}
}

View File

@@ -56,7 +56,7 @@
<!-- 图生图参数 -->
<div class="bg-white rounded-xl p-4 shadow-sm mb-3" v-if="jimengStore.useImageInput">
<ImageUpload
v-model="jimengStore.imageToImageParams.image_input[0]"
v-model="jimengStore.imageToImageParams.image_input"
:max-count="1"
:multiple="false"
/>
@@ -220,16 +220,13 @@
<div class="bg-white rounded-xl p-4 shadow-sm mb-3">
<div class="flex justify-between items-center w-full">
<label class="text-gray-700 font-semibold">使用图片辅助生成</label>
<el-switch v-model="jimengStore.textToVideoParams.use_image_input" size="default" />
<el-switch v-model="jimengStore.useImageInput" size="default" />
</div>
</div>
<div
class="bg-white rounded-xl p-4 shadow-sm mb-3"
v-if="jimengStore.textToVideoParams.use_image_input"
>
<div class="bg-white rounded-xl p-4 shadow-sm mb-3" v-if="jimengStore.useImageInput">
<ImageUpload
v-model="jimengStore.textToVideoParams.image_input"
v-model="jimengStore.imageToVideoParams.image_input"
:max-count="2"
:multiple="true"
/>
@@ -268,7 +265,7 @@
<!-- 作品列表 -->
<div class="jimeng-create__works">
<h2 class="jimeng-create__works-title">我的作品</h2>
<div class="jimeng-create__works-list space-y-4">
<div class="jimeng-create__works-list space-y-4" v-if="jimengStore.currentList.length > 0">
<div
v-for="item in jimengStore.currentList"
:key="item.id"
@@ -290,6 +287,28 @@
</div>
</template>
</el-image>
<div
v-else-if="item.video_url"
class="jimeng-create__works-item-thumb-placeholder relative"
>
<video
:src="item.video_url"
preload="auto"
loop="loop"
muted="muted"
class="w-full h-full object-cover"
>
您的浏览器不支持视频播放
</video>
<div
class="video-mask absolute top-0 left-0 w-full h-full flex justify-center items-center"
@click="jimengStore.playMedia(item)"
>
<div class="play-btn">
<img src="/images/play.svg" alt="播放" />
</div>
</div>
</div>
<div v-else class="jimeng-create__works-item-thumb-placeholder">
<i
:class="
@@ -297,18 +316,6 @@
"
></i>
</div>
<!-- 播放/查看按钮 -->
<button
v-if="item.status === 'completed'"
@click="jimengStore.playMedia(item)"
class="jimeng-create__works-item-thumb-overlay"
>
<i
:class="
item.type.includes('video') ? 'iconfont icon-play' : 'iconfont icon-eye'
"
></i>
</button>
<!-- 失败状态 -->
<div
@@ -371,50 +378,44 @@
<!-- 快捷操作按钮 -->
<div class="jimeng-create__works-item-quick-actions">
<!-- 复制提示词 -->
<button
v-if="item.prompt"
@click="jimengStore.copyPrompt(item.prompt)"
class="jimeng-create__works-item-quick-action-btn"
title="复制提示词"
>
<i class="iconfont icon-copy"></i>
</button>
<span v-if="item.status === 'success'">
<!-- 画同款 -->
<span v-if="item.status === 'success'" class="flex">
<!-- 复制提示词 -->
<button
@click="jimengStore.drawSame(item)"
v-if="item.prompt"
@click="jimengStore.copyPrompt(item.prompt)"
class="jimeng-create__works-item-quick-action-btn"
title="画同款"
title="复制提示词"
>
<i class="iconfont icon-image-list"></i>
<i class="iconfont icon-copy"></i>
</button>
<!-- 下载 -->
<button
v-if="item.status === 'completed' && (item.img_url || item.video_url)"
v-if="item.status === 'success' && (item.img_url || item.video_url)"
@click="jimengStore.downloadFile(item)"
:disabled="item.downloading"
class="jimeng-create__works-item-quick-action-btn"
title="下载"
class="p-2 text-blue-500"
>
<i v-if="item.downloading" class="iconfont icon-loading animate-spin"></i>
<i v-else class="iconfont icon-download"></i></button
></span>
<i v-else class="iconfont icon-download"></i>
<span class="ml-1">下载</span>
</button>
</span>
<!-- 重试 -->
<button
v-if="item.status === 'failed'"
@click="jimengStore.retryTask(item.id)"
class="jimeng-create__works-item-quick-action-btn"
title="重试"
class="p-2 text-green-500"
>
<i class="iconfont icon-refresh"></i>
<span class="ml-1">重试</span>
</button>
<!-- 删除 -->
<button @click="jimengStore.removeJob(item)" class="p-2">
<i class="iconfont icon-remove"></i> 删除
<button @click="jimengStore.removeJob(item)" class="p-2 text-red-500">
<i class="iconfont icon-remove"></i>
<span class="ml-1">删除</span>
</button>
</div>
@@ -424,7 +425,9 @@
class="jimeng-create__works-item-error"
>
<div class="jimeng-create__works-item-error-content">
<span class="jimeng-create__works-item-error-text">{{ item.err_msg }}</span>
<span class="jimeng-create__works-item-error-text line-clamp-3">{{
item.err_msg
}}</span>
<button
@click="jimengStore.copyErrorMsg(item.err_msg)"
class="jimeng-create__works-item-error-copy-btn"
@@ -449,6 +452,10 @@
没有更多了
</div>
</div>
<div class="px-4" v-else>
<van-empty description="暂无数据" image-size="120" />
</div>
</div>
<!-- 媒体预览弹窗 -->
@@ -461,21 +468,15 @@
<div class="jimeng-create__media-dialog-header">
<h3>媒体预览</h3>
<button @click="jimengStore.closeMediaDialog">
<i class="iconfont icon-close"></i>
<i class="iconfont icon-error"></i>
</button>
</div>
<div class="jimeng-create__media-dialog-body">
<img
v-if="jimengStore.currentMediaUrl && !jimengStore.currentMediaUrl.includes('video')"
:src="jimengStore.currentMediaUrl"
class="w-full max-h-[60vh] object-contain rounded-lg"
/>
<video
v-else-if="jimengStore.currentMediaUrl"
:src="jimengStore.currentMediaUrl"
controls
autoplay
class="w-full max-h-[60vh] rounded-lg"
class="w-full max-h-[60vh] rounded-lg object-cover"
>
您的浏览器不支持视频播放
</video>
@@ -535,5 +536,5 @@ const goBack = () => {
</script>
<style lang="scss" scoped>
@import '@/assets/css/mobile/jimeng.scss';
@use '@/assets/css/mobile/jimeng.scss';
</style>

View File

@@ -16,9 +16,12 @@
</div>
</div>
<div class="login-prompt" v-else>
<el-button type="primary" size="large" @click="router.push('/mobile/login')"
>立即登录</el-button
<button
class="py-3 px-5 bg-gradient-to-r from-green-400 to-blue-400 text-white rounded-xl disabled:from-gray-400 disabled:to-gray-400 disabled:cursor-not-allowed hover:from-green-500 hover:to-blue-500 transition-all duration-200 flex items-center justify-center space-x-2"
@click="router.push('/login')"
>
立即登录
</button>
</div>
</div>
</div>
@@ -278,7 +281,6 @@ onMounted(() => {
})
.catch(() => {
isLogin.value = false
showLoginDialog(router)
})
})

View File

@@ -233,7 +233,7 @@
<!-- 作品列表 -->
<div class="p-4">
<h2 class="text-lg font-semibold text-gray-900 mb-4">我的作品</h2>
<div class="space-y-4">
<div class="space-y-4" v-if="suno.list.length > 0">
<div v-for="item in suno.list" :key="item.id" class="bg-white rounded-xl p-4 shadow-sm">
<div class="flex space-x-4">
<div class="flex-shrink-0">
@@ -447,6 +447,10 @@
没有更多了
</div>
</div>
<div class="px-4" v-else>
<van-empty description="暂无数据" image-size="120" />
</div>
</div>
<!-- 音乐播放器 -->
@@ -496,6 +500,7 @@ import CustomSelect from '@/components/mobile/CustomSelect.vue'
import { useSunoStore } from '@/store/mobile/suno'
import { onMounted, onUnmounted } from 'vue'
import { useRouter } from 'vue-router'
import { checkSession } from '@/store/cache'
const router = useRouter()
const suno = useSunoStore()
@@ -523,13 +528,19 @@ const handleScroll = () => {
let tastPullHandler = null
onMounted(() => {
suno.fetchData(1)
tastPullHandler = setInterval(() => {
if (suno.taskPulling) {
suno.refreshFirstPage()
}
}, 5000)
window.addEventListener('scroll', handleScroll)
checkSession()
.then(() => {
suno.fetchData(1)
tastPullHandler = setInterval(() => {
if (suno.taskPulling) {
suno.refreshFirstPage()
}
}, 5000)
window.addEventListener('scroll', handleScroll)
})
.catch(() => {
console.warn('用户未登录')
})
})
onUnmounted(() => {
if (tastPullHandler) clearInterval(tastPullHandler)
@@ -538,128 +549,5 @@ onUnmounted(() => {
</script>
<style lang="scss" scoped>
/* 自定义动画 */
@keyframes fade-in {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes fade-out {
from {
opacity: 1;
transform: translateY(0);
}
to {
opacity: 0;
transform: translateY(-10px);
}
}
@keyframes slide-up {
from {
opacity: 0;
transform: translateY(100%);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes scale-up {
from {
opacity: 0;
transform: scale(0.9);
}
to {
opacity: 1;
transform: scale(1);
}
}
.animate-fade-in {
animation: fade-in 0.3s ease-out;
}
.animate-fade-out {
animation: fade-out 0.3s ease-out;
}
.animate-slide-up {
animation: slide-up 0.3s ease-out;
}
.animate-scale-up {
animation: scale-up 0.3s ease-out;
}
/* 文本截断 */
.line-clamp-2 {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
/* 滚动监听自动加载更多 */
.scroll-container {
height: 100vh;
overflow-y: auto;
}
/* 深色模式适配 */
@media (prefers-color-scheme: dark) {
.bg-gray-50 {
background-color: #1f2937;
}
.bg-white {
background-color: #374151;
}
.text-gray-900 {
color: #f9fafb;
}
.text-gray-700 {
color: #d1d5db;
}
.text-gray-600 {
color: #9ca3af;
}
.text-gray-500 {
color: #6b7280;
}
.border-gray-200 {
border-color: #4b5563;
}
.bg-gray-100:hover {
background-color: #4b5563;
}
}
/* el-upload 组件样式定制 */
.upload-area {
width: 100%;
:deep(.el-upload) {
width: 100%;
display: block;
}
:deep(.el-button) {
width: 100%;
display: block;
}
}
@use '@/assets/css/mobile/suno.scss';
</style>

View File

@@ -438,7 +438,7 @@
<!-- 作品列表 -->
<div class="p-4">
<h2 class="text-lg font-semibold text-gray-900 mb-4">我的作品</h2>
<div class="space-y-4">
<div class="space-y-4" v-if="video.currentList.length > 0">
<div
v-for="item in video.currentList"
:key="item.id"
@@ -573,6 +573,10 @@
没有更多了
</div>
</div>
<div class="px-4" v-else>
<van-empty description="暂无数据" image-size="120" />
</div>
</div>
<!-- 视频预览弹窗 -->
@@ -611,6 +615,7 @@ import { useVideoStore } from '@/store/mobile/video'
import { showConfirmDialog } from 'vant'
import { onMounted, onUnmounted } from 'vue'
import { useRouter } from 'vue-router'
import { checkSession } from '@/store/cache'
const router = useRouter()
const video = useVideoStore()
@@ -623,13 +628,17 @@ const goBack = () => {
// 定时轮询等副作用
let tastPullHandler = null
onMounted(() => {
video.fetchData(1)
video.fetchUserPower()
tastPullHandler = setInterval(() => {
if (video.taskPulling) {
checkSession()
.then(() => {
video.fetchData(1)
}
}, 5000)
video.fetchUserPower()
tastPullHandler = setInterval(() => {
if (video.taskPulling) {
video.fetchData(1)
}
}, 5000)
})
.catch(() => {})
})
onUnmounted(() => {
if (tastPullHandler) clearInterval(tastPullHandler)