Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
C
center-book
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
EzijingWeb
center-book
Commits
77cf6ebc
提交
77cf6ebc
authored
7月 20, 2026
作者:
王鹏飞
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
refactor(admin): move legacy implementations into modules
上级
9ec935b8
全部展开
隐藏空白字符变更
内嵌
并排
正在显示
85 个修改的文件
包含
2338 行增加
和
20 行删除
+2338
-20
Layout.jsx
apps/admin/src/modules/access/Layout.jsx
+5
-0
api.ts
apps/admin/src/modules/access/role/api.ts
+4
-0
routes.tsx
apps/admin/src/modules/access/routes.tsx
+1
-1
oss.js
apps/admin/src/modules/account/oss.js
+23
-0
AccountView.jsx
apps/admin/src/modules/account/views/AccountView.jsx
+171
-1
Layout.jsx
apps/admin/src/modules/advertisements/Layout.jsx
+5
-0
api.ts
apps/admin/src/modules/advertisements/advert/api.ts
+1
-2
AdvertImageUpload.tsx
...es/advertisements/advert/components/AdvertImageUpload.tsx
+1
-1
routes.tsx
apps/admin/src/modules/advertisements/routes.tsx
+1
-1
api.ts
apps/admin/src/modules/auth/api.ts
+1
-1
login-api.js
apps/admin/src/modules/auth/request/login-api.js
+5
-0
login.js
apps/admin/src/modules/auth/request/login.js
+38
-0
sso-api.js
apps/admin/src/modules/auth/request/sso-api.js
+9
-0
sso.js
apps/admin/src/modules/auth/request/sso.js
+121
-0
AuthLayout.jsx
apps/admin/src/modules/auth/views/AuthLayout.jsx
+20
-1
AuthLayout.less
apps/admin/src/modules/auth/views/AuthLayout.less
+0
-0
LoginView.jsx
apps/admin/src/modules/auth/views/LoginView.jsx
+288
-1
LoginView.less
apps/admin/src/modules/auth/views/LoginView.less
+0
-0
BooksLayout.jsx
apps/admin/src/modules/books/BooksLayout.jsx
+7
-0
audit.less
apps/admin/src/modules/books/audit/audit.less
+33
-0
PreviewModal.jsx
...admin/src/modules/books/audit/components/PreviewModal.jsx
+0
-0
routes.tsx
apps/admin/src/modules/books/audit/routes.tsx
+1
-1
AuditDetailView.tsx
apps/admin/src/modules/books/audit/views/AuditDetailView.tsx
+1
-1
api.ts
apps/admin/src/modules/books/management/api.ts
+14
-0
api.js
apps/admin/src/modules/books/management/chapters/api.js
+56
-0
BindKnowledgeGraph.jsx
...oks/management/chapters/components/BindKnowledgeGraph.jsx
+74
-0
EditChapterEditors.jsx
...oks/management/chapters/components/EditChapterEditors.jsx
+50
-0
form-chapter-title.jsx
...oks/management/chapters/components/form-chapter-title.jsx
+98
-0
index.jsx
apps/admin/src/modules/books/management/chapters/index.jsx
+0
-0
index.less
apps/admin/src/modules/books/management/chapters/index.less
+130
-0
request.js
apps/admin/src/modules/books/management/chapters/request.js
+360
-0
ManagementAddEdit.jsx
...modules/books/management/components/ManagementAddEdit.jsx
+111
-1
ManagementChapter.jsx
...modules/books/management/components/ManagementChapter.jsx
+1
-1
routes.tsx
apps/admin/src/modules/books/routes.tsx
+1
-1
api.ts
apps/admin/src/modules/books/sale/api.ts
+21
-0
SaleDiscussionDetail.jsx
...rc/modules/books/sale/components/SaleDiscussionDetail.jsx
+245
-1
SaleDiscussionDetail.less
...c/modules/books/sale/components/SaleDiscussionDetail.less
+37
-0
SaleEdit.jsx
apps/admin/src/modules/books/sale/components/SaleEdit.jsx
+0
-0
Layout.jsx
apps/admin/src/modules/members/Layout.jsx
+5
-0
routes.tsx
apps/admin/src/modules/members/routes.tsx
+1
-1
SettingsLayout.jsx
apps/admin/src/modules/settings/SettingsLayout.jsx
+11
-0
AppVersionListView.jsx
...modules/settings/app-version/views/AppVersionListView.jsx
+1
-1
request.js
apps/admin/src/modules/settings/help/request.js
+23
-0
HelpAddEditView.jsx
...admin/src/modules/settings/help/views/HelpAddEditView.jsx
+1
-1
routes.tsx
apps/admin/src/modules/settings/routes.tsx
+1
-1
api.ts
apps/admin/src/modules/student-book/api.ts
+1
-1
request.js
apps/admin/src/modules/student-book/request.js
+360
-0
StudentBookView.jsx
.../admin/src/modules/student-book/views/StudentBookView.jsx
+0
-0
StudentBookView.less
...admin/src/modules/student-book/views/StudentBookView.less
+0
-0
Layout.jsx
apps/admin/src/modules/teachers/Layout.jsx
+0
-0
TeacherListView.jsx
...admin/src/modules/teachers/list/views/TeacherListView.jsx
+0
-0
routes.tsx
apps/admin/src/modules/teachers/routes.tsx
+0
-0
index.jsx
apps/admin/src/pages/advertisement/index.jsx
+0
-0
index.less
apps/admin/src/pages/books/audit/index.less
+0
-0
preview.jsx
apps/admin/src/pages/books/audit/preview.jsx
+0
-0
index.jsx
apps/admin/src/pages/books/index.jsx
+0
-0
index.jsx
apps/admin/src/pages/books/management/addedit/index.jsx
+0
-0
index.jsx
apps/admin/src/pages/books/sale/discussDetail/index.jsx
+0
-0
index.less
apps/admin/src/pages/books/sale/discussDetail/index.less
+0
-0
edit.jsx
apps/admin/src/pages/books/sale/edit.jsx
+0
-0
api.js
apps/admin/src/pages/books/section/api.js
+0
-0
BindKnowledgeGraph.jsx
...src/pages/books/section/components/BindKnowledgeGraph.jsx
+0
-0
EditChapterEditors.jsx
...src/pages/books/section/components/EditChapterEditors.jsx
+0
-0
form-chapter-title.jsx
...src/pages/books/section/components/form-chapter-title.jsx
+0
-0
index.jsx
apps/admin/src/pages/books/section/index.jsx
+0
-0
index.less
apps/admin/src/pages/books/section/index.less
+0
-0
request.js
apps/admin/src/pages/books/section/request.js
+0
-0
index.jsx
apps/admin/src/pages/jurisdiction/index.jsx
+0
-0
index.jsx
apps/admin/src/pages/member/index.jsx
+0
-0
requet.js
apps/admin/src/pages/setting/help/addedit/requet.js
+0
-0
index.jsx
apps/admin/src/pages/setting/index.jsx
+0
-0
index.jsx
apps/admin/src/pages/setting/personalized-setting/index.jsx
+0
-0
index.jsx
apps/admin/src/pages/setting/point-management/index.jsx
+0
-0
request.js
apps/admin/src/pages/setting/point-management/request.js
+0
-0
index.jsx
apps/admin/src/pages/student/book/index.jsx
+0
-0
request.js
apps/admin/src/pages/student/book/request.js
+0
-0
index.jsx
apps/admin/src/pages/teacher/index.jsx
+0
-0
index.jsx
apps/admin/src/pages/user-module/index.jsx
+0
-0
index.jsx
apps/admin/src/pages/user-module/login/index.jsx
+0
-0
api.js
apps/admin/src/pages/user-module/login/request/api.js
+0
-0
index.js
apps/admin/src/pages/user-module/login/request/index.js
+0
-0
api.js
apps/admin/src/pages/user-module/request/api.js
+0
-0
request.jsx
apps/admin/src/pages/user-module/request/request.jsx
+0
-0
index.jsx
apps/admin/src/pages/user-module/userInfo/index.jsx
+0
-0
requet.js
apps/admin/src/pages/user-module/userInfo/requet.js
+0
-0
没有找到文件。
apps/admin/src/modules/access/Layout.jsx
0 → 100644
浏览文件 @
77cf6ebc
import
{
Outlet
}
from
'react-router'
const
AccessLayout
=
()
=>
<
Outlet
/>
export
default
AccessLayout
apps/admin/src/modules/access/role/api.ts
浏览文件 @
77cf6ebc
...
@@ -100,3 +100,7 @@ export function setRolePermissions(roleId: number, powerList: Array<string | num
...
@@ -100,3 +100,7 @@ export function setRolePermissions(roleId: number, powerList: Array<string | num
export
function
getAllPermissions
()
{
export
function
getAllPermissions
()
{
return
getPayload
<
PermissionRecord
[]
>
(
"/system/power/getListAll"
,
{});
return
getPayload
<
PermissionRecord
[]
>
(
"/system/power/getListAll"
,
{});
}
}
export
function
getTeacherRoles
()
{
return
getPayload
<
RoleRow
[]
>
(
"/user/role/getAllList"
,
{
type
:
2
});
}
apps/admin/src/modules/access/routes.tsx
浏览文件 @
77cf6ebc
...
@@ -2,7 +2,7 @@ import { lazy } from "react";
...
@@ -2,7 +2,7 @@ import { lazy } from "react";
import
{
Navigate
,
useRoutes
}
from
"react-router"
;
import
{
Navigate
,
useRoutes
}
from
"react-router"
;
import
ModuleBoundary
from
"@/app/ModuleBoundary"
;
import
ModuleBoundary
from
"@/app/ModuleBoundary"
;
const
AccessLayout
=
lazy
(()
=>
import
(
"
@/pages/jurisdiction/index
"
));
const
AccessLayout
=
lazy
(()
=>
import
(
"
./Layout
"
));
const
AdminRoutes
=
lazy
(()
=>
import
(
"./admin/routes"
));
const
AdminRoutes
=
lazy
(()
=>
import
(
"./admin/routes"
));
const
RoleRoutes
=
lazy
(()
=>
import
(
"./role/routes"
));
const
RoleRoutes
=
lazy
(()
=>
import
(
"./role/routes"
));
...
...
apps/admin/src/modules/account/oss.js
0 → 100644
浏览文件 @
77cf6ebc
import
axios
from
"@/utils/request.js"
;
import
qs
from
"qs"
;
import
{
message
}
from
"antd"
;
import
{
get
}
from
"lodash-es"
;
// oss
const
getAliOSSSTSToken
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
"/common/OssUpload/getUploadToken"
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"获取OSS令牌失败!"
);
if
(
code
===
200
)
{
return
data
;
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
return
false
;
}
};
export
{
getAliOSSSTSToken
};
apps/admin/src/modules/account/views/AccountView.jsx
浏览文件 @
77cf6ebc
export
{
default
}
from
"@/pages/user-module/userInfo"
;
import
{
useState
,
useEffect
}
from
"react"
;
import
{
Form
,
Input
,
Button
,
Space
,
Row
,
Col
,
Drawer
}
from
"antd"
;
import
users
from
"@/assets/images/icon/userinfo.png"
;
import
{
changePass
,
changeInfo
,
getUserInfo
}
from
"@/layout/request"
;
import
{
useNavigate
}
from
"react-router"
;
import
UploadImage
from
"@/components/uploadImage"
;
const
UserInfo
=
()
=>
{
const
navigator
=
useNavigate
();
const
[
imageUrl
,
setImageUrl
]
=
useState
(
""
);
const
[
form
]
=
Form
.
useForm
();
const
[
form2
]
=
Form
.
useForm
();
const
[
showModal
,
setShowModal
]
=
useState
(
false
);
const
fetchData
=
async
(
obj
)
=>
{
try
{
const
userData
=
await
getUserInfo
(
obj
);
form
.
setFieldsValue
({
real_name
:
userData
.
real_name
,
tel
:
userData
.
tel
,
pic
:
userData
.
pic
,
});
const
imageUrl
=
userData
.
pic
;
setImageUrl
(
imageUrl
);
}
catch
(
error
)
{
console
.
error
(
"Error fetching user data:"
,
error
);
}
};
useEffect
(()
=>
{
fetchData
();
},
[]);
const
changePasswrd
=
async
(
obj
)
=>
{
await
changePass
(
obj
);
setShowModal
(
false
);
};
const
submitForm
=
async
(
obj
)
=>
{
const
updatedData
=
await
changeInfo
({
...
obj
});
if
(
updatedData
)
{
await
fetchData
();
}
};
return
(
<
div
style=
{
{
padding
:
"20px 0"
}
}
>
<
Form
form=
{
form
}
labelCol=
{
{
span
:
2
}
}
onFinish=
{
submitForm
}
>
<
Form
.
Item
label=
"头像"
className=
"uploadPar"
name=
"pic"
>
<
UploadImage
value=
{
imageUrl
?
imageUrl
:
users
}
onChange=
{
(
url
)
=>
setImageUrl
(
url
)
}
></
UploadImage
>
</
Form
.
Item
>
<
Form
.
Item
label=
"管理员名称"
name=
"real_name"
rules=
{
[{
required
:
true
,
message
:
"请输入管理员名称"
}]
}
>
<
Input
autoComplete=
"off"
placeholder=
"请输入管理员名称"
style=
{
{
width
:
200
}
}
></
Input
>
</
Form
.
Item
>
<
Form
.
Item
label=
"手机号"
name=
"tel"
rules=
{
[{
required
:
true
,
message
:
"请输入手机号"
}]
}
>
<
Input
autoComplete=
"off"
placeholder=
"请输入手机号"
style=
{
{
width
:
200
}
}
></
Input
>
</
Form
.
Item
>
<
Form
.
Item
label=
"密码"
>
<
Button
type=
"primary"
ghost
onClick=
{
()
=>
setShowModal
(
true
)
}
>
修改密码
</
Button
>
</
Form
.
Item
>
<
Form
.
Item
wrapperCol=
{
{
offset
:
2
}
}
>
<
Space
size=
{
20
}
>
<
Button
onClick=
{
()
=>
navigator
(
-
1
)
}
>
取消
</
Button
>
<
Button
type=
"primary"
htmlType=
"submit"
>
保存
</
Button
>
</
Space
>
</
Form
.
Item
>
</
Form
>
<
Drawer
open=
{
showModal
}
onClose=
{
()
=>
{
setShowModal
(
false
);
}
}
mask=
{
false
}
maskClosable=
{
false
}
footer=
{
null
}
centered
destroyOnClose
keyboard=
{
false
}
>
<
Form
labelCol=
{
{
span
:
5
}
}
form=
{
form2
}
onFinish=
{
changePasswrd
}
>
<
Form
.
Item
label=
"旧密码"
name=
"old_password"
rules=
{
[{
required
:
true
,
message
:
"请输入旧密码"
}]
}
>
<
Input
.
Password
autoComplete=
"off"
placeholder=
"请输入旧密码"
></
Input
.
Password
>
</
Form
.
Item
>
<
Form
.
Item
label=
"新密码"
name=
"password"
rules=
{
[
{
required
:
true
,
message
:
"请输入新密码"
},
{
pattern
:
/^
((?=
.*
\d)(?=
.*
[
A-Z
])(?=
.*
[
a-z
]))
|
((?=
.*
\d)(?=
.*
[
A-Z
])(?=
.*
[\W
_
]))
|
((?=
.*
\d)(?=
.*
[
a-z
])(?=
.*
[\W
_
]))
|
((?=
.*
[
A-Z
])(?=
.*
[
a-z
])(?=
.*
[\W
_
]))[
a-zA-Z
\d\W
_
]
{8,12}$/
,
message
:
"密码至少满足三种格式(大写字母、小写字母、数字、特殊符号), 长度为8~12位字符!"
,
trigger
:
[
"change"
,
"blur"
],
},
{
validator
(
_
,
value
)
{
if
(
!
value
||
form2
.
getFieldValue
(
"re_password"
)
===
value
)
{
form2
.
setFields
([{
name
:
"re_password"
,
errors
:
[
""
]
}]);
return
Promise
.
resolve
();
}
form2
.
setFields
([{
name
:
"re_password"
,
errors
:
[
"两次输入的密码不一致"
]
}]);
return
Promise
.
reject
();
},
},
]
}
>
<
Input
.
Password
autoComplete=
"off"
placeholder=
"请输入新密码"
></
Input
.
Password
>
</
Form
.
Item
>
<
Form
.
Item
label=
"确认新密码"
name=
"re_password"
rules=
{
[
{
required
:
true
,
message
:
"请确认新密码"
},
{
pattern
:
/^
((?=
.*
\d)(?=
.*
[
A-Z
])(?=
.*
[
a-z
]))
|
((?=
.*
\d)(?=
.*
[
A-Z
])(?=
.*
[\W
_
]))
|
((?=
.*
\d)(?=
.*
[
a-z
])(?=
.*
[\W
_
]))
|
((?=
.*
[
A-Z
])(?=
.*
[
a-z
])(?=
.*
[\W
_
]))[
a-zA-Z
\d\W
_
]
{8,12}$/
,
message
:
"密码至少满足三种格式(大写字母、小写字母、数字、特殊符号), 长度为8~12位字符!"
,
trigger
:
[
"change"
,
"blur"
],
},
{
validator
(
_
,
value
)
{
if
(
!
value
||
form2
.
getFieldValue
(
"password"
)
===
value
)
{
return
Promise
.
resolve
();
}
return
Promise
.
reject
(
new
Error
(
"两次输入的密码不一致"
));
},
},
]
}
>
<
Input
.
Password
autoComplete=
"off"
placeholder=
"请确认新密码"
></
Input
.
Password
>
</
Form
.
Item
>
<
Form
.
Item
wrapperCol=
{
{
offset
:
5
}
}
>
<
Row
justify=
{
"center"
}
>
<
Space
size=
{
20
}
>
<
Col
>
<
Button
onClick=
{
()
=>
setShowModal
(
false
)
}
>
取消
</
Button
>
</
Col
>
<
Col
>
<
Button
type=
"primary"
htmlType=
"submit"
>
确认
</
Button
>
</
Col
>
</
Space
>
</
Row
>
</
Form
.
Item
>
</
Form
>
</
Drawer
>
</
div
>
);
};
export
default
UserInfo
;
apps/admin/src/modules/advertisements/Layout.jsx
0 → 100644
浏览文件 @
77cf6ebc
import
{
Outlet
}
from
'react-router'
const
AdvertisementsLayout
=
()
=>
<
Outlet
/>
export
default
AdvertisementsLayout
apps/admin/src/modules/advertisements/advert/api.ts
浏览文件 @
77cf6ebc
...
@@ -2,7 +2,6 @@ import { message } from "antd";
...
@@ -2,7 +2,6 @@ import { message } from "antd";
// @ts-expect-error The legacy workspace does not install the qs declaration package.
// @ts-expect-error The legacy workspace does not install the qs declaration package.
import
qs
from
"qs"
;
import
qs
from
"qs"
;
import
{
getPositionList
as
getLegacyPositionList
}
from
"@/pages/advertisement/adsense/request.js"
;
import
request
from
"@/utils/request.js"
;
import
request
from
"@/utils/request.js"
;
import
type
{
AdvertQuery
}
from
"./query"
;
import
type
{
AdvertQuery
}
from
"./query"
;
...
@@ -90,7 +89,7 @@ export function changeAdvertStatus(id: number, status: "0" | "1") {
...
@@ -90,7 +89,7 @@ export function changeAdvertStatus(id: number, status: "0" | "1") {
}
}
export
async
function
getAdvertPositions
():
Promise
<
AdvertPosition
[]
|
false
>
{
export
async
function
getAdvertPositions
():
Promise
<
AdvertPosition
[]
|
false
>
{
const
result
=
await
get
LegacyPositionList
(
);
const
result
=
await
get
Payload
<
{
list
?:
AdvertPosition
[]
}
>
(
"/ad/position/getList"
,
{}
);
if
(
!
result
)
return
false
;
if
(
!
result
)
return
false
;
return
(
result
.
list
??
[])
as
AdvertPosition
[];
return
(
result
.
list
??
[])
as
AdvertPosition
[];
}
}
apps/admin/src/modules/advertisements/advert/components/AdvertImageUpload.tsx
浏览文件 @
77cf6ebc
...
@@ -5,7 +5,7 @@ import type { UploadProps } from "antd";
...
@@ -5,7 +5,7 @@ import type { UploadProps } from "antd";
import
dayjs
from
"dayjs"
;
import
dayjs
from
"dayjs"
;
import
{
useEffect
,
useState
}
from
"react"
;
import
{
useEffect
,
useState
}
from
"react"
;
import
{
getAliOSSSTSToken
}
from
"@/
pages/setting/help/addedit/reque
t"
;
import
{
getAliOSSSTSToken
}
from
"@/
modules/settings/help/reques
t"
;
interface
OssClient
{
interface
OssClient
{
put
:
(
path
:
string
,
file
:
File
)
=>
Promise
<
{
url
:
string
}
>
;
put
:
(
path
:
string
,
file
:
File
)
=>
Promise
<
{
url
:
string
}
>
;
...
...
apps/admin/src/modules/advertisements/routes.tsx
浏览文件 @
77cf6ebc
...
@@ -2,7 +2,7 @@ import { lazy } from "react";
...
@@ -2,7 +2,7 @@ import { lazy } from "react";
import
{
Navigate
,
useRoutes
}
from
"react-router"
;
import
{
Navigate
,
useRoutes
}
from
"react-router"
;
import
ModuleBoundary
from
"@/app/ModuleBoundary"
;
import
ModuleBoundary
from
"@/app/ModuleBoundary"
;
const
AdvertisementsLayout
=
lazy
(()
=>
import
(
"
@/pages/advertisement/index
"
));
const
AdvertisementsLayout
=
lazy
(()
=>
import
(
"
./Layout
"
));
const
AdvertRoutes
=
lazy
(()
=>
import
(
"./advert/routes"
));
const
AdvertRoutes
=
lazy
(()
=>
import
(
"./advert/routes"
));
const
AdsenseRoutes
=
lazy
(()
=>
import
(
"./adsense/routes"
));
const
AdsenseRoutes
=
lazy
(()
=>
import
(
"./adsense/routes"
));
...
...
apps/admin/src/modules/auth/api.ts
浏览文件 @
77cf6ebc
export
*
from
"
@/pages/user-module/login/request
"
;
export
*
from
"
./request/login
"
;
apps/admin/src/modules/auth/request/login-api.js
0 → 100644
浏览文件 @
77cf6ebc
const
api
=
{
login
:
"/user/login"
,
getCode
:
"/user/login/verify"
,
};
export
default
api
;
apps/admin/src/modules/auth/request/login.js
0 → 100644
浏览文件 @
77cf6ebc
import
axios
from
"@/utils/request.js"
;
import
qs
from
"qs"
;
import
api
from
"./login-api.js"
;
import
{
get
}
from
"lodash-es"
;
import
{
message
}
from
"antd"
;
const
login
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
api
.
login
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"数据获取失败!"
);
if
(
msg
===
"Undefined index: verify"
)
{
message
.
error
(
"请先点击按钮进行验证"
);
return
false
;
}
if
(
code
===
200
)
{
return
{
code
,
...
data
,
};
}
else
{
message
.
error
(
msg
);
return
{
msg
,
};
}
}
catch
(
error
)
{
console
.
error
(
error
);
let
msg
=
get
(
error
.
response
,
"data.msg"
,
""
);
if
(
msg
)
{
message
.
error
(
msg
);
}
return
false
;
}
};
export
{
login
};
apps/admin/src/modules/auth/request/sso-api.js
0 → 100644
浏览文件 @
77cf6ebc
const
api
=
{
getCaptcha
:
"/users/generate_image_code"
,
// 获取验证码 GET
sendSMS
:
"/docapi/users/send_sms"
,
// 发送手机验证码
loginByPhone
:
"/docapi/users/phone_login"
,
// 手机号码形式登录
loginByUsername
:
"/docapi/users/login"
,
// 用户名密码登录
checkSSOLogin
:
"/user/checkSsoLogin"
,
// sso 登录
};
export
default
api
;
apps/admin/src/modules/auth/request/sso.js
0 → 100644
浏览文件 @
77cf6ebc
import
axios
from
"@/utils/request"
;
import
{
message
}
from
"antd"
;
import
api
from
"./sso-api"
;
import
{
get
}
from
"lodash-es"
;
import
qs
from
"qs"
;
// 获取图形验证码
const
getCaptcha
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
get
(
api
.
getCaptcha
,
obj
);
const
status
=
get
(
res
,
"status"
,
0
);
const
data
=
get
(
res
,
"data"
,
""
);
if
(
status
===
200
)
{
return
data
;
}
}
catch
(
error
)
{
console
.
error
(
error
);
let
msg
=
get
(
error
.
response
,
"data.msg"
,
""
);
if
(
msg
)
{
message
.
error
(
msg
);
}
return
false
;
}
};
// 发送短信验证码
const
sendSMS
=
async
(
data
)
=>
{
try
{
const
res
=
await
axios
.
post
(
api
.
sendSMS
,
data
);
const
code
=
get
(
res
,
"data.code"
,
0
);
const
msg
=
get
(
res
,
"data.message"
,
"发送失败"
);
if
(
code
===
200
)
{
message
.
success
(
"验证码发送成功!"
);
return
true
;
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
console
.
error
(
error
);
let
msg
=
get
(
error
.
response
,
"data.msg"
,
""
);
if
(
msg
)
{
message
.
error
(
msg
);
}
return
false
;
}
};
// 用户名登录
const
userNameLogin
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
api
.
loginByUsername
,
obj
);
const
code
=
get
(
res
,
"data.code"
,
0
);
const
msg
=
get
(
res
,
"data.message"
,
"登录失败"
);
const
data
=
get
(
res
,
"data.data"
,
""
);
if
(
code
===
200
)
{
return
data
;
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
console
.
error
(
error
);
let
msg
=
get
(
error
.
response
,
"data.msg"
,
""
);
if
(
msg
)
{
message
.
error
(
msg
);
}
return
false
;
}
};
// 手机号登录
const
phoneLogin
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
api
.
loginByPhone
,
obj
);
const
code
=
get
(
res
,
"data.code"
,
0
);
const
msg
=
get
(
res
,
"data.message"
,
"登录失败"
);
const
data
=
get
(
res
,
"data.data"
,
""
);
if
(
code
===
200
)
{
return
data
;
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
console
.
error
(
error
);
let
msg
=
get
(
error
.
response
,
"data.msg"
,
""
);
if
(
msg
)
{
message
.
error
(
msg
);
}
return
false
;
}
};
const
checkSSOLogin
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
api
.
checkSSOLogin
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"数据获取失败!"
);
if
(
msg
===
"Undefined index: verify"
)
{
message
.
error
(
"请先点击按钮进行验证"
);
return
false
;
}
if
(
code
===
200
)
{
return
data
;
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
console
.
error
(
error
);
let
msg
=
get
(
error
.
response
,
"data.msg"
,
""
);
if
(
msg
)
{
message
.
error
(
msg
);
}
return
false
;
}
};
export
{
getCaptcha
,
sendSMS
,
userNameLogin
,
phoneLogin
,
checkSSOLogin
};
apps/admin/src/modules/auth/views/AuthLayout.jsx
浏览文件 @
77cf6ebc
export
{
default
}
from
"@/pages/user-module"
;
import
{
Outlet
}
from
"react-router"
;
import
"./AuthLayout.less"
;
const
User
=
()
=>
{
return
(
<
div
className=
"user-content"
>
<
div
className=
"form-container"
>
<
div
className=
"left-container"
></
div
>
<
div
className=
"form-field-box"
>
<
div
className=
"form-field"
>
<
Outlet
/>
</
div
>
</
div
>
</
div
>
</
div
>
);
};
export
default
User
;
apps/admin/src/
pages/user-module/index
.less
→
apps/admin/src/
modules/auth/views/AuthLayout
.less
浏览文件 @
77cf6ebc
File moved
apps/admin/src/modules/auth/views/LoginView.jsx
浏览文件 @
77cf6ebc
export
{
default
}
from
"@/pages/user-module/login"
;
import
React
,
{
useState
,
useEffect
,
useRef
}
from
"react"
;
import
{
Form
,
Input
,
Button
,
Row
,
Col
,
Space
,
Image
,
message
}
from
"antd"
;
import
{
CloseOutlined
,
UserOutlined
,
LockOutlined
}
from
"@ant-design/icons"
;
import
{
useNavigate
}
from
"react-router"
;
import
{
checkSSOLogin
}
from
"../request/sso"
;
import
"./LoginView.less"
;
import
loginBtn
from
"@/assets/images/loginBtn.png"
;
import
loginBtn2
from
"@/assets/images/loginBtn2.png"
;
import
Icon1
from
"@/assets/login/1.png"
;
import
Icon2
from
"@/assets/login/2.png"
;
import
Icon3
from
"@/assets/login/3.png"
;
import
Icon4
from
"@/assets/login/4.png"
;
import
Icon5
from
"@/assets/login/5.png"
;
import
Icon6
from
"@/assets/login/6.png"
;
import
Icon7
from
"@/assets/login/7.png"
;
import
Icon8
from
"@/assets/login/8.png"
;
import
Icon9
from
"@/assets/login/9.png"
;
import
Icon10
from
"@/assets/login/10.png"
;
import
Icon11
from
"@/assets/login/11.png"
;
import
Icon12
from
"@/assets/login/12.png"
;
import
Icon13
from
"@/assets/login/13.png"
;
import
Icon14
from
"@/assets/login/14.png"
;
import
Icon15
from
"@/assets/login/15.png"
;
import
Icon16
from
"@/assets/login/16.png"
;
import
Icon17
from
"@/assets/login/17.png"
;
import
Icon18
from
"@/assets/login/18.png"
;
import
Icon19
from
"@/assets/login/19.png"
;
import
Icon20
from
"@/assets/login/20.png"
;
import
Icon21
from
"@/assets/login/21.png"
;
import
Icon22
from
"@/assets/login/22.png"
;
import
Icon23
from
"@/assets/login/23.png"
;
import
{
login
}
from
"../request/login"
;
import
logo
from
"@/assets/images/icon_logo_login.png"
;
import
{
RotateVerify
}
from
"../../../utils/captcha"
;
const
Login
=
()
=>
{
const
navigate
=
useNavigate
();
const
[
form
]
=
Form
.
useForm
();
const
[
isActive
,
setIsActive
]
=
useState
(
0
);
const
[
loading
,
setLoading
]
=
useState
(
false
);
const
[
captchaURL
,
setCaptchaURL
]
=
useState
(
""
);
const
[
captchaStatus
,
setCaptchaStatus
]
=
useState
(
false
);
const
[
captchaText
,
setCaptchaText
]
=
useState
(
"发送验证码"
);
const
[
showCaptcha
,
setShowCaptcha
]
=
useState
(
false
);
const
[
isLoggedIn
,
setIsLoggedIn
]
=
useState
(
false
);
//登录图片切换
const
[
isLoginBtn
,
setIsLoginBtn
]
=
useState
(
false
);
//是否点击了登录按钮
const
[
code
,
setCode
]
=
useState
(
""
);
const
[
disLf
,
setDisLf
]
=
useState
(
""
);
const
[
initialValues
,
setinitialValues
]
=
useState
({
tel
:
""
,
password
:
""
,
});
const
timer
=
useRef
();
const
getSSOInfo
=
async
()
=>
{
const
isSSOData
=
await
checkSSOLogin
();
if
(
isSSOData
.
run
===
"login"
)
{
}
else
if
(
isSSOData
.
token
)
{
localStorage
.
setItem
(
"kiwi.token"
,
isSSOData
.
token
);
navigate
(
"/"
);
return
;
}
};
useEffect
(()
=>
{
getSSOInfo
();
},
[]);
// 登录
const
toLayout
=
async
(
obj
)
=>
{
setLoading
(
true
);
if
(
isLoginBtn
)
{
const
data
=
await
login
({
...
obj
,
code
:
code
,
disLf
:
disLf
,
});
if
(
data
.
code
===
200
)
{
localStorage
.
setItem
(
"kiwi.token"
,
data
.
token
);
navigate
(
"/"
);
return
;
}
else
{
form
.
setFields
([{
name
:
"password"
,
errors
:
[
data
.
msg
]
}]);
}
}
else
{
message
.
error
(
"请先完成按钮验证"
);
}
// 刷新验证码
// await refreshCaptcha();
setLoading
(
false
);
};
const
handleStartVerification
=
()
=>
{
setShowCaptcha
(
true
);
};
// 点击×
const
handleGoBack
=
()
=>
{
setShowCaptcha
(
false
);
};
useEffect
(()
=>
{
if
(
showCaptcha
)
{
const
rotateWrapEle
=
document
.
querySelector
(
"#rotateWrap1"
);
// 确保 DOM 元素存在之后再进行初始化
if
(
rotateWrapEle
)
{
const
myRotateVerify
=
new
RotateVerify
(
"#rotateWrap1"
,
{
initText
:
"滑动将图片转正"
,
slideImage
:
[
Icon1
,
Icon2
,
Icon3
,
Icon4
,
Icon5
,
Icon6
,
Icon7
,
Icon8
,
Icon9
,
Icon10
,
Icon11
,
Icon12
,
Icon13
,
Icon14
,
Icon15
,
Icon16
,
Icon17
,
Icon18
,
Icon4
,
Icon19
,
Icon20
,
Icon21
,
Icon22
,
Icon23
,
],
initUrl
:
"/user/login/initData"
,
verifyUrl
:
"/user/login/checkVerify"
,
getSuccessState
:
function
(
data
)
{
console
.
log
(
"验证成功"
,
data
);
setDisLf
(
data
.
disLf
);
setCode
(
data
.
code
);
if
(
data
.
disLf
)
{
setShowCaptcha
(
false
);
setIsLoggedIn
(
true
);
setIsLoginBtn
(
true
);
}
},
});
// 如果需要,在这里处理卸载时清理资源
return
()
=>
{
console
.
log
(
myRotateVerify
.
initUrl
);
// 清理或销毁 RotateVerify 实例等操作
if
(
myRotateVerify
&&
typeof
myRotateVerify
.
destroy
===
"function"
)
{
myRotateVerify
.
destroy
();
}
};
}
}
},
[
showCaptcha
]);
return
(
<
div
className=
{
showCaptcha
?
"captcha-container"
:
"normal-container"
}
>
{
showCaptcha
&&
(
<
div
className=
"rotateWrap"
>
<
div
className=
"cuo"
onClick=
{
handleGoBack
}
>
<
CloseOutlined
/>
</
div
>
<
span
className=
"top-s"
>
身份验证
</
span
>
<
span
className=
"top-x"
>
拖动滑块,使图片角度为正
</
span
>
<
div
id=
"rotateWrap1"
>
<
div
className=
"rotateverify-contaniner"
>
<
div
className=
"rotate-can-wrap"
>
<
canvas
className=
"rotateCan rotate-can"
width=
"200"
height=
"200"
></
canvas
>
<
div
className=
"statusBg status-bg"
></
div
>
</
div
>
<
div
className=
"control-wrap slideDragWrap"
>
<
div
className=
"control-tips"
>
<
p
className=
"c-tips-txt cTipsTxt"
>
滑动将图片转正
</
p
>
</
div
>
<
div
className=
"control-bor-wrap controlBorWrap"
></
div
>
<
div
className=
"control-btn slideDragBtn"
>
{
/* <i className='control-btn-ico'></i> */
}
<
div
className=
"control-btn-ico"
></
div
>
</
div
>
</
div
>
</
div
>
</
div
>
</
div
>
)
}
{
!
showCaptcha
&&
(
<
div
className=
"img-logo"
>
<
img
src=
{
logo
}
className=
"img"
/>
</
div
>
)
}
{
!
showCaptcha
&&
<
div
className=
"login-header"
>
欢迎登录
</
div
>
}{
" "
}
{
!
showCaptcha
&&
(
<
div
className=
"form-data-container"
>
<
Form
form=
{
form
}
onFinish=
{
toLayout
}
autoComplete=
"off"
initialValues=
{
initialValues
}
>
<>
<
Form
.
Item
name=
"tel"
rules=
{
[
{
required
:
true
,
message
:
"请输入手机号!"
},
{
pattern
:
/^1
[
3-9
]\d
{9}$/
,
message
:
"请输入正确格式的手机号"
},
]
}
>
<
Input
autoComplete=
"off"
prefix=
{
<
UserOutlined
/>
}
size=
"large"
placeholder=
"请输入手机号"
/>
</
Form
.
Item
>
<
Form
.
Item
name=
"password"
rules=
{
[{
required
:
true
,
message
:
"请输入密码!"
}]
}
>
<
Input
.
Password
autoComplete=
"off"
prefix=
{
<
LockOutlined
/>
}
size=
"large"
placeholder=
"请输入密码"
/>
</
Form
.
Item
>
{
/* <Form.Item name='verify' rules={[{ required: true, message: '请输入验证码!' }]}>
<Row gutter={16}>
<Col span={16}>
<Input
prefix={<SetIcon src={IconCaptcha} />}
size='large'
placeholder='请输入验证码'
/>
</Col>
<Col span={8}>
<img
src={captchaURL}
alt='图形验证码'
className='captcha'
onClick={refreshCaptcha}
/>
</Col>
</Row>
</Form.Item> */
}
<
Form
.
Item
name=
"verify"
onClick=
{
handleStartVerification
}
>
<
div
style=
{
{
width
:
"100%"
,
height
:
"100%"
,
pointerEvents
:
"none"
}
}
>
{
isLoggedIn
?
(
<
Image
src=
{
loginBtn2
}
style=
{
{
width
:
"100%"
,
height
:
"100%"
,
}
}
/>
)
:
(
<
Image
src=
{
loginBtn
}
style=
{
{
width
:
"100%"
,
height
:
"100%"
,
}
}
/>
)
}
</
div
>
</
Form
.
Item
>
</>
<
Form
.
Item
className=
"login-submit-btn"
>
<
Button
htmlType=
"submit"
loading=
{
loading
}
type=
"primary"
size=
"large"
>
登录
</
Button
>
</
Form
.
Item
>
</
Form
>
</
div
>
)
}
</
div
>
);
};
export
default
Login
;
apps/admin/src/
pages/user-module/login/index
.less
→
apps/admin/src/
modules/auth/views/LoginView
.less
浏览文件 @
77cf6ebc
File moved
apps/admin/src/modules/books/BooksLayout.jsx
0 → 100644
浏览文件 @
77cf6ebc
import
React
from
"react"
;
import
{
Outlet
}
from
"react-router"
;
const
Book
=
()
=>
{
return
<
Outlet
/>;
};
export
default
Book
;
apps/admin/src/modules/books/audit/audit.less
0 → 100644
浏览文件 @
77cf6ebc
.auditPanel {
background: #fbfbfb;
margin-bottom: 30px;
}
.auditdetail {
.ant-steps-item-icon {
width: 50px !important;
height: 100px;
}
.imgel {
.user {
width: 50px;
height: 50px;
position: relative;
background-size: cover;
}
.status {
width: 20px;
height: 20px;
position: absolute;
right: 0;
bottom: 0;
}
}
// .ant-steps-item-description {
// height: 150px;
// }
.ant-steps-item-tail {
display: none !important;
}
}
apps/admin/src/modules/books/audit/components/PreviewModal.jsx
浏览文件 @
77cf6ebc
差异被折叠。
点击展开。
apps/admin/src/modules/books/audit/routes.tsx
浏览文件 @
77cf6ebc
import
{
Navigate
,
Outlet
,
useRoutes
}
from
"react-router"
;
import
{
Navigate
,
Outlet
,
useRoutes
}
from
"react-router"
;
import
AuditDetailView
from
"./views/AuditDetailView"
;
import
AuditDetailView
from
"./views/AuditDetailView"
;
import
AuditListView
from
"./views/AuditListView"
;
import
AuditListView
from
"./views/AuditListView"
;
import
"
@/pages/books/audit/index
.less"
;
import
"
./audit
.less"
;
function
Layout
()
{
return
<
Outlet
/>;
}
function
Layout
()
{
return
<
Outlet
/>;
}
export
default
function
AuditRoutes
()
{
return
useRoutes
([{
Component
:
Layout
,
children
:
[{
index
:
true
,
Component
:
AuditListView
},
{
path
:
"dataset"
,
Component
:
AuditListView
},
{
path
:
"detail"
,
Component
:
AuditDetailView
},
{
path
:
"*"
,
element
:
<
Navigate
to=
"."
replace
/>
}]
}]);
}
export
default
function
AuditRoutes
()
{
return
useRoutes
([{
Component
:
Layout
,
children
:
[{
index
:
true
,
Component
:
AuditListView
},
{
path
:
"dataset"
,
Component
:
AuditListView
},
{
path
:
"detail"
,
Component
:
AuditDetailView
},
{
path
:
"*"
,
element
:
<
Navigate
to=
"."
replace
/>
}]
}]);
}
apps/admin/src/modules/books/audit/views/AuditDetailView.tsx
浏览文件 @
77cf6ebc
...
@@ -4,7 +4,7 @@ import { useLocation, useNavigate } from "react-router";
...
@@ -4,7 +4,7 @@ import { useLocation, useNavigate } from "react-router";
import
{
useSelector
}
from
"react-redux"
;
import
{
useSelector
}
from
"react-redux"
;
import
{
addExamine
,
getExamineList
}
from
"../api"
;
import
{
addExamine
,
getExamineList
}
from
"../api"
;
import
AuditHistory
from
"../components/AuditHistory"
;
import
AuditHistory
from
"../components/AuditHistory"
;
import
"
@/pages/books/audit/index
.less"
;
import
"
../audit
.less"
;
export
default
function
AuditDetailView
()
{
export
default
function
AuditDetailView
()
{
const
location
=
useLocation
();
const
navigate
=
useNavigate
();
const
id
=
(
location
.
state
as
{
id
?:
string
|
number
}
|
null
)?.
id
;
const
{
operationPermissionsList
=
[]
}
=
useSelector
((
state
:
any
)
=>
state
.
user
);
const
[
form
]
=
Form
.
useForm
();
const
[
history
,
setHistory
]
=
useState
<
any
[]
>
([]);
const
[
loading
,
setLoading
]
=
useState
(
false
);
const
[
forceOpen
,
setForceOpen
]
=
useState
(
false
);
const
[
forceMessage
,
setForceMessage
]
=
useState
(
""
);
const
location
=
useLocation
();
const
navigate
=
useNavigate
();
const
id
=
(
location
.
state
as
{
id
?:
string
|
number
}
|
null
)?.
id
;
const
{
operationPermissionsList
=
[]
}
=
useSelector
((
state
:
any
)
=>
state
.
user
);
const
[
form
]
=
Form
.
useForm
();
const
[
history
,
setHistory
]
=
useState
<
any
[]
>
([]);
const
[
loading
,
setLoading
]
=
useState
(
false
);
const
[
forceOpen
,
setForceOpen
]
=
useState
(
false
);
const
[
forceMessage
,
setForceMessage
]
=
useState
(
""
);
const
loadHistory
=
async
()
=>
{
if
(
!
id
)
return
;
const
data
:
any
=
await
getExamineList
(
id
);
if
(
data
)
setHistory
(
data
);
};
const
loadHistory
=
async
()
=>
{
if
(
!
id
)
return
;
const
data
:
any
=
await
getExamineList
(
id
);
if
(
data
)
setHistory
(
data
);
};
...
...
apps/admin/src/modules/books/management/api.ts
浏览文件 @
77cf6ebc
...
@@ -3,6 +3,7 @@ import { message } from "antd";
...
@@ -3,6 +3,7 @@ import { message } from "antd";
import
qs
from
"qs"
;
import
qs
from
"qs"
;
import
request
from
"@/utils/request.js"
;
import
request
from
"@/utils/request.js"
;
import
legacyAxios
from
"@/utils/axios"
;
import
type
{
ManagementQuery
}
from
"./query"
;
import
type
{
ManagementQuery
}
from
"./query"
;
...
@@ -80,6 +81,19 @@ export function deleteManagementBook(id: number) {
...
@@ -80,6 +81,19 @@ export function deleteManagementBook(id: number) {
return
mutate
(
"/book/teacher/del"
,
{
id
});
return
mutate
(
"/book/teacher/del"
,
{
id
});
}
}
// 编辑页仍沿用旧接口封装的返回值形状;保留在管理模块中,避免页面反向依赖旧目录。
export
function
getBook
(
params
:
ApiParams
)
{
return
legacyAxios
.
post
(
"/api/book/teacher/getInfoById"
,
params
);
}
export
function
addBook
(
params
:
ApiParams
)
{
return
legacyAxios
.
post
(
"/api/book/teacher/add"
,
params
);
}
export
function
updateBook
(
params
:
ApiParams
)
{
return
legacyAxios
.
post
(
"/api/book/teacher/edit"
,
params
);
}
export
function
exportManagementBook
(
id
:
number
)
{
export
function
exportManagementBook
(
id
:
number
)
{
return
getPayload
<
ExportBookResult
>
(
"/book/teacher/export"
,
{
id
});
return
getPayload
<
ExportBookResult
>
(
"/book/teacher/export"
,
{
id
});
}
}
...
...
apps/admin/src/modules/books/management/chapters/api.js
0 → 100644
浏览文件 @
77cf6ebc
import
axios
from
"@/utils/axios"
;
// 获取书籍详情
export
function
getBook
(
data
)
{
return
axios
.
post
(
"/api/book/teacher/getInfoById"
,
data
);
}
// 获取章节列表
export
function
getChapterList
(
data
)
{
return
axios
.
post
(
"/api/book/teacher/chapter/getAllList"
,
data
);
}
// 获取章节详情
export
function
getChapter
(
data
)
{
return
axios
.
post
(
"/api/book/teacher/chapter/getInfoById"
,
data
);
}
// 添加章节
export
function
addChapter
(
data
)
{
return
axios
.
post
(
"/api/book/teacher/chapter/add"
,
data
);
}
// 修改章节
export
function
updateChapter
(
data
)
{
return
axios
.
post
(
"/api/book/teacher/chapter/edit"
,
data
);
}
// 删除章节
export
function
delChapter
(
data
)
{
return
axios
.
post
(
"/api/book/teacher/chapter/del"
,
data
);
}
// 章节排序
export
function
sortChapter
(
data
)
{
return
axios
.
post
(
"/api/book/teacher/chapter/dragOrder"
,
data
);
}
// 获取章节编辑者信息
export
function
getChapterEditors
(
data
)
{
return
axios
.
post
(
"/api/book/teacher/chapter/getEditors"
,
data
);
}
// 保存章节编辑者
export
function
updateChapterEditors
(
data
)
{
return
axios
.
post
(
"/api/book/teacher/chapter/saveEditors"
,
data
);
}
// 知识图谱列表
export
function
getTagList
(
params
)
{
return
axios
.
get
(
"/api/resource/v1/course/course/tag-list"
,
{
params
});
}
// 知识图谱关联书籍章节
export
function
bindTag
(
data
)
{
return
axios
.
post
(
"/api/resource/v1/course/course/tag-add-book"
,
data
);
}
apps/admin/src/modules/books/management/chapters/components/BindKnowledgeGraph.jsx
0 → 100644
浏览文件 @
77cf6ebc
import
{
useState
,
useEffect
,
useCallback
}
from
"react"
;
import
{
Modal
,
Tree
,
App
,
Button
,
Flex
,
Empty
}
from
"antd"
;
import
{
getTagList
,
bindTag
}
from
"../api"
;
function
getIds
(
nodes
)
{
let
ids
=
[];
nodes
.
forEach
((
node
)
=>
{
ids
.
push
(
node
.
id
);
if
(
node
.
children
&&
node
.
children
.
length
>
0
)
{
ids
=
ids
.
concat
(
getIds
(
node
.
children
));
}
});
return
ids
;
}
const
BindKnowledgeGraph
=
({
chapter
=
{},
...
props
})
=>
{
const
{
message
}
=
App
.
useApp
();
const
[
treeData
,
setTreeData
]
=
useState
([]);
const
[
expandedKeys
,
setExpandedKeys
]
=
useState
([]);
const
fetchList
=
useCallback
(()
=>
{
getTagList
({
type
:
2
,
parent_id
:
chapter
.
book_id
,
chapter_id
:
chapter
.
id
}).
then
((
res
)
=>
{
setTreeData
(
res
.
data
);
setExpandedKeys
(
getIds
(
res
.
data
));
});
},
[
chapter
]);
useEffect
(()
=>
{
fetchList
();
},
[
fetchList
]);
const
toggleBind
=
async
(
node
)
=>
{
await
bindTag
({
tag_id
:
node
.
id
,
book_id
:
chapter
.
book_id
,
chapter_id
:
chapter
.
id
,
option_type
:
node
.
is_checked
?
"delete"
:
"add"
,
});
message
.
success
(
"操作成功"
);
fetchList
();
};
const
titleRender
=
(
node
)
=>
{
return
(
<
Flex
justify=
"space-between"
>
<
span
>
{
node
.
name
}
</
span
>
<
Button
color=
"primary"
variant=
"link"
size=
"small"
onClick=
{
()
=>
toggleBind
(
node
)
}
>
{
node
.
is_checked
?
"取消关联"
:
"关联"
}
</
Button
>
</
Flex
>
);
};
return
(
<
Modal
title=
"关联知识图谱"
centered
{
...
props
}
footer=
{
null
}
>
{
treeData
.
length
>
0
?
(
<
Tree
blockNode
selectable=
{
false
}
treeData=
{
treeData
}
fieldNames=
{
{
title
:
"name"
,
key
:
"id"
}
}
expandedKeys=
{
expandedKeys
}
titleRender=
{
titleRender
}
onExpand=
{
setExpandedKeys
}
/>
)
:
(
<
Empty
image=
{
Empty
.
PRESENTED_IMAGE_SIMPLE
}
description=
"暂无知识图谱"
/>
)
}
</
Modal
>
);
};
export
default
BindKnowledgeGraph
;
apps/admin/src/modules/books/management/chapters/components/EditChapterEditors.jsx
0 → 100644
浏览文件 @
77cf6ebc
import
{
useState
,
useEffect
}
from
"react"
;
import
{
Modal
,
Form
,
Radio
,
Space
,
App
}
from
"antd"
;
import
{
getChapterEditors
,
updateChapterEditors
}
from
"../api"
;
const
EditChapterEditors
=
({
chapter
=
{},
onChange
,
...
props
})
=>
{
const
{
message
}
=
App
.
useApp
();
const
[
editors
,
setEditors
]
=
useState
([]);
const
[
value
,
setValue
]
=
useState
(
""
);
useEffect
(()
=>
{
getChapterEditors
({
book_id
:
chapter
.
book_id
,
chapter_id
:
chapter
.
id
}).
then
((
res
)
=>
{
setEditors
(
res
.
data
.
editors
||
[]);
const
value
=
res
.
data
.
selected_editor_ids
[
0
]
||
""
;
setValue
(
value
);
});
},
[
chapter
]);
const
handleSubmit
=
async
()
=>
{
await
updateChapterEditors
({
book_id
:
chapter
.
book_id
,
chapter_id
:
chapter
.
id
,
editor_id
:
value
,
});
message
.
success
(
"设置成功"
);
onChange
&&
onChange
();
};
return
(
<
Modal
title=
"设置章节编写者"
centered
{
...
props
}
onOk=
{
handleSubmit
}
>
<
Form
labelCol=
{
{
span
:
8
}
}
>
<
Form
.
Item
label=
"当前章节"
>
{
chapter
.
title
}
</
Form
.
Item
>
<
Form
.
Item
label=
"编写者"
>
<
Radio
.
Group
value=
{
value
}
onChange=
{
(
e
)
=>
setValue
(
e
.
target
.
value
)
}
>
<
Space
direction=
"vertical"
>
{
editors
.
map
((
item
)
=>
{
return
(
<
Radio
value=
{
item
.
editor_id
}
key=
{
item
.
editor_id
}
>
{
item
.
real_name
}
(
{
item
.
tel
}
)
</
Radio
>
);
})
}
</
Space
>
</
Radio
.
Group
>
</
Form
.
Item
>
</
Form
>
</
Modal
>
);
};
export
default
EditChapterEditors
;
apps/admin/src/modules/books/management/chapters/components/form-chapter-title.jsx
0 → 100644
浏览文件 @
77cf6ebc
import
{
useState
,
useEffect
,
useRef
}
from
"react"
;
import
{
Form
,
Button
,
Space
,
Input
}
from
"antd"
;
import
{
setTreeChapter
}
from
"@/store/modules/user"
;
import
{
useDispatch
}
from
"react-redux"
;
import
{
chapterEdit
,
chapterAdd
,
sectionAdd
}
from
"../request"
;
const
EditChapterTitle
=
(
props
)
=>
{
const
{
editValue
,
setEditValue
,
editKey
,
setEditKey
,
parentId
,
bookId
,
getChapterTreeList
,
expandedKeys
,
setExpandedKeys
,
editorLoading
,
newChapterChange
,
}
=
props
;
const
dispatch
=
useDispatch
();
const
[
form
]
=
Form
.
useForm
();
const
[
loading
,
setLoading
]
=
useState
(
false
);
const
[
initValues
,
setInitValues
]
=
useState
({
title
:
editValue
});
const
inputRef
=
useRef
();
useEffect
(()
=>
{
if
(
inputRef
.
current
)
{
inputRef
.
current
.
focus
();
}
},
[]);
useEffect
(()
=>
{
if
(
inputRef
.
current
)
{
inputRef
.
current
.
focus
();
}
},
[
editorLoading
]);
useEffect
(()
=>
{
form
.
setFieldsValue
({
title
:
editValue
});
setInitValues
({
title
:
editValue
});
},
[
editValue
]);
const
onFinish
=
async
(
values
)
=>
{
setLoading
(
true
);
let
data
=
null
;
if
(
parentId
)
{
data
=
await
chapterAdd
({
pid
:
parentId
===
-
1
?
0
:
parentId
,
book_id
:
bookId
,
name
:
values
.
title
,
});
}
else
{
data
=
await
chapterEdit
({
id
:
editKey
,
name
:
values
.
title
});
}
await
dispatch
(
setTreeChapter
({
saveBookId
:
bookId
,
saveChapterId
:
data
.
id
}));
if
(
data
)
{
if
(
parentId
)
{
await
sectionAdd
({
book_id
:
bookId
,
chapter_id
:
data
.
id
,
content
:
""
,
word_count
:
0
});
}
setEditKey
(
false
);
setEditValue
(
null
);
await
getChapterTreeList
();
if
(
parentId
)
{
let
temp
=
[...
expandedKeys
,
parentId
];
setExpandedKeys
(
temp
);
await
newChapterChange
(
data
.
id
,
values
.
title
);
}
}
setLoading
(
false
);
};
return
(
<
Form
layout=
"vertical"
form=
{
form
}
onFinish=
{
onFinish
}
initialValues=
{
initValues
}
>
<
Form
.
Item
label=
"章节标题"
name=
"title"
rules=
{
[{
required
:
true
,
message
:
"请输入章节标题"
}]
}
extra=
"最多30个字符"
>
<
Input
ref=
{
inputRef
}
autoFocus
maxLength=
{
30
}
placeholder=
""
allowClear
/>
</
Form
.
Item
>
<
Form
.
Item
className=
"editor-form-buttons"
wrapperCol=
{
{
offset
:
9
,
span
:
16
}
}
>
<
Space
size=
{
20
}
>
<
Button
type=
"default"
disabled=
{
loading
}
onClick=
{
()
=>
setEditKey
(
false
)
}
>
取消
</
Button
>
<
Button
type=
"primary"
loading=
{
loading
}
htmlType=
"submit"
>
确认
</
Button
>
</
Space
>
</
Form
.
Item
>
</
Form
>
);
};
export
default
EditChapterTitle
;
apps/admin/src/modules/books/management/chapters/index.jsx
0 → 100644
浏览文件 @
77cf6ebc
差异被折叠。
点击展开。
apps/admin/src/modules/books/management/chapters/index.less
0 → 100644
浏览文件 @
77cf6ebc
.examine {
height: 100%;
.content-box {
height: 100%;
box-sizing: border-box;
overflow: hidden;
.book-content-row {
height: 100%;
overflow: hidden;
display: flex;
gap: 0;
.book-content-tree {
height: 100%;
overflow: hidden;
transition: width 0s;
}
.book-content-editor {
height: 100%;
overflow: hidden;
}
}
.resize-handle {
width: 6px;
cursor: col-resize;
background: transparent;
position: relative;
flex-shrink: 0;
z-index: 10;
transition: background 0.2s;
&:hover,
&:active {
background: #1890ff;
border-radius: 3px;
}
&::after {
content: "";
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 2px;
height: 30px;
background: #d9d9d9;
border-radius: 1px;
transition: background 0.2s;
}
&:hover::after,
&:active::after {
background: #fff;
}
}
.ant-descriptions-item-label {
padding: 10px !important;
}
.ant-descriptions-view {
border: none;
}
.border {
border: 1px solid #e5e5e5;
height: 100%;
display: flex;
overflow-x: hidden;
overflow-y: auto;
flex-direction: column;
border-radius: 6px;
.section-left-top {
height: 85px;
}
.ant-descriptions.ant-descriptions-bordered > .ant-descriptions-view .ant-descriptions-row {
border-bottom: 1px solid #e5e5e5;
&:nth-of-type(2) {
display: none;
}
}
}
.editor-right {
height: 100%;
.ant-spin-nested-loading,
.ant-spin-container {
height: 100%;
}
}
}
.draggable-tree {
flex: 1;
height: calc(100vh - 285px);
overflow-y: auto;
overflow-x: hidden;
width: 98%;
&.ant-tree .ant-tree-node-content-wrapper {
width: 100%;
}
.ant-tree-switcher-noop {
// display: none;
width: 10px;
}
&.ant-tree .ant-tree-node-content-wrapper {
overflow: hidden;
}
}
.chapter-tree-item {
display: flex;
justify-content: space-between;
overflow: hidden;
.title {
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
padding-right: 10px;
max-height: 24px;
line-height: 24px;
white-space: nowrap;
}
}
}
.chapter-title-modal {
.ant-modal {
.ant-modal-close {
inset-inline-end: 17px;
top: 16px;
}
.ant-modal-content {
padding: 15px 18px;
}
.ant-divider {
margin: 15px 0;
}
}
}
apps/admin/src/modules/books/management/chapters/request.js
0 → 100644
浏览文件 @
77cf6ebc
import
axios
from
"@/utils/request.js"
;
import
qs
from
"qs"
;
import
{
get
}
from
"lodash-es"
;
import
{
message
}
from
"antd"
;
// 用户信息
const
getUserInfo
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
"/user/user/getUserInfo"
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"数据获取失败!"
);
if
(
code
===
200
)
{
return
data
;
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
return
false
;
}
};
// 获取角色已选权限
const
getPowerByRoleId
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
"/user/role/getPowerByRoleId"
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"数据获取失败!"
);
if
(
code
===
200
)
{
return
data
;
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
return
false
;
}
};
// 章节列表
const
getAllList
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
"/book/teacher/chapter/getAllList"
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"数据获取失败!"
);
if
(
code
===
200
)
{
return
{
code
,
data
,
};
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
return
false
;
}
};
// 添加章节
const
chapterAdd
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
"/book/teacher/chapter/add"
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"数据获取失败!"
);
if
(
code
===
200
)
{
// message.success('添加成功');
return
data
;
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
return
false
;
}
};
// 章节详情
const
getInfoById
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
"/book/teacher/chapter/getInfoById"
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"数据获取失败!"
);
if
(
code
===
200
)
{
return
data
;
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
return
false
;
}
};
// 修改章节
const
chapterEdit
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
"/book/teacher/chapter/edit"
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"数据获取失败!"
);
if
(
code
===
200
)
{
message
.
success
(
msg
);
return
true
;
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
return
false
;
}
};
// 删除章节
const
chapterDel
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
"/book/teacher/chapter/del"
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"数据获取失败!"
);
if
(
code
===
200
)
{
message
.
success
(
msg
);
return
true
;
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
return
false
;
}
};
// 拖拽章节排序
const
dragOrder
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
"/book/teacher/chapter/dragOrder"
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"数据获取失败!"
);
if
(
code
===
200
)
{
message
.
success
(
msg
);
return
true
;
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
return
false
;
}
};
// 获取章节内容
const
getInfoByChapterId
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
"/book/teacher/section/getInfoByChapterId"
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"数据获取失败!"
);
if
(
code
===
200
)
{
return
data
;
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
return
false
;
}
};
// 添加章节内容
const
sectionAdd
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
"/book/teacher/section/add"
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"数据获取失败!"
);
if
(
code
===
200
)
{
message
.
success
(
msg
);
return
true
;
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
return
false
;
}
};
// 修改章节内容
const
sectionEdit
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
"/book/teacher/section/edit"
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"数据获取失败!"
);
if
(
code
===
200
)
{
// message.success(msg);
return
true
;
}
else
{
message
.
error
(
msg
);
return
{
code
,
msg
,
data
};
}
}
catch
(
error
)
{
return
false
;
}
};
// 获取章节的题库列表
const
getQuestionList
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
"/book/chapter/question/getQuestionList"
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"数据获取失败!"
);
if
(
code
===
200
)
{
return
data
;
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
return
false
;
}
};
// 移除课后题
const
questionDel
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
"/book/chapter/question/del"
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"数据获取失败!"
);
if
(
code
===
200
)
{
return
data
;
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
return
false
;
}
};
// 添加课后题
const
questionAdd
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
"/book/chapter/question/add"
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"数据获取失败!"
);
if
(
code
===
200
)
{
return
data
;
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
return
false
;
}
};
// 发布审核
const
release
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
"/book/teacher/release"
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"数据获取失败!"
);
if
(
code
===
200
)
{
return
true
;
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
return
false
;
}
};
// 模板列表
const
templateGetList
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
"/book/template/getList"
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"数据获取失败!"
);
if
(
code
===
200
)
{
return
true
;
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
return
false
;
}
};
// 模板导入
const
templateImport
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
"/book/template/import"
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"数据获取失败!"
);
if
(
code
===
200
)
{
return
true
;
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
return
false
;
}
};
// 书籍导入
const
teacherImport
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
"/book/teacher/import"
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"数据获取失败!"
);
if
(
code
===
200
)
{
return
true
;
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
return
false
;
}
};
// 保存历史记录
const
getRecordList
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
"/book/teacher/section/getRecordList"
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"数据获取失败!"
);
if
(
code
===
200
)
{
return
data
;
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
return
false
;
}
};
export
{
getAllList
,
chapterAdd
,
getInfoById
,
chapterEdit
,
chapterDel
,
dragOrder
,
getInfoByChapterId
,
sectionAdd
,
sectionEdit
,
getQuestionList
,
questionDel
,
questionAdd
,
release
,
templateGetList
,
templateImport
,
teacherImport
,
getRecordList
,
getPowerByRoleId
,
getUserInfo
,
};
apps/admin/src/modules/books/management/components/ManagementAddEdit.jsx
浏览文件 @
77cf6ebc
export
{
default
}
from
"@/pages/books/management/addedit"
;
import
{
useState
,
useEffect
}
from
"react"
;
import
{
Button
,
Form
,
Input
,
Flex
,
message
}
from
"antd"
;
import
WangEditor
from
"@/components/editor"
;
import
UploadImage
from
"@/components/uploadImage"
;
import
{
useLocation
,
useNavigate
}
from
"react-router"
;
import
{
addBook
,
updateBook
,
getBook
}
from
"../api"
;
import
SelectTeacher
from
"@/components/selectTeacher"
;
const
BookAddEdit
=
()
=>
{
const
navigate
=
useNavigate
();
const
location
=
useLocation
();
const
isEdit
=
!!
location
.
state
?.
id
;
const
[
form
]
=
Form
.
useForm
();
const
[
img
,
setImg
]
=
useState
(
""
);
// 编辑器内容
const
[
html
,
setHtml
]
=
useState
(
""
);
// 详情信息
const
fetchInfo
=
async
()
=>
{
const
{
data
}
=
await
getBook
({
id
:
location
.
state
.
id
});
setImg
(
data
.
img
);
setHtml
(
data
.
content
);
const
formFields
=
{
...
data
,
editors
:
data
.
editors_list
.
map
((
item
)
=>
{
return
{
label
:
item
.
real_name
,
value
:
item
.
editor_id
};
}),
};
form
.
setFieldsValue
(
formFields
);
};
useEffect
(()
=>
{
if
(
isEdit
)
fetchInfo
();
},
[
isEdit
]);
const
onFinish
=
async
(
values
)
=>
{
const
editors
=
values
.
editors
?.
map
((
item
)
=>
item
.
value
)
||
[];
const
params
=
{
...
values
,
img
,
editors
};
if
(
editors
.
length
===
0
)
delete
params
.
editors
;
const
res
=
isEdit
?
await
updateBook
({
id
:
location
.
state
.
id
,
...
params
})
:
await
addBook
(
params
);
message
.
success
(
res
.
message
);
navigate
(
-
1
);
};
return
(
<
Form
form=
{
form
}
onFinish=
{
onFinish
}
labelCol=
{
{
span
:
2
}
}
>
<
Form
.
Item
label=
"书籍名称"
name=
"name"
rules=
{
[
{
required
:
true
,
message
:
"请输入书籍名称"
},
{
max
:
30
,
message
:
"最大30字符"
},
]
}
>
<
Input
autoComplete=
"off"
placeholder=
"请输入书籍名称"
style=
{
{
width
:
260
}
}
></
Input
>
</
Form
.
Item
>
<
Form
.
Item
label=
"作者"
name=
"authors"
rules=
{
[
{
required
:
true
,
message
:
"请输入作者"
},
{
max
:
30
,
message
:
"最大30字符"
},
]
}
>
<
Input
autoComplete=
"off"
placeholder=
"请输入作者"
style=
{
{
width
:
260
}
}
></
Input
>
</
Form
.
Item
>
<
Form
.
Item
name=
"img"
label=
"缩略图"
className=
"uploadPar"
>
<
UploadImage
value=
{
img
}
onChange=
{
(
url
)
=>
setImg
(
url
)
}
></
UploadImage
>
</
Form
.
Item
>
<
Form
.
Item
label=
"编辑推荐"
name=
"introduction"
rules=
{
[{
max
:
65535
,
message
:
"最多65535字符"
}]
}
>
<
Input
.
TextArea
placeholder=
"请输入编辑推荐"
autoSize=
{
{
maxRows
:
8
,
minRows
:
5
}
}
style=
{
{
width
:
910
}
}
/>
</
Form
.
Item
>
<
Form
.
Item
label=
"编写者"
name=
"editors"
>
<
SelectTeacher
placeholder=
"请选择编写者"
style=
{
{
width
:
260
}
}
></
SelectTeacher
>
</
Form
.
Item
>
<
Form
.
Item
label=
"简介"
name=
"content"
>
<
WangEditor
value=
{
html
}
onChange=
{
(
editor
)
=>
form
.
setFieldValue
(
"content"
,
editor
.
getHtml
())
}
></
WangEditor
>
</
Form
.
Item
>
<
Form
.
Item
wrapperCol=
{
{
span
:
24
}
}
>
<
Flex
gap=
{
20
}
justify=
"center"
>
<
Button
onClick=
{
()
=>
{
navigate
(
-
1
);
}
}
>
取消
</
Button
>
<
Button
type=
"primary"
htmlType=
"submit"
>
确认
</
Button
>
</
Flex
>
</
Form
.
Item
>
</
Form
>
);
};
export
default
BookAddEdit
;
apps/admin/src/modules/books/management/components/ManagementChapter.jsx
浏览文件 @
77cf6ebc
export
{
default
}
from
"
@/pages/books/section
"
;
export
{
default
}
from
"
../chapters
"
;
apps/admin/src/modules/books/routes.tsx
浏览文件 @
77cf6ebc
...
@@ -2,7 +2,7 @@ import { lazy } from "react";
...
@@ -2,7 +2,7 @@ import { lazy } from "react";
import
{
Navigate
,
useRoutes
}
from
"react-router"
;
import
{
Navigate
,
useRoutes
}
from
"react-router"
;
import
ModuleBoundary
from
"@/app/ModuleBoundary"
;
import
ModuleBoundary
from
"@/app/ModuleBoundary"
;
const
BooksLayout
=
lazy
(()
=>
import
(
"
@/pages/books/index
"
));
const
BooksLayout
=
lazy
(()
=>
import
(
"
./BooksLayout
"
));
const
ManagementRoutes
=
lazy
(()
=>
import
(
"./management/routes"
));
const
ManagementRoutes
=
lazy
(()
=>
import
(
"./management/routes"
));
const
AuditRoutes
=
lazy
(()
=>
import
(
"./audit/routes"
));
const
AuditRoutes
=
lazy
(()
=>
import
(
"./audit/routes"
));
const
ClassifyRoutes
=
lazy
(()
=>
import
(
"./classify/routes"
));
const
ClassifyRoutes
=
lazy
(()
=>
import
(
"./classify/routes"
));
...
...
apps/admin/src/modules/books/sale/api.ts
浏览文件 @
77cf6ebc
...
@@ -8,3 +8,24 @@ async function post(path: string, data: Record<string, unknown>, notify = false)
...
@@ -8,3 +8,24 @@ async function post(path: string, data: Record<string, unknown>, notify = false)
export
const
getSaleList
=
(
query
:
SaleQuery
)
=>
post
(
"/book/book/getList"
,
query
);
export
const
getSaleList
=
(
query
:
SaleQuery
)
=>
post
(
"/book/book/getList"
,
query
);
export
const
changeSaleStatus
=
(
id
:
string
|
number
,
status
:
string
)
=>
post
(
"/book/book/changeStatus"
,
{
id
,
status
},
true
);
export
const
changeSaleStatus
=
(
id
:
string
|
number
,
status
:
string
)
=>
post
(
"/book/book/changeStatus"
,
{
id
,
status
},
true
);
export
const
getSaleDiscussionList
=
(
query
:
SaleDiscussionQuery
)
=>
post
(
"/comment/comment/getCommentList"
,
query
);
export
const
getSaleDiscussionList
=
(
query
:
SaleDiscussionQuery
)
=>
post
(
"/comment/comment/getCommentList"
,
query
);
export
const
getListAll
=
(
data
:
Record
<
string
,
unknown
>
)
=>
post
(
"/book/chapter/getListAll"
,
data
);
export
const
getInfoById
=
(
data
:
Record
<
string
,
unknown
>
)
=>
post
(
"/book/book/getInfoById"
,
data
);
export
const
publisherList
=
(
data
:
Record
<
string
,
unknown
>
)
=>
post
(
"/book/publisher/getListAll"
,
data
);
export
const
publisherAdd
=
(
data
:
Record
<
string
,
unknown
>
)
=>
post
(
"/book/publisher/add"
,
data
,
true
);
export
const
editBook
=
(
data
:
Record
<
string
,
unknown
>
)
=>
post
(
"/book/book/edit"
,
data
,
true
);
export
const
getCommentInfo
=
(
data
:
Record
<
string
,
unknown
>
)
=>
post
(
"/comment/comment/getCommentInfo"
,
data
);
export
const
commentDel
=
async
(
data
:
Record
<
string
,
unknown
>
)
=>
{
const
result
=
await
post
(
"/comment/comment/del"
,
data
,
true
);
return
result
!==
false
;
};
export
const
commentReply
=
async
(
data
:
Record
<
string
,
unknown
>
)
=>
{
const
result
=
await
post
(
"/comment/comment/reply"
,
data
,
true
);
return
result
!==
false
;
};
apps/admin/src/modules/books/sale/components/SaleDiscussionDetail.jsx
浏览文件 @
77cf6ebc
export
{
default
}
from
"@/pages/books/sale/discussDetail"
;
import
{
Card
,
Input
,
Button
,
Space
,
Row
,
Col
,
Modal
,
Form
}
from
"antd"
;
import
{
DeleteOutlined
,
FacebookFilled
,
MessageOutlined
}
from
"@ant-design/icons"
;
import
"./SaleDiscussionDetail.less"
;
import
User
from
"@/assets/images/icon/user.png"
;
import
{
useState
,
useEffect
}
from
"react"
;
import
{
useLocation
}
from
"react-router"
;
import
{
getCommentInfo
,
commentReply
,
commentDel
}
from
"../api"
;
const
{
TextArea
}
=
Input
;
const
DiscussDetail
=
()
=>
{
const
[
showReply
,
setShowReply
]
=
useState
(
false
);
const
[
delMoadal
,
setDelModal
]
=
useState
(
false
);
const
{
state
:
{
id
,
name
,
book_id
},
}
=
useLocation
();
const
[
form
]
=
Form
.
useForm
();
const
[
data
,
setData
]
=
useState
({});
const
[
loading
,
setLoading
]
=
useState
(
false
);
const
[
commentId
,
setcommentId
]
=
useState
(
0
);
// 获取列表
const
init
=
async
()
=>
{
setLoading
(
true
);
const
data
=
await
getCommentInfo
({
id
,
book_id
});
console
.
log
(
data
);
setData
(
data
);
setLoading
(
false
);
};
useEffect
(()
=>
{
init
();
},
[]);
useEffect
(()
=>
{
if
(
!
showReply
)
{
form
.
setFieldsValue
({
content
:
""
});
form
.
resetFields
();
}
},
[
showReply
]);
// 显示回复弹框
const
showReplyFn
=
(
id
)
=>
{
setcommentId
(
id
);
setShowReply
(
true
);
};
// 点击确认回复
const
handleReply
=
async
(
obj
)
=>
{
const
bool
=
await
commentReply
({
...
obj
,
id
:
commentId
,
book_id
});
if
(
!
bool
)
return
;
setShowReply
(
false
);
init
();
};
const
handleDel
=
async
()
=>
{
const
bool
=
await
commentDel
({
id
:
commentId
,
book_id
});
if
(
!
bool
)
return
;
setDelModal
(
false
);
init
();
};
return
(
<
div
className=
"DiscussDetail"
>
<
Modal
open=
{
showReply
}
onCancel=
{
()
=>
{
setShowReply
(
false
);
}
}
maskClosable=
{
false
}
footer=
{
null
}
centered
closeIcon=
{
null
}
keyboard=
{
false
}
>
<
br
/>
<
Form
form=
{
form
}
onFinish=
{
handleReply
}
>
<
Form
.
Item
label=
"内容"
name=
"content"
rules=
{
[{
required
:
true
,
message
:
"请输入内容"
}]
}
>
<
TextArea
placeholder=
"请输入内容"
autoSize=
{
{
minRows
:
3
,
maxRows
:
5
,
}
}
></
TextArea
>
</
Form
.
Item
>
<
Form
.
Item
>
<
Row
gutter=
{
20
}
justify=
{
"center"
}
>
<
Col
>
<
Button
onClick=
{
()
=>
setShowReply
(
false
)
}
>
取消
</
Button
>
</
Col
>
<
Col
>
<
Button
type=
"primary"
htmlType=
"submit"
>
确认
</
Button
>
</
Col
>
</
Row
>
</
Form
.
Item
>
</
Form
>
</
Modal
>
<
Modal
mask=
{
false
}
centered
open=
{
delMoadal
}
onOk=
{
handleDel
}
onCancel=
{
()
=>
setDelModal
(
false
)
}
footer=
{
(
_
,
{
OkBtn
,
CancelBtn
})
=>
{
return
(
<
Row
justify=
{
"center"
}
className=
"delModal"
>
<
Space
>
<
CancelBtn
/>
<
OkBtn
/>
</
Space
>
</
Row
>
);
}
}
okText=
"确认"
>
<
p
style=
{
{
textAlign
:
"center"
,
padding
:
"50px 0 30px"
,
fontSize
:
16
}
}
>
评论将永久删除,是否继续?
</
p
>
</
Modal
>
<
Card
className=
"card"
title=
{
`书名:《${name}》`
}
loading=
{
loading
}
>
<
div
className=
"discussBox"
>
<
Row
className=
"discussItem"
gutter=
{
10
}
>
<
Col
className=
"img"
>
<
img
src=
{
data
.
person_pic
||
User
}
width=
{
28
}
height=
{
28
}
style=
{
{
borderRadius
:
"50%"
,
objectFit
:
"cover"
}
}
/>
</
Col
>
<
Col
className=
"discuss"
flex=
{
1
}
>
<
div
className=
"name"
>
{
data
.
person_name
}
</
div
>
{
/* <div className='content'>{data?.content && data.content[0].content}</div> */
}
<
div
className=
"content"
>
{
data
?.
content
&&
data
.
content
.
map
((
item
,
index
)
=>
{
const
type
=
item
.
types
;
const
value
=
item
.
content
;
if
(
type
===
"audio"
)
{
return
(
<
div
key=
{
index
}
>
<
span
>
<
audio
controls
>
<
source
src=
{
value
}
type=
"audio/mp3"
/>
Your browser does not support the audio element.
</
audio
>
</
span
>
</
div
>
);
}
else
if
(
type
===
"text"
)
{
return
<
span
key=
{
index
}
>
{
value
}
</
span
>;
}
else
if
(
type
===
"image"
)
{
return
<
img
height=
{
100
}
src=
{
value
}
></
img
>;
}
})
}
</
div
>
<
Space
>
<
Button
type=
"text"
className=
"reply"
onClick=
{
()
=>
showReplyFn
(
data
.
id
)
}
icon=
{
<
MessageOutlined
/>
}
>
回复
</
Button
>
<
Button
type=
"text"
className=
"del"
icon=
{
<
DeleteOutlined
/>
}
onClick=
{
()
=>
{
setDelModal
(
true
);
setcommentId
(
data
.
id
);
}
}
>
删除
</
Button
>
</
Space
>
</
Col
>
</
Row
>
{
data
.
child
&&
data
.
child
.
map
((
item
)
=>
(
<
Row
className=
"discussItem reply"
key=
{
item
.
id
}
gutter=
{
10
}
>
<
Col
span=
{
1
}
></
Col
>
<
Col
className=
"img"
>
<
img
src=
{
item
.
person_pic
||
User
}
width=
{
28
}
height=
{
28
}
style=
{
{
borderRadius
:
"50%"
,
objectFit
:
"cover"
}
}
/>
</
Col
>
<
Col
className=
"discuss"
flex=
{
1
}
>
<
div
className=
"name"
>
{
item
.
person_name
}
</
div
>
<
div
className=
"content"
>
{
item
.
content
&&
item
.
content
.
map
((
item
,
index
)
=>
(
<
div
key=
{
index
}
>
{
item
.
types
==
"text"
&&
<
span
>
{
item
.
content
}
</
span
>
}
{
item
.
types
==
"image"
&&
<
img
src=
{
item
.
content
}
></
img
>
}
{
item
.
types
==
"audio"
&&
<
audio
controls
src=
{
item
.
content
}
/>
}
</
div
>
))
}
</
div
>
<
Space
>
<
Button
type=
"text"
className=
"reply"
onClick=
{
()
=>
showReplyFn
(
item
.
id
)
}
icon=
{
<
MessageOutlined
/>
}
>
回复
</
Button
>
<
Button
type=
"text"
className=
"del"
icon=
{
<
DeleteOutlined
/>
}
onClick=
{
()
=>
{
setDelModal
(
true
);
setcommentId
(
item
.
id
);
}
}
>
删除
</
Button
>
</
Space
>
</
Col
>
</
Row
>
))
}
</
div
>
{
/* <div className="discussCreate">
<Row gutter={10}>
<Col><div className="img"><img src={User} width={28} height={28} /></div></Col>
<Col><Input autoComplete="off" placeholder="发布你的评论" style={{width:754}}></Input ></Col>
<Col>
<Space>
<Button>取消</Button>
<Button type="primary">回复</Button>
</Space>
</Col>
</Row>
</div> */
}
</
Card
>
</
div
>
);
};
export
default
DiscussDetail
;
apps/admin/src/modules/books/sale/components/SaleDiscussionDetail.less
0 → 100644
浏览文件 @
77cf6ebc
.DiscussDetail {
.reply {
color: #aa1941;
}
.del {
color: #999999;
}
.card {
.ant-card-body {
height: calc(100vh - 260px);
overflow: auto;
}
}
.discussItem {
.discuss {
&::after {
display: block;
content: "";
width: 100%;
height: 1px;
background: #e5e5e57f;
margin-top: 16px;
margin-bottom: 10px;
}
.name {
font-size: 12px;
color: #333333;
font-weight: 500;
margin-bottom: 4px;
}
.content {
font-size: 12px;
color: #333333;
}
}
}
}
apps/admin/src/modules/books/sale/components/SaleEdit.jsx
浏览文件 @
77cf6ebc
差异被折叠。
点击展开。
apps/admin/src/modules/members/Layout.jsx
0 → 100644
浏览文件 @
77cf6ebc
import
{
Outlet
}
from
'react-router'
const
MembersLayout
=
()
=>
<
Outlet
/>
export
default
MembersLayout
apps/admin/src/modules/members/routes.tsx
浏览文件 @
77cf6ebc
...
@@ -2,7 +2,7 @@ import { lazy } from "react";
...
@@ -2,7 +2,7 @@ import { lazy } from "react";
import
{
Navigate
,
useRoutes
}
from
"react-router"
;
import
{
Navigate
,
useRoutes
}
from
"react-router"
;
import
ModuleBoundary
from
"@/app/ModuleBoundary"
;
import
ModuleBoundary
from
"@/app/ModuleBoundary"
;
const
MembersLayout
=
lazy
(()
=>
import
(
"
@/pages/member/index
"
));
const
MembersLayout
=
lazy
(()
=>
import
(
"
./Layout
"
));
const
MemberListRoutes
=
lazy
(()
=>
import
(
"./list/routes"
));
const
MemberListRoutes
=
lazy
(()
=>
import
(
"./list/routes"
));
const
MemberLevelRoutes
=
lazy
(()
=>
import
(
"./level/routes"
));
const
MemberLevelRoutes
=
lazy
(()
=>
import
(
"./level/routes"
));
...
...
apps/admin/src/modules/settings/SettingsLayout.jsx
0 → 100644
浏览文件 @
77cf6ebc
import
React
from
"react"
;
import
{
Outlet
}
from
"react-router"
;
const
Role
=
()
=>
{
return
(
<
div
>
<
Outlet
/>
</
div
>
);
};
export
default
Role
;
apps/admin/src/modules/settings/app-version/views/AppVersionListView.jsx
浏览文件 @
77cf6ebc
...
@@ -21,7 +21,7 @@ import dayjs from "dayjs";
...
@@ -21,7 +21,7 @@ import dayjs from "dayjs";
import
Add
from
"@/assets/images/icon/add.png"
;
import
Add
from
"@/assets/images/icon/add.png"
;
import
{
useSelector
}
from
"react-redux"
;
import
{
useSelector
}
from
"react-redux"
;
import
AliOSS
from
"ali-oss"
;
import
AliOSS
from
"ali-oss"
;
import
{
getAliOSSSTSToken
}
from
"
@/pages/setting/help/addedit/reque
t"
;
import
{
getAliOSSSTSToken
}
from
"
../../help/reques
t"
;
const
AppVersion
=
()
=>
{
const
AppVersion
=
()
=>
{
const
[
data
,
setData
]
=
useState
([]);
const
[
data
,
setData
]
=
useState
([]);
const
[
page_size
,
setpage_size
]
=
useState
(
10
);
const
[
page_size
,
setpage_size
]
=
useState
(
10
);
...
...
apps/admin/src/modules/settings/help/request.js
0 → 100644
浏览文件 @
77cf6ebc
import
axios
from
"@/utils/request.js"
;
import
qs
from
"qs"
;
import
{
message
}
from
"antd"
;
import
{
get
}
from
"lodash-es"
;
// oss
const
getAliOSSSTSToken
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
"/common/OssUpload/getUploadToken"
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"获取OSS令牌失败!"
);
if
(
code
===
200
)
{
return
data
;
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
return
false
;
}
};
export
{
getAliOSSSTSToken
};
apps/admin/src/modules/settings/help/views/HelpAddEditView.jsx
浏览文件 @
77cf6ebc
...
@@ -11,7 +11,7 @@ import { uploadFiles } from "@/utils/upload";
...
@@ -11,7 +11,7 @@ import { uploadFiles } from "@/utils/upload";
import
AliOSS
from
"ali-oss"
;
import
AliOSS
from
"ali-oss"
;
import
dayjs
from
"dayjs"
;
import
dayjs
from
"dayjs"
;
import
{
getAliOSSSTSToken
}
from
"
@/pages/setting/help/addedit/reque
t"
;
import
{
getAliOSSSTSToken
}
from
"
../reques
t"
;
import
"./HelpAddEditView.less"
;
import
"./HelpAddEditView.less"
;
...
...
apps/admin/src/modules/settings/routes.tsx
浏览文件 @
77cf6ebc
...
@@ -2,7 +2,7 @@ import { lazy } from "react";
...
@@ -2,7 +2,7 @@ import { lazy } from "react";
import
{
Navigate
,
useRoutes
}
from
"react-router"
;
import
{
Navigate
,
useRoutes
}
from
"react-router"
;
import
ModuleBoundary
from
"@/app/ModuleBoundary"
;
import
ModuleBoundary
from
"@/app/ModuleBoundary"
;
const
SettingsLayout
=
lazy
(()
=>
import
(
"
@/pages/setting/index
"
));
const
SettingsLayout
=
lazy
(()
=>
import
(
"
./SettingsLayout
"
));
const
HelpRoutes
=
lazy
(()
=>
import
(
"./help/routes"
));
const
HelpRoutes
=
lazy
(()
=>
import
(
"./help/routes"
));
const
AppliedRoutes
=
lazy
(()
=>
import
(
"./applied/routes"
));
const
AppliedRoutes
=
lazy
(()
=>
import
(
"./applied/routes"
));
const
PersonalizedRoutes
=
lazy
(()
=>
import
(
"./personalized/routes"
));
const
PersonalizedRoutes
=
lazy
(()
=>
import
(
"./personalized/routes"
));
...
...
apps/admin/src/modules/student-book/api.ts
浏览文件 @
77cf6ebc
export
*
from
"
@/pages/student/book
/request"
;
export
*
from
"
.
/request"
;
apps/admin/src/modules/student-book/request.js
0 → 100644
浏览文件 @
77cf6ebc
import
axios
from
"@/utils/request.js"
;
import
qs
from
"qs"
;
import
{
get
}
from
"lodash-es"
;
import
{
message
}
from
"antd"
;
// 用户信息
const
getUserInfo
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
"/user/user/getUserInfo"
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"数据获取失败!"
);
if
(
code
===
200
)
{
return
data
;
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
return
false
;
}
};
// 获取角色已选权限
const
getPowerByRoleId
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
"/user/role/getPowerByRoleId"
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"数据获取失败!"
);
if
(
code
===
200
)
{
return
data
;
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
return
false
;
}
};
// 章节列表
const
getAllList
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
"/book/teacher/chapter/getAllList"
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"数据获取失败!"
);
if
(
code
===
200
)
{
return
{
code
,
data
,
};
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
return
false
;
}
};
// 添加章节
const
chapterAdd
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
"/book/teacher/chapter/add"
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"数据获取失败!"
);
if
(
code
===
200
)
{
// message.success('添加成功');
return
data
;
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
return
false
;
}
};
// 章节详情
const
getInfoById
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
"/book/teacher/chapter/getInfoById"
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"数据获取失败!"
);
if
(
code
===
200
)
{
return
data
;
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
return
false
;
}
};
// 修改章节
const
chapterEdit
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
"/book/teacher/chapter/edit"
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"数据获取失败!"
);
if
(
code
===
200
)
{
message
.
success
(
msg
);
return
true
;
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
return
false
;
}
};
// 删除章节
const
chapterDel
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
"/book/teacher/chapter/del"
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"数据获取失败!"
);
if
(
code
===
200
)
{
message
.
success
(
msg
);
return
true
;
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
return
false
;
}
};
// 拖拽章节排序
const
dragOrder
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
"/book/teacher/chapter/dragOrder"
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"数据获取失败!"
);
if
(
code
===
200
)
{
message
.
success
(
msg
);
return
true
;
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
return
false
;
}
};
// 获取章节内容
const
getInfoByChapterId
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
"/book/teacher/section/getInfoByChapterId"
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"数据获取失败!"
);
if
(
code
===
200
)
{
return
data
;
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
return
false
;
}
};
// 添加章节内容
const
sectionAdd
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
"/book/teacher/section/add"
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"数据获取失败!"
);
if
(
code
===
200
)
{
message
.
success
(
msg
);
return
true
;
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
return
false
;
}
};
// 修改章节内容
const
sectionEdit
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
"/book/teacher/section/edit"
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"数据获取失败!"
);
if
(
code
===
200
)
{
// message.success(msg);
return
true
;
}
else
{
message
.
error
(
msg
);
return
{
code
,
msg
,
data
};
}
}
catch
(
error
)
{
return
false
;
}
};
// 获取章节的题库列表
const
getQuestionList
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
"/book/chapter/question/getQuestionList"
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"数据获取失败!"
);
if
(
code
===
200
)
{
return
data
;
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
return
false
;
}
};
// 移除课后题
const
questionDel
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
"/book/chapter/question/del"
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"数据获取失败!"
);
if
(
code
===
200
)
{
return
data
;
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
return
false
;
}
};
// 添加课后题
const
questionAdd
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
"/book/chapter/question/add"
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"数据获取失败!"
);
if
(
code
===
200
)
{
return
data
;
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
return
false
;
}
};
// 发布审核
const
release
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
"/book/teacher/release"
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"数据获取失败!"
);
if
(
code
===
200
)
{
return
true
;
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
return
false
;
}
};
// 模板列表
const
templateGetList
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
"/book/template/getList"
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"数据获取失败!"
);
if
(
code
===
200
)
{
return
true
;
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
return
false
;
}
};
// 模板导入
const
templateImport
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
"/book/template/import"
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"数据获取失败!"
);
if
(
code
===
200
)
{
return
true
;
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
return
false
;
}
};
// 书籍导入
const
teacherImport
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
"/book/teacher/import"
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"数据获取失败!"
);
if
(
code
===
200
)
{
return
true
;
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
return
false
;
}
};
// 保存历史记录
const
getRecordList
=
async
(
obj
)
=>
{
try
{
const
res
=
await
axios
.
post
(
"/book/teacher/section/getRecordList"
,
qs
.
stringify
(
obj
));
const
code
=
get
(
res
,
"data.code"
,
0
);
const
data
=
get
(
res
,
"data.data"
,
[]);
const
msg
=
get
(
res
,
"data.message"
,
"数据获取失败!"
);
if
(
code
===
200
)
{
return
data
;
}
else
{
message
.
error
(
msg
);
return
false
;
}
}
catch
(
error
)
{
return
false
;
}
};
export
{
getAllList
,
chapterAdd
,
getInfoById
,
chapterEdit
,
chapterDel
,
dragOrder
,
getInfoByChapterId
,
sectionAdd
,
sectionEdit
,
getQuestionList
,
questionDel
,
questionAdd
,
release
,
templateGetList
,
templateImport
,
teacherImport
,
getRecordList
,
getPowerByRoleId
,
getUserInfo
,
};
apps/admin/src/modules/student-book/views/StudentBookView.jsx
浏览文件 @
77cf6ebc
差异被折叠。
点击展开。
apps/admin/src/
pages/student/book/index
.less
→
apps/admin/src/
modules/student-book/views/StudentBookView
.less
浏览文件 @
77cf6ebc
File moved
apps/admin/src/modules/teachers/Layout.jsx
0 → 100644
浏览文件 @
77cf6ebc
差异被折叠。
点击展开。
apps/admin/src/modules/teachers/list/views/TeacherListView.jsx
浏览文件 @
77cf6ebc
差异被折叠。
点击展开。
apps/admin/src/modules/teachers/routes.tsx
浏览文件 @
77cf6ebc
差异被折叠。
点击展开。
apps/admin/src/pages/advertisement/index.jsx
浏览文件 @
77cf6ebc
差异被折叠。
点击展开。
apps/admin/src/pages/books/audit/index.less
浏览文件 @
77cf6ebc
差异被折叠。
点击展开。
apps/admin/src/pages/books/audit/preview.jsx
浏览文件 @
77cf6ebc
差异被折叠。
点击展开。
apps/admin/src/pages/books/index.jsx
浏览文件 @
77cf6ebc
差异被折叠。
点击展开。
apps/admin/src/pages/books/management/addedit/index.jsx
浏览文件 @
77cf6ebc
差异被折叠。
点击展开。
apps/admin/src/pages/books/sale/discussDetail/index.jsx
浏览文件 @
77cf6ebc
差异被折叠。
点击展开。
apps/admin/src/pages/books/sale/discussDetail/index.less
浏览文件 @
77cf6ebc
差异被折叠。
点击展开。
apps/admin/src/pages/books/sale/edit.jsx
浏览文件 @
77cf6ebc
差异被折叠。
点击展开。
apps/admin/src/pages/books/section/api.js
浏览文件 @
77cf6ebc
差异被折叠。
点击展开。
apps/admin/src/pages/books/section/components/BindKnowledgeGraph.jsx
浏览文件 @
77cf6ebc
差异被折叠。
点击展开。
apps/admin/src/pages/books/section/components/EditChapterEditors.jsx
浏览文件 @
77cf6ebc
差异被折叠。
点击展开。
apps/admin/src/pages/books/section/components/form-chapter-title.jsx
浏览文件 @
77cf6ebc
差异被折叠。
点击展开。
apps/admin/src/pages/books/section/index.jsx
浏览文件 @
77cf6ebc
差异被折叠。
点击展开。
apps/admin/src/pages/books/section/index.less
浏览文件 @
77cf6ebc
差异被折叠。
点击展开。
apps/admin/src/pages/books/section/request.js
浏览文件 @
77cf6ebc
差异被折叠。
点击展开。
apps/admin/src/pages/jurisdiction/index.jsx
浏览文件 @
77cf6ebc
差异被折叠。
点击展开。
apps/admin/src/pages/member/index.jsx
浏览文件 @
77cf6ebc
差异被折叠。
点击展开。
apps/admin/src/pages/setting/help/addedit/requet.js
浏览文件 @
77cf6ebc
差异被折叠。
点击展开。
apps/admin/src/pages/setting/index.jsx
浏览文件 @
77cf6ebc
差异被折叠。
点击展开。
apps/admin/src/pages/setting/personalized-setting/index.jsx
浏览文件 @
77cf6ebc
差异被折叠。
点击展开。
apps/admin/src/pages/setting/point-management/index.jsx
浏览文件 @
77cf6ebc
差异被折叠。
点击展开。
apps/admin/src/pages/setting/point-management/request.js
浏览文件 @
77cf6ebc
差异被折叠。
点击展开。
apps/admin/src/pages/student/book/index.jsx
浏览文件 @
77cf6ebc
差异被折叠。
点击展开。
apps/admin/src/pages/student/book/request.js
浏览文件 @
77cf6ebc
差异被折叠。
点击展开。
apps/admin/src/pages/teacher/index.jsx
浏览文件 @
77cf6ebc
差异被折叠。
点击展开。
apps/admin/src/pages/user-module/index.jsx
浏览文件 @
77cf6ebc
差异被折叠。
点击展开。
apps/admin/src/pages/user-module/login/index.jsx
浏览文件 @
77cf6ebc
差异被折叠。
点击展开。
apps/admin/src/pages/user-module/login/request/api.js
浏览文件 @
77cf6ebc
差异被折叠。
点击展开。
apps/admin/src/pages/user-module/login/request/index.js
浏览文件 @
77cf6ebc
差异被折叠。
点击展开。
apps/admin/src/pages/user-module/request/api.js
浏览文件 @
77cf6ebc
差异被折叠。
点击展开。
apps/admin/src/pages/user-module/request/request.jsx
浏览文件 @
77cf6ebc
差异被折叠。
点击展开。
apps/admin/src/pages/user-module/userInfo/index.jsx
浏览文件 @
77cf6ebc
差异被折叠。
点击展开。
apps/admin/src/pages/user-module/userInfo/requet.js
浏览文件 @
77cf6ebc
差异被折叠。
点击展开。
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论