Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
A
adx-manager-node
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
1
Merge Requests
1
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
杨贺晨吉
adx-manager-node
Commits
8874e05e
Commit
8874e05e
authored
Apr 11, 2025
by
杨贺晨吉
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 开发1
parent
eeb7db42
Changes
26
Hide whitespace changes
Inline
Side-by-side
Showing
26 changed files
with
881 additions
and
140 deletions
+881
-140
auto-imports.d.ts
auto-imports.d.ts
+25
-0
App.tsx
src/App.tsx
+2
-1
index.ts
src/apis/mediaAccount/index.ts
+27
-0
type.ts
src/apis/mediaAccount/type.ts
+37
-0
type.ts
src/apis/type.ts
+4
-0
DraggerUpload.tsx
src/components/common/DraggerUpload.tsx
+197
-0
TableSelect.tsx
src/components/common/TableSelect.tsx
+0
-0
Index.tsx
src/components/mediaAccount/Index.tsx
+48
-0
addAccount.tsx
src/components/mediaAccount/addAccount.tsx
+99
-0
const.ts
src/components/mediaAccount/const.ts
+0
-0
index.less
src/components/mediaAccount/index.less
+3
-0
list.tsx
src/components/mediaAccount/list.tsx
+194
-0
search.tsx
src/components/mediaAccount/search.tsx
+61
-0
store.ts
src/components/mediaAccount/store.ts
+64
-0
useColumns.tsx
src/components/mediaAccount/useColumns.tsx
+0
-0
index.css
src/index.css
+9
-1
addAccount.tsx
src/pages/Media/mediaAccount/addAccount.tsx
+0
-23
index.tsx
src/pages/Media/mediaAccount/index.tsx
+4
-10
list.tsx
src/pages/Media/mediaAccount/list.tsx
+0
-65
search.tsx
src/pages/Media/mediaAccount/search.tsx
+0
-38
REG.ts
src/utils/REG.ts
+5
-0
index.ts
src/utils/index.ts
+1
-1
string.ts
src/utils/string.ts
+5
-0
upload.ts
src/utils/upload.ts
+75
-0
tsconfig.app.json
tsconfig.app.json
+8
-1
vite.config.ts
vite.config.ts
+13
-0
No files found.
auto-imports.d.ts
View file @
8874e05e
...
...
@@ -9,7 +9,10 @@ declare global {
const
Button
:
typeof
import
(
'antd'
)[
'Button'
]
const
Card
:
typeof
import
(
'antd'
)[
'Card'
]
const
Checkbox
:
typeof
import
(
'antd'
)[
'Checkbox'
]
const
Col
:
typeof
import
(
'antd'
)[
'Col'
]
const
DatePicker
:
typeof
import
(
'antd'
)[
'DatePicker'
]
const
DraggerUpload
:
typeof
import
(
'./src/components/common/DraggerUpload'
)[
'default'
]
const
Flex
:
typeof
import
(
'antd'
)[
'Flex'
]
const
Form
:
typeof
import
(
'antd'
)[
'Form'
]
const
Input
:
typeof
import
(
'antd'
)[
'Input'
]
const
Layout
:
typeof
import
(
'antd'
)[
'Layout'
]
...
...
@@ -26,6 +29,7 @@ declare global {
const
Role
:
typeof
import
(
'./src/constants/enums/index'
)[
'Role'
]
const
Route
:
typeof
import
(
'react-router-dom'
)[
'Route'
]
const
Routes
:
typeof
import
(
'react-router-dom'
)[
'Routes'
]
const
Row
:
typeof
import
(
'antd'
)[
'Row'
]
const
Rules
:
typeof
import
(
'./src/utils/REG'
)[
'Rules'
]
const
Select
:
typeof
import
(
'antd'
)[
'Select'
]
const
Space
:
typeof
import
(
'antd'
)[
'Space'
]
...
...
@@ -35,10 +39,17 @@ declare global {
const
Upload
:
typeof
import
(
'antd'
)[
'Upload'
]
const
UserList
:
typeof
import
(
'./src/constants/userList'
)[
'UserList'
]
const
action
:
typeof
import
(
'mobx'
)[
'action'
]
const
addMediaAccountAPI
:
typeof
import
(
'./src/apis/mediaAccount/index'
)[
'addMediaAccountAPI'
]
const
autorun
:
typeof
import
(
'mobx'
)[
'autorun'
]
const
axios
:
typeof
import
(
'axios'
)[
'default'
]
const
buildREG
:
typeof
import
(
'./src/utils/REG'
)[
'buildREG'
]
const
changeAEByIdAPI
:
typeof
import
(
'./src/apis/mediaAccount/index'
)[
'changeAEByIdAPI'
]
const
changeAEListByIdAPI
:
typeof
import
(
'./src/apis/mediaAccount/index'
)[
'changeAEListByIdAPI'
]
const
changeDate
:
typeof
import
(
'./src/utils/date'
)[
'changeDate'
]
const
changePEByIdAPI
:
typeof
import
(
'./src/apis/mediaAccount/index'
)[
'changePEByIdAPI'
]
const
changeStatueByIdAPI
:
typeof
import
(
'./src/apis/mediaAccount/index'
)[
'changeStatueByIdAPI'
]
const
checkIsImage
:
typeof
import
(
'./src/utils/upload'
)[
'checkIsImage'
]
const
checkIsVideo
:
typeof
import
(
'./src/utils/upload'
)[
'checkIsVideo'
]
const
computed
:
typeof
import
(
'mobx'
)[
'computed'
]
const
cookie
:
typeof
import
(
'./src/utils/cookie'
)[
'default'
]
const
counterStore
:
typeof
import
(
'./src/stores/counterStore'
)[
'counterStore'
]
...
...
@@ -52,10 +63,17 @@ declare global {
const
forwardRef
:
typeof
import
(
'react'
)[
'forwardRef'
]
const
getCustomList
:
typeof
import
(
'./src/apis/index'
)[
'getCustomList'
]
const
getFailedRecords
:
typeof
import
(
'./src/apis/index'
)[
'getFailedRecords'
]
const
getFileUrl
:
typeof
import
(
'./src/utils/upload'
)[
'getFileUrl'
]
const
getImgInfo
:
typeof
import
(
'./src/utils/upload'
)[
'getImgInfo'
]
const
getMediaAccountAPI
:
typeof
import
(
'./src/apis/mediaAccount/index'
)[
'getMediaAccountAPI'
]
const
getMediaAccountListAPI
:
typeof
import
(
'./src/apis/mediaAccount/index'
)[
'getMediaAccountListAPI'
]
const
getRealTime
:
typeof
import
(
'./src/apis/index'
)[
'getRealTime'
]
const
getSuffix
:
typeof
import
(
'./src/utils/upload'
)[
'getSuffix'
]
const
getSvgaInfo
:
typeof
import
(
'./src/utils/upload'
)[
'getSvgaInfo'
]
const
getTopOnlineApp
:
typeof
import
(
'./src/apis/index'
)[
'getTopOnlineApp'
]
const
getUserById
:
typeof
import
(
'./src/apis/user/index'
)[
'getUserById'
]
const
getUserList
:
typeof
import
(
'./src/apis/user/index'
)[
'getUserList'
]
const
getVideoInfo
:
typeof
import
(
'./src/utils/upload'
)[
'getVideoInfo'
]
const
intercept
:
typeof
import
(
'mobx'
)[
'intercept'
]
const
isEmail
:
typeof
import
(
'./src/utils/REG'
)[
'isEmail'
]
const
isNothing
:
typeof
import
(
'./src/utils/index'
)[
'isNothing'
]
...
...
@@ -81,6 +99,7 @@ declare global {
const
request
:
typeof
import
(
'./src/utils/request'
)[
'default'
]
const
runInAction
:
typeof
import
(
'mobx'
)[
'runInAction'
]
const
smartFenToYuan
:
typeof
import
(
'./src/utils/money'
)[
'smartFenToYuan'
]
const
splitStrBy
:
typeof
import
(
'./src/utils/string'
)[
'splitStrBy'
]
const
startTransition
:
typeof
import
(
'react'
)[
'startTransition'
]
const
theme
:
typeof
import
(
'antd'
)[
'theme'
]
const
toJS
:
typeof
import
(
'mobx'
)[
'toJS'
]
...
...
@@ -120,6 +139,12 @@ declare global {
}
// for type re-export
declare
global
{
// @ts-ignore
export
type
{
mediaSearchP
,
mediaAccountList
,
mediaAccount
,
changeParams
}
from
'./src/apis/mediaAccount/type'
import
(
'./src/apis/mediaAccount/type'
)
// @ts-ignore
export
type
{
paginationType
}
from
'./src/apis/type'
import
(
'./src/apis/type'
)
// @ts-ignore
export
type
{
UserEntity
}
from
'./src/apis/user/type'
import
(
'./src/apis/user/type'
)
...
...
src/App.tsx
View file @
8874e05e
...
...
@@ -3,6 +3,7 @@ import { Suspense } from 'react'
import
{
StyleProvider
}
from
'@ant-design/cssinjs'
import
routes
from
'~react-pages'
import
{
ConfigProvider
}
from
'antd'
import
zhCN
from
'antd/lib/locale/zh_CN'
import
Layouts
from
'./layouts/index.tsx'
...
...
@@ -10,7 +11,7 @@ const App: React.FC = () => {
return
(
<
Suspense
fallback=
{
<
Spin
fullscreen
/>
}
>
<
StyleProvider
layer
>
<
ConfigProvider
>
<
ConfigProvider
locale=
{
zhCN
}
>
<
Layouts
>
{
useRoutes
(
routes
)
}
</
Layouts
>
</
ConfigProvider
>
</
StyleProvider
>
...
...
src/apis/mediaAccount/index.ts
0 → 100644
View file @
8874e05e
export
const
getMediaAccountListAPI
=
(
params
:
mediaSearchP
)
=>
{
return
request
.
post
<
mediaSearchP
,
mediaAccountList
[]
>
(
'/ab'
,
params
)
}
export
const
addMediaAccountAPI
=
(
params
:
mediaAccount
)
=>
{
return
request
.
post
<
mediaAccount
,
boolean
>
(
'/ab3'
,
params
)
}
export
const
getMediaAccountAPI
=
(
id
:
number
|
string
)
=>
{
return
request
.
post
<
number
,
mediaAccount
>
(
'/ab3'
,
{
id
})
}
export
const
changeStatueByIdAPI
=
(
params
:
changeParams
)
=>
{
return
request
.
post
<
changeParams
,
boolean
>
(
'/ac'
,
params
)
}
export
const
changeAEByIdAPI
=
(
params
:
changeParams
)
=>
{
return
request
.
post
<
changeParams
,
boolean
>
(
'/abc'
,
params
)
}
export
const
changePEByIdAPI
=
(
params
:
changeParams
)
=>
{
return
request
.
post
<
changeParams
,
boolean
>
(
'/abcd'
,
params
)
}
export
const
changeAEListByIdAPI
=
(
params
:
changeParams
)
=>
{
return
request
.
post
<
changeParams
,
boolean
>
(
'/abcde'
,
params
)
}
src/apis/mediaAccount/type.ts
0 → 100644
View file @
8874e05e
export
interface
mediaSearchP
extends
paginationType
{
mediaId
:
number
|
string
mediaName
:
string
AE
:
string
PE
:
string
}
export
interface
mediaAccountList
{
mediaId
:
number
|
string
mediaName
:
string
mediaType
:
string
mediaC
:
string
mediaTime
:
string
AE
:
string
AEName
:
string
PE
:
string
statue
:
boolean
}
export
interface
mediaAccount
{
mediaName
:
string
cName
:
string
pe
:
string
phone
:
string
email
:
string
account
:
string
pic1
:
string
pic2
:
string
}
export
interface
changeParams
{
mediaId
:
number
|
string
statue
?:
boolean
AE
?:
string
PE
?:
string
AEList
?:
string
[]
}
src/apis/type.ts
0 → 100644
View file @
8874e05e
export
interface
paginationType
{
pageSize
:
number
currentPage
:
number
}
src/components/common/DraggerUpload.tsx
0 → 100644
View file @
8874e05e
import
type
{
GetProp
,
UploadProps
}
from
'antd'
import
{
LoadingOutlined
,
PlusOutlined
}
from
'@ant-design/icons'
import
numeral
from
'numeral'
type
FileType
=
Parameters
<
GetProp
<
UploadProps
,
'beforeUpload'
>>
[
0
]
const
XCsrfToken
=
cookie
.
get
(
'csrf_token'
)
||
''
const
defaultHeaders
=
{
'X-Csrf-Token'
:
XCsrfToken
,
}
interface
isLoading
{
loading
:
boolean
}
const
UploadButton
=
(
load
:
isLoading
)
=>
(
<
button
style=
{
{
border
:
0
,
background
:
'none'
}
}
type=
'button'
>
{
load
.
loading
?
<
LoadingOutlined
/>
:
<
PlusOutlined
/>
}
{
!
load
.
loading
&&
<
div
className=
'ant-upload-text'
>
点击上传
</
div
>
}
</
button
>
)
const
ImgAccept
=
[
'.jpg'
,
'.jpeg'
,
'.png'
]
const
DefaultAccept
=
[...
ImgAccept
,
'.mp4'
]
interface
IDraggerUploadProps
extends
UploadProps
{
value
?:
string
width
?:
number
height
?:
number
size
?:
number
// 单位是mb
videoSize
?:
number
// 单位是mb
videoDuration
?:
number
// 单位秒s
duration
?:
number
displayZoomSize
?:
number
// 默认预览图适配系数
autoZoomSize
?:
boolean
// 预览图是否自动适配图片宽高
checkSize
?:
boolean
//是否校验宽高
render
?:
()
=>
React
.
ReactNode
// 自定义默认的上传背景内容
getUploadUrl
?:
(
url
:
string
)
=>
void
// 上传成功后的参数回调
}
const
DraggerUpload
:
React
.
FC
<
IDraggerUploadProps
>
=
observer
(
(
{
value
,
width
,
height
,
checkSize
=
true
,
size
=
5
,
// 默认是5mb
videoSize
,
videoDuration
,
displayZoomSize
=
1
,
autoZoomSize
=
false
,
getUploadUrl
,
name
=
'file'
,
action
=
'https://ssp-manager.tuiatest.cn/upload/index'
,
data
,
showUploadList
=
false
,
accept
=
DefaultAccept
,
beforeUpload
=
()
=>
{
return
true
},
render
,
...
restProps
},
ref
)
=>
{
const
[
imgUrl
,
changeImgUrl
]
=
useState
(
value
)
const
[
loading
,
changeLoading
]
=
useState
(
false
)
const
[
messageApi
,
contextHolder
]
=
message
.
useMessage
()
useEffect
(()
=>
{
changeImgUrl
(
value
)
},
[
value
])
const
commonBeforeUpload
:
UploadProps
[
'beforeUpload'
]
=
async
function
(
file
:
FileType
,
FileList
:
FileType
[])
{
return
new
Promise
<
void
>
(
async
(
resolve
,
reject
)
=>
{
// 默认校验
if
(
checkIsImage
(
file
))
{
await
getImgInfo
(
file
).
then
(({
width
:
imgWidth
,
height
:
imgHeight
,
size
:
imgSize
})
=>
{
const
isWidthValid
=
width
?
imgWidth
===
width
:
true
const
isHeightValid
=
height
?
imgHeight
===
height
:
true
if
((
!
isWidthValid
||
!
isHeightValid
)
&&
checkSize
)
{
messageApi
.
error
(
height
?
`请上传宽
${
width
}
,高
${
height
}
的图片`
:
`请上传宽
${
width
}
的图片`
)
return
false
}
if
(
imgSize
>
size
*
1024
*
1024
)
{
messageApi
.
error
(
`请上传不大于
${
numeral
(
size
*
1024
*
1024
).
format
(
'0b'
)}
的图片`
)
return
false
}
return
true
})
}
if
(
checkIsVideo
(
file
))
{
await
getVideoInfo
(
file
).
then
(({
duration
=
0
})
=>
{
if
(
videoSize
&&
videoSize
*
1024
*
1024
<
file
.
size
)
{
messageApi
.
error
(
`请上传不大于
${
numeral
(
videoSize
*
1024
*
1024
).
format
(
'0b'
)}
的视频`
)
return
false
}
if
(
videoDuration
&&
videoDuration
<
duration
)
{
messageApi
.
error
(
`请上传不长于
${
videoDuration
}
s的视频`
)
return
false
}
})
}
// 自定义校验
const
canUpload
=
await
beforeUpload
?.(
file
,
FileList
)
if
(
!
canUpload
)
{
reject
(
new
Error
(
'上传失败'
))
return
}
resolve
()
changeLoading
(
true
)
return
true
})
}
// 不手动修改上传内容(联调后看看需不需要在添加)
const
commonOnChange
:
UploadProps
[
'onChange'
]
=
(
info
)
=>
{
console
.
log
(
'info'
,
info
)
changeLoading
(
true
)
const
{
file
:
{
status
,
response
},
}
=
info
if
(
status
===
'error'
)
{
changeLoading
(
false
)
changeImgUrl
(
'http://yun.dui88.com/-rr2kxnz9cm-e1lpywd8t.png'
)
getUploadUrl
?.(
'http://yun.dui88.com/-rr2kxnz9cm-e1lpywd8t.png'
)
messageApi
.
error
(
`
${
info
.
file
.
name
}
上传失败,请重新上传。`
)
}
// 接口
// if (status !== 'uploading') {
// if (response) {
// const { data, code, msg } = response
// if (code === 200) {
// getUploadUrl?.(data.url)
// changeLoading(false)
// } else {
// messageApi.error(msg)
// }
// }
// }
}
const
displayStyle
=
useMemo
(()
=>
{
if
(
!
width
||
!
height
)
return
{}
let
zoomSize
=
displayZoomSize
if
(
autoZoomSize
)
{
if
(
width
>
300
)
{
zoomSize
=
0.5
}
if
(
width
>
500
)
{
zoomSize
=
0.3
}
}
return
{
width
:
width
*
zoomSize
,
height
:
height
*
zoomSize
}
},
[
width
,
height
,
autoZoomSize
,
displayZoomSize
])
return
(
<>
{
contextHolder
}
<
Upload
ref=
{
ref
}
multiple=
{
false
}
name=
{
name
}
showUploadList=
{
showUploadList
}
action=
{
action
}
data=
{
data
}
headers=
{
defaultHeaders
}
accept=
{
Array
.
isArray
(
accept
)
?
accept
?.
join
(
','
)
:
accept
}
disabled=
{
loading
||
restProps
.
disabled
}
{
...
restProps
}
beforeUpload=
{
commonBeforeUpload
}
onChange=
{
commonOnChange
}
>
{
render
?
(
imgUrl
&&
!
loading
?
(
<
div
style=
{
{
width
:
192
,
margin
:
16
}
}
>
<
img
src=
{
value
}
alt=
'avatar'
style=
{
displayStyle
}
/>
</
div
>
)
:
(
render
()
)
)
:
(
<
div
style=
{
displayStyle
}
>
{
imgUrl
&&
!
loading
?
<
img
src=
{
imgUrl
}
style=
{
displayStyle
}
/>
:
<
UploadButton
loading=
{
loading
}
/>
}
</
div
>
)
}
</
Upload
>
</>
)
},
{
forwardRef
:
true
,
}
)
export
default
DraggerUpload
src/components/
User/a
.tsx
→
src/components/
common/TableSelect
.tsx
View file @
8874e05e
File moved
src/components/mediaAccount/Index.tsx
0 → 100644
View file @
8874e05e
import
List
from
'@components/mediaAccount/list.tsx'
import
Search
from
'@components/mediaAccount/search.tsx'
import
{
mediaAccountStore
}
from
'./store.ts'
const
MediaAccountIndex
=
observer
(()
=>
{
const
{
searchParams
}
=
mediaAccountStore
// 接口获取数据
const
{
data
=
[
{
mediaId
:
1
,
mediaName
:
'test'
,
mediaType
:
'test'
,
mediaC
:
'test'
,
mediaTime
:
'test'
,
AE
:
'test'
,
AEName
:
'test,test2'
,
PE
:
'test'
,
statue
:
true
,
},
{
mediaId
:
2
,
mediaName
:
'test2'
,
mediaType
:
'test2'
,
mediaC
:
'test2'
,
mediaTime
:
'test2'
,
AE
:
'test2'
,
AEName
:
'test1,test2'
,
PE
:
'test2'
,
statue
:
false
,
},
],
run
,
loading
,
}
=
useRequest
(
getMediaAccountListAPI
,
{
defaultParams
:
[
searchParams
]
})
return
(
<
Spin
spinning=
{
loading
}
>
<
Space
direction=
'vertical'
style=
{
{
display
:
'flex'
}
}
size=
'middle'
>
<
Search
searchRun=
{
run
}
/>
<
List
data=
{
data
}
searchRun=
{
run
}
/>
</
Space
>
</
Spin
>
)
})
export
default
MediaAccountIndex
src/components/mediaAccount/addAccount.tsx
0 → 100644
View file @
8874e05e
import
{
mediaAccountStore
}
from
'./store.ts'
const
AddModal
:
React
.
FC
=
observer
(()
=>
{
const
{
isModalOpen
:
open
,
setModalOpen
,
addMediaAccountFc
,
mediaAccount
,
setMediaAccount
}
=
mediaAccountStore
const
[
form
]
=
Form
.
useForm
()
const
[
imageUrl
,
setImageUrl
]
=
useState
<
string
>
()
const
[
imageUrl2
,
setImageUrl2
]
=
useState
<
string
>
()
const
handleCancel
=
()
=>
{
setModalOpen
(
false
)
}
const
handleOk
=
async
(
e
:
React
.
MouseEvent
<
HTMLElement
,
MouseEvent
>
)
=>
{
e
.
preventDefault
()
form
.
validateFields
()
.
then
((
values
)
=>
{
console
.
log
(
values
)
addMediaAccountFc
({
...
values
})
handleCancel
()
})
.
catch
((
err
)
=>
{
console
.
error
(
'Validation Failed:'
,
err
)
})
}
useEffect
(()
=>
{
if
(
open
)
{
form
.
setFieldsValue
(
mediaAccount
)
}
else
{
// ?
setTimeout
(()
=>
{
form
.
resetFields
()
setMediaAccount
(
undefined
)
},
100
)
}
},
[
mediaAccount
,
open
])
return
(
<
Modal
title=
'创建媒体'
open=
{
open
}
onOk=
{
handleOk
}
onCancel=
{
handleCancel
}
okText=
'提交审核'
>
<
Form
form=
{
form
}
labelCol=
{
{
flex
:
'110px'
}
}
wrapperCol=
{
{
flex
:
1
}
}
labelAlign=
'left'
labelWrap
colon=
{
false
}
style=
{
{
maxWidth
:
600
}
}
>
<
Form
.
Item
label=
'媒体名称'
name=
'mediaName'
rules=
{
[{
required
:
true
}]
}
>
<
Input
/>
</
Form
.
Item
>
<
Form
.
Item
label=
'公司名称'
name=
'cName'
rules=
{
[{
required
:
true
}]
}
>
<
Input
/>
</
Form
.
Item
>
<
Form
.
Item
label=
'对接人姓名'
name=
'pe'
rules=
{
[{
required
:
true
}]
}
>
<
Input
/>
</
Form
.
Item
>
<
Form
.
Item
label=
'对接人电话'
name=
'phone'
rules=
{
[{
required
:
true
}]
}
>
<
Input
/>
</
Form
.
Item
>
<
Form
.
Item
label=
'对接人邮箱'
name=
'email'
rules=
{
[{
required
:
true
}]
}
>
<
Input
/>
</
Form
.
Item
>
<
Form
.
Item
label=
'收款账户信息'
name=
'account'
rules=
{
[{
required
:
true
}]
}
>
<
Input
/>
</
Form
.
Item
>
<
Form
.
Item
label=
'营业执照'
name=
'pic1'
rules=
{
[{
required
:
true
}]
}
>
<
DraggerUpload
value=
{
imageUrl
}
data=
{
{
id
:
1
,
name
:
'yhcj'
}
}
getUploadUrl=
{
(
url
:
string
)
=>
{
form
.
setFieldValue
(
'pic1'
,
url
)
setImageUrl
(
url
)
}
}
/>
</
Form
.
Item
>
<
Form
.
Item
label=
'基本账户信息(开户许可证)'
name=
'pic2'
rules=
{
[{
required
:
true
}]
}
>
<
DraggerUpload
value=
{
imageUrl2
}
data=
{
{
id
:
1
,
name
:
'yhcj'
}
}
getUploadUrl=
{
(
url
:
string
)
=>
{
form
.
setFieldValue
(
'pic2'
,
url
)
setImageUrl2
(
url
)
}
}
/>
</
Form
.
Item
>
</
Form
>
</
Modal
>
)
})
export
default
AddModal
src/
pages/Media
/mediaAccount/const.ts
→
src/
components
/mediaAccount/const.ts
View file @
8874e05e
File moved
src/components/mediaAccount/index.less
0 → 100644
View file @
8874e05e
.search-form {
display: flex;
}
\ No newline at end of file
src/components/mediaAccount/list.tsx
0 → 100644
View file @
8874e05e
import
type
{
TableColumnsType
}
from
'antd'
import
AddModal
from
'./addAccount.tsx'
import
{
mediaAccountStore
}
from
'./store.ts'
interface
ListProp
{
data
:
mediaAccountList
[]
searchRun
:
(
param
:
mediaSearchP
)
=>
void
}
const
List
:
React
.
FC
<
ListProp
>
=
observer
((
prop
:
ListProp
)
=>
{
const
{
data
,
searchRun
}
=
prop
const
{
setModalOpen
,
searchParams
,
getMediaAccountFc
}
=
mediaAccountStore
const
editAddModal
=
(
id
:
number
|
string
)
=>
{
setModalOpen
(
true
)
getMediaAccountFc
(
id
)
}
const
handlePageChange
=
async
(
page
:
number
,
pageSize
:
number
)
=>
{
const
param
=
{
...
searchParams
,
pageSize
:
pageSize
,
currentPage
:
page
,
}
searchRun
(
param
)
console
.
log
(
'handlePageChange'
,
param
)
}
const
changeStatue
=
(
id
:
string
|
number
,
statue
:
boolean
)
=>
{
console
.
log
(
id
,
statue
)
const
l
=
changeStatueByIdAPI
({
mediaId
:
id
,
statue
})
console
.
log
(
l
)
}
const
[
flag
,
changeFlag
]
=
useState
(
false
)
const
changeAE
=
(
id
:
string
|
number
,
name
:
string
)
=>
{
console
.
log
(
id
,
name
)
const
l
=
changeAEByIdAPI
({
mediaId
:
id
,
AE
:
name
})
console
.
log
(
l
)
}
const
changeAEList
=
(
id
:
string
|
number
,
name
:
string
[])
=>
{
console
.
log
(
id
,
name
)
const
l
=
changeAEListByIdAPI
({
mediaId
:
id
,
AEList
:
name
})
console
.
log
(
l
)
}
const
changePE
=
(
id
:
string
|
number
,
name
:
string
)
=>
{
console
.
log
(
id
,
name
)
const
l
=
changePEByIdAPI
({
mediaId
:
id
,
PE
:
name
})
console
.
log
(
l
)
}
const
columns
:
TableColumnsType
<
mediaAccountList
>
=
[
{
title
:
'媒体ID'
,
dataIndex
:
'mediaId'
,
key
:
'mediaId'
,
},
{
title
:
'媒体名称'
,
dataIndex
:
'mediaName'
,
key
:
'mediaName'
,
},
{
title
:
'媒体类型'
,
dataIndex
:
'mediaType'
,
key
:
'mediaType'
,
},
{
title
:
'媒体接入方式'
,
dataIndex
:
'mediaC'
,
key
:
'mediaC'
,
},
{
title
:
'媒体接入时间'
,
dataIndex
:
'mediaTime'
,
key
:
'mediaTime'
,
},
{
title
:
'所属主运营'
,
dataIndex
:
'AE'
,
key
:
'AE'
,
render
:
(
AE
,
record
)
=>
{
return
(
<
Space
size=
'middle'
>
{
flag
?
(
<
Select
defaultValue=
{
AE
}
style=
{
{
width
:
120
}
}
onChange=
{
async
(
value
)
=>
{
await
changeAE
(
record
.
mediaId
,
value
)
changeFlag
(
false
)
}
}
>
<
Select
.
Option
value=
'test'
>
test
</
Select
.
Option
>
<
Select
.
Option
value=
'test2'
>
test2
</
Select
.
Option
>
</
Select
>
)
:
AE
?
(
<
a
onClick=
{
()
=>
changeFlag
(
true
)
}
>
{
AE
}
</
a
>
)
:
(
<
a
onClick=
{
()
=>
changeFlag
(
true
)
}
>
-
</
a
>
)
}
</
Space
>
)
},
},
{
title
:
'其他运营'
,
dataIndex
:
'AEName'
,
key
:
'AEName'
,
render
:
(
AEName
,
record
)
=>
{
return
(
<
Space
size=
'middle'
>
{
flag
?
(
<
Select
mode=
'multiple'
defaultValue=
{
AEName
?.
split
(
','
)
}
style=
{
{
width
:
120
}
}
onChange=
{
async
(
value
)
=>
{
await
changeAEList
(
record
.
mediaId
,
value
)
changeFlag
(
false
)
}
}
>
<
Select
.
Option
value=
'test'
>
test
</
Select
.
Option
>
<
Select
.
Option
value=
'test1'
>
test1
</
Select
.
Option
>
<
Select
.
Option
value=
'test2'
>
test2
</
Select
.
Option
>
</
Select
>
)
:
AEName
?
(
<
a
onClick=
{
()
=>
changeFlag
(
true
)
}
>
{
AEName
}
</
a
>
)
:
(
<
a
onClick=
{
()
=>
changeFlag
(
true
)
}
>
-
</
a
>
)
}
</
Space
>
)
},
},
{
title
:
'所属媒介'
,
dataIndex
:
'PE'
,
key
:
'PE'
,
render
:
(
PE
,
record
)
=>
{
return
(
<
Space
size=
'middle'
>
{
flag
?
(
<
Select
defaultValue=
{
PE
}
style=
{
{
width
:
120
}
}
onChange=
{
async
(
value
)
=>
{
await
changePE
(
record
.
mediaId
,
value
)
changeFlag
(
false
)
}
}
>
<
Select
.
Option
value=
'test'
>
test
</
Select
.
Option
>
<
Select
.
Option
value=
'test2'
>
test2
</
Select
.
Option
>
</
Select
>
)
:
PE
?
(
<
a
onClick=
{
()
=>
changeFlag
(
true
)
}
>
{
PE
}
</
a
>
)
:
(
<
a
onClick=
{
()
=>
changeFlag
(
true
)
}
>
-
</
a
>
)
}
</
Space
>
)
},
},
{
title
:
'审核状态'
,
dataIndex
:
'statue'
,
key
:
'statue'
,
render
:
(
statue
,
record
)
=>
(
<
Space
size=
'middle'
>
<
Switch
checked=
{
statue
}
onChange=
{
(
checked
:
boolean
)
=>
changeStatue
(
record
.
mediaId
,
checked
)
}
/>
</
Space
>
),
},
{
title
:
'操作'
,
key
:
'action'
,
render
:
(
_
,
record
)
=>
(
<
Space
size=
'middle'
>
<
a
onClick=
{
()
=>
editAddModal
(
record
.
mediaId
)
}
>
设置
</
a
>
</
Space
>
),
},
]
return
(
<>
<
Table
<
mediaAccountList
>
dataSource=
{
data
}
columns=
{
columns
}
pagination=
{
{
pageSizeOptions
:
[
10
,
20
,
50
],
showQuickJumper
:
true
,
total
:
500
,
onChange
:
handlePageChange
}
}
/
>
<
AddModal
/>
</>
)
})
export default List
src/components/mediaAccount/search.tsx
0 → 100644
View file @
8874e05e
const
{
Item
:
FormItem
}
=
Form
import
{
mediaAccountStore
}
from
'./store'
interface
SearchProp
{
searchRun
:
(
param
:
mediaSearchP
)
=>
void
}
const
Search
:
React
.
FC
<
SearchProp
>
=
observer
((
prop
:
SearchProp
)
=>
{
const
[
form
]
=
Form
.
useForm
()
const
{
searchRun
}
=
prop
const
{
setModalOpen
,
searchParams
,
setSearchParams
}
=
mediaAccountStore
function
handleSearch
(
e
:
React
.
MouseEvent
<
HTMLElement
,
MouseEvent
>
)
{
e
.
preventDefault
()
form
.
validateFields
()
.
then
((
values
)
=>
{
setSearchParams
({
...
values
})
searchRun
({
...
searchParams
,
...
values
})
})
.
catch
((
err
)
=>
{
console
.
error
(
'Validation Failed:'
,
err
)
})
}
const
handleAdd
=
()
=>
{
setModalOpen
(
true
)
}
return
(
<
Form
className=
'fill'
layout=
'inline'
form=
{
form
}
>
<
Flex
className=
'fill'
gap=
'small'
justify=
'flex-start'
wrap
>
<
FormItem
label=
'媒体ID'
name=
'mediaId'
rules=
{
[
Rules
.
ids
]
}
>
<
Input
style=
{
{
width
:
200
}
}
placeholder=
'请输入媒体ID间隔用,隔开'
/>
</
FormItem
>
<
FormItem
label=
'媒体名称'
name=
'mediaName'
rules=
{
[
Rules
.
name
]
}
>
<
Input
style=
{
{
width
:
200
}
}
placeholder=
'请输入媒体名称'
/>
</
FormItem
>
<
FormItem
label=
'运营'
name=
'AE'
rules=
{
[
Rules
.
name
]
}
>
<
Input
style=
{
{
width
:
200
}
}
placeholder=
'请输入运营'
/>
</
FormItem
>
<
FormItem
label=
'媒介'
name=
'PE'
rules=
{
[
Rules
.
name
]
}
>
<
Input
style=
{
{
width
:
200
}
}
placeholder=
'请输入媒介'
/>
</
FormItem
>
</
Flex
>
<
Flex
className=
'fill'
justify=
'flex-end'
>
<
FormItem
layout=
'vertical'
style=
{
{
paddingTop
:
'10px'
,
display
:
'flex'
,
justifyContent
:
'flex-end'
}
}
>
<
Button
type=
'primary'
onClick=
{
handleAdd
}
>
创建媒体
</
Button
>
</
FormItem
>
<
FormItem
layout=
'vertical'
style=
{
{
paddingTop
:
'10px'
,
display
:
'flex'
,
justifyContent
:
'flex-end'
}
}
>
<
Button
type=
'primary'
htmlType=
'submit'
onClick=
{
(
e
:
React
.
MouseEvent
<
HTMLElement
,
MouseEvent
>
)
=>
handleSearch
(
e
)
}
>
搜索
</
Button
>
</
FormItem
>
</
Flex
>
</
Form
>
)
})
export
default
Search
src/components/mediaAccount/store.ts
0 → 100644
View file @
8874e05e
class
MediaAccountStore
{
isModalOpen
=
false
searchParams
:
mediaSearchP
=
{
mediaId
:
''
,
mediaName
:
''
,
AE
:
''
,
PE
:
''
,
pageSize
:
15
,
currentPage
:
1
,
}
mediaAccount
:
mediaAccount
|
undefined
=
{
mediaName
:
''
,
cName
:
''
,
pe
:
''
,
phone
:
''
,
email
:
''
,
account
:
''
,
pic1
:
''
,
pic2
:
''
,
}
constructor
()
{
makeAutoObservable
(
this
)
// 自动推断类型
}
getModalOpen
=
()
=>
{
return
this
.
isModalOpen
}
setModalOpen
=
(
value
:
boolean
)
=>
{
this
.
isModalOpen
=
value
}
setSearchParams
=
(
value
:
mediaSearchP
)
=>
{
this
.
searchParams
=
{
...
this
.
searchParams
,
...
value
}
}
setMediaAccount
=
(
value
:
mediaAccount
|
undefined
)
=>
{
this
.
mediaAccount
=
value
?
{
...
value
}
:
undefined
}
addMediaAccountFc
=
(
params
:
mediaAccount
)
=>
{
console
.
log
(
'params'
,
params
)
const
res
=
addMediaAccountAPI
(
params
)
console
.
log
(
res
)
}
getMediaAccountFc
=
(
id
:
number
|
string
)
=>
{
const
res
=
getMediaAccountAPI
(
id
)
console
.
log
(
res
)
this
.
setMediaAccount
({
mediaName
:
'text'
,
cName
:
'text'
,
pe
:
'text'
,
phone
:
'text'
,
email
:
'text'
,
account
:
'text'
,
pic1
:
'http://yun.dui88.com/-rr2kxnz9cm-e1lpywd8t.png'
,
pic2
:
'http://yun.dui88.com/-rr2kxnz9cm-e1lpywd8t.png'
,
})
}
}
export
const
mediaAccountStore
=
new
MediaAccountStore
()
src/
pages/Media/mediaAccount/store.ts
→
src/
components/mediaAccount/useColumns.tsx
View file @
8874e05e
File moved
src/index.css
View file @
8874e05e
...
...
@@ -2,4 +2,12 @@
@layer
theme
,
base
,
components
,
antd
,
untilities
;
@import
'tailwindcss'
;
@import
'antd/dist/reset.css'
;
\ No newline at end of file
@import
'antd/dist/reset.css'
;
.fill
{
width
:
100%
;
padding
:
0
;
margin
:
0
;
}
src/pages/Media/mediaAccount/addAccount.tsx
deleted
100644 → 0
View file @
eeb7db42
interface
AddAccountProps
{
open
:
boolean
handleClose
:
()
=>
void
}
const
AddModal
:
React
.
FC
<
AddAccountProps
>
=
observer
((
prop
:
AddAccountProps
)
=>
{
const
{
handleClose
,
open
}
=
prop
const
handleOk
=
()
=>
{
handleClose
()
}
const
handleCancel
=
()
=>
{
handleClose
()
}
return
(
<
Modal
title=
'Basic Modal'
open=
{
open
}
onOk=
{
handleOk
}
onCancel=
{
handleCancel
}
>
<
p
>
Some contents...
</
p
>
<
p
>
Some contents...
</
p
>
<
p
>
Some contents...
</
p
>
</
Modal
>
)
})
export
default
AddModal
src/pages/Media/mediaAccount/index.tsx
View file @
8874e05e
import
List
from
'./list.tsx'
import
Search
from
'./search.tsx'
import
MediaAccountIndex
from
'@components/mediaAccount/index.tsx'
const
StatementTypeIn
=
observer
(()
=>
{
return
(
<
Space
direction=
'vertical'
style=
{
{
display
:
'flex'
}
}
size=
'middle'
>
<
Search
/>
<
List
/>
</
Space
>
)
const
Index
=
observer
(()
=>
{
return
<
MediaAccountIndex
/>
})
export
default
StatementTypeIn
export
default
Index
src/pages/Media/mediaAccount/list.tsx
deleted
100644 → 0
View file @
eeb7db42
import
type
{
TableProps
}
from
'antd'
import
AddModal
from
'./addAccount.tsx'
interface
DataType
{
key
:
string
name
:
string
age
:
number
address
:
string
}
const
List
:
React
.
FC
=
observer
(()
=>
{
const
[
isModalOpen
,
setIsModalOpen
]
=
useState
(
false
)
const
handleShowAddModal
=
()
=>
{
setIsModalOpen
(
true
)
}
const
columns
:
TableProps
<
DataType
>
[
'columns'
]
=
[
{
title
:
'姓名'
,
dataIndex
:
'name'
,
key
:
'name'
,
},
{
title
:
'年龄'
,
dataIndex
:
'age'
,
key
:
'age'
,
},
{
title
:
'住址'
,
dataIndex
:
'address'
,
key
:
'address'
,
},
{
title
:
'Action'
,
key
:
'action'
,
render
:
()
=>
(
<
Space
size=
'middle'
>
<
a
onClick=
{
handleShowAddModal
}
>
查看
</
a
>
</
Space
>
),
},
]
const
dataSource
:
DataType
[]
=
[
{
key
:
'1'
,
name
:
'胡彦斌'
,
age
:
32
,
address
:
'西湖区湖底公园1号'
,
},
{
key
:
'2'
,
name
:
'胡彦祖'
,
age
:
42
,
address
:
'西湖区湖底公园1号'
,
},
]
return
(
<>
<
Table
dataSource=
{
dataSource
}
columns=
{
columns
}
/>
<
AddModal
open=
{
isModalOpen
}
handleClose=
{
()
=>
setIsModalOpen
(
false
)
}
/>
</>
)
})
export
default
List
src/pages/Media/mediaAccount/search.tsx
deleted
100644 → 0
View file @
eeb7db42
const
{
Item
:
FormItem
}
=
Form
const
Search
:
React
.
FC
=
observer
(()
=>
{
const
[
form
]
=
Form
.
useForm
()
function
handleSearch
(
e
:
React
.
MouseEvent
<
HTMLElement
,
MouseEvent
>
)
{
e
.
preventDefault
()
form
.
validateFields
()
.
then
((
values
)
=>
{
values
.
dealIdList
=
values
.
dealIdList
?.
split
(
','
)
console
.
log
(
'Received values of form: '
,
values
)
})
.
catch
((
err
)
=>
{
console
.
error
(
'Validation Failed:'
,
err
)
})
}
return
(
<
Form
layout=
'inline'
form=
{
form
}
>
<
FormItem
name=
'dealIdList'
rules=
{
[
Rules
.
ids
]
}
>
<
Input
style=
{
{
width
:
200
}
}
placeholder=
'请输入排期单ID间隔用,隔开'
/>
</
FormItem
>
<
FormItem
name=
'dealName'
rules=
{
[
Rules
.
name
]
}
>
<
Input
style=
{
{
width
:
200
}
}
placeholder=
'请输入排期单名称'
/>
</
FormItem
>
<
FormItem
>
<
Button
type=
'primary'
htmlType=
'submit'
onClick=
{
(
e
:
React
.
MouseEvent
<
HTMLElement
,
MouseEvent
>
)
=>
handleSearch
(
e
)
}
>
搜索
</
Button
>
</
FormItem
>
</
Form
>
)
})
export
default
Search
src/utils/REG.ts
View file @
8874e05e
...
...
@@ -70,6 +70,10 @@ const Rules = {
pattern
:
REGEX
.
POSITIVE_INTEGER
,
message
:
'请输入正整数'
,
},
nonSpecialChar
:
{
pattern
:
REGEX
.
NON_SPECIAL_CHARACTERS
,
message
:
'请输入非特殊字符'
,
},
intLt1e100
:
{
pattern
:
/^
([
1-9
][
0-9
]{0,1}
|100
)
$/
,
message
:
'请输入1-100整数'
,
...
...
@@ -91,6 +95,7 @@ const Rules = {
pattern
:
/^
(\d
|
[
1-9
]\d
|100
)(\.\d{1,2})?
$/
,
message
:
'请输入正确的百分比'
,
},
}
export
{
isEmail
,
buildREG
,
Rules
}
src/utils/index.ts
View file @
8874e05e
export
function
isNothing
(
value
:
number
|
void
|
string
|
null
)
{
export
function
isNothing
(
value
:
number
|
void
|
string
|
null
|
Array
<
string
|
number
>
)
{
return
(
value
===
''
||
value
===
undefined
||
...
...
src/utils/string.ts
0 → 100644
View file @
8874e05e
export
function
splitStrBy
(
str
:
string
|
string
[],
separator
=
','
)
{
if
(
isNothing
(
str
))
return
[]
if
(
Array
.
isArray
(
str
))
return
str
return
str
.
split
(
separator
).
filter
(
Boolean
)
}
src/utils/upload.ts
0 → 100644
View file @
8874e05e
interface
Video
{
error
?:
boolean
duration
?:
number
width
?:
number
height
?:
number
type
?:
string
size
?:
number
}
interface
Image
{
width
:
number
height
:
number
size
:
number
}
export
const
getVideoInfo
:
(
file
:
File
)
=>
Promise
<
Video
>
=
(
file
)
=>
{
const
videoDOM
=
document
.
createElement
(
'video'
)
as
HTMLVideoElement
videoDOM
.
src
=
URL
.
createObjectURL
(
file
)
const
evt
=
'loadedmetadata'
return
new
Promise
((
resolve
)
=>
{
videoDOM
.
onerror
=
()
=>
{
resolve
({
error
:
true
})
}
videoDOM
.
addEventListener
(
evt
,
function
()
{
const
{
videoWidth
:
width
,
videoHeight
:
height
}
=
this
resolve
({
duration
:
videoDOM
.
duration
||
0
,
type
:
'MP4'
,
size
:
file
.
size
,
width
,
height
,
})
})
})
}
export
const
getImgInfo
:
(
file
:
File
)
=>
Promise
<
Image
>
=
(
file
)
=>
{
return
new
Promise
((
res
)
=>
{
if
(
typeof
FileReader
===
'function'
)
{
const
{
size
}
=
file
// 读取图片数据
const
reader
=
new
FileReader
()
reader
.
onload
=
function
(
e
:
ProgressEvent
<
FileReader
>
)
{
const
data
=
e
.
target
?.
result
// 加载图片获取图片真实宽度和高度
const
image
=
new
Image
()
image
.
onload
=
function
()
{
const
width
=
image
.
width
const
height
=
image
.
height
res
({
width
,
height
,
size
})
}
image
.
src
=
data
as
string
}
reader
.
readAsDataURL
(
file
)
}
else
{
console
.
log
(
'你的浏览器不支持图片大小判断,请更换现代浏览器,例如Chrome'
)
}
})
}
const
videoSnapshotSuffix
=
'?x-oss-process=video/snapshot,t_1000,m_fast,w_200'
export
const
getFileUrl
=
(
fileUrl
:
string
)
=>
{
if
(
fileUrl
?.
match
(
/.mp4$/
)
&&
!
fileUrl
?.
includes
(
videoSnapshotSuffix
))
{
return
fileUrl
+
videoSnapshotSuffix
}
return
fileUrl
}
export
const
getSuffix
=
(
url
:
string
)
=>
{
return
url
?.
replace
(
/.+
\.
/
,
''
)
}
export
const
checkIsVideo
=
(
file
:
File
):
boolean
=>
{
return
/.mp4/
.
test
(
file
.
name
)
}
export
const
checkIsImage
=
(
file
:
File
):
boolean
=>
{
return
/.jpg|.jpeg|.png|.gif/
.
test
(
file
.
name
)
}
tsconfig.app.json
View file @
8874e05e
...
...
@@ -20,7 +20,14 @@
"noUnusedLocals"
:
true
,
"noUnusedParameters"
:
true
,
"noFallthroughCasesInSwitch"
:
true
,
"noUncheckedSideEffectImports"
:
true
"noUncheckedSideEffectImports"
:
true
,
"paths"
:
{
"@/*"
:
[
"./src/*"
],
"@assets/*"
:
[
"./src/assets/*"
],
"@components/*"
:
[
"./src/components/*"
],
"@hooks/*"
:
[
"./src/hooks/*"
],
"@styles/*"
:
[
"./src/styles/*"
],
}
},
"include"
:
[
"src"
,
...
...
vite.config.ts
View file @
8874e05e
...
...
@@ -62,6 +62,9 @@ export default defineConfig(({ mode }) => ({
'Radio'
,
'Switch'
,
'Upload'
,
'Flex'
,
'Row'
,
'Col'
,
],
axios
:
[[
'default'
,
'axios'
]],
'pixiu-number-toolkit'
:
[
'REGEX'
],
...
...
@@ -97,4 +100,14 @@ export default defineConfig(({ mode }) => ({
target
:
`/
${
PUBLIC_FOLDER
}
/assets/`
,
}),
],
resolve
:
{
alias
:
{
'@'
:
'/src'
,
'@components'
:
'/src/components'
,
'@hooks'
:
'/src/hooks'
,
'@stores'
:
'/src/stores'
,
'@apis'
:
'/src/apis'
,
'@constants'
:
'/src/constants'
,
},
},
}))
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment