Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
Y
yaoai-video
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
姚珂
yaoai-video
Commits
2cdd280b
Commit
2cdd280b
authored
May 20, 2026
by
yaoke.yk
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
页面整体调整
parent
3cd16618
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
241 additions
and
11 deletions
+241
-11
Layout.tsx
doc/html/src/app/components/Layout.tsx
+0
-0
Dashboard.tsx
doc/html/src/app/pages/Dashboard.tsx
+0
-0
LoginPage.tsx
doc/html/src/app/pages/LoginPage.tsx
+22
-6
NewProject.tsx
doc/html/src/app/pages/NewProject.tsx
+0
-0
OutlineGeneration.tsx
doc/html/src/app/pages/OutlineGeneration.tsx
+165
-4
useAi.ts
doc/html/src/hooks/useAi.ts
+9
-1
ai.ts
doc/html/src/lib/api/ai.ts
+4
-0
theme.css
doc/html/src/styles/theme.css
+9
-0
OutlineController.java
...main/java/com/yaoai/api/controller/OutlineController.java
+9
-0
OutlinePipelineService.java
...va/com/yaoai/pipeline/service/OutlinePipelineService.java
+5
-0
OutlinePipelineServiceImpl.java
...oai/pipeline/service/impl/OutlinePipelineServiceImpl.java
+18
-0
No files found.
doc/html/src/app/components/Layout.tsx
View file @
2cdd280b
This diff is collapsed.
Click to expand it.
doc/html/src/app/pages/Dashboard.tsx
View file @
2cdd280b
This diff is collapsed.
Click to expand it.
doc/html/src/app/pages/LoginPage.tsx
View file @
2cdd280b
...
@@ -9,10 +9,20 @@ import { useAuth } from "../../hooks/useAuth";
...
@@ -9,10 +9,20 @@ import { useAuth } from "../../hooks/useAuth";
export
function
LoginPage
()
{
export
function
LoginPage
()
{
const
{
login
,
loginPending
,
loginError
}
=
useAuth
();
const
{
login
,
loginPending
,
loginError
}
=
useAuth
();
const
[
form
,
setForm
]
=
useState
({
email
:
""
,
password
:
""
});
const
[
form
,
setForm
]
=
useState
({
email
:
""
,
password
:
""
});
const
[
formError
,
setFormError
]
=
useState
<
string
|
null
>
(
null
);
const
handleSubmit
=
(
e
:
React
.
FormEvent
)
=>
{
const
handleSubmit
=
(
e
:
React
.
FormEvent
)
=>
{
e
.
preventDefault
();
e
.
preventDefault
();
login
(
form
);
const
email
=
form
.
email
.
trim
();
const
password
=
form
.
password
.
trim
();
if
(
!
email
||
!
password
)
{
setFormError
(
"请输入邮箱和密码"
);
return
;
}
setFormError
(
null
);
login
({
email
,
password
});
};
};
return
(
return
(
...
@@ -23,7 +33,7 @@ export function LoginPage() {
...
@@ -23,7 +33,7 @@ export function LoginPage() {
<
CardDescription
>
登录您的账号
</
CardDescription
>
<
CardDescription
>
登录您的账号
</
CardDescription
>
</
CardHeader
>
</
CardHeader
>
<
CardContent
>
<
CardContent
>
<
form
onSubmit=
{
handleSubmit
}
className=
"space-y-4"
>
<
form
onSubmit=
{
handleSubmit
}
className=
"space-y-4"
noValidate
>
<
div
className=
"space-y-2"
>
<
div
className=
"space-y-2"
>
<
Label
htmlFor=
"email"
>
邮箱
</
Label
>
<
Label
htmlFor=
"email"
>
邮箱
</
Label
>
<
Input
<
Input
...
@@ -32,7 +42,10 @@ export function LoginPage() {
...
@@ -32,7 +42,10 @@ export function LoginPage() {
placeholder=
"you@example.com"
placeholder=
"you@example.com"
required
required
value=
{
form
.
email
}
value=
{
form
.
email
}
onChange=
{
(
e
)
=>
setForm
((
f
)
=>
({
...
f
,
email
:
e
.
target
.
value
}))
}
onChange=
{
(
e
)
=>
{
setFormError
(
null
);
setForm
((
f
)
=>
({
...
f
,
email
:
e
.
target
.
value
}));
}
}
/>
/>
</
div
>
</
div
>
<
div
className=
"space-y-2"
>
<
div
className=
"space-y-2"
>
...
@@ -43,13 +56,16 @@ export function LoginPage() {
...
@@ -43,13 +56,16 @@ export function LoginPage() {
placeholder=
"••••••••"
placeholder=
"••••••••"
required
required
value=
{
form
.
password
}
value=
{
form
.
password
}
onChange=
{
(
e
)
=>
setForm
((
f
)
=>
({
...
f
,
password
:
e
.
target
.
value
}))
}
onChange=
{
(
e
)
=>
{
setFormError
(
null
);
setForm
((
f
)
=>
({
...
f
,
password
:
e
.
target
.
value
}));
}
}
/>
/>
</
div
>
</
div
>
{
loginError
&&
(
{
(
formError
||
loginError
)
&&
(
<
p
className=
"text-sm text-destructive"
>
<
p
className=
"text-sm text-destructive"
>
{
loginError
instanceof
Error
?
loginError
.
message
:
"登录失败"
}
{
formError
??
(
loginError
instanceof
Error
?
loginError
.
message
:
"登录失败"
)
}
</
p
>
</
p
>
)
}
)
}
...
...
doc/html/src/app/pages/NewProject.tsx
View file @
2cdd280b
This diff is collapsed.
Click to expand it.
doc/html/src/app/pages/OutlineGeneration.tsx
View file @
2cdd280b
This diff is collapsed.
Click to expand it.
doc/html/src/hooks/useAi.ts
View file @
2cdd280b
import
{
useMutation
,
useQuery
,
useQueryClient
}
from
"@tanstack/react-query"
;
import
{
useMutation
,
useQuery
,
useQueryClient
}
from
"@tanstack/react-query"
;
import
{
aiApi
}
from
"../lib/api/ai"
;
import
{
aiApi
}
from
"../lib/api/ai"
;
import
type
{
Character
,
Episode
,
Scene
,
Storyboard
,
StructuredVideoRequest
}
from
"../lib/api/ai"
;
import
type
{
Character
,
Episode
,
Outline
,
Scene
,
Storyboard
,
StructuredVideoRequest
}
from
"../lib/api/ai"
;
// ---- Characters ----
// ---- Characters ----
const
charactersKey
=
(
pid
:
string
)
=>
[
"characters"
,
pid
];
const
charactersKey
=
(
pid
:
string
)
=>
[
"characters"
,
pid
];
...
@@ -84,6 +84,14 @@ export function useGenerateOutline(projectId: string) {
...
@@ -84,6 +84,14 @@ export function useGenerateOutline(projectId: string) {
});
});
}
}
export
function
useUpdateOutline
(
projectId
:
string
)
{
const
qc
=
useQueryClient
();
return
useMutation
({
mutationFn
:
(
patch
:
Partial
<
Outline
>
)
=>
aiApi
.
updateOutline
(
projectId
,
patch
),
onSuccess
:
()
=>
qc
.
invalidateQueries
({
queryKey
:
outlineKey
(
projectId
)
}),
});
}
// ---- Episodes ----
// ---- Episodes ----
export
function
useEpisodes
(
projectId
:
string
)
{
export
function
useEpisodes
(
projectId
:
string
)
{
return
useQuery
({
return
useQuery
({
...
...
doc/html/src/lib/api/ai.ts
View file @
2cdd280b
...
@@ -152,6 +152,10 @@ export const aiApi = {
...
@@ -152,6 +152,10 @@ export const aiApi = {
const
r
=
await
apiClient
.
get
(
`/projects/
${
projectId
}
/outline`
);
const
r
=
await
apiClient
.
get
(
`/projects/
${
projectId
}
/outline`
);
return
r
.
data
.
data
;
return
r
.
data
.
data
;
},
},
updateOutline
:
async
(
projectId
:
string
,
patch
:
Partial
<
Outline
>
):
Promise
<
Outline
>
=>
{
const
r
=
await
apiClient
.
put
(
`/projects/
${
projectId
}
/outline`
,
patch
);
return
r
.
data
.
data
;
},
// ---- Episodes ----
// ---- Episodes ----
generateEpisodes
:
async
(
projectId
:
string
):
Promise
<
Episode
[]
>
=>
{
generateEpisodes
:
async
(
projectId
:
string
):
Promise
<
Episode
[]
>
=>
{
...
...
doc/html/src/styles/theme.css
View file @
2cdd280b
...
@@ -137,6 +137,15 @@
...
@@ -137,6 +137,15 @@
font-size
:
var
(
--font-size
);
font-size
:
var
(
--font-size
);
}
}
html
,
body
,
#root
{
width
:
100%
;
min-width
:
0
;
height
:
100%
;
margin
:
0
;
}
h1
{
h1
{
font-size
:
var
(
--text-2xl
);
font-size
:
var
(
--text-2xl
);
font-weight
:
var
(
--font-weight-medium
);
font-weight
:
var
(
--font-weight-medium
);
...
...
yaoai-comic-studio/yaoai-api/src/main/java/com/yaoai/api/controller/OutlineController.java
View file @
2cdd280b
...
@@ -52,6 +52,15 @@ public class OutlineController {
...
@@ -52,6 +52,15 @@ public class OutlineController {
return
ApiResponse
.
success
(
OutlineDTO
.
from
(
outline
));
return
ApiResponse
.
success
(
OutlineDTO
.
from
(
outline
));
}
}
@Operation
(
summary
=
"编辑项目大纲"
)
@PutMapping
(
"/outline"
)
public
ApiResponse
<
OutlineDTO
>
updateOutline
(
@PathVariable
Long
projectId
,
@RequestBody
Outline
req
)
{
Long
tenantId
=
TenantContext
.
get
();
Outline
outline
=
outlinePipelineService
.
updateOutline
(
projectId
,
tenantId
,
req
);
return
ApiResponse
.
success
(
OutlineDTO
.
from
(
outline
));
}
@Operation
(
summary
=
"生成分集内容(使用最新大纲)"
)
@Operation
(
summary
=
"生成分集内容(使用最新大纲)"
)
@PostMapping
(
"/episodes/generate"
)
@PostMapping
(
"/episodes/generate"
)
public
ApiResponse
<
List
<
EpisodeDTO
>>
generateEpisodes
(
@PathVariable
Long
projectId
)
{
public
ApiResponse
<
List
<
EpisodeDTO
>>
generateEpisodes
(
@PathVariable
Long
projectId
)
{
...
...
yaoai-comic-studio/yaoai-pipeline/src/main/java/com/yaoai/pipeline/service/OutlinePipelineService.java
View file @
2cdd280b
...
@@ -19,6 +19,11 @@ public interface OutlinePipelineService {
...
@@ -19,6 +19,11 @@ public interface OutlinePipelineService {
Outline
getOutline
(
Long
projectId
,
Long
tenantId
);
Outline
getOutline
(
Long
projectId
,
Long
tenantId
);
/**
* 手动编辑大纲基础信息(title/genre/synopsis/episodeCount,非 null 字段才更新)。
*/
Outline
updateOutline
(
Long
projectId
,
Long
tenantId
,
Outline
req
);
List
<
Episode
>
getEpisodes
(
Long
projectId
,
Long
tenantId
);
List
<
Episode
>
getEpisodes
(
Long
projectId
,
Long
tenantId
);
/**
/**
...
...
yaoai-comic-studio/yaoai-pipeline/src/main/java/com/yaoai/pipeline/service/impl/OutlinePipelineServiceImpl.java
View file @
2cdd280b
...
@@ -205,6 +205,24 @@ public class OutlinePipelineServiceImpl implements OutlinePipelineService {
...
@@ -205,6 +205,24 @@ public class OutlinePipelineServiceImpl implements OutlinePipelineService {
}
}
@Override
@Override
public
Outline
updateOutline
(
Long
projectId
,
Long
tenantId
,
Outline
req
)
{
Outline
existing
=
outlineMapper
.
findLatestByProject
(
projectId
,
tenantId
);
if
(
existing
==
null
)
{
throw
new
BizException
(
ErrorCode
.
NOT_FOUND
,
"大纲不存在,请先生成或保存大纲"
);
}
if
(
req
.
getTitle
()
!=
null
)
existing
.
setTitle
(
req
.
getTitle
());
if
(
req
.
getGenre
()
!=
null
)
existing
.
setGenre
(
req
.
getGenre
());
if
(
req
.
getSynopsis
()
!=
null
)
existing
.
setSynopsis
(
req
.
getSynopsis
());
if
(
req
.
getEpisodeCount
()
!=
null
&&
req
.
getEpisodeCount
()
>
0
)
{
existing
.
setEpisodeCount
(
req
.
getEpisodeCount
());
}
existing
.
setStatus
(
"ready"
);
outlineMapper
.
updateById
(
existing
);
log
.
info
(
"Outline updated: id={}, projectId={}"
,
existing
.
getId
(),
projectId
);
return
existing
;
}
@Override
public
List
<
Episode
>
getEpisodes
(
Long
projectId
,
Long
tenantId
)
{
public
List
<
Episode
>
getEpisodes
(
Long
projectId
,
Long
tenantId
)
{
return
episodeMapper
.
findByProject
(
projectId
,
tenantId
);
return
episodeMapper
.
findByProject
(
projectId
,
tenantId
);
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment