Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
C
center-book
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
EzijingWeb
center-book
Commits
8f59c494
提交
8f59c494
authored
7月 20, 2026
作者:
王鹏飞
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
refactor(admin): migrate books discussion module
上级
b2266adf
显示空白字符变更
内嵌
并排
正在显示
6 个修改的文件
包含
325 行增加
和
2 行删除
+325
-2
api.ts
apps/admin/src/modules/books/discussion/api.ts
+26
-0
query.ts
apps/admin/src/modules/books/discussion/query.ts
+27
-0
routes.tsx
apps/admin/src/modules/books/discussion/routes.tsx
+8
-0
useDiscussionList.ts
apps/admin/src/modules/books/discussion/useDiscussionList.ts
+64
-0
DiscussionView.tsx
...min/src/modules/books/discussion/views/DiscussionView.tsx
+198
-0
routes.tsx
apps/admin/src/modules/books/routes.tsx
+2
-2
没有找到文件。
apps/admin/src/modules/books/discussion/api.ts
0 → 100644
浏览文件 @
8f59c494
import
{
message
}
from
"antd"
;
import
request
from
"@/utils/request"
;
import
type
{
DiscussionQuery
}
from
"./query"
;
async
function
post
(
path
:
string
,
data
:
Record
<
string
,
unknown
>
,
notify
=
false
)
{
try
{
const
r
=
(
await
request
.
post
(
path
,
new
URLSearchParams
(
data
as
Record
<
string
,
string
>
).
toString
(),
))
as
{
data
?:
{
code
?:
number
;
data
?:
any
;
message
?:
string
}
};
if
(
r
.
data
?.
code
===
200
)
{
if
(
notify
)
message
.
success
(
r
.
data
.
message
);
return
r
.
data
.
data
;
}
message
.
error
(
r
.
data
?.
message
||
"数据获取失败!"
);
}
catch
{}
return
false
;
}
export
const
getDiscussionList
=
(
q
:
DiscussionQuery
)
=>
post
(
"/comment/comment/getAllCommentList"
,
q
);
export
const
deleteComment
=
(
id
:
any
,
book_id
:
any
)
=>
post
(
"/comment/comment/delComment"
,
{
id
,
book_id
},
true
);
export
const
changeCommentStatus
=
(
data
:
any
)
=>
post
(
"/comment/comment/changeStatus"
,
data
,
true
);
export
const
getBooks
=
()
=>
post
(
"/book/book/getAllList"
,
{});
export
const
getDiscussionSystem
=
()
=>
post
(
"/system/config/getSystem"
,
{
type
:
3
});
export
const
editDiscussionSystem
=
(
set_value
:
string
)
=>
post
(
"/system/config/systemEdit"
,
{
type
:
3
,
set_value
},
true
);
apps/admin/src/modules/books/discussion/query.ts
0 → 100644
浏览文件 @
8f59c494
import
type
{
Dayjs
}
from
"dayjs"
;
export
interface
DiscussionFilters
{
book_id
?:
any
;
title
?:
string
;
time
?:
[
Dayjs
|
null
,
Dayjs
|
null
]
|
null
;
}
export
interface
DiscussionQuery
{
page
:
number
;
page_size
:
number
;
book_id
?:
any
;
title
?:
string
;
start_time
?:
number
;
end_time
?:
number
;
}
export
function
buildDiscussionQuery
(
page
:
number
,
pageSize
:
number
,
f
:
DiscussionFilters
,
):
DiscussionQuery
{
const
q
:
DiscussionQuery
=
{
page
,
page_size
:
pageSize
,
book_id
:
f
.
book_id
};
if
(
f
.
title
)
q
.
title
=
f
.
title
;
if
(
f
.
time
?.[
0
]
&&
f
.
time
[
1
])
{
q
.
start_time
=
f
.
time
[
0
].
startOf
(
"day"
).
unix
();
q
.
end_time
=
f
.
time
[
1
].
endOf
(
"day"
).
unix
();
}
return
q
;
}
apps/admin/src/modules/books/discussion/routes.tsx
0 → 100644
浏览文件 @
8f59c494
import
{
Navigate
,
useRoutes
}
from
"react-router"
;
import
DiscussionView
from
"./views/DiscussionView"
;
export
default
function
DiscussionRoutes
()
{
return
useRoutes
([
{
index
:
true
,
Component
:
DiscussionView
},
{
path
:
"*"
,
element
:
<
Navigate
to=
"/books/discussion"
/>
},
]);
}
apps/admin/src/modules/books/discussion/useDiscussionList.ts
0 → 100644
浏览文件 @
8f59c494
import
{
useCallback
,
useEffect
,
useRef
,
useState
}
from
"react"
;
import
{
getDiscussionList
}
from
"./api"
;
import
{
buildDiscussionQuery
,
type
DiscussionFilters
,
type
DiscussionQuery
}
from
"./query"
;
export
function
useDiscussionList
(
initialBook
?:
any
)
{
const
[
filters
,
setFilters
]
=
useState
<
DiscussionFilters
>
({
book_id
:
initialBook
});
const
[
page
,
setPage
]
=
useState
(
1
);
const
[
pageSize
,
setPageSize
]
=
useState
(
10
);
const
[
rows
,
setRows
]
=
useState
<
any
[]
>
([]);
const
[
total
,
setTotal
]
=
useState
(
0
);
const
[
loading
,
setLoading
]
=
useState
(
true
);
const
[
error
,
setError
]
=
useState
<
Error
|
null
>
(
null
);
const
last
=
useRef
<
DiscussionQuery
>
(
buildDiscussionQuery
(
1
,
10
,
{
book_id
:
initialBook
}));
const
load
=
useCallback
(
async
(
q
:
DiscussionQuery
)
=>
{
last
.
current
=
q
;
setLoading
(
true
);
try
{
const
r
:
any
=
await
getDiscussionList
(
q
);
if
(
!
r
)
throw
new
Error
(
"请求失败"
);
setRows
(
r
.
list
||
[]);
setTotal
(
r
.
total
||
0
);
setError
(
null
);
}
catch
(
e
)
{
setError
(
e
instanceof
Error
?
e
:
new
Error
(
"请求失败"
));
}
finally
{
setLoading
(
false
);
}
},
[]);
useEffect
(()
=>
{
if
(
filters
.
book_id
)
void
load
(
last
.
current
);
},
[
filters
.
book_id
,
load
]);
const
run
=
(
p
:
number
,
s
:
number
,
f
=
filters
)
=>
void
load
(
buildDiscussionQuery
(
p
,
s
,
f
));
const
search
=
()
=>
{
setPage
(
1
);
run
(
1
,
pageSize
);
};
return
{
filters
,
setFilters
,
page
,
pageSize
,
rows
,
total
,
loading
,
error
,
search
,
reset
:
()
=>
{
const
f
=
{
book_id
:
filters
.
book_id
};
setFilters
(
f
);
setPage
(
1
);
run
(
1
,
pageSize
,
f
);
},
refresh
:
()
=>
run
(
page
,
pageSize
),
retry
:
()
=>
void
load
(
last
.
current
),
changePage
:
(
p
:
number
)
=>
{
setPage
(
p
);
run
(
p
,
pageSize
);
},
changePageSize
:
(
s
:
number
)
=>
{
setPage
(
1
);
setPageSize
(
s
);
run
(
1
,
s
);
},
};
}
apps/admin/src/modules/books/discussion/views/DiscussionView.tsx
0 → 100644
浏览文件 @
8f59c494
import
{
App
,
Button
,
DatePicker
,
Drawer
,
Form
,
Image
,
Input
,
Radio
,
Select
,
Space
,
Switch
,
}
from
"antd"
;
import
type
{
ColumnsType
}
from
"antd/es/table"
;
import
{
useEffect
,
useState
}
from
"react"
;
import
{
useSelector
}
from
"react-redux"
;
import
{
AppList
,
type
AppListFilterItem
}
from
"@/shared/components/AppList"
;
import
{
changeCommentStatus
,
deleteComment
,
editDiscussionSystem
,
getBooks
,
getDiscussionSystem
,
}
from
"../api"
;
import
type
{
DiscussionFilters
}
from
"../query"
;
import
{
useDiscussionList
}
from
"../useDiscussionList"
;
const
{
RangePicker
}
=
DatePicker
;
export
default
function
DiscussionView
()
{
const
[
books
,
setBooks
]
=
useState
<
any
[]
>
([]);
const
[
systemOpen
,
setSystemOpen
]
=
useState
(
false
);
const
[
form
]
=
Form
.
useForm
();
const
{
modal
}
=
App
.
useApp
();
const
{
operationPermissionsList
=
[]
}
=
useSelector
((
s
:
any
)
=>
s
.
user
);
useEffect
(()
=>
{
void
getBooks
().
then
((
b
:
any
)
=>
b
&&
setBooks
(
b
));
},
[]);
const
list
=
useDiscussionList
(
books
[
0
]?.
id
);
useEffect
(()
=>
{
if
(
books
[
0
]
&&
!
list
.
filters
.
book_id
)
list
.
setFilters
({
...
list
.
filters
,
book_id
:
books
[
0
].
id
});
},
[
books
]);
const
items
:
AppListFilterItem
<
DiscussionFilters
>
[]
=
[
{
name
:
"book_id"
,
label
:
"书籍名称"
,
render
:
(
f
)
=>
(
<
Select
showSearch
value=
{
f
.
value
}
style=
{
{
width
:
160
}
}
onChange=
{
f
.
onChange
}
>
{
books
.
map
((
b
)
=>
(
<
Select
.
Option
key=
{
b
.
id
}
value=
{
b
.
id
}
>
{
b
.
name
}
</
Select
.
Option
>
))
}
</
Select
>
),
},
{
name
:
"title"
,
label
:
"话题"
,
render
:
(
f
)
=>
(
<
Input
allowClear
value=
{
f
.
value
||
""
}
onChange=
{
(
e
)
=>
f
.
onChange
(
e
.
target
.
value
)
}
placeholder=
"请输入话题"
/>
),
},
{
name
:
"time"
,
label
:
"讨论时间"
,
render
:
(
f
)
=>
<
RangePicker
allowClear
value=
{
f
.
value
}
onChange=
{
(
v
)
=>
f
.
onChange
(
v
)
}
/>,
},
];
const
columns
:
ColumnsType
<
any
>
=
[
{
title
:
"ID"
,
dataIndex
:
"id"
},
{
title
:
"书籍名称"
,
dataIndex
:
"name"
},
{
title
:
"话题"
,
dataIndex
:
"title"
,
width
:
200
},
{
title
:
"讨论人"
,
dataIndex
:
"person_name"
},
{
title
:
"讨论时间"
,
dataIndex
:
"create_time"
},
{
title
:
"讨论内容"
,
dataIndex
:
"content"
,
render
:
(
content
:
any
[])
=>
!
content
?.
length
?
"暂无内容"
:
content
.
map
((
x
,
i
)
=>
x
.
types
===
"audio"
?
(
<
audio
controls
key=
{
i
}
>
<
source
src=
{
x
.
content
}
type=
"audio/mp3"
/>
</
audio
>
)
:
x
.
types
===
"image"
?
(
<
Image
height=
{
100
}
src=
{
x
.
content
}
key=
{
i
}
/>
)
:
(
<
span
key=
{
i
}
>
{
x
.
types
===
"text"
?
x
.
content
:
"其他类型"
}
</
span
>
),
),
},
{
title
:
"审核"
,
dataIndex
:
"status"
,
render
:
(
_
,
row
)
=>
(
<
Switch
checked=
{
row
.
status
===
1
}
onChange=
{
async
()
=>
{
if
(
await
changeCommentStatus
({
id
:
row
.
id
,
status
:
row
.
status
===
1
?
2
:
1
,
book_id
:
list
.
filters
.
book_id
,
})
)
list
.
refresh
();
}
}
/>
),
},
{
title
:
"操作"
,
render
:
(
_
,
row
)
=>
operationPermissionsList
.
includes
(
"/books/discussion/delComment"
)
&&
(
<
Button
onClick=
{
()
=>
modal
.
confirm
({
title
:
"提示"
,
content
:
"讨论将永久删除,是否继续?"
,
onOk
:
async
()
=>
{
if
(
await
deleteComment
(
row
.
id
,
list
.
filters
.
book_id
))
list
.
refresh
();
},
})
}
>
删除
</
Button
>
),
},
];
return
(
<
div
>
<
AppList
rowKey=
"id"
columns=
{
columns
}
data=
{
{
rows
:
list
.
rows
,
total
:
list
.
total
,
loading
:
list
.
loading
,
error
:
list
.
error
}
}
filters=
{
{
value
:
list
.
filters
,
items
,
onChange
:
list
.
setFilters
,
onSearch
:
list
.
search
,
onReset
:
list
.
reset
,
onRefresh
:
list
.
refresh
,
}
}
pagination=
{
{
page
:
list
.
page
,
pageSize
:
list
.
pageSize
,
pageSizeOptions
:
[
10
,
20
,
30
,
40
],
onChange
:
list
.
changePage
,
onPageSizeChange
:
list
.
changePageSize
,
}
}
toolbar=
{
operationPermissionsList
.
includes
(
"/books/discussion/getSystem"
)
?
(
<
Button
type=
"primary"
ghost
onClick=
{
async
()
=>
{
const
s
:
any
=
await
getDiscussionSystem
();
form
.
setFieldsValue
({
set_value
:
s
?.
set_value
});
setSystemOpen
(
true
);
}
}
>
审核设置
</
Button
>
)
:
null
}
onRetry=
{
list
.
retry
}
/>
<
Drawer
open=
{
systemOpen
}
onClose=
{
()
=>
setSystemOpen
(
false
)
}
footer=
{
null
}
mask=
{
false
}
>
<
Form
form=
{
form
}
onFinish=
{
async
(
v
)
=>
{
if
(
await
editDiscussionSystem
(
v
.
set_value
))
setSystemOpen
(
false
);
}
}
>
<
Form
.
Item
name=
"set_value"
label=
"评论是否需要审核"
>
<
Radio
.
Group
>
<
Radio
value=
"1"
>
是
</
Radio
>
<
Radio
value=
"0"
>
否
</
Radio
>
</
Radio
.
Group
>
</
Form
.
Item
>
<
Space
>
<
Button
onClick=
{
()
=>
setSystemOpen
(
false
)
}
>
取消
</
Button
>
<
Button
htmlType=
"submit"
type=
"primary"
>
提交
</
Button
>
</
Space
>
</
Form
>
</
Drawer
>
</
div
>
);
}
apps/admin/src/modules/books/routes.tsx
浏览文件 @
8f59c494
...
...
@@ -18,7 +18,7 @@ const SaleEdit = lazy(() => import("@/pages/books/sale/edit"));
const
DiscussList
=
lazy
(()
=>
import
(
"@/pages/books/sale/discussList/index"
));
const
DiscussDetail
=
lazy
(()
=>
import
(
"@/pages/books/sale/discussDetail/index"
));
const
QuestionBank
=
lazy
(()
=>
import
(
"@/pages/books/question-bank/index"
));
const
Discussion
=
lazy
(()
=>
import
(
"@/pages/books/discussion/index
"
));
const
Discussion
Routes
=
lazy
(()
=>
import
(
"./discussion/routes
"
));
const
OrderManagementLayout
=
lazy
(()
=>
import
(
"@/pages/books/order-management/index"
));
const
OrderTable
=
lazy
(()
=>
import
(
"@/pages/books/order-management/tab/table"
));
const
SaleStatistics
=
lazy
(()
=>
import
(
"@/pages/books/order-management/tab/salesStatistics"
));
...
...
@@ -63,7 +63,7 @@ export default function BooksRoutes() {
],
},
{
path
:
"question-bank"
,
Component
:
QuestionBank
},
{
path
:
"discussion
"
,
Component
:
Discussion
},
{
path
:
"discussion
/*"
,
Component
:
DiscussionRoutes
},
{
path
:
"order-management"
,
Component
:
OrderManagementLayout
,
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论