Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
J
jinfa-platform
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
shenshaokai
jinfa-platform
Commits
a776c57b
Commit
a776c57b
authored
Sep 24, 2021
by
前端-李俊鑫
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
内容管理-初步
parent
b1a84a91
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
44 changed files
with
4871 additions
and
1 deletion
+4871
-1
package.json
package.json
+2
-1
advertisementInfo.tsx
src/pages/content/advertisement/advertisementInfo.tsx
+137
-0
index.tsx
src/pages/content/advertisement/index.tsx
+217
-0
advertisementInfoSchema.tsx
.../content/advertisement/schema/advertisementInfoSchema.tsx
+104
-0
index.tsx
src/pages/content/advertisement/schema/index.tsx
+203
-0
announceInfo.tsx
src/pages/content/announcements/announceInfo.tsx
+112
-0
index.tsx
src/pages/content/announcements/index.tsx
+224
-0
announceInfoSchema.tsx
...pages/content/announcements/schema/announceInfoSchema.tsx
+138
-0
index.tsx
src/pages/content/announcements/schema/index.tsx
+219
-0
index.less
src/pages/content/category/index.less
+19
-0
index.tsx
src/pages/content/category/index.tsx
+230
-0
schema.tsx
src/pages/content/category/schema.tsx
+98
-0
columnInfo.tsx
src/pages/content/columnManagement/columnInfo.tsx
+174
-0
index.tsx
src/pages/content/columnManagement/index.tsx
+150
-0
index.tsx
src/pages/content/columnManagement/schema/index.tsx
+119
-0
index.tsx
src/pages/content/components/CustomCheckbox/index.tsx
+19
-0
index.tsx
src/pages/content/components/CustomEditor/index.tsx
+26
-0
index.tsx
src/pages/content/components/CustomSearch/index.tsx
+30
-0
styles.less
src/pages/content/components/CustomSearch/styles.less
+13
-0
FilterTable.tsx
src/pages/content/components/FilterTable/FilterTable.tsx
+74
-0
FlexLayout.tsx
src/pages/content/components/FilterTable/FlexLayout.tsx
+61
-0
index.tsx
src/pages/content/components/FilterTable/index.tsx
+9
-0
index.tsx
src/pages/content/components/TablePagination/index.tsx
+27
-0
Tags.less
src/pages/content/components/Tags/Tags.less
+58
-0
Tags.tsx
src/pages/content/components/Tags/Tags.tsx
+89
-0
index.tsx
src/pages/content/components/Tags/index.tsx
+6
-0
index.tsx
src/pages/content/components/WrapCustomUpload/index.tsx
+32
-0
constant.ts
src/pages/content/constant.ts
+0
-0
useAsyncDataSource.tsx
src/pages/content/hooks/useAsyncDataSource.tsx
+31
-0
useInitialValues.tsx
src/pages/content/hooks/useInitialValues.tsx
+18
-0
useValidator.tsx
src/pages/content/hooks/useValidator.tsx
+34
-0
imageInfo.tsx
src/pages/content/imagesManagement/imageInfo.tsx
+116
-0
index.tsx
src/pages/content/imagesManagement/index.tsx
+149
-0
imageInfoSchema.tsx
...pages/content/imagesManagement/schema/imageInfoSchema.tsx
+97
-0
index.tsx
src/pages/content/imagesManagement/schema/index.tsx
+150
-0
index.tsx
src/pages/content/infomation/index.tsx
+308
-0
infomationInfo.tsx
src/pages/content/infomation/infomationInfo.tsx
+239
-0
index.tsx
src/pages/content/infomation/schema/index.tsx
+271
-0
infomationInfoSchema.tsx
src/pages/content/infomation/schema/infomationInfoSchema.tsx
+302
-0
statusList.ts
src/pages/content/statusList.ts
+63
-0
index.tsx
src/pages/content/tagsManagement/index.tsx
+143
-0
index.tsx
src/pages/content/tagsManagement/schema/index.tsx
+106
-0
tagsInfo.tsx
src/pages/content/tagsManagement/tagsInfo.tsx
+127
-0
utils.tsx
src/pages/content/utils/utils.tsx
+127
-0
No files found.
package.json
View file @
a776c57b
...
...
@@ -132,4 +132,4 @@
"
ssh2
"
:
"^0.8.9"
,
"
util
"
:
"^0.12.3"
}
}
}
\ No newline at end of file
src/pages/content/advertisement/advertisementInfo.tsx
0 → 100644
View file @
a776c57b
import
React
,
{
useState
}
from
'react'
;
import
{
PageHeaderWrapper
}
from
"@ant-design/pro-layout"
;
import
ReutrnEle
from
'@/components/ReturnEle'
;
import
{
usePageStatus
}
from
'@/hooks/usePageStatus'
;
import
{
history
,
Prompt
}
from
'umi'
;
import
{
Card
}
from
'antd'
;
import
{
SchemaForm
,
createFormActions
,
FormButtonGroup
,
Submit
,
FormEffectHooks
}
from
'@formily/antd'
import
advertisementInfoSchema
from
'./schema/advertisementInfoSchema'
;
import
{
Input
,
Select
,
Button
}
from
'antd'
;
// import CustomUpload from '@/components/NiceForm/components/CustomUpload';
import
{
PublicApi
}
from
'@/services/api'
;
import
{
useInitialValues
}
from
'../hooks/useInitialValues'
;
import
CustomUpload
from
'../components/WrapCustomUpload'
;
import
useCustomValidator
from
'../hooks/useValidator'
import
{
sortedList
,
ADVERTISE_WEB_COLUMN_TYPE
,
ADVERTISE_APP_COLUMN_TYPE
}
from
'../utils/utils'
;
enum
ChannelEnum
{
WEB
=
1
,
APP
=
2
,
}
const
WEB_COLUMN_TYPE
=
Object
.
keys
(
ADVERTISE_WEB_COLUMN_TYPE
).
map
((
item
)
=>
{
return
{
label
:
ADVERTISE_WEB_COLUMN_TYPE
[
item
],
value
:
parseInt
(
item
)
}
})
const
APP_COLUMN_TYPE
=
Object
.
keys
(
ADVERTISE_APP_COLUMN_TYPE
).
map
((
item
)
=>
{
return
{
label
:
ADVERTISE_APP_COLUMN_TYPE
[
item
],
value
:
parseInt
(
item
)
}
})
const
actions
=
createFormActions
();
const
{
onFieldValueChange$
}
=
FormEffectHooks
;
const
AdvertisementInfo
=
()
=>
{
useCustomValidator
()
const
{
id
,
preview
}
=
usePageStatus
();
const
initialValues
=
useInitialValues
({
id
:
id
},
PublicApi
.
getManageContentAdvertGet
);
const
[
submitLoading
,
setSubmitLoading
]
=
useState
(
false
);
const
[
unsaved
,
setUnsaved
]
=
useState
(
true
);
const
isEdit
=
id
&&
!
preview
;
const
isAdd
=
!
id
&&
!
preview
;
const
isView
=
id
&&
preview
;
const
handleSubmit
=
(
value
)
=>
{
console
.
log
(
value
)
// const { title, columnType, sort, link, imageUrl} = value;
const
serviceActions
=
isAdd
?
PublicApi
.
postManageContentAdvertAdd
:
PublicApi
.
postManageContentAdvertUpdate
let
tempData
=
value
;
const
postData
=
isAdd
?
tempData
:
{...
tempData
,
id
};
setSubmitLoading
(
true
);
setUnsaved
(
false
);
serviceActions
(
postData
).
then
((
data
)
=>
{
setSubmitLoading
(
false
);
if
(
data
.
code
===
1000
)
{
history
.
push
(
'/content/advertisement'
)
}
})
}
const
formEffects
=
()
=>
()
=>
{
onFieldValueChange$
(
'channel'
).
subscribe
(
fieldState
=>
{
const
isActive
=
fieldState
.
active
;
let
options
:
{
label
:
string
,
value
:
number
|
string
}[]
=
[]
if
(
fieldState
.
value
===
ChannelEnum
.
WEB
)
{
options
=
WEB_COLUMN_TYPE
}
else
{
options
=
APP_COLUMN_TYPE
}
actions
.
setFieldState
(
'columnType'
,
(
state
)
=>
{
state
.
props
[
"x-component-props"
][
"options"
]
=
options
;
if
(
isActive
)
{
state
.
value
=
""
;
}
})
})
}
const
handleCancel
=
()
=>
{
history
.
push
(
'/content/advertisement'
)
}
return
(
<
PageHeaderWrapper
onBack=
{
()
=>
history
.
goBack
()
}
backIcon=
{
<
ReutrnEle
description=
"返回"
/>
}
title=
{
isAdd
?
'新建广告'
:
isEdit
?
'编辑广告'
:
'查看广告'
}
>
<
Card
>
<
SchemaForm
schema=
{
advertisementInfoSchema
}
actions=
{
actions
}
components=
{
{
Input
,
Select
,
Submit
,
CustomUpload
}
}
initialValues=
{
initialValues
?.
data
}
onSubmit=
{
handleSubmit
}
editable=
{
isAdd
||
isEdit
}
effects=
{
formEffects
()
}
expressionScope=
{
{
label
:
(
<
div
>
{
isAdd
||
isEdit
?
<
span
style=
{
{
color
:
'#ff4d4f'
}
}
>
*
</
span
>
:
null
}
广告图片
</
div
>
)
}
}
>
{
isAdd
||
isEdit
?
(
<
FormButtonGroup
offset=
{
3
}
>
<
Submit
loading=
{
submitLoading
}
>
提交
</
Submit
>
<
Button
onClick=
{
handleCancel
}
>
取消
</
Button
>
</
FormButtonGroup
>
)
:
<></>
}
</
SchemaForm
>
<
Prompt
when=
{
unsaved
&&
(
isAdd
||
isEdit
)
}
message=
"内容未保存,确定离开?"
></
Prompt
>
</
Card
>
</
PageHeaderWrapper
>
)
}
export
default
AdvertisementInfo
src/pages/content/advertisement/index.tsx
0 → 100644
View file @
a776c57b
import
React
,
{
useEffect
,
useState
}
from
'react'
;
import
{
FilterTable
}
from
'../components/FilterTable'
;
import
{
Card
,
Input
,
Button
,
Table
,
Dropdown
,
Menu
,
Select
,
Space
,
Popconfirm
,
Modal
}
from
'antd'
;
import
{
createVirtualBox
,
createFormActions
,
FormEffectHooks
,
createEffectHook
}
from
'@formily/antd'
;
import
{
history
,
Link
}
from
'umi'
;
import
{
DownOutlined
,
UpOutlined
}
from
'@ant-design/icons'
;
import
{
timeRange
}
from
'@/utils/index'
;
import
{
PublicApi
}
from
'@/services/api'
;
import
TablePagination
from
'../components/TablePagination'
;
import
{
tagColorStyle
,
getTableDataSource
,
setFormStatus
}
from
'../utils/utils'
;
import
{
merge
}
from
'rxjs'
;
import
CustomSearch
from
'../components/CustomSearch'
;
const
{
onFormInit$
,
onFieldValueChange$
}
=
FormEffectHooks
const
{
Search
}
=
Input
;
const
SchemaButton
=
createVirtualBox
(
'button'
,
Button
);
const
SchemaTable
=
createVirtualBox
(
'SchemaTable'
,
Table
);
const
SchemaDropDown
=
createVirtualBox
(
'SchemaDropDown'
,
Dropdown
.
Button
);
const
actions
=
createFormActions
();
import
advertisementSchema
from
'./schema'
;
const
getData
=
async
(
params
:
any
)
=>
{
const
res
=
await
PublicApi
.
getManageContentAdvertPage
(
params
);
return
res
.
data
}
const
Advertisement
=
()
=>
{
useEffect
(()
=>
{
const
params
=
{
current
:
1
,
pageSize
:
10
}
getTableDataSource
(
actions
,
params
,
getData
);
},
[])
const
advertisementEffects
=
()
=>
()
=>
{
onFormInit$
().
subscribe
(()
=>
{
actions
.
setFieldState
(
'FILTERS'
,
state
=>
{
state
.
visible
=
false
;
})
})
merge
(
onFieldValueChange$
(
'status'
),
onFieldValueChange$
(
'time'
),
).
subscribe
(
fieldState
=>
{
if
(
fieldState
.
value
!=
null
)
{
handleSearch
({})
}
}
)
onFieldValueChange$
(
'pagination'
).
subscribe
((
state
)
=>
{
handleSearch
({...
state
.
value
})
})
}
const
handleSearch
=
async
(
params
)
=>
{
const
title
=
actions
.
getFieldValue
(
'search'
);
const
status
=
actions
.
getFieldValue
(
'status'
);
// 状态
const
time
=
actions
.
getFieldValue
(
'time'
);
const
{
st
,
et
}
=
timeRange
(
time
);
const
postData
=
{
title
:
title
||
''
,
status
:
status
!=
0
?
status
:
''
,
startTime
:
st
||
null
,
endTime
:
et
||
null
,
current
:
1
,
pageSize
:
10
,
...
params
,
}
getTableDataSource
(
actions
,
postData
,
getData
);
}
const
handleDelete
=
(
id
)
=>
{
Modal
.
confirm
({
title
:
'确定要执行这个操作吗'
,
onOk
:
()
=>
{
PublicApi
.
postManageContentAdvertDelete
({
id
:
id
})
.
then
((
data
)
=>
{
const
paginationValue
=
actions
.
getFieldValue
(
'pagination'
);
handleSearch
({...
paginationValue
})
})
},
})
}
// 修改状态
const
handleUpdateStatus
=
(
id
,
status
)
=>
{
// 该方法是上下架 所以 enableStatus 无用,随意传
PublicApi
.
postManageContentAdvertUpdateStatus
({
id
:
id
,
shelfStatus
:
status
,
enableStatus
:
0
})
.
then
((
data
)
=>
{
const
paginationValue
=
actions
.
getFieldValue
(
'pagination'
);
handleSearch
({...
paginationValue
})
});
}
// 重设页码
const
resetPagination
=
(
params
)
=>
{
const
paginationValue
=
actions
.
getFieldValue
(
'pagination'
);
actions
.
setFieldValue
(
'pagination'
,
{
...
paginationValue
,
...
params
})
}
return
(
<
Card
>
<
FilterTable
schema=
{
advertisementSchema
}
components=
{
{
CustomSearch
,
// SchemaFlexRowLayout,
// SchemaFlexColumnLayout,
SchemaDropDown
,
Select
,
Table
,
TablePagination
}
}
actions=
{
actions
}
expressionScope=
{
{
goToCreate
:
()
=>
{
history
.
push
(
`/content/advertisement/add`
)
},
reset
:
()
=>
{
actions
.
setFieldValue
(
'search'
);
actions
.
setFieldValue
(
'status'
);
// 状态
actions
.
setFieldValue
(
'time'
);
resetPagination
({
current
:
1
})
handleSearch
({});
},
search
:
(
value
)
=>
{
resetPagination
({
current
:
1
})
handleSearch
({
title
:
value
,
current
:
1
});
},
renderStatus
:
(
text
,
record
)
=>
{
const
STATUSMAP
=
{
"1"
:
"待上架"
,
"2"
:
"已上架"
,
"3"
:
"已下架"
}
return
(
<
span
style=
{
{...
tagColorStyle
[
record
.
status
],
padding
:
'3px 5px'
}
}
>
{
STATUSMAP
[
record
.
status
]
}
</
span
>
)
},
toggleFilters
:
()
=>
{
actions
.
setFieldState
(
'FILTERS'
,
state
=>
{
const
visible
=
!
state
.
visible
;
state
.
visible
=
visible
;
actions
.
setFieldState
(
'HIGHT_FILTER_BTN'
,
(
state
)
=>
{
//@ts-ignore
state
.
props
[
'x-component-props'
].
children
=
(
<
div
>
高级搜索
{
visible
?
<
UpOutlined
/>
:
<
DownOutlined
/>
}
</
div
>
)
})
});
},
renderOperation
:
(
val
,
record
)
=>
{
const
status
=
[
""
,
"上架"
,
"下架"
,
"上架"
];
const
canModify
=
[
1
,
3
]
const
menu
=
(
<
Menu
>
<
Menu
.
Item
>
<
Link
to=
{
`/content/advertisement/detail?id=${record.id}`
}
>
编辑
</
Link
>
</
Menu
.
Item
>
<
Menu
.
Item
onClick=
{
()
=>
handleDelete
(
record
.
id
)
}
>
<
a
>
删除
</
a
>
</
Menu
.
Item
>
</
Menu
>
)
return
(
<
Space
>
{
/* 这里反向操作, 上架的对应的是下架, 待上架,下架对应的是上架 */
}
<
Popconfirm
title=
"确定要执行这个操作吗"
onConfirm=
{
()
=>
handleUpdateStatus
(
record
.
id
,
status
[
record
.
status
]
==
'上架'
?
2
:
3
)
}
okText=
"是"
cancelText=
"否"
>
<
a
href=
"#"
>
{
status
[
record
.
status
]
}
</
a
>
</
Popconfirm
>
{
/* // 只有待上架, 已下架架才有 修改和删除 */
}
{
canModify
.
includes
(
record
.
status
)
?
(
<
Dropdown
overlay=
{
menu
}
>
<
a
>
更多
<
DownOutlined
/>
</
a
>
</
Dropdown
>
)
:
null
}
</
Space
>
)
},
}
}
effects=
{
advertisementEffects
()
}
>
</
FilterTable
>
</
Card
>
)
}
export
default
Advertisement
;
src/pages/content/advertisement/schema/advertisementInfoSchema.tsx
0 → 100644
View file @
a776c57b
import
{
sortedList
,
}
from
'../../utils/utils'
;
const
sortListOptions
=
sortedList
(
1
,
6
);
const
schema
=
{
type
:
'object'
,
properties
:
{
layout
:
{
type
:
'object'
,
'x-component'
:
'mega-layout'
,
'x-component-props'
:
{
labelCol
:
3
,
wrapperCol
:
10
,
labelAlign
:
'left'
},
properties
:
{
title
:
{
type
:
'string'
,
title
:
'标题'
,
'x-component'
:
'Input'
,
'x-component-props'
:
{
placeholder
:
'最长60个字符,30个汉字'
},
"x-rules"
:
[
{
"required"
:
true
,
"message"
:
"最长60个字符,30个汉字"
},
{
limitByte
:
true
,
// 自定义校验规则
maxByte
:
60
,
}
]
},
channel
:
{
title
:
'投放渠道'
,
type
:
'string'
,
"x-component"
:
'Select'
,
'x-component-props'
:
{
options
:
[
{
label
:
'Web'
,
value
:
1
},
{
label
:
'App'
,
value
:
2
},
],
},
"x-rules"
:
[{
"required"
:
true
,
"message"
:
"请选择投放渠道"
}],
},
columnType
:
{
title
:
'栏目'
,
type
:
'string'
,
'x-component'
:
'Select'
,
'x-component-props'
:
{
options
:
[]
},
"x-rules"
:
[{
"required"
:
true
,
"message"
:
"请选择栏目"
}],
},
sort
:
{
title
:
'广告排序'
,
type
:
'string'
,
'x-component'
:
'Select'
,
'x-component-props'
:
{
options
:
sortListOptions
},
"x-rules"
:
[{
"required"
:
true
,
"message"
:
"请选择广告排序"
}],
},
link
:
{
title
:
'跳转链接'
,
type
:
'string'
,
'x-component'
:
'Input'
,
"x-rules"
:
[
{
limitByte
:
true
,
// 自定义校验规则
maxByte
:
100
,
}
]
},
imageUrl
:
{
type
:
"object"
,
title
:
"{{label}}"
,
name
:
"imageUrl"
,
"x-component"
:
"CustomUpload"
,
"x-component-props"
:
{
size
:
'无'
,
fileMaxSize
:
300
,
},
"x-rules"
:
{
"required"
:
true
,
"message"
:
"请上传图片"
},
},
}
}
}
}
export
default
schema
src/pages/content/advertisement/schema/index.tsx
0 → 100644
View file @
a776c57b
import
EyePreview
from
'@/components/EyePreview'
;
import
{
DownOutlined
}
from
'@ant-design/icons'
;
import
{
TimeList
}
from
'../../statusList'
;
import
moment
from
'moment'
;
import
React
from
'react'
;
import
{
ADVERTISE_WEB_COLUMN_TYPE
,
ADVERTISE_APP_COLUMN_TYPE
}
from
'../../utils/utils'
;
const
ALL_TYPE
=
Object
.
assign
({},
ADVERTISE_WEB_COLUMN_TYPE
,
ADVERTISE_APP_COLUMN_TYPE
);
const
CustomTimeList
=
[{
label
:
'全部'
,
value
:
0
}].
concat
(
TimeList
.
slice
(
1
));
const
columns
=
[
{
title
:
'ID'
,
dataIndex
:
'id'
},
{
title
:
'标题'
,
dataIndex
:
'title'
,
render
:
(
text
:
string
,
record
:
any
)
=>
(
<
EyePreview
url=
{
`/content/advertisement/detail?id=${record.id}&preview=1`
}
>
{
text
}
</
EyePreview
>
)
},
{
title
:
'栏目'
,
dataIndex
:
'columnType'
,
render
:
(
text
,
record
)
=>
{
return
(
<
div
>
{
ALL_TYPE
[
text
]
}
</
div
>
)
},
},
{
title
:
'发布时间'
,
dataIndex
:
'createTime'
,
render
:
(
text
)
=>
(
moment
(
text
).
format
(
'YYYY-MM-DD HH:mm:ss'
)
)
},
{
title
:
'状态'
,
dataIndex
:
'status'
,
render
:
"{{renderStatus}}"
},
{
title
:
'操作'
,
render
:
"{{renderOperation}}"
}
];
/**
* 广告管理列表也 schemat
*/
const
advertisementSchema
=
{
type
:
'object'
,
properties
:
{
layout
:
{
type
:
'object'
,
// 'x-component': 'mega-layout',
'x-component'
:
'CustomFlexRowLayout'
,
'x-component-props'
:
{
justify
:
'space-between'
,
align
:
'center'
},
properties
:
{
'left-layout'
:
{
type
:
'object'
,
name
:
'left-layout'
,
'x-component'
:
'CustomFlexRowLayout'
,
'x-component-props'
:
{
justify
:
'start'
,
align
:
'center'
},
properties
:
{
createBtn
:
{
type
:
"object"
,
name
:
"createBtn"
,
"x-component"
:
"button"
,
"x-component-props"
:
{
"onClick"
:
"{{goToCreate}}"
,
"children"
:
"新建"
,
"type"
:
'primary'
,
style
:
{
width
:
'112px'
,
margin
:
'0 0 15px 0'
}
}
},
}
},
'right-layout'
:
{
type
:
'object'
,
name
:
'rigth-layout'
,
"x-component"
:
'CustomFlexColumnLayout'
,
properties
:
{
controllers
:
{
type
:
'object'
,
name
:
'controllers'
,
'x-component'
:
'CustomFlexRowLayout'
,
'x-component-props'
:
{
justify
:
'end'
,
},
properties
:
{
search
:
{
type
:
'string'
,
name
:
'name'
,
'x-component'
:
'CustomSearch'
,
'x-component-props'
:
{
placeholder
:
"请填写标题名称"
,
"onSearch"
:
"{{search}}"
,
}
},
'HIGHT_FILTER_BTN'
:
{
type
:
'string'
,
name
:
'HIGHT_FILTER_BTN'
,
'x-component'
:
'button'
,
'x-component-props'
:
{
"children"
:
(
<
div
>
高级搜索
<
DownOutlined
/></
div
>
),
"onClick"
:
"{{toggleFilters}}"
,
style
:
{
margin
:
'0 15px'
}
}
},
reset
:
{
type
:
'string'
,
name
:
'reset'
,
"x-component"
:
"button"
,
"x-component-props"
:
{
"onClick"
:
"{{reset}}"
,
"children"
:
"重置"
,
}
},
}
},
'FILTERS'
:
{
type
:
'object'
,
name
:
'FILTERS'
,
'x-component'
:
'CustomFlexRowLayout'
,
'x-component-props'
:
{
justify
:
'end'
},
properties
:
{
status
:
{
name
:
'status'
,
type
:
'string'
,
'x-component'
:
'Select'
,
'x-component-props'
:
{
options
:
[
{
label
:
'状态(全部)'
,
value
:
'0'
},
{
label
:
'待上架'
,
value
:
'1'
},
{
label
:
'已上架'
,
value
:
'2'
},
{
label
:
'已下架'
,
value
:
'3'
},
],
defaultValue
:
'0'
,
placeholder
:
'请选择状态'
,
style
:
{
width
:
'160px'
,
margin
:
'0 15px'
}
}
},
time
:
{
name
:
'time'
,
type
:
'string'
,
'x-component'
:
'Select'
,
'x-component-props'
:
{
placeholder
:
'发布时间(全部)'
,
options
:
CustomTimeList
,
style
:
{
width
:
'160px'
,
}
}
}
}
}
}
}
}
},
"table"
:
{
"key"
:
"table"
,
"type"
:
"object"
,
"name"
:
"table"
,
"x-component"
:
"Table"
,
"x-component-props"
:
{
"columns"
:
columns
,
"rowKey"
:
"id"
,
pagination
:
false
,
}
},
pagination
:
{
type
:
'object'
,
'x-component'
:
"TablePagination"
,
'x-style'
:
{
display
:
'flex'
,
flexDirection
:
'row'
,
justifyContent
:
'flex-end'
},
'x-component-props'
:
{
showQuickJumper
:
true
,
pageSize
:
10
,
size
:
'small'
}
}
}
}
export
default
advertisementSchema
src/pages/content/announcements/announceInfo.tsx
0 → 100644
View file @
a776c57b
import
React
,
{
useState
,
useEffect
}
from
'react'
;
import
{
PageHeaderWrapper
}
from
"@ant-design/pro-layout"
;
import
ReutrnEle
from
'@/components/ReturnEle'
;
import
{
usePageStatus
}
from
'@/hooks/usePageStatus'
;
import
{
history
,
Prompt
}
from
'umi'
;
import
{
Card
,
Button
}
from
'antd'
;
import
{
SchemaForm
,
createFormActions
,
FormButtonGroup
,
Submit
}
from
'@formily/antd'
import
announceInfoSchema
from
'./schema/announceInfoSchema'
;
import
{
Input
,
Select
}
from
'antd'
;
import
CustomUpload
from
'@/components/NiceForm/components/CustomUpload'
;
import
CustomEditor
from
'../components/CustomEditor'
;
import
{
PublicApi
}
from
'@/services/api'
;
import
{
useInitialValues
}
from
'../hooks/useInitialValues'
;
import
CustomCheckbox
from
'../components/CustomCheckbox'
;
import
BraftEditor
from
'braft-editor'
;
import
{
setFormStatus
}
from
'../utils/utils'
;
import
useCustomValidator
from
'../hooks/useValidator'
const
actions
=
createFormActions
();
const
AdvertisementInfo
=
()
=>
{
useCustomValidator
();
const
{
id
,
preview
}
=
usePageStatus
();
const
initialValues
:
any
=
useInitialValues
({
id
:
id
},
PublicApi
.
getManageContentNoticeGet
);
const
[
submitLoading
,
setSubmitLoading
]
=
useState
(
false
);
const
[
unsaved
,
setUnsaved
]
=
useState
(
true
);
const
isEdit
=
id
&&
!
preview
;
const
isAdd
=
!
id
&&
!
preview
;
const
isView
=
id
&&
preview
;
useEffect
(()
=>
{
const
data
=
initialValues
?.
data
||
{}
const
content
=
data
?.
content
;
if
(
content
)
{
const
editorState
=
BraftEditor
.
createEditorState
(
content
);
actions
.
setFieldValue
(
'layout.contentLayout.content'
,
editorState
);
}
setFormStatus
(
actions
,
'layout.contentLayout.content'
,
'readOnly'
,
isView
);
},
[
initialValues
])
const
handleSubmit
=
(
value
)
=>
{
console
.
log
(
value
)
const
{
content
,
top
,
...
rest
}
=
value
;
const
editorContent
=
content
.
toHTML
();
// const { title, columnType, sort, link, imageUrl} = value;
const
serviceActions
=
isAdd
?
PublicApi
.
postManageContentNoticeAdd
:
PublicApi
.
postManageContentNoticeUpdate
let
tempData
=
{...
rest
,
content
:
editorContent
,
top
:
top
?
1
:
0
};
const
postData
=
isAdd
?
tempData
:
{...
tempData
,
id
};
setSubmitLoading
(
true
)
setUnsaved
(
false
)
serviceActions
(
postData
).
then
((
data
)
=>
{
setSubmitLoading
(
false
);
if
(
data
.
code
===
1000
)
{
history
.
push
(
'/content/announcements'
)
}
})
}
const
handleCancel
=
()
=>
{
history
.
push
(
'/content/announcements'
)
}
return
(
<
PageHeaderWrapper
onBack=
{
()
=>
history
.
goBack
()
}
backIcon=
{
<
ReutrnEle
description=
"返回"
/>
}
title=
{
isAdd
?
'新建公告'
:
isEdit
?
'编辑公告'
:
'查看公告'
}
>
<
Card
>
<
SchemaForm
schema=
{
announceInfoSchema
}
actions=
{
actions
}
components=
{
{
Input
,
Select
,
Submit
,
CustomUpload
,
CustomEditor
,
CustomCheckbox
}
}
initialValues=
{
initialValues
?.
data
}
onSubmit=
{
handleSubmit
}
editable=
{
isAdd
||
isEdit
}
expressionScope=
{
{
label
:
(
<
div
>
{
isAdd
||
isEdit
?
<
span
style=
{
{
color
:
'#ff4d4f'
}
}
>
*
</
span
>
:
null
}
栏目
</
div
>
)
}
}
>
{
isAdd
||
isEdit
?
(
<
FormButtonGroup
offset=
{
3
}
>
<
Submit
loading=
{
submitLoading
}
>
提交
</
Submit
>
<
Button
onClick=
{
handleCancel
}
>
取消
</
Button
>
</
FormButtonGroup
>
)
:
<></>
}
</
SchemaForm
>
<
Prompt
when=
{
unsaved
&&
(
isAdd
||
isEdit
)
}
message=
"您还有未保存的内容,是否确定要离开?"
></
Prompt
>
</
Card
>
</
PageHeaderWrapper
>
)
}
export
default
AdvertisementInfo
src/pages/content/announcements/index.tsx
0 → 100644
View file @
a776c57b
import
React
,
{
useEffect
,
useState
}
from
'react'
;
import
{
FilterTable
,
SchemaFlexRowLayout
,
SchemaFlexColumnLayout
}
from
'../components/FilterTable'
;
import
{
Card
,
Input
,
Button
,
Table
,
Dropdown
,
Menu
,
Select
,
Space
,
Popconfirm
,
Modal
}
from
'antd'
;
import
{
createVirtualBox
,
createFormActions
,
FormEffectHooks
,
createEffectHook
}
from
'@formily/antd'
;
import
{
history
,
Link
}
from
'umi'
;
import
{
DownOutlined
,
DeleteOutlined
,
UpOutlined
}
from
'@ant-design/icons'
;
import
{
timeRange
}
from
'@/utils/index'
;
import
{
PublicApi
}
from
'@/services/api'
;
import
{
tagColorStyle
,
getTableDataSource
}
from
'../utils/utils'
;
import
{
merge
}
from
'rxjs'
import
TablePagination
from
'../components/TablePagination'
;
import
CustomSearch
from
'../components/CustomSearch'
;
const
{
onFormInit$
,
onFieldValueChange$
,
onFieldChange$
}
=
FormEffectHooks
const
{
Search
}
=
Input
;
const
SchemaButton
=
createVirtualBox
(
'button'
,
Button
);
const
SchemaTable
=
createVirtualBox
(
'SchemaTable'
,
Table
);
const
SchemaDropDown
=
createVirtualBox
(
'SchemaDropDown'
,
Dropdown
.
Button
);
const
actions
=
createFormActions
();
import
advertisementSchema
from
'./schema'
;
const
getData
=
async
(
params
:
any
)
=>
{
const
res
=
await
PublicApi
.
getManageContentNoticePage
(
params
);
return
res
.
data
}
const
Announcements
=
()
=>
{
useEffect
(()
=>
{
const
params
=
{
current
:
1
,
pageSize
:
10
}
getTableDataSource
(
actions
,
params
,
getData
);
},
[])
const
announcementEffects
=
()
=>
()
=>
{
onFormInit$
().
subscribe
(()
=>
{
actions
.
setFieldState
(
'FILTERS'
,
state
=>
{
state
.
visible
=
false
;
})
})
merge
(
onFieldValueChange$
(
'columnType'
),
onFieldValueChange$
(
'status'
),
onFieldValueChange$
(
'time'
),
).
subscribe
(
fieldState
=>
{
if
(
fieldState
.
active
&&
fieldState
.
value
!=
null
)
{
handleSearch
({})
}
}
)
// 页码发生改变
onFieldValueChange$
(
'pagination'
).
subscribe
((
state
)
=>
{
handleSearch
({...
state
.
value
})
})
}
const
handleSearch
=
async
(
params
)
=>
{
const
title
=
actions
.
getFieldValue
(
'search'
);
const
columnType
=
actions
.
getFieldValue
(
'columnType'
);
const
status
=
actions
.
getFieldValue
(
'status'
);
// 状态
const
time
=
actions
.
getFieldValue
(
'time'
);
const
{
st
,
et
}
=
timeRange
(
time
);
const
postData
=
{
title
:
title
||
''
,
columnType
:
columnType
!=
0
?
columnType
:
''
,
status
:
status
!=
0
?
status
:
''
,
startTime
:
st
,
endTime
:
et
,
current
:
1
,
pageSize
:
10
,
...
params
}
getTableDataSource
(
actions
,
postData
,
getData
);
}
const
handleDelete
=
(
id
)
=>
{
Modal
.
confirm
({
title
:
'确定要执行这个操作?'
,
onOk
:
()
=>
{
PublicApi
.
postManageContentNoticeDelete
({
id
:
id
})
.
then
((
data
)
=>
{
const
paginationValue
=
actions
.
getFieldValue
(
'pagination'
);
handleSearch
({...
paginationValue
})
})
}
})
}
// 修改状态
const
handleUpdateStatus
=
(
id
,
status
)
=>
{
// 该方法是上下架 所以 enableStatus 无用,随意传
PublicApi
.
postManageContentNoticeUpdateStatus
({
id
:
id
,
shelfStatus
:
status
,
enableStatus
:
0
})
.
then
((
data
)
=>
{
const
paginationValue
=
actions
.
getFieldValue
(
'pagination'
);
handleSearch
({...
paginationValue
})
});
}
// 重设页码
const
resetPagination
=
(
params
)
=>
{
const
paginationValue
=
actions
.
getFieldValue
(
'pagination'
);
actions
.
setFieldValue
(
'pagination'
,
{
...
paginationValue
,
...
params
})
}
return
(
<
Card
>
<
FilterTable
schema=
{
advertisementSchema
}
components=
{
{
CustomSearch
,
// SchemaFlexRowLayout,
// SchemaFlexColumnLayout,
SchemaDropDown
,
Select
,
Table
,
TablePagination
}
}
actions=
{
actions
}
expressionScope=
{
{
goToCreate
:
()
=>
{
history
.
push
(
`/content/announcements/add`
)
},
reset
:
()
=>
{
actions
.
setFieldValue
(
'search'
);
actions
.
setFieldValue
(
'columnType'
);
actions
.
setFieldValue
(
'status'
);
// 状态
actions
.
setFieldValue
(
'time'
);
resetPagination
({
current
:
1
})
handleSearch
({
current
:
1
})
},
search
:
(
value
)
=>
{
resetPagination
({
current
:
1
})
handleSearch
({
title
:
value
,
current
:
1
});
},
// eslint-disable-next-line react/display-name
renderStatus
:
(
text
,
record
)
=>
{
const
STATUSMAP
=
{
"1"
:
"待上架"
,
"2"
:
"已上架"
,
"3"
:
"已下架"
}
return
(
<
span
style=
{
{...
tagColorStyle
[
record
.
status
],
padding
:
'3px 5px'
}
}
>
{
STATUSMAP
[
record
.
status
]
}
</
span
>
)
},
toggleFilters
:
()
=>
{
actions
.
setFieldState
(
'FILTERS'
,
state
=>
{
const
visible
=
!
state
.
visible
;
state
.
visible
=
visible
;
actions
.
setFieldState
(
'HIGHT_FILTER_BTN'
,
(
state
)
=>
{
//@ts-ignore
state
.
props
[
'x-component-props'
].
children
=
(
<
div
>
高级搜索
{
visible
?
<
UpOutlined
/>
:
<
DownOutlined
/>
}
</
div
>
)
})
});
},
// eslint-disable-next-line react/display-name
renderOperation
:
(
val
,
record
)
=>
{
const
status
=
[
""
,
"上架"
,
"下架"
,
"上架"
];
const
canModify
=
[
1
,
3
]
const
menu
=
(
<
Menu
>
<
Menu
.
Item
>
<
Link
to=
{
`/content/announcements/detail?id=${record.id}`
}
>
编辑
</
Link
>
</
Menu
.
Item
>
<
Menu
.
Item
onClick=
{
()
=>
handleDelete
(
record
.
id
)
}
>
<
a
>
删除
</
a
>
</
Menu
.
Item
>
</
Menu
>
)
return
(
<
Space
>
{
/* 这里反向操作, 上架的对应的是下架, 待上架,下架对应的是上架 */
}
<
Popconfirm
title=
"确定要执行这个操作吗"
onConfirm=
{
()
=>
handleUpdateStatus
(
record
.
id
,
status
[
record
.
status
]
==
'上架'
?
2
:
3
)
}
okText=
"是"
cancelText=
"否"
>
<
a
href=
"#"
>
{
status
[
record
.
status
]
}
</
a
>
</
Popconfirm
>
{
/* // 只有待上架, 已下架架才有 修改和删除 */
}
{
canModify
.
includes
(
record
.
status
)
?
(
<
Dropdown
overlay=
{
menu
}
>
<
a
>
更多
<
DownOutlined
/>
</
a
>
</
Dropdown
>
)
:
null
}
</
Space
>
)
},
}
}
effects=
{
announcementEffects
()
}
>
</
FilterTable
>
</
Card
>
)
}
export
default
Announcements
;
src/pages/content/announcements/schema/announceInfoSchema.tsx
0 → 100644
View file @
a776c57b
import
{
ANNOUNCE_COLUMN_TYPE
,
transfer2Options
}
from
'../../utils/utils'
;
const
columnsList
=
transfer2Options
(
ANNOUNCE_COLUMN_TYPE
);
const
schema
=
{
type
:
'object'
,
properties
:
{
layout
:
{
type
:
'object'
,
'x-component'
:
'mega-layout'
,
'x-component-props'
:
{
labelCol
:
3
,
wrapperCol
:
10
,
labelAlign
:
'left'
},
properties
:
{
title
:
{
type
:
'string'
,
title
:
'标题'
,
'x-component'
:
'Input'
,
'x-component-props'
:
{
placeholder
:
'最长60个字符,30个汉字'
},
"x-rules"
:
[
{
"required"
:
true
,
"message"
:
"最长60个字符,30个汉字"
},
{
limitByte
:
true
,
// 自定义校验规则
maxByte
:
60
,
}
]
},
columnTypeLayout
:
{
type
:
'object'
,
'x-component'
:
'mega-layout'
,
"x-component-props"
:
{
"label"
:
"{{label}}"
,
wrapperCol
:
24
,
//
grid
:
true
,
columns
:
6
,
autoRow
:
false
,
layoutProps
:
{
"wrapperCol"
:
16
,
},
style
:
{
marginBottom
:
0
},
},
properties
:
{
columnType
:
{
name
:
'columnType'
,
type
:
'string'
,
'x-component'
:
'Select'
,
'x-mega-props'
:
{
span
:
2
},
'x-component-props'
:
{
style
:
{
width
:
'95%'
},
options
:
columnsList
,
},
"x-rules"
:
[{
"required"
:
true
,
"message"
:
"请选择栏目"
}],
},
top
:
{
name
:
'top'
,
type
:
'string'
,
'x-component'
:
'CustomCheckbox'
,
'x-mega-props'
:
{
span
:
1
},
'x-component-props'
:
{
children
:
'置顶'
,
}
}
}
},
contentLayout
:
{
'x-component'
:
'mega-layout'
,
"x-component-props"
:
{
layoutProps
:
{
"wrapperCol"
:
21
,
},
wrapperCol
:
23
,
},
properties
:
{
content
:
{
type
:
"string"
,
name
:
'content'
,
title
:
'内容'
,
"x-component"
:
'CustomEditor'
,
"x-component-parent-props"
:
{
style
:
{
border
:
'1px solid #DCDFE6'
}
},
"x-rules"
:
{
"required"
:
true
,
"message"
:
"请输入内容"
},
"x-component-props"
:
{
contentStyle
:
{
height
:
256
,
},
// onChange: "{{editorChange}}",
excludeControls
:
[
'letter-spacing'
,
'line-height'
,
'clear'
,
'headings'
,
'list-ol'
,
'list-ul'
,
'remove-styles'
,
'superscript'
,
'subscript'
,
'hr'
,
],
media
:
{
// 如果要允许上传视频的话,需要重写uploadFn, https://www.yuque.com/braft-editor/be/gz44tn
accepts
:
{
video
:
false
,
audio
:
false
,
}
}
},
}
}
}
}
}
}
}
export
default
schema
src/pages/content/announcements/schema/index.tsx
0 → 100644
View file @
a776c57b
import
EyePreview
from
'@/components/EyePreview'
;
import
{
DownOutlined
}
from
'@ant-design/icons'
;
import
{
TimeList
}
from
'../../statusList'
;
import
moment
from
'moment'
;
import
React
from
'react'
;
import
{
ANNOUNCE_COLUMN_TYPE
,
transfer2Options
}
from
'../../utils/utils'
;
const
ALL
=
[{
label
:
'栏目(全部)'
,
value
:
0
}]
const
COLUMNSOPTIONS
=
ALL
.
concat
(
transfer2Options
(
ANNOUNCE_COLUMN_TYPE
));
const
columns
=
[
{
title
:
'ID'
,
dataIndex
:
'id'
},
{
title
:
'栏目'
,
dataIndex
:
'columnType'
,
render
:
(
text
,
record
)
=>
{
return
(
<
div
>
{
ANNOUNCE_COLUMN_TYPE
[
text
]
}
</
div
>
)
}
},
{
title
:
'标题'
,
dataIndex
:
'title'
,
render
:
(
text
:
string
,
record
:
any
)
=>
(
<
EyePreview
url=
{
`/content/announcements/detail?id=${record.id}&preview=1`
}
>
{
text
}
</
EyePreview
>
)
},
{
title
:
'发布时间'
,
dataIndex
:
'createTime'
,
render
:
(
text
)
=>
(
moment
(
text
).
format
(
'YYYY-MM-DD HH:mm:ss'
)
)
},
{
title
:
'状态'
,
dataIndex
:
'status'
,
render
:
"{{renderStatus}}"
},
{
title
:
'操作'
,
render
:
"{{renderOperation}}"
}
];
/**
* 公告管理列表也 schemat
*/
const
announcementSchema
=
{
type
:
'object'
,
properties
:
{
layout
:
{
type
:
'object'
,
// 'x-component': 'mega-layout',
'x-component'
:
'CustomFlexRowLayout'
,
'x-component-props'
:
{
justify
:
'space-between'
,
align
:
'center'
},
properties
:
{
'left-layout'
:
{
type
:
'object'
,
name
:
'left-layout'
,
'x-component'
:
'CustomFlexRowLayout'
,
'x-component-props'
:
{
justify
:
'start'
,
align
:
'center'
},
properties
:
{
createBtn
:
{
type
:
"object"
,
name
:
"createBtn"
,
"x-component"
:
"button"
,
"x-component-props"
:
{
"onClick"
:
"{{goToCreate}}"
,
"children"
:
"新建"
,
"type"
:
'primary'
,
style
:
{
width
:
'112px'
,
margin
:
'0 0 15px 0'
}
}
},
}
},
'right-layout'
:
{
type
:
'object'
,
name
:
'rigth-layout'
,
"x-component"
:
'CustomFlexColumnLayout'
,
properties
:
{
controllers
:
{
type
:
'object'
,
name
:
'controllers'
,
'x-component'
:
'CustomFlexRowLayout'
,
'x-component-props'
:
{
justify
:
'end'
,
},
properties
:
{
search
:
{
type
:
'string'
,
name
:
'name'
,
'x-component'
:
'CustomSearch'
,
'x-component-props'
:
{
placeholder
:
"请填写标题名称"
,
"onSearch"
:
"{{search}}"
,
}
},
'HIGHT_FILTER_BTN'
:
{
type
:
'string'
,
name
:
'HIGHT_FILTER_BTN'
,
'x-component'
:
'button'
,
'x-component-props'
:
{
"children"
:
(
<
div
>
高级搜索
<
DownOutlined
/></
div
>
),
"onClick"
:
"{{toggleFilters}}"
,
style
:
{
margin
:
'0 15px'
}
}
},
reset
:
{
type
:
'string'
,
name
:
'reset'
,
"x-component"
:
"button"
,
"x-component-props"
:
{
"onClick"
:
"{{reset}}"
,
"children"
:
"重置"
,
}
},
}
},
'FILTERS'
:
{
type
:
'object'
,
name
:
'FILTERS'
,
'x-component'
:
'CustomFlexRowLayout'
,
'x-component-props'
:
{
justify
:
'end'
},
properties
:
{
columnType
:
{
type
:
'string'
,
'x-component'
:
'Select'
,
'x-component-props'
:
{
style
:
{
width
:
'160px'
},
options
:
COLUMNSOPTIONS
,
defaultValue
:
0
,
}
},
status
:
{
name
:
'status'
,
type
:
'string'
,
'x-component'
:
'Select'
,
'x-component-props'
:
{
options
:
[
{
label
:
'状态(全部)'
,
value
:
'0'
},
{
label
:
'待上架'
,
value
:
'1'
},
{
label
:
'已上架'
,
value
:
'2'
},
{
label
:
'已下架'
,
value
:
'3'
},
],
defaultValue
:
'0'
,
placeholder
:
'请选择状态'
,
style
:
{
width
:
'160px'
,
margin
:
'0 15px'
}
}
},
time
:
{
name
:
'time'
,
type
:
'string'
,
'x-component'
:
'Select'
,
'x-component-props'
:
{
placeholder
:
'发布时间(全部)'
,
options
:
TimeList
,
style
:
{
width
:
'160px'
,
}
}
}
}
}
}
}
}
},
"table"
:
{
"key"
:
"table"
,
"type"
:
"object"
,
"name"
:
"table"
,
"x-component"
:
"Table"
,
"x-component-props"
:
{
"columns"
:
columns
,
"rowKey"
:
"id"
,
pagination
:
false
,
// "pagination": {
// showQuickJumper: true,
// size: "small",
// "onChange": "{{paginationChange}}",
// },
// "rowSelection": "{{rowSelection}}"
}
},
pagination
:
{
type
:
'object'
,
'x-component'
:
"TablePagination"
,
'x-style'
:
{
display
:
'flex'
,
flexDirection
:
'row'
,
justifyContent
:
'flex-end'
},
'x-component-props'
:
{
showQuickJumper
:
true
,
pageSize
:
10
,
size
:
'small'
}
}
}
}
export
default
announcementSchema
src/pages/content/category/index.less
0 → 100644
View file @
a776c57b
.page {
display: flex;
flex-direction: row;
justify-content: space-between;
height: 100%;
overflow: hidden;
.tree {
min-width: 488px;
height: 100%;
margin-right: 16px;
}
.editPanel {
flex: 1;
background-color: #fff;
padding: 16px;
border-radius: 8px;
}
}
src/pages/content/category/index.tsx
0 → 100644
View file @
a776c57b
import
React
,
{
useState
,
useEffect
,
useMemo
}
from
'react'
import
{
Row
,
Col
,
Popconfirm
,
Button
,
Card
,
Tooltip
}
from
'antd'
;
import
Children
from
'@/components/NiceForm/components/Children'
;
import
{
PageHeaderWrapper
}
from
'@ant-design/pro-layout'
;
import
TabTree
,
{
useTreeActions
,
createTreeActions
}
from
'@/components/TabTree'
;
import
SchemaForm
,
{
createFormActions
,
LifeCycleTypes
,
FormEffectHooks
,
FormButtonGroup
}
from
'@formily/antd'
;
import
{
Checkbox
}
from
'@formily/antd-components'
import
{
classSchema
}
from
'./schema'
import
{
PublicApi
}
from
'@/services/api'
;
import
{
useTreeTabs
}
from
'@/hooks/useTreeTabs'
;
import
NiceForm
from
'@/components/NiceForm'
;
import
{
GetManageContentCategoryAllResponse
}
from
'@/services/PlatformApi/id8545'
;
import
styles
from
'./index.less'
;
import
{
BorderOuterOutlined
,
QuestionCircleOutlined
}
from
'@ant-design/icons'
;
const
{
ON_FORM_INPUT_CHANGE
}
=
LifeCycleTypes
enum
FormState
{
FREE
,
// 空闲状态
EDIT
,
// 编辑状态
ADD
,
// 新增状态
}
type
TreeDataType
=
{
id
:
number
,
title
:
string
,
children
:
TreeDataType
[],
key
:
string
,
level
:
number
,
parentId
:
number
,
}
/**
* 递归改变数据结构
* @param treeData
* @param level
* @returns
*/
const
transferTreeData
=
(
treeData
:
GetManageContentCategoryAllResponse
,
level
:
string
,
checkedKeys
):
TreeDataType
[]
=>
{
let
res
:
TreeDataType
[]
=
[];
for
(
let
i
=
0
;
i
<
treeData
.
length
;
i
++
)
{
const
item
=
treeData
[
i
];
const
key
=
level
+
item
.
id
let
result
:
TreeDataType
=
{
id
:
item
.
id
,
title
:
item
.
name
,
key
:
key
,
level
:
item
.
level
,
parentId
:
item
.
parentId
,
children
:
[],
}
if
(
item
.
status
)
{
checkedKeys
.
push
(
key
);
}
if
(
item
.
list
.
length
!==
0
)
{
result
.
children
=
transferTreeData
(
item
.
list
as
GetManageContentCategoryAllResponse
,
key
+
"-"
,
checkedKeys
);
}
res
.
push
(
result
)
}
return
res
}
const
formActions
=
createFormActions
()
const
treeActions
=
createTreeActions
()
const
fetchClassTreeData
=
async
(
params
?)
=>
{
const
res
=
await
PublicApi
.
getManageContentCategoryAll
();
return
res
}
const
ClassProperty
:
React
.
FC
<
{}
>
=
()
=>
{
const
{
treeStatus
,
setTreeStatus
,
treeData
,
setIsEditForm
,
//是否编辑状态
nodeRecord
,
setNodeRecord
,
handleSelect
,
getTreeMaps
,
setTreeMaps
,
resetMenu
,
toolsRender
,
handleDeleteMenu
}
=
useTreeTabs
({
treeActions
,
formActions
,
deleteMenu
:
PublicApi
.
postManageContentCategoryDelete
,
fetchMenuData
:
fetchClassTreeData
,
fetchItemDetailData
:
PublicApi
.
getManageContentCategoryGet
})
const
tempCheckedKeys
=
[]
const
transferTreeDatarRes
:
TreeDataType
[]
=
useMemo
(()
=>
transferTreeData
(
treeData
,
""
,
tempCheckedKeys
),
[
treeData
])
// const checkedKeys = useMemo(() => tempCheckedKeys, [transferTreeDatarRes])
const
formInitValue
=
(
nodeRecord
&&
treeStatus
===
FormState
.
EDIT
)
?
getTreeMaps
(
nodeRecord
.
key
)
:
{}
const
formValue
=
formInitValue
?
{...
formInitValue
,
status
:
[
formInitValue
.
status
]}
:
{}
const
is3Level
=
useMemo
(()
=>
{
if
(
!
nodeRecord
||
nodeRecord
.
parentId
===
0
)
{
return
1
;
}
// 通脱nodeRecord 的parentId 和 _key 判断创建节点还是子节点
const
{
parentId
,
_key
}
=
nodeRecord
;
const
splitRes
=
_key
.
split
(
"-"
);
let
flag
=
splitRes
.
length
;
let
i
=
1
;
for
(
;
i
<=
splitRes
.
length
;
i
++
)
{
if
(
splitRes
[
i
-
1
]
===
parentId
?.
toString
())
{
console
.
log
(
i
);
flag
=
i
+
1
;
break
;
}
}
return
flag
},
[
nodeRecord
])
const
onFinish
=
async
(
values
:
{
id
:
number
,
parentId
:
number
,
name
:
string
,
describe
:
string
,
status
:
string
[],
level
:
number
})
=>
{
const
_key
=
nodeRecord
?.
_key
?.
split
(
"-"
);
const
isEdit
=
treeStatus
===
FormState
.
EDIT
;
let
parentId
=
nodeRecord
?.
parentId
||
0
;
if
(
nodeRecord
&&
!
isEdit
&&
is3Level
===
4
)
{
parentId
=
_key
[
1
]
}
const
service
=
!
isEdit
?
PublicApi
.
postManageContentCategoryAdd
:
PublicApi
.
postManageContentCategoryUpdate
;
let
postData
:
any
=
{
name
:
values
.
name
,
describe
:
values
.
describe
,
status
:
values
.
status
?.[
0
]
||
0
,
level
:
is3Level
===
4
?
3
:
is3Level
,
parentId
:
parentId
,
}
if
(
isEdit
)
{
postData
=
{
...
postData
,
parentId
:
values
.
parentId
,
id
:
values
.
id
,
level
:
values
.
level
}
}
const
{
code
,
data
}
=
await
service
(
postData
);
if
(
code
===
1000
)
{
resetMenu
()
setTreeStatus
(
FormState
.
FREE
)
setNodeRecord
(
null
)
}
}
const
clickSelect
=
(
key
,
node
)
=>
{
handleSelect
(
key
,
node
)
// flag = false
}
useEffect
(()
=>
{
// 这里有个奇怪的地方,不知道为什么要医疗nodeRecord
if
(
treeStatus
===
FormState
.
ADD
&&
is3Level
===
3
||
is3Level
===
4
)
{
formActions
.
setFieldValue
(
"level"
,
3
);
}
},
[
treeStatus
,
nodeRecord
,
is3Level
])
return
(
<
div
className=
{
styles
.
page
}
>
<
div
className=
{
styles
.
tree
}
>
<
Card
>
<
h3
className=
"mb-30"
>
选择要编辑的项目
</
h3
>
{
treeData
&&
treeData
.
length
>
0
?
<
TabTree
fetchData
=
{
params
=
>
fetchClassTreeData(params)}
treeData=
{
transferTreeDatarRes
}
toolsRender=
{
toolsRender
}
actions=
{
treeActions
}
handleSelect=
{
(
key
,
node
)
=>
clickSelect
(
key
,
node
)
}
customKey="id"
/
>
:
<
Button
block
type=
'primary'
onClick=
{
()
=>
handleSelect
()
}
>
暂无菜单, 开始新增
</
Button
>
}
</
Card
>
</
div
>
<
div
className=
{
styles
.
editPanel
}
>
{
treeStatus
!==
FormState
.
FREE
&&
<>
<
h3
className=
"commonPanelTitle mb-30"
>
{
treeStatus
===
FormState
.
ADD
?
'新增'
:
'编辑'
}
</
h3
>
<
NiceForm
value=
{
formValue
}
components=
{
{
Checkbox
,
CheckboxGroup
:
Checkbox
.
Group
}
}
name=
'classForm'
onSubmit=
{
onFinish
}
actions=
{
formActions
}
effects=
{
(
$
,
action
)
=>
{}
}
schema=
{
classSchema
}
expressionScope=
{
{
showWarn
:
(
<
Tooltip
placement=
"topLeft"
title=
{
"只能同时对7个一级分类下的第三级分类设置推荐分类,且每个一级分类下最多只允许设置2个推荐分类"
}
>
<
span
style=
{
{
marginTop
:
'-12px'
,
width
:
'50px'
}
}
>
<
QuestionCircleOutlined
/>
</
span
>
</
Tooltip
>
)
}
}
>
<
FormButtonGroup
>
<
Button
htmlType=
'submit'
type=
"primary"
>
保存
</
Button
>
<
Popconfirm
title=
"确定要删除吗?"
okText=
"是"
cancelText=
"否"
onConfirm=
{
handleDeleteMenu
}
>
{
treeStatus
!==
FormState
.
ADD
&&
<
Button
>
删除
</
Button
>
}
</
Popconfirm
>
</
FormButtonGroup
>
</
NiceForm
>
</>
}
</
div
>
</
div
>
)
}
export
default
ClassProperty
src/pages/content/category/schema.tsx
0 → 100644
View file @
a776c57b
import
{
ISchema
}
from
'@formily/antd'
;
export
const
classSchema
:
ISchema
=
{
type
:
'object'
,
properties
:
{
megaLayout
:
{
type
:
'object'
,
"x-component"
:
"mega-layout"
,
"x-component-props"
:
{
grid
:
true
,
columns
:
16
,
labelAlign
:
'top'
},
properties
:
{
noField1
:
{
type
:
'object'
,
"x-component"
:
'mega-layout'
,
"x-component-props"
:
{
full
:
true
,
"wrapperWidth"
:
507
,
},
"x-mega-props"
:
{
span
:
1
},
properties
:
{
name
:
{
type
:
'string'
,
title
:
'分类名称'
,
required
:
true
,
"x-component-props"
:
{
placeholder
:
'请输入品类名称'
},
"x-rules"
:
[
{
limitByte
:
true
,
maxByte
:
16
}
]
},
describe
:
{
type
:
'textarea'
,
title
:
'类型'
,
required
:
true
,
"x-component-props"
:
{
placeholder
:
'最多100个字符,50个汉字'
},
"x-rules"
:
[
{
limitByte
:
true
,
maxByte
:
100
}
]
},
level
:
{
type
:
'string'
,
visible
:
false
,
'x-linkages'
:
[
{
type
:
'value:visible'
,
target
:
'*(inlineLayout)'
,
condition
:
'{{$value === 3}}'
},
]
},
inlineLayout
:
{
type
:
'object'
,
"x-component"
:
"mega-layout"
,
"x-component-props"
:
{
inline
:
true
,
},
properties
:
{
status
:
{
title
:
''
,
'x-component'
:
'CheckboxGroup'
,
enum
:
[
{
label
:
'推荐分类'
,
value
:
1
},
],
"x-mega-props"
:
{
"addonAfter"
:
"{{showWarn}}"
,
// wrapperWidth: 130
},
},
}
}
// status1: {
// title: '',
// 'x-component': 'Children',
// "x-component-props": {
// "children": "{{renderCheckBox()}}"
// }
// }
}
},
}
}
}
}
src/pages/content/columnManagement/columnInfo.tsx
0 → 100644
View file @
a776c57b
import
React
,
{
useState
,
useEffect
}
from
'react'
;
import
{
SchemaForm
,
Submit
,
FormButtonGroup
,
Reset
}
from
'@formily/antd'
;
import
{
Card
,
Select
,
Input
,
Button
}
from
'antd'
;
import
{
PageHeaderWrapper
}
from
'@ant-design/pro-layout'
;
import
ReutrnEle
from
'@/components/ReturnEle'
;
import
{
usePageStatus
}
from
'@/hooks/usePageStatus'
;
import
{
history
,
Prompt
}
from
'umi'
;
import
{
PublicApi
}
from
'@/services/api'
;
import
useCustomValidator
from
'../hooks/useValidator'
interface
IOption
{
value
:
number
|
string
,
label
:
number
|
string
}
const
sortedList
=
(()
=>
{
let
res
:
IOption
[]
=
[]
for
(
let
i
=
1
;
i
<=
30
;
i
++
)
{
let
data
:
IOption
=
{
label
:
i
,
value
:
i
}
res
.
push
(
data
);
}
return
res
})()
const
schema
=
{
type
:
'object'
,
properties
:
{
layout
:
{
name
:
'layout'
,
type
:
'object'
,
'x-component'
:
'mega-layout'
,
'x-component-props'
:
{
"labelCol"
:
3
,
"wrapperCol"
:
10
,
"labelAlign"
:
"left"
},
properties
:
{
name
:
{
name
:
'name'
,
title
:
'栏目名称'
,
'x-component'
:
'Input'
,
"required"
:
true
,
"x-rules"
:
[
{
"required"
:
true
,
"message"
:
"最长20个字符,10个汉字"
},
{
limitByte
:
true
,
// 自定义校验规则
maxByte
:
20
,
}
]
},
type
:
{
title
:
'栏目分类'
,
'x-component'
:
'Select'
,
"x-component-props"
:
{
options
:
[
{
label
:
'市场行情'
,
value
:
1
},
{
label
:
'资讯'
,
value
:
2
},
]
},
"required"
:
true
,
"x-rules"
:
[
{
"required"
:
true
,
"message"
:
"请选择栏目分类"
},
]
},
sort
:
{
name
:
'sort'
,
title
:
'栏目排序'
,
'x-component'
:
'Select'
,
"required"
:
true
,
"x-rules"
:
{
"required"
:
true
,
"message"
:
"请选择栏目排序"
},
"x-component-props"
:
{
options
:
sortedList
}
},
}
}
}
}
const
useInitialValues
=
(
id
)
=>
{
const
[
state
,
setState
]
=
useState
({})
useEffect
(()
=>
{
if
(
id
)
{
PublicApi
.
getManageContentColumnGet
({
id
:
id
})
.
then
((
data
)
=>
{
setState
(
data
);
})
}
},
[
id
])
return
state
}
const
ColumnInfo
=
()
=>
{
useCustomValidator
();
const
{
id
,
preview
}
=
usePageStatus
();
const
[
submitLoading
,
setSubmitLoading
]
=
useState
(
false
);
const
initialValues
=
useInitialValues
(
id
);
const
[
unsaved
,
setUnsaved
]
=
useState
(
true
);
const
isEdit
=
id
&&
!
preview
;
const
isAdd
=
!
id
&&
!
preview
;
const
handleSubmit
=
async
(
value
:
{
name
:
string
,
sort
:
number
,
type
:
number
})
=>
{
const
{
name
,
sort
,
type
}
=
value
;
const
serviceActions
=
isAdd
?
PublicApi
.
postManageContentColumnAdd
:
PublicApi
.
postManageContentColumnUpdate
const
postData
=
{
id
,
name
,
sort
,
type
};
setSubmitLoading
(
true
)
setUnsaved
(
false
)
try
{
const
{
data
,
code
}
=
await
serviceActions
(
postData
);
if
(
code
===
1000
)
{
history
.
push
(
'/content/columnsManagement'
)
}
}
finally
{
setSubmitLoading
(
false
);
}
}
const
handleCancel
=
()
=>
{
history
.
push
(
'/content/columnsManagement'
)
}
return
(
<
div
>
<
PageHeaderWrapper
onBack=
{
()
=>
history
.
goBack
()
}
backIcon=
{
<
ReutrnEle
description=
"返回"
/>
}
title=
{
!
id
?
'新建栏目'
:
'编辑栏目'
}
>
<
Card
>
<
SchemaForm
initialValues=
{
initialValues
?.
data
}
onSubmit=
{
handleSubmit
}
editable=
{
isAdd
||
isEdit
}
schema=
{
schema
}
components=
{
{
Input
,
Select
,
Submit
}
}
>
{
isAdd
||
isEdit
?
(
<
FormButtonGroup
offset=
{
3
}
>
<
Submit
loading=
{
submitLoading
}
>
提交
</
Submit
>
<
Button
onClick=
{
handleCancel
}
>
取消
</
Button
>
</
FormButtonGroup
>
)
:
<></>
}
</
SchemaForm
>
</
Card
>
</
PageHeaderWrapper
>
<
Prompt
when=
{
unsaved
&&
(
isAdd
||
isEdit
)
}
message=
"您还有未保存的内容,是否确定要离开?"
/>
</
div
>
)
}
export
default
ColumnInfo
src/pages/content/columnManagement/index.tsx
0 → 100644
View file @
a776c57b
import
React
,
{
useEffect
,
useState
}
from
'react'
;
import
{
FilterTable
,
SchemaFlexRowLayout
}
from
'../components/FilterTable'
;
import
{
Card
,
Input
,
Button
,
Table
,
Space
,
Popconfirm
}
from
'antd'
;
import
{
createVirtualBox
,
createFormActions
,
FormEffectHooks
,
createEffectHook
,
registerFormFields
,
connect
}
from
'@formily/antd'
;
import
{
history
,
Link
}
from
'umi'
;
import
{
PublicApi
}
from
'@/services/api'
;
import
StatusSwitch
from
'@/components/StatusSwitch'
;
import
columnManagementSchemat
from
'./schema'
;
import
{
getTableDataSource
}
from
'../utils/utils'
;
import
TablePagination
from
'../components/TablePagination'
;
import
CustomSearch
from
'../components/CustomSearch'
;
const
{
onFieldValueChange$
}
=
FormEffectHooks
// const { Search } = Input;
const
SchemaButton
=
createVirtualBox
(
'button'
,
Button
);
const
SchemaTable
=
createVirtualBox
(
'SchemaTable'
,
Table
);
// registerFormFields({ FlexRowLayout: connect()(FlexRowLayout) })
const
actions
=
createFormActions
();
const
getData
=
async
(
params
)
=>
{
const
res
=
await
PublicApi
.
getManageContentColumnPage
(
params
)
return
res
.
data
}
const
columnList
:
React
.
FC
<
{}
>
=
()
=>
{
const
columnEffects
=
()
=>
()
=>
{
onFieldValueChange$
(
'pagination'
).
subscribe
((
state
)
=>
{
handleSearch
({...
state
.
value
})
})
}
useEffect
(()
=>
{
const
params
=
{
current
:
1
,
pageSize
:
10
}
getTableDataSource
(
actions
,
params
,
getData
);
},
[])
const
handleModify
=
(
value
)
=>
{
const
{
id
,
status
}
=
value
;
const
postData
=
{
id
:
id
,
enableStatus
:
(
status
^
1
),
}
//@ts-ignore
PublicApi
.
postManageContentColumnUpdateStatus
(
postData
).
then
((
data
)
=>
{
const
paginationValue
=
actions
.
getFieldValue
(
'pagination'
);
handleSearch
({...
paginationValue
})
})
}
// 栏目删除
const
handleRemove
=
(
id
:
number
)
=>
{
///manage/contentColumn/delete
PublicApi
.
postManageContentColumnDelete
({
id
:
id
})
.
then
((
data
)
=>
{
const
paginationValue
=
actions
.
getFieldValue
(
'pagination'
);
handleSearch
({...
paginationValue
})
})
}
const
handleSearch
=
async
(
params
)
=>
{
const
title
=
actions
.
getFieldValue
(
'search'
);
const
postData
=
{
name
:
title
||
''
,
current
:
1
,
pageSize
:
10
,
...
params
,
}
getTableDataSource
(
actions
,
postData
,
getData
);
}
// 重设页码
const
resetPagination
=
(
params
)
=>
{
const
paginationValue
=
actions
.
getFieldValue
(
'pagination'
);
actions
.
setFieldValue
(
'pagination'
,
{
...
paginationValue
,
...
params
})
}
return
(
<
Card
>
<
FilterTable
schema=
{
columnManagementSchemat
}
components=
{
{
CustomSearch
,
TablePagination
,
SchemaButton
,
Table
}
}
actions=
{
actions
}
expressionScope=
{
{
goToCreate
:
()
=>
{
// console.log("goToCreate")
history
.
push
(
`/content/columnsManagement/add`
)
},
search
:
(
value
)
=>
{
resetPagination
({
current
:
1
})
handleSearch
({
title
:
value
,
current
:
1
});
},
renderOperation
:
(
val
,
record
)
=>
{
return
(
// 无效 status == 0 可以删除修改该
<
Space
>
{
record
.
status
===
0
?
<>
<
Link
to=
{
`/content/columnsManagement/detail?id=${record.id}`
}
>
编辑
</
Link
>
<
Popconfirm
title=
"确定要执行这个操作?"
onConfirm=
{
()
=>
handleRemove
(
record
.
id
)
}
okText=
"是"
cancelText=
"否"
>
<
a
>
删除
</
a
>
</
Popconfirm
>
</>
:
null
}
</
Space
>
)
},
renderStatus
:
(
text
,
record
)
=>
{
return
(
<
StatusSwitch
handleConfirm=
{
()
=>
handleModify
(
record
)
}
record=
{
record
}
fieldNames=
"status"
/>
)
},
reset
:
()
=>
{
actions
.
setFieldValue
(
'search'
);
resetPagination
({
current
:
1
})
handleSearch
({
current
:
1
})
},
// paginationChange: (page: number, pageSize: number) =>
{
// paginationChange(page, pageSize)
//
}
}
}
effects=
{
columnEffects
()
}
/>
</
Card
>
)
}
export
default
columnList
\ No newline at end of file
src/pages/content/columnManagement/schema/index.tsx
0 → 100644
View file @
a776c57b
import
React
from
'react'
;
import
EyePreview
from
'@/components/EyePreview'
;
const
columns
=
[
{
title
:
'ID'
,
dataIndex
:
'id'
},
{
title
:
'栏目名称'
,
dataIndex
:
'name'
,
render
:
(
text
:
string
,
record
:
any
)
=>
(
<
EyePreview
url=
{
`/content/columnsManagement/detail?id=${record.id}&preview=1`
}
>
{
text
}
</
EyePreview
>
)
},
{
title
:
'栏目分类'
,
dataIndex
:
'type'
,
render
:
(
text
)
=>
text
===
1
?
'市场行情'
:
'资讯'
},
{
title
:
'栏目排序'
,
dataIndex
:
'sort'
},
{
title
:
'状态'
,
dataIndex
:
'status'
,
filters
:
[
{
text
:
'有效'
,
value
:
1
,
},
{
text
:
'无效'
,
value
:
0
,
},
],
onFilter
:
(
value
,
record
)
=>
record
.
status
===
value
,
render
:
"{{renderStatus}}"
},
{
title
:
'操作'
,
render
:
"{{renderOperation}}"
}
];
const
schema
=
{
type
:
'object'
,
properties
:
{
layout
:
{
type
:
'object'
,
// 'x-component': 'mega-layout',
'x-component'
:
'CustomFlexRowLayout'
,
'x-component-props'
:
{
justify
:
'space-between'
},
properties
:
{
createBtn
:
{
type
:
"object"
,
name
:
"createBtn"
,
"x-component"
:
"button"
,
"x-component-props"
:
{
"onClick"
:
"{{goToCreate}}"
,
"children"
:
"新建"
,
"type"
:
'primary'
}
},
'right-layout'
:
{
type
:
'object'
,
name
:
'rigth-layout'
,
"x-component"
:
'CustomFlexRowLayout'
,
"x-component-props"
:
{
justify
:
'center'
},
properties
:
{
search
:
{
type
:
'string'
,
name
:
'search'
,
'x-component'
:
'CustomSearch'
,
'x-component-props'
:
{
placeholder
:
"请填写栏目名称"
,
"onSearch"
:
"{{search}}"
,
}
},
searchBtn
:
{
type
:
'string'
,
name
:
'searchBtn'
,
"x-component"
:
"button"
,
"x-component-props"
:
{
"onClick"
:
"{{reset}}"
,
"children"
:
"重置"
,
style
:
{
marginLeft
:
'15px'
}
}
},
}
}
}
},
"table"
:
{
"key"
:
"table"
,
"type"
:
"object"
,
"name"
:
"table"
,
"x-component"
:
"SchemaTable"
,
"x-component-props"
:
{
"columns"
:
columns
,
"rowKey"
:
"id"
,
"pagination"
:
false
}
},
pagination
:
{
type
:
'object'
,
'x-component'
:
"TablePagination"
,
'x-style'
:
{
display
:
'flex'
,
flexDirection
:
'row'
,
justifyContent
:
'flex-end'
},
'x-component-props'
:
{
showQuickJumper
:
true
,
pageSize
:
10
,
size
:
'small'
}
}
}
}
export
default
schema
src/pages/content/components/CustomCheckbox/index.tsx
0 → 100644
View file @
a776c57b
import
React
from
'react'
;
import
{
Checkbox
}
from
'antd'
;
const
CustomCheckbox
=
(
props
)
=>
{
console
.
log
(
props
);
const
editable
=
props
.
editable
const
handleChange
=
(
e
)
=>
{
props
.
mutators
.
change
(
e
.
target
.
checked
)
}
return
(
<
Checkbox
disabled=
{
!
editable
}
checked=
{
props
.
value
}
onChange=
{
handleChange
}
>
置顶
</
Checkbox
>
)
}
CustomCheckbox
.
isFieldComponent
=
true
export
default
CustomCheckbox
\ No newline at end of file
src/pages/content/components/CustomEditor/index.tsx
0 → 100644
View file @
a776c57b
import
React
from
'react'
;
import
'braft-editor/dist/index.css'
;
import
BraftEditor
from
'braft-editor'
;
// const SchemaEditor = createVirtualBox('SchemaEditor', BraftEditor);
const
CustomEditor
=
(
props
)
=>
{
const
editorProps
=
props
.
props
[
'x-component-props'
];
const
parentProps
=
props
.
props
[
'x-component-parent-props'
];
const
handleChange
=
(
editorState
)
=>
{
const
isEmpty
=
editorState
.
isEmpty
();
const
value
=
isEmpty
?
null
:
editorState
props
.
mutators
.
change
(
value
)
}
return
(
<
div
{
...
parentProps
}
>
<
BraftEditor
{
...
editorProps
}
value=
{
props
.
value
||
''
}
onChange=
{
handleChange
}
/>
</
div
>
)
}
CustomEditor
.
isFieldComponent
=
true
;
export
default
CustomEditor
src/pages/content/components/CustomSearch/index.tsx
0 → 100644
View file @
a776c57b
import
React
from
'react'
;
import
{
Input
}
from
'antd'
;
import
styles
from
'./styles.less'
const
{
Search
}
=
Input
;
const
CustomSearch
=
(
props
)
=>
{
const
editable
=
props
.
editable
const
componentProps
=
props
.
props
[
'x-component-props'
];
const
handleChange
=
(
e
)
=>
{
props
.
mutators
.
change
(
e
.
target
.
value
)
}
return
(
<
div
className=
{
styles
.
container
}
>
<
Search
disabled=
{
!
editable
}
value=
{
props
.
value
}
onChange=
{
handleChange
}
{
...
componentProps
}
// onSearch={value => console.log(value)}
/>
</
div
>
)
}
CustomSearch
.
isFieldComponent
=
true
export
default
CustomSearch
src/pages/content/components/CustomSearch/styles.less
0 → 100644
View file @
a776c57b
.container {
:global {
.input-search {
// background-color: red;
.ant-input-wrapper {
.ant-input {
height: 32px !important;
}
}
}
}
}
src/pages/content/components/FilterTable/FilterTable.tsx
0 → 100644
View file @
a776c57b
import
React
,
{
useEffect
}
from
'react'
;
import
{
SchemaForm
,
registerVirtualBox
,
SchemaField
,
registerValidationRules
}
from
'@formily/antd'
;
import
{
Row
,
Col
}
from
'antd'
;
// import { FormMegaLayout, Input } from '@formily/antd-components';
const
renderCol
=
(
schema
)
=>
{
const
{
flexcol
=
{},
}
=
schema
&&
schema
[
'x-component-props'
]
||
{};
const
flexProps
=
schema
[
'x-flex-props'
]
||
{}
return
<
Col
{
...
flexcol
}
{
...
flexProps
}
key=
{
schema
.
path
}
>
<
SchemaField
schema=
{
schema
.
toJSON
()
}
path=
{
schema
.
path
}
/>
</
Col
>
}
registerVirtualBox
(
'CustomFlexRowLayout'
,
(
props
)
=>
{
const
schemaProps
=
props
;
const
childProperties
=
schemaProps
.
schema
&&
schemaProps
.
schema
.
getOrderProperties
()
||
[];
const
{
justify
=
"start"
,
align
=
"top"
}
=
schemaProps
&&
schemaProps
.
props
&&
schemaProps
.
props
[
'x-component-props'
]
||
{}
return
(
<
Row
justify=
{
justify
}
align=
{
align
}
>
{
childProperties
.
map
((
v
,
i
,
arr
)
=>
renderCol
(
v
.
schema
))
}
</
Row
>
)
})
const
FlexColumnLayoutStyle
=
{
'display'
:
'flex'
,
'flexDirection'
:
'column'
}
registerVirtualBox
(
'CustomFlexColumnLayout'
,
(
props
)
=>
{
const
schemaProps
=
props
;
const
childProperties
=
schemaProps
.
schema
&&
schemaProps
.
schema
.
getOrderProperties
()
||
[];
const
{
style
}
=
schemaProps
&&
schemaProps
.
props
&&
schemaProps
.
props
[
'x-component-props'
]
||
{};
return
(
<
div
style=
{
{...
FlexColumnLayoutStyle
,
...
style
}
}
>
{
childProperties
.
map
((
v
)
=>
{
const
{
flexCol
=
{}
}
=
v
.
schema
&&
v
.
schema
[
'x-component-props'
]
||
{};
return
(
<
div
{
...
flexCol
}
key=
{
v
.
schema
.
path
}
>
<
SchemaField
schema=
{
v
.
schema
.
toJSON
()
}
path=
{
v
.
schema
.
path
}
/>
</
div
>
)
})
}
</
div
>
)
})
const
FilterTable
=
(
props
)
=>
{
const
{
actions
,
schema
,
components
,
...
rest
}
=
props
;
return
(
<
div
>
<
SchemaForm
components=
{
components
}
actions=
{
actions
}
schema=
{
schema
}
{
...
rest
}
>
</
SchemaForm
>
</
div
>
)
}
export
default
FilterTable
;
\ No newline at end of file
src/pages/content/components/FilterTable/FlexLayout.tsx
0 → 100644
View file @
a776c57b
import
React
from
'react'
;
import
{
Row
,
Col
}
from
'antd'
;
import
{
SchemaField
}
from
"@formily/antd"
;
const
renderCol
=
(
schema
)
=>
{
const
{
flexcol
=
{},
}
=
schema
&&
schema
[
'x-component-props'
]
||
{};
const
flexProps
=
schema
[
'x-flex-props'
]
||
{}
return
<
Col
{
...
flexcol
}
{
...
flexProps
}
key=
{
schema
.
path
}
>
<
SchemaField
schema=
{
schema
.
toJSON
()
}
path=
{
schema
.
path
}
/>
</
Col
>
}
const
SchemaFlexRowLayout
=
(
props
)
=>
{
const
schemaProps
=
props
;
console
.
log
(
"FlexRowLayout"
,
schemaProps
);
const
childProperties
=
schemaProps
.
schema
&&
schemaProps
.
schema
.
getOrderProperties
()
||
[];
const
{
justify
=
"start"
,
align
=
"top"
}
=
schemaProps
&&
schemaProps
.
props
&&
schemaProps
.
props
[
'x-component-props'
]
||
{}
return
(
<
Row
justify=
{
justify
}
align=
{
align
}
>
{
childProperties
.
map
((
v
,
i
,
arr
)
=>
renderCol
(
v
.
schema
))
}
</
Row
>
)
}
SchemaFlexRowLayout
.
isVirtualFieldComponent
=
true
const
FlexColumnLayoutStyle
=
{
'display'
:
'flex'
,
'flexDirection'
:
'column'
}
const
SchemaFlexColumnLayout
=
(
props
)
=>
{
const
schemaProps
=
props
;
console
.
log
(
"FlexColumnLayout"
,
schemaProps
);
const
childProperties
=
schemaProps
.
schema
&&
schemaProps
.
schema
.
getOrderProperties
()
||
[];
console
.
log
(
"childProperties"
,
childProperties
)
const
{
style
}
=
schemaProps
&&
schemaProps
.
props
&&
schemaProps
.
props
[
'x-component-props'
]
||
{};
return
(
<
div
style=
{
{...
FlexColumnLayoutStyle
,
...
style
}
}
>
{
childProperties
.
map
((
v
)
=>
{
const
{
flexCol
=
{}
}
=
v
.
schema
&&
v
.
schema
[
'x-component-props'
]
||
{};
return
(
<
div
{
...
flexCol
}
key=
{
v
.
schema
.
path
}
>
<
SchemaField
schema=
{
v
.
schema
.
toJSON
()
}
path=
{
v
.
schema
.
path
}
/>
</
div
>
)
})
}
</
div
>
)
}
SchemaFlexColumnLayout
.
isVirtualFieldComponent
=
true
export
{
SchemaFlexRowLayout
,
SchemaFlexColumnLayout
}
\ No newline at end of file
src/pages/content/components/FilterTable/index.tsx
0 → 100644
View file @
a776c57b
import
FilterTable
from
'./FilterTable'
;
import
{
SchemaFlexRowLayout
,
SchemaFlexColumnLayout
}
from
'./FlexLayout'
;
export
{
FilterTable
,
SchemaFlexRowLayout
,
SchemaFlexColumnLayout
}
\ No newline at end of file
src/pages/content/components/TablePagination/index.tsx
0 → 100644
View file @
a776c57b
import
React
from
'react'
;
import
{
Pagination
}
from
'antd'
;
const
TablePagination
=
(
props
)
=>
{
const
componentProps
=
props
.
props
[
"x-component-props"
];
const
total
=
componentProps
.
total
;
const
parentStyle
=
props
.
props
[
'x-style'
];
const
handleChange
=
(
page
,
pageSize
)
=>
{
props
.
mutators
.
change
({
current
:
page
,
pageSize
});
}
return
(
<
div
style=
{
parentStyle
}
>
{
total
>
0
?
<
Pagination
{
...
componentProps
}
current=
{
props
.
value
?.
current
||
1
}
onChange=
{
handleChange
}
></
Pagination
>
:
null
}
</
div
>
)
}
TablePagination
.
isFieldComponent
=
true
export
default
TablePagination
\ No newline at end of file
src/pages/content/components/Tags/Tags.less
0 → 100644
View file @
a776c57b
.tagContainer {
.selection {
display: flex;
flex-direction: row;
justify-content: flex-start;
flex-wrap: wrap;
.selectionItem {
// height: 24px;
font-size: 12px;
padding: 0px 7px;
margin: 0 16px 16px 0;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
background-color: @secondary-color;
color: @main-color;
border-radius: 4px;
.icon {
margin-left: 4px;
cursor: pointer;
}
}
}
.tips {
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #909399;
line-height: 12px;
}
.tags {
display: flex;
flex-direction: row;
flex-wrap: wrap;
cursor: pointer;
user-select: none;
.tagItem {
// height: 28px;
padding: 0 6px;
background: #F4F5F7;
border-radius: 4px;
font-size: 12px;
color: #606266;
display: flex;
justify-content: center;
align-items: center;
margin-right: 16px;
margin-bottom: 16px;
}
}
}
src/pages/content/components/Tags/Tags.tsx
0 → 100644
View file @
a776c57b
import
React
,
{
useState
,
useEffect
}
from
'react'
;
import
styles
from
'./Tags.less'
;
import
{
CloseCircleOutlined
}
from
'@ant-design/icons'
;
const
Tags
=
(
props
)
=>
{
const
seletedTag
=
props
.
props
[
'x-component-props'
][
'seletedTag'
]
;
const
editable
=
props
.
editable
;
const
[
tags
,
setTags
]
=
useState
<
number
[]
>
([]);
useEffect
(()
=>
{
if
(
seletedTag
instanceof
Array
)
{
setTags
(
seletedTag
);
}
},
[
seletedTag
])
const
handleItemSelect
=
(
params
)
=>
{
const
{
value
}
=
params
;
if
(
tags
.
includes
(
value
))
{
return
;
}
const
onChange
=
props
.
props
[
'x-component-props'
][
'onChange'
];
setTags
((
state
)
=>
{
const
current
=
state
;
const
res
=
[...
current
,
value
];
!!
onChange
&&
onChange
(
res
);
return
res
})
}
const
handleCancel
=
(
params
)
=>
{
const
{
value
}
=
params
;
const
onChange
=
props
.
props
[
'x-component-props'
][
'onChange'
];
setTags
((
state
)
=>
{
const
current
=
state
;
const
res
=
current
.
filter
((
item
)
=>
item
!==
value
);
!!
onChange
&&
onChange
(
res
);
return
res
;
})
}
const
dataSource
=
props
.
props
[
'x-component-props'
][
'dataSource'
]
||
[];
const
selected
=
dataSource
.
filter
((
item
)
=>
tags
.
includes
(
item
.
value
)
)
return
(
<
div
className=
{
styles
.
tagContainer
}
>
<
div
className=
{
styles
.
selection
}
>
{
selected
.
map
((
item
)
=>
{
return
(
<
div
className=
{
styles
.
selectionItem
}
key=
{
item
.
value
}
>
<
span
>
{
item
.
label
}
</
span
>
{
editable
?
<
span
className=
{
styles
.
icon
}
onClick=
{
()
=>
handleCancel
(
item
)
}
><
CloseCircleOutlined
/></
span
>
:
null
}
</
div
>
)
})
}
</
div
>
{
editable
?
<>
<
p
className=
{
styles
.
tips
}
>
从下列标签中选择
</
p
>
<
div
className=
{
styles
.
tags
}
>
{
dataSource
.
map
((
item
)
=>
{
return
(
<
div
className=
{
styles
.
tagItem
}
key=
{
item
.
value
}
onClick=
{
()
=>
handleItemSelect
(
item
)
}
>
{
item
.
label
}
</
div
>
)
})
}
</
div
>
</>
:
null
}
</
div
>
)
}
Tags
.
isFieldComponent
=
true
export
default
Tags
;
src/pages/content/components/Tags/index.tsx
0 → 100644
View file @
a776c57b
import
CustomTags
from
'./Tags'
;
export
{
CustomTags
}
\ No newline at end of file
src/pages/content/components/WrapCustomUpload/index.tsx
0 → 100644
View file @
a776c57b
import
React
from
'react'
;
import
CustomUpload
from
'@/components/NiceForm/components/CustomUpload'
;
const
WrapCustomUpload
=
(
props
)
=>
{
const
imgUrl
=
props
.
value
;
const
errors
=
props
.
errors
;
const
editable
=
props
.
editable
;
return
(
<>
{
editable
?
<
div
>
<
CustomUpload
{
...
props
}
></
CustomUpload
>
{
errors
.
length
>
0
?
<
p
style=
{
{
color
:
'#ff4d4f'
}
}
>
{
errors
.
join
(
","
)
}
</
p
>
:
null
}
</
div
>
:
<
div
>
<
img
src=
{
imgUrl
}
style=
{
{
width
:
'104px'
,
height
:
'104px'
}
}
/>
</
div
>
}
</>
)
}
WrapCustomUpload
.
isFieldComponent
=
true
export
default
WrapCustomUpload
\ No newline at end of file
src/pages/content/constant.ts
0 → 100644
View file @
a776c57b
src/pages/content/hooks/useAsyncDataSource.tsx
0 → 100644
View file @
a776c57b
import
{
createFormActions
,
FormEffectHooks
,
createEffectHook
}
from
'@formily/antd'
;
const
{
onFormInit$
}
=
FormEffectHooks
const
customEvent$
=
createEffectHook
(
'requestAsyncDataSource'
);
const
useAsyncDataSource
=
(
name
:
string
,
service
:
any
)
=>
{
const
{
dispatch
,
setFieldState
}
=
createFormActions
()
onFormInit$
().
subscribe
(()
=>
{
// 这里需要调用一下loading
service
().
then
(
res
=>
{
//请求结束可以dispatch一个自定义事件收尾,方便后续针对该事件做联动
setFieldState
(
name
,
state
=>
{
// @ts-ignore
state
.
props
[
"x-component-props"
][
"dataSource"
]
=
res
})
//@ts-ignore
dispatch
(
'requestAsyncDataSource'
,
{
name
,
payload
:
res
})
})
})
customEvent$
().
subscribe
(()
=>
{
console
.
log
(
"requestAsyncDataSource"
)
})
}
export
{
useAsyncDataSource
}
\ No newline at end of file
src/pages/content/hooks/useInitialValues.tsx
0 → 100644
View file @
a776c57b
import
React
,
{
useEffect
,
useState
}
from
'react'
;
const
useInitialValues
=
(
params
,
service
)
=>
{
const
[
state
,
setState
]
=
useState
(
null
)
useEffect
(()
=>
{
if
(
params
.
id
)
{
service
(
params
).
then
((
data
)
=>
{
setState
(
data
);
})
}
},
[
params
.
id
])
return
state
}
export
{
useInitialValues
}
src/pages/content/hooks/useValidator.tsx
0 → 100644
View file @
a776c57b
import
React
,
{
useEffect
,
useState
}
from
'react'
;
import
{
registerValidationRules
}
from
'@formily/antd'
;
const
useCustomValidator
=
()
=>
{
useEffect
(()
=>
{
//自定义校验规则
registerValidationRules
({
limitByte
:
(
value
,
desc
,
rules
)
=>
{
const
{
allowChineseTransform
=
true
,
maxByte
}
=
desc
;
let
str
=
value
;
let
message
=
`不能超过
${
maxByte
}
个字符`
if
(
allowChineseTransform
)
{
str
=
str
.
replace
(
/
[\u
4E00-
\u
9FA5
]
/g
,
"AA"
);
message
+=
`,或者
${
maxByte
/
2
}
个汉字`
}
return
str
.
length
>
maxByte
?
message
:
""
;
},
isInteger
:
(
value
,
des
,
rules
)
=>
{
if
(
typeof
value
==
'undefined'
||
value
==
''
)
{
return
''
}
const
isNumber
=
/^
\d
+$/
;
const
message
=
des
?
"只允许填写正整数"
:
des
const
pattern
=
/
[
0-9
]
+
\.[
0-9
]
*/
;
return
!
isNumber
.
test
(
value
)
||
pattern
.
test
(
value
)
?
message
:
""
}
});
},
[])
}
export
default
useCustomValidator
src/pages/content/imagesManagement/imageInfo.tsx
0 → 100644
View file @
a776c57b
import
React
,
{
useState
}
from
'react'
;
import
{
PageHeaderWrapper
}
from
"@ant-design/pro-layout"
;
import
ReutrnEle
from
'@/components/ReturnEle'
;
import
{
usePageStatus
}
from
'@/hooks/usePageStatus'
;
import
{
history
,
Prompt
}
from
'umi'
;
import
{
Card
,
Button
}
from
'antd'
;
import
{
SchemaForm
,
createFormActions
,
FormButtonGroup
,
FormEffectHooks
,
Submit
,
Reset
}
from
'@formily/antd'
import
imageInfoSchema
from
'./schema/imageInfoSchema'
;
import
{
Input
,
Select
}
from
'antd'
;
import
CustomUpload
from
'../components/WrapCustomUpload'
;
import
{
PublicApi
}
from
'@/services/api'
;
import
{
useInitialValues
}
from
'../hooks/useInitialValues'
;
import
useCustomValidator
from
'../hooks/useValidator'
import
{
setFormStatus
,
SCENE
,
POSITION
,
transfer2Options
,
}
from
'../utils/utils'
;
const
{
onFieldValueChange$
}
=
FormEffectHooks
const
actions
=
createFormActions
();
// 暂时写死, 所在位置跟使用场景相关联,当选择Web时去除所有App
const
WEB_OPTION
=
transfer2Options
(
POSITION
).
filter
((
item
)
=>
!
item
.
label
.
includes
(
"APP"
))
const
APP_OPTION
=
transfer2Options
(
POSITION
).
filter
((
item
)
=>
item
.
label
.
includes
(
"APP"
))
const
ImageInfo
=
()
=>
{
useCustomValidator
();
const
{
id
,
preview
}
=
usePageStatus
();
const
initialValues
:
any
=
useInitialValues
({
id
:
id
},
PublicApi
.
getManageContentImageGet
);
const
[
submitLoading
,
setSubmitLoading
]
=
useState
(
false
);
const
[
unsaved
,
setUnsaved
]
=
useState
(
true
);
const
isEdit
=
id
&&
!
preview
;
const
isAdd
=
!
id
&&
!
preview
;
const
isView
=
id
&&
preview
;
const
handleSubmit
=
(
value
)
=>
{
const
serviceActions
=
isAdd
?
PublicApi
.
postManageContentImageAdd
:
PublicApi
.
postManageContentImageUpdate
let
tempData
=
value
;
const
postData
=
isAdd
?
tempData
:
{...
tempData
,
id
};
setSubmitLoading
(
true
)
setUnsaved
(
false
)
serviceActions
(
postData
).
then
((
data
)
=>
{
setSubmitLoading
(
false
);
if
(
data
.
code
===
1000
)
{
history
.
push
(
'/content/imagesManagement'
)
}
})
}
const
handleCancel
=
()
=>
{
history
.
push
(
'/content/imagesManagement'
)
}
const
ImageInfoEffects
=
()
=>
()
=>
{
onFieldValueChange$
(
'layout.useScene'
).
subscribe
((
state
)
=>
{
if
(
state
.
initialValue
!=
state
.
value
)
{
actions
.
setFieldValue
(
'layout.position'
,
null
)
setFormStatus
(
actions
,
'layout.position'
,
'options'
,
state
.
value
==
1
?
WEB_OPTION
:
APP_OPTION
)
}
})
}
return
(
<
PageHeaderWrapper
onBack=
{
()
=>
history
.
goBack
()
}
backIcon=
{
<
ReutrnEle
description=
"返回"
/>
}
title=
{
isAdd
?
'新建图片'
:
isEdit
?
'编辑图片'
:
'查看图片'
}
>
<
Card
>
<
SchemaForm
schema=
{
imageInfoSchema
}
actions=
{
actions
}
components=
{
{
Input
,
Select
,
Submit
,
CustomUpload
}
}
initialValues=
{
initialValues
?.
data
}
onSubmit=
{
handleSubmit
}
editable=
{
isAdd
||
isEdit
}
expressionScope=
{
{
label
:
(
<
div
>
{
isAdd
||
isEdit
?
<
span
style=
{
{
color
:
'#ff4d4f'
}
}
>
*
</
span
>
:
null
}
图片
</
div
>
)
}
}
effects=
{
ImageInfoEffects
()
}
>
{
isAdd
||
isEdit
?
(
<
FormButtonGroup
offset=
{
3
}
>
<
Submit
loading=
{
submitLoading
}
>
提交
</
Submit
>
<
Button
onClick=
{
handleCancel
}
>
取消
</
Button
>
</
FormButtonGroup
>
)
:
<></>
}
</
SchemaForm
>
</
Card
>
<
Prompt
when=
{
unsaved
&&
(
isAdd
||
isEdit
)
}
message=
"您还有未保存的内容,是否确定要离开?"
/>
</
PageHeaderWrapper
>
)
}
export
default
ImageInfo
src/pages/content/imagesManagement/index.tsx
0 → 100644
View file @
a776c57b
import
React
,
{
useEffect
,
useState
}
from
'react'
;
import
{
FilterTable
,
SchemaFlexRowLayout
,
SchemaFlexColumnLayout
}
from
'../components/FilterTable'
;
import
{
Card
,
Input
,
Button
,
Table
,
Dropdown
,
Select
,
Space
,
Popconfirm
}
from
'antd'
;
import
{
createVirtualBox
,
createFormActions
,
FormEffectHooks
}
from
'@formily/antd'
;
import
{
history
,
Link
}
from
'umi'
;
import
{
PublicApi
}
from
'@/services/api'
;
import
{
getTableDataSource
}
from
'../utils/utils'
;
import
ImagementSchema
from
'./schema'
;
import
StatusSwitch
from
'@/components/StatusSwitch'
;
import
TablePagination
from
'../components/TablePagination'
;
import
CustomSearch
from
'../components/CustomSearch'
// const { Search } = Input;
const
{
onFieldValueChange$
}
=
FormEffectHooks
const
SchemaButton
=
createVirtualBox
(
'button'
,
Button
);
// const SchemaTable = createVirtualBox('SchemaTable', Table);
const
SchemaDropDown
=
createVirtualBox
(
'SchemaDropDown'
,
Dropdown
.
Button
);
const
actions
=
createFormActions
();
const
getData
=
async
(
params
:
any
)
=>
{
const
res
=
await
PublicApi
.
getManageContentImagePage
(
params
);
return
res
.
data
}
const
ImagesManagement
=
()
=>
{
useEffect
(()
=>
{
const
params
=
{
current
:
1
,
pageSize
:
10
}
getTableDataSource
(
actions
,
params
,
getData
);
},
[])
const
ImagesManagementEffects
=
()
=>
()
=>
{
onFieldValueChange$
(
'pagination'
).
subscribe
((
state
)
=>
{
handleSearch
({...
state
.
value
})
})
}
const
handleSearch
=
async
(
params
)
=>
{
const
title
=
actions
.
getFieldValue
(
'search'
);
const
postData
=
{
name
:
title
||
''
,
current
:
1
,
pageSize
:
10
,
...
params
,
}
getTableDataSource
(
actions
,
postData
,
getData
);
}
const
handleDelete
=
(
id
)
=>
{
PublicApi
.
postManageContentImageDelete
({
id
:
id
})
.
then
((
data
)
=>
{
const
paginationValue
=
actions
.
getFieldValue
(
'pagination'
);
handleSearch
({...
paginationValue
})
})
}
// 修改状态
const
handleUpdateStatus
=
(
id
,
status
)
=>
{
const
postData
=
{
id
:
id
,
enableStatus
:
status
,
shelfStatus
:
0
};
PublicApi
.
postManageContentImageUpdateStatus
(
postData
)
.
then
((
data
)
=>
{
const
paginationValue
=
actions
.
getFieldValue
(
'pagination'
);
handleSearch
({...
paginationValue
})
});
}
// 重设页码
const
resetPagination
=
(
params
)
=>
{
const
paginationValue
=
actions
.
getFieldValue
(
'pagination'
);
actions
.
setFieldValue
(
'pagination'
,
{
...
paginationValue
,
...
params
})
}
return
(
<
Card
>
<
FilterTable
schema=
{
ImagementSchema
}
components=
{
{
CustomSearch
,
// SchemaFlexRowLayout,
// SchemaFlexColumnLayout,
SchemaDropDown
,
Select
,
Table
,
TablePagination
,
SchemaButton
}
}
effects=
{
ImagesManagementEffects
()
}
actions=
{
actions
}
expressionScope=
{
{
goToCreate
:
()
=>
{
history
.
push
(
`/content/imagesManagement/add`
)
},
reset
:
()
=>
{
actions
.
setFieldValue
(
"search"
);
resetPagination
({
current
:
1
})
handleSearch
({
name
:
null
,
current
:
1
})
},
search
:
(
value
)
=>
{
resetPagination
({
current
:
1
})
handleSearch
({
name
:
value
,
current
:
1
});
},
renderStatus
:
(
text
,
record
)
=>
{
return
(
<
StatusSwitch
handleConfirm=
{
()
=>
handleUpdateStatus
(
record
.
id
,
record
.
status
^
1
)
}
record=
{
record
}
fieldNames=
"status"
/>
)
},
renderOperation
:
(
val
,
record
)
=>
{
return
(
<
Space
>
{
/* // 只有 无效 才有 修改和删除 */
}
{
record
.
status
==
0
?
(
<>
<
Link
to=
{
`/content/imagesManagement/detail?id=${record.id}`
}
>
编辑
</
Link
>
<
Popconfirm
title=
"确定要执行这个操作吗"
onConfirm=
{
()
=>
handleDelete
(
record
.
id
)
}
okText=
"是"
cancelText=
"否"
>
<
a
href=
"#"
>
删除
</
a
>
</
Popconfirm
>
</>
)
:
null
}
</
Space
>
)
},
}
}
>
</
FilterTable
>
</
Card
>
)
}
export
default
ImagesManagement
;
\ No newline at end of file
src/pages/content/imagesManagement/schema/imageInfoSchema.tsx
0 → 100644
View file @
a776c57b
import
{
SCENE
,
POSITION
,
transfer2Options
,
sortedList
}
from
'../../utils/utils'
;
const
SCENEOPTIONS
=
transfer2Options
(
SCENE
);
const
POSITIONOPTIONS
=
transfer2Options
(
POSITION
);
const
SORTLISTOPTIONS
=
sortedList
(
1
,
11
);
/**
* 内容管理 - 图片详情
* 下面就是一个mega-layout 布局
*/
const
schema
=
{
type
:
'object'
,
properties
:
{
layout
:
{
type
:
'object'
,
'x-component'
:
'mega-layout'
,
'x-component-props'
:
{
labelCol
:
3
,
wrapperCol
:
10
,
labelAlign
:
'left'
},
properties
:
{
name
:
{
type
:
'string'
,
title
:
'图片名称'
,
'x-component'
:
'Input'
,
'x-component-props'
:
{
placeholder
:
'最长30个字符,15个汉字'
},
"x-rules"
:
[
{
"required"
:
true
,
"message"
:
"最长30个字符,15个汉字"
},
{
limitByte
:
true
,
// 自定义校验规则
maxByte
:
30
,
}
]
},
useScene
:
{
title
:
'使用场景'
,
type
:
'string'
,
'x-component'
:
'Select'
,
'x-component-props'
:
{
options
:
SCENEOPTIONS
},
"x-rules"
:
[{
"required"
:
true
,
"message"
:
"请选择栏目"
}],
},
position
:
{
title
:
'所在位置'
,
type
:
'string'
,
'x-component'
:
'Select'
,
'x-component-props'
:
{
options
:
POSITIONOPTIONS
},
"x-rules"
:
[{
"required"
:
true
,
"message"
:
"请选择广告排序"
}],
},
sort
:
{
title
:
'图片排序'
,
type
:
'string'
,
'x-component'
:
'Select'
,
'x-component-props'
:
{
options
:
SORTLISTOPTIONS
},
"x-rules"
:
[{
"required"
:
true
,
"message"
:
"请选择图片排序"
}],
},
imageUrl
:
{
type
:
"object"
,
title
:
"{{label}}"
,
name
:
"imageUrl"
,
"x-component"
:
"CustomUpload"
,
"x-component-props"
:
{
size
:
'无'
,
fileMaxSize
:
300
},
"x-rules"
:
[{
"required"
:
true
,
"message"
:
"请上传图片"
}],
},
}
}
}
}
export
default
schema
\ No newline at end of file
src/pages/content/imagesManagement/schema/index.tsx
0 → 100644
View file @
a776c57b
import
EyePreview
from
'@/components/EyePreview'
;
import
React
from
'react'
;
import
{
SCENE
,
POSITION
}
from
'../../utils/utils'
const
columns
=
[
{
title
:
'ID'
,
dataIndex
:
'id'
},
{
title
:
'图片名称'
,
dataIndex
:
'name'
,
render
:
(
text
:
string
,
record
:
any
)
=>
(
<
EyePreview
url=
{
`/content/imagesManagement/detail?id=${record.id}&preview=1`
}
>
{
text
}
</
EyePreview
>
)},
{
title
:
'使用场景'
,
dataIndex
:
'useScene'
,
render
:
(
text
,
record
)
=>
{
return
(
<
div
>
{
SCENE
[
text
]
}
</
div
>
)
}
},
{
title
:
'所在位置'
,
dataIndex
:
'position'
,
render
:
(
text
,
record
)
=>
{
return
(
<
div
>
{
POSITION
[
text
]
}
</
div
>
)
}
},
{
title
:
'状态'
,
dataIndex
:
'status'
,
render
:
"{{renderStatus}}"
},
{
title
:
'操作'
,
render
:
"{{renderOperation}}"
}
];
/**
* 图片管理列表页 schema
*/
const
schema
=
{
type
:
'object'
,
properties
:
{
layout
:
{
type
:
'object'
,
// 'x-component': 'mega-layout',
'x-component'
:
'CustomFlexRowLayout'
,
'x-component-props'
:
{
justify
:
'space-between'
,
align
:
'center'
},
properties
:
{
'left-layout'
:
{
type
:
'object'
,
name
:
'left-layout'
,
'x-component'
:
'CustomFlexRowLayout'
,
'x-component-props'
:
{
justify
:
'start'
,
align
:
'center'
},
properties
:
{
createBtn
:
{
type
:
"object"
,
name
:
"createBtn"
,
"x-component"
:
"button"
,
"x-component-props"
:
{
"onClick"
:
"{{goToCreate}}"
,
"children"
:
"新建"
,
"type"
:
'primary'
,
style
:
{
width
:
'112px'
,
margin
:
'0 0 15px 0'
}
}
},
}
},
'right-layout'
:
{
type
:
'object'
,
name
:
'rigth-layout'
,
"x-component"
:
'CustomFlexColumnLayout'
,
properties
:
{
controllers
:
{
type
:
'object'
,
name
:
'controllers'
,
'x-component'
:
'CustomFlexRowLayout'
,
'x-component-props'
:
{
justify
:
'end'
,
},
properties
:
{
search
:
{
type
:
'string'
,
name
:
'name'
,
'x-component'
:
'CustomSearch'
,
'x-component-props'
:
{
placeholder
:
"请填写图片名称"
,
"onSearch"
:
"{{search}}"
,
}
},
reset
:
{
type
:
'string'
,
name
:
'reset'
,
"x-component"
:
"button"
,
"x-component-props"
:
{
"onClick"
:
"{{reset}}"
,
"children"
:
"重置"
,
style
:
{
margin
:
'0 10px'
}
}
},
}
},
}
}
}
},
"table"
:
{
"key"
:
"table"
,
"type"
:
"object"
,
"name"
:
"table"
,
"x-component"
:
"Table"
,
"x-component-props"
:
{
"columns"
:
columns
,
"rowKey"
:
"id"
,
"pagination"
:
false
// "rowSelection": "{{rowSelection}}"
}
},
pagination
:
{
type
:
'object'
,
'x-component'
:
"TablePagination"
,
'x-style'
:
{
display
:
'flex'
,
flexDirection
:
'row'
,
justifyContent
:
'flex-end'
},
'x-component-props'
:
{
showQuickJumper
:
true
,
pageSize
:
10
,
size
:
'small'
}
}
}
}
export
default
schema
\ No newline at end of file
src/pages/content/infomation/index.tsx
0 → 100644
View file @
a776c57b
This diff is collapsed.
Click to expand it.
src/pages/content/infomation/infomationInfo.tsx
0 → 100644
View file @
a776c57b
import
React
,
{
useEffect
,
useState
}
from
'react'
;
import
{
SchemaForm
,
Submit
,
FormButtonGroup
,
Reset
,
createFormActions
,
registerValidationRules
,
FormEffectHooks
}
from
'@formily/antd'
;
import
{
Card
,
Select
,
Input
,
Checkbox
,
Button
}
from
'antd'
;
import
{
PageHeaderWrapper
}
from
'@ant-design/pro-layout'
;
import
ReutrnEle
from
'@/components/ReturnEle'
;
import
{
usePageStatus
}
from
'@/hooks/usePageStatus'
;
import
{
history
,
Prompt
}
from
'umi'
;
// import CustomUpload from '@/components/NiceForm/components/CustomUpload';
import
{
CustomTags
}
from
'../components/Tags'
;
import
CustomEditor
from
'../components/CustomEditor'
;
import
BraftEditor
from
'braft-editor'
;
import
{
useInitialValues
}
from
'../hooks/useInitialValues'
;
import
{
PublicApi
}
from
'@/services/api'
;
import
infomationInfoSchema
from
'./schema/infomationInfoSchema'
;
import
CustomUpload
from
'../components/WrapCustomUpload'
;
import
useCustomValidator
from
'../hooks/useValidator'
import
{
GetManageContentCategoryAllResponse
}
from
'@/services/PlatformApi'
;
import
{
COLUMN_CATEGORY
}
from
'../constant'
;
const
actions
=
createFormActions
();
const
{
onFieldValueChange$
,
onFieldInputChange$
}
=
FormEffectHooks
const
{
TextArea
}
=
Input
;
/**
* 栏目分类
* 1.市场行情;2.资讯
*/
type
ColumnType
=
0
|
1
|
2
;
type
ColumnListType
=
{
label
:
string
,
value
:
number
,
type
:
1
|
2
|
number
&
{}
}
const
InfomationInfo
=
()
=>
{
useCustomValidator
();
const
{
id
,
preview
}
=
usePageStatus
();
// const [isTop, setIsTop] = useState(1);
const
[
labelIds
,
setLabelIds
]
=
useState
<
number
[]
>
([]);
const
[
submitLoading
,
setSubmitLoading
]
=
useState
(
false
);
const
[
unsaved
,
setUnsaved
]
=
useState
(
true
);
const
[
type
,
setType
]
=
useState
<
ColumnType
>
(
0
);
const
initialValues
=
useInitialValues
({
id
:
id
},
PublicApi
.
getManageContentInformationGet
);
const
[
category
,
setCategory
]
=
useState
<
GetManageContentCategoryAllResponse
>
([]);
const
[
column
,
setColumn
]
=
useState
<
ColumnListType
[]
>
([])
const
isEdit
=
id
&&
!
preview
;
const
isAdd
=
!
id
&&
!
preview
;
const
isView
=
id
&&
preview
;
// 设置form 的某字段的值
const
setFormStatus
=
(
name
:
string
,
key
:
string
,
value
:
any
)
=>
{
actions
.
setFieldState
(
name
,
state
=>
{
// @ts-ignore
state
.
props
[
'x-component-props'
][
key
]
=
value
})
}
useEffect
(()
=>
{
async
function
getColumn
()
{
const
res
=
await
PublicApi
.
getManageContentColumnAll
();
const
list
=
res
.
data
.
map
((
item
)
=>
({
label
:
item
.
name
,
value
:
item
.
id
,
type
:
item
.
type
}));
setFormStatus
(
"layout.columnId"
,
"options"
,
list
)
setColumn
(
list
)
}
getColumn
()
},
[])
useEffect
(()
=>
{
async
function
getLabels
()
{
const
res
=
await
PublicApi
.
getManageContentLabelAll
();
const
labels
=
res
.
data
.
map
((
item
)
=>
({
label
:
item
.
name
,
value
:
item
.
id
}));
setFormStatus
(
"layout.labelIds"
,
"dataSource"
,
labels
)
}
getLabels
()
},
[])
/**
* 获取行情分类
*/
useEffect
(()
=>
{
async
function
getCategory
()
{
const
{
data
,
code
,
message
}
=
await
PublicApi
.
getManageContentCategoryAll
();
if
(
code
!==
1000
)
return
;
const
list
=
data
.
map
((
_item
)
=>
({
label
:
_item
.
name
,
value
:
_item
.
id
,
children
:
_item
.
list
})
);
setFormStatus
(
"layout.categoryLayout.firstCategoryId"
,
"options"
,
list
);
// sethasGetCategory(true)
setCategory
(
data
);
}
getCategory
();
},
[])
useEffect
(()
=>
{
if
(
initialValues
===
null
)
{
return
;
}
const
data
=
initialValues
!
.
data
||
{}
const
content
=
data
.
content
;
if
(
content
)
{
const
editorState
=
BraftEditor
.
createEditorState
(
content
);
actions
.
setFieldValue
(
'layout.contentLayout.content'
,
editorState
);
}
setFormStatus
(
'layout.contentLayout.content'
,
'readOnly'
,
isView
);
/** @tofix 这里写的不是很好, 这里分类联动应该单独一个组件抽离 */
if
(
category
)
{
actions
.
setFieldValue
(
'layout.categoryLayout.firstCategoryName'
,
data
.
firstCategoryName
);
const
secondCategory
=
category
.
filter
((
_row
)
=>
_row
.
id
===
data
.
firstCategoryId
)[
0
]?.
list
||
[];
const
options
=
secondCategory
.
map
((
_row
:
any
)
=>
({
label
:
_row
.
name
,
value
:
_row
.
id
,
children
:
_row
.
list
}))
setFormStatus
(
'layout.categoryLayout.secondCategoryId'
,
'options'
,
options
);
// actions.setFieldValue('layout.categoryLayout.secondCategoryId', data.secondCategoryId);
const
thirdCategory
=
options
.
filter
((
_row
)
=>
_row
.
value
===
data
.
secondCategoryId
)[
0
]?.
children
||
[];
const
thirdOptions
=
thirdCategory
.
map
((
_row
:
any
)
=>
({
label
:
_row
.
name
,
value
:
_row
.
id
,
children
:
_row
.
list
}))
setFormStatus
(
'layout.categoryLayout.thirdlyCategoryId'
,
'options'
,
thirdOptions
);
// actions.setFieldValue('layout.categoryLayout.thirdlyCategoryId', data.thirdlyCategoryId);
}
if
(
column
)
{
const
targetColumn
=
column
.
filter
((
_item
)
=>
_item
.
value
===
data
.
columnId
)[
0
];
if
(
targetColumn
)
{
actions
.
setFieldState
(
'layout.columnId'
,
state
=>
{
state
.
props
[
'description'
]
=
`栏目分类:
${
COLUMN_CATEGORY
[
targetColumn
?.
type
]
||
''
}
`
})
setType(targetColumn?.type)
}
}
setFormStatus('layout.imageUpload', 'imgUrl', data.imageUrl)
// setIsTop(data.top);
setLabelIds(data.labelIds)
setFormStatus('layout.labelIds', 'seletedTag', data.labelIds)
}, [initialValues, category, column])
const handleSubmit = (value) => {
const content = value.content.toHTML();
const tempPostData = {
...value,
type: type,
labelIds: labelIds || [],
content: content,
}
const serviceActions = isAdd
? PublicApi.postManageContentInformationAdd
: PublicApi.postManageContentInformationUpdate
const postData = isAdd ? tempPostData : {...tempPostData, id: id};
setSubmitLoading(true)
setUnsaved(false)
serviceActions(postData).then((data) => {
setSubmitLoading(false);
if(data.code === 1000) {
history.push('/content/infomations')
}
})
}
const handleCancel = () => {
history.push('/content/infomations')
}
return (
<div>
<PageHeaderWrapper
onBack={() => history.goBack()}
backIcon={<ReutrnEle description="返回" />}
title={isAdd ? '新建资讯' : isEdit ? '编辑资讯' : '查看资讯'}
>
<Card>
<SchemaForm
value={initialValues?.data}
onSubmit={handleSubmit}
schema={infomationInfoSchema}
editable={isAdd || isEdit}
actions={actions}
components={{
Input, Select, Submit,
TextArea, Checkbox,
CustomUpload, CustomTags, CustomEditor,
}}
effects={($) => {
onFieldValueChange$('layout.columnId').subscribe(({ value }) => {
actions.setFieldState('layout.columnId', state => {
const currentType = state.props["x-component-props"]!.options?.filter((_row) => _row.value === value)[0];
state["props"]["description"] = `
栏目分类:
$
{
currentType
&&
(
COLUMN_CATEGORY
[
currentType
.
type
])}
`;
setType(currentType ? currentType.type : 0)
})
})
onFieldInputChange$('layout.categoryLayout.*(firstCategoryId,secondCategoryId)').subscribe(({ value, props, name }) => {
const matchName = name.match(/(.*?)Id/);
if(matchName?.length !== 2) {
return
}
const target = props["x-component-props"]!.options.filter((_row) => _row.value === value)[0];
actions.setFieldValue(`
layout
.
categoryLayout
.
$
{
matchName
[
1
]}
Name
`, target?.label)
const childrenName = name === 'firstCategoryId' ? 'secondCategoryId' : 'thirdlyCategoryId';
const optionChildren = target?.children || [];
const list = optionChildren?.map((_item) => ({ label: _item.name, value: _item.id, children: _item.list }) );
actions.setFieldState(`
layout
.
categoryLayout
.
$
{
childrenName
}
`, state => {
state.value = "",
state.props['x-component-props']!["options"] = list;
})
})
}}
expressionScope={{
tagOnChange: (value) => {
setLabelIds(value);
},
label: (
<div>
{
isAdd || isEdit
? <span style={{color: '#ff4d4f'}}>* </span>
: null
}
图片
</div>
)
}}
>
{
isAdd || isEdit
? (
<FormButtonGroup offset={3}>
<Submit loading={submitLoading}>提交</Submit>
<Button onClick={handleCancel}>取消</Button>
</FormButtonGroup>
)
: <></>
}
</SchemaForm>
</Card>
<Prompt when={(isAdd || isEdit) && unsaved} message="您还有未保存的内容,是否确定要离开?" />
</PageHeaderWrapper>
</div>
)
}
export default InfomationInfo
src/pages/content/infomation/schema/index.tsx
0 → 100644
View file @
a776c57b
import
EyePreview
from
'@/components/EyePreview'
;
import
{
DownOutlined
,
DeleteOutlined
,
UpOutlined
}
from
'@ant-design/icons'
;
import
{
timeRange
}
from
'@/utils/index'
;
import
{
TimeList
}
from
'../../statusList'
;
import
{
COLUMN_CATEGORY
}
from
'../../constant'
;
import
moment
from
'moment'
;
import
React
from
'react'
;
const
CustomTimeList
=
[{
label
:
'全部'
,
value
:
0
}].
concat
(
TimeList
.
slice
(
1
));
const
columns
=
[
{
title
:
'ID'
,
dataIndex
:
'id'
},
{
title
:
'栏目分类'
,
dataIndex
:
'type'
,
render
:
(
text
)
=>
COLUMN_CATEGORY
[
text
],
},
{
title
:
'栏目'
,
dataIndex
:
'columnName'
},
{
title
:
'标题'
,
dataIndex
:
'title'
,
render
:
(
text
:
string
,
record
:
any
)
=>
(
<
EyePreview
url=
{
`/content/infomations/detail?id=${record.id}&preview=1`
}
>
{
text
}
</
EyePreview
>
)
},
{
title
:
'分类'
,
dataIndex
:
'categoryName'
},
{
title
:
'推荐标签'
,
dataIndex
:
'labelNames'
},
{
title
:
'排序'
,
dataIndex
:
'sort'
,
sorter
:
(
a
,
b
)
=>
a
.
sort
-
b
.
sort
,
},
{
title
:
'发布时间'
,
dataIndex
:
'createTime'
,
sorter
:
(
a
,
b
)
=>
a
.
createTime
-
b
.
createTime
,
render
:
(
text
)
=>
(
moment
(
text
).
format
(
'YYYY-MM-DD HH:mm:ss'
)
)
},
{
title
:
'状态'
,
dataIndex
:
'status'
,
filters
:
[
{
text
:
'待上架'
,
value
:
'1'
},
{
text
:
'已上架'
,
value
:
'2'
},
{
text
:
'已下架'
,
value
:
'3'
},
],
onFilter
:
(
value
,
record
)
=>
{
return
record
.
status
.
toString
().
includes
(
value
)
},
render
:
"{{renderStatus}}"
},
{
title
:
'操作'
,
render
:
"{{renderOperation}}"
}
];
/**
* 这等于是一个flex 布局
* flexRow, FlewColumn 布局的高级搜索
* 咨询管理 schema
*/
const
infomationSchema
=
{
type
:
'object'
,
properties
:
{
layout
:
{
type
:
'object'
,
// 'x-component': 'mega-layout',
'x-component'
:
'CustomFlexRowLayout'
,
'x-component-props'
:
{
justify
:
'space-between'
,
align
:
'center'
},
properties
:
{
'left-layout'
:
{
type
:
'object'
,
name
:
'left-layout'
,
'x-component'
:
'CustomFlexRowLayout'
,
'x-component-props'
:
{
justify
:
'start'
,
align
:
'center'
},
properties
:
{
createBtn
:
{
type
:
"object"
,
name
:
"createBtn"
,
"x-component"
:
"button"
,
"x-component-props"
:
{
"onClick"
:
"{{goToCreate}}"
,
"children"
:
"新建"
,
"type"
:
'primary'
,
style
:
{
width
:
'112px'
,
margin
:
'0 0 15px 0'
}
}
},
batchGrounding
:
{
type
:
'object'
,
name
:
'batchUpdata'
,
'x-component'
:
'button'
,
'x-component-props'
:
{
"onClick"
:
"{{batchGrounding}}"
,
"children"
:
"批量上架"
,
style
:
{
margin
:
'0 0 0 15px'
}
}
},
undercarriage
:
{
type
:
'object'
,
name
:
'undercarriage'
,
'x-component'
:
'button'
,
'x-component-props'
:
{
"onClick"
:
"{{undercarriage}}"
,
"children"
:
"批量下架"
,
style
:
{
margin
:
'0 15px'
}
}
},
more
:
{
type
:
'object'
,
name
:
'more'
,
'x-component'
:
'SchemaDropDown'
,
'x-component-props'
:
{
overlay
:
"{{menu}}"
,
children
:
'更多'
,
icon
:
<
DownOutlined
/>
}
}
}
},
'right-layout'
:
{
type
:
'object'
,
name
:
'rigth-layout'
,
"x-component"
:
'CustomFlexColumnLayout'
,
properties
:
{
controllers
:
{
type
:
'object'
,
name
:
'controllers'
,
'x-component'
:
'CustomFlexRowLayout'
,
'x-component-props'
:
{
justify
:
'end'
,
},
properties
:
{
search
:
{
type
:
'string'
,
name
:
'name'
,
'x-component'
:
'CustomSearch'
,
'x-component-props'
:
{
placeholder
:
"请填写标题名称"
,
style
:
{
marginRight
:
'12px'
},
"onSearch"
:
"{{search}}"
,
}
},
'HIGHT_FILTER_BTN'
:
{
type
:
'string'
,
name
:
'HIGHT_FILTER_BTN'
,
'x-component'
:
'button'
,
'x-component-props'
:
{
"children"
:
(
<
div
>
高级搜索
<
DownOutlined
/></
div
>
),
"onClick"
:
"{{toggleFilters}}"
,
style
:
{
margin
:
'0 15px'
}
}
},
reset
:
{
type
:
'string'
,
name
:
'reset'
,
"x-component"
:
"button"
,
"x-component-props"
:
{
"onClick"
:
"{{reset}}"
,
"children"
:
"重置"
,
}
},
}
},
'FILTERS'
:
{
type
:
'object'
,
name
:
'FILTERS'
,
'x-component'
:
'CustomFlexRowLayout'
,
'x-component-props'
:
{
justify
:
'end'
},
properties
:
{
columns
:
{
name
:
'columns'
,
type
:
'string'
,
'x-component'
:
'Select'
,
'x-component-props'
:
{
placeholder
:
'请选择栏目'
,
style
:
{
width
:
'160px'
}
}
},
status
:
{
name
:
'status'
,
type
:
'string'
,
'x-component'
:
'Select'
,
'x-component-props'
:
{
options
:
[
{
label
:
'全部'
,
value
:
'0'
},
{
label
:
'待上架'
,
value
:
'1'
},
{
label
:
'已上架'
,
value
:
'2'
},
{
label
:
'已下架'
,
value
:
'3'
},
],
placeholder
:
'请选择状态'
,
style
:
{
width
:
'160px'
,
margin
:
'0 15px'
}
}
},
time
:
{
name
:
'time'
,
type
:
'string'
,
'x-component'
:
'Select'
,
'x-component-props'
:
{
placeholder
:
'发布时间(全部)'
,
options
:
CustomTimeList
,
style
:
{
width
:
'160px'
,
}
}
}
}
}
}
}
}
},
"table"
:
{
"key"
:
"table"
,
"type"
:
"object"
,
"name"
:
"table"
,
"x-component"
:
"Table"
,
"x-component-props"
:
{
"columns"
:
columns
,
"rowKey"
:
"id"
,
"pagination"
:
false
,
"rowSelection"
:
"{{rowSelection}}"
}
},
pagination
:
{
type
:
'object'
,
'x-component'
:
"TablePagination"
,
'x-style'
:
{
display
:
'flex'
,
flexDirection
:
'row'
,
justifyContent
:
'flex-end'
},
'x-component-props'
:
{
showQuickJumper
:
true
,
pageSize
:
10
,
size
:
'small'
}
}
}
}
export
{
infomationSchema
}
src/pages/content/infomation/schema/infomationInfoSchema.tsx
0 → 100644
View file @
a776c57b
interface
IOption
{
value
:
number
|
string
,
label
:
number
|
string
}
const
sortedList
=
(()
=>
{
let
res
:
IOption
[]
=
[]
for
(
let
i
=
1
;
i
<=
10
;
i
++
)
{
let
data
:
IOption
=
{
label
:
i
,
value
:
i
}
res
.
push
(
data
);
}
return
res
})()
const
schema
=
{
type
:
'object'
,
properties
:
{
layout
:
{
name
:
'layout'
,
type
:
'object'
,
'x-component'
:
'mega-layout'
,
'x-component-props'
:
{
"labelCol"
:
3
,
"wrapperCol"
:
10
,
"labelAlign"
:
"left"
,
},
properties
:
{
title
:
{
name
:
'title'
,
title
:
'标题'
,
'x-component'
:
'Input'
,
'x-component-props'
:
{
placeholder
:
'最长30个汉字,60个字符'
,
},
"x-rules"
:
[
{
"required"
:
true
,
"message"
:
"请填写标题"
},
{
limitByte
:
true
,
maxByte
:
60
}
]
},
columnId
:
{
name
:
'columnId'
,
title
:
'栏目'
,
'x-component'
:
'Select'
,
"x-component-props"
:
{
style
:
{
marginBottom
:
'8px'
},
},
description
:
"栏目分类"
,
"x-rules"
:
{
"required"
:
true
,
"message"
:
"请选择咨询说明"
},
},
recommendLabel
:
{
name
:
'recommendLabel'
,
title
:
'推荐标签'
,
type
:
'string'
,
'x-component'
:
'Select'
,
"x-component-props"
:
{
style
:
{
marginTop
:
'12px'
},
allowClear
:
true
,
options
:
[
{
label
:
'头条文章'
,
value
:
1
},
{
label
:
'轮播新闻'
,
value
:
2
},
{
label
:
'图片新闻'
,
value
:
3
},
{
label
:
'推荐阅读'
,
value
:
4
},
{
label
:
'行情推荐'
,
value
:
5
},
{
label
:
'本栏推荐'
,
value
:
6
}
],
},
},
// sortLayout: {
// type: 'object',
// 'x-component': 'mega-layout',
// "x-component-props": {
// "label": "推荐排序",
// // wrapperCol: 23,
// // layoutProps: {
// // "wrapperCol": 12,
// // },
// style: {
// marginBottom: 0
// },
// // addonAfter: "{{isTop}}"
// },
// properties: {
// sort: {
// name: 'sort',
// type: 'string',
// 'x-component': 'Select',
// 'x-component-props': {
// // style: {
// // width: '100%'
// // },
// options: sortedList,
// allowClear: true,
// }
// },
// }
// },
sort
:
{
name
:
'sort'
,
type
:
'string'
,
title
:
'推荐排序'
,
'x-component'
:
'Select'
,
'x-component-props'
:
{
options
:
sortedList
,
allowClear
:
true
,
}
},
readCount
:
{
name
:
'readCount'
,
title
:
'浏览数'
,
type
:
'string'
,
'x-component'
:
'Input'
,
'x-component-props'
:
{
style
:
{
width
:
'100%'
}
},
'x-rules'
:
[
{
isInteger
:
true
,
}
]
},
categoryLayout
:
{
type
:
'object'
,
'x-component'
:
'mega-layout'
,
'x-component-props'
:
{
grid
:
true
,
full
:
true
,
label
:
"行情资讯分类:"
,
"wrapperCol"
:
24
,
},
properties
:
{
firstCategoryId
:
{
type
:
'string'
,
"x-component"
:
"Select"
,
'x-component-props'
:
{
options
:
[],
},
'x-linkages'
:
[
{
type
:
'value:visible'
,
target
:
'*(secondCategoryId)'
,
condition
:
`{{!!$value}}`
,
},
]
},
firstCategoryName
:
{
type
:
'string'
,
display
:
false
,
},
secondCategoryId
:
{
type
:
'string'
,
'x-component'
:
"Select"
,
'x-component-props'
:
{
options
:
[],
},
'x-linkages'
:
[
{
type
:
'value:visible'
,
target
:
'*(thirdlyCategoryId)'
,
condition
:
'{{!!$value}}'
},
]
},
secondCategoryName
:
{
type
:
'string'
,
display
:
false
,
},
thirdlyCategoryId
:
{
type
:
'string'
,
'x-component'
:
"Select"
,
'x-component-props'
:
{
options
:
[],
},
},
thirdlyCategoryName
:
{
type
:
'string'
,
display
:
false
}
}
},
labelIds
:
{
name
:
'labelIds'
,
title
:
'咨询标签'
,
"x-component"
:
'CustomTags'
,
"x-component-props"
:
{
layoutProps
:
{
"wrapperCol"
:
12
,
},
"onChange"
:
"{{tagOnChange}}"
,
}
},
imageUrl
:
{
type
:
"object"
,
title
:
"{{label}}"
,
name
:
"imageUrl"
,
"x-component"
:
"CustomUpload"
,
"x-component-props"
:
{
size
:
'无'
,
// onChange: "{{uploadImage}}",
fileMaxSize
:
300
},
"x-rules"
:
{
"required"
:
true
,
"message"
:
"请上传图片"
},
},
digest
:
{
type
:
'string'
,
name
:
'digest'
,
title
:
'摘要'
,
"x-component"
:
'TextArea'
,
"x-component-props"
:
{
placeholder
:
"最长300个字符,150个汉字"
,
rows
:
5
,
},
"x-rules"
:
[
{
"required"
:
true
,
"message"
:
"最长300个字符,150个汉字"
},
{
limitByte
:
true
,
maxByte
:
300
}
],
},
contentLayout
:
{
'x-component'
:
'mega-layout'
,
"x-component-props"
:
{
layoutProps
:
{
"wrapperCol"
:
21
,
},
wrapperCol
:
23
,
},
properties
:
{
content
:
{
type
:
"string"
,
name
:
'content'
,
title
:
'内容'
,
"x-component"
:
'CustomEditor'
,
"x-component-parent-props"
:
{
style
:
{
border
:
'1px solid #DCDFE6'
}
},
"x-rules"
:
{
"required"
:
true
,
"message"
:
"请输入内容"
},
"x-component-props"
:
{
contentStyle
:
{
height
:
256
,
},
excludeControls
:
[
'letter-spacing'
,
'line-height'
,
'clear'
,
'headings'
,
'list-ol'
,
'list-ul'
,
'remove-styles'
,
'superscript'
,
'subscript'
,
'hr'
,
],
media
:
{
// 如果要允许上传视频的话,需要重写uploadFn, https://www.yuque.com/braft-editor/be/gz44tn
accepts
:
{
video
:
false
,
audio
:
false
,
}
}
},
}
}
}
}
}
}
}
export
default
schema
;
src/pages/content/statusList.ts
0 → 100644
View file @
a776c57b
/*
* @Author: LeeJiancong
* @Date: 2020-08-01 11:06:09
* @LastEditors: LeeJiancong
* @LastEditTime: 2020-08-01 11:07:49
*/
export
const
TimeList
=
[
{
label
:
'发布时间(全部)'
,
value
:
0
},
{
label
:
'今天'
,
value
:
1
},
{
label
:
'一周内'
,
value
:
2
},
{
label
:
'一个月内'
,
value
:
3
},
{
label
:
'三个月内'
,
value
:
4
},
{
label
:
'六个月内'
,
value
:
5
},
{
label
:
'一年内'
,
value
:
6
},
{
label
:
'一年前'
,
value
:
7
}
]
export
const
outSideStatusList
=
[
{
label
:
'外部状态(全部)'
,
value
:
''
},
{
label
:
'待提交'
,
value
:
1
},
{
label
:
'待确认'
,
value
:
2
},
{
label
:
'接受物流单'
,
value
:
3
},
{
label
:
'不接受物流单'
,
value
:
4
}
]
export
const
statusList
=
[
{
text
:
'待提交'
,
value
:
1
},
{
text
:
'待确认'
,
value
:
2
},
{
text
:
'接受物流单'
,
value
:
3
},
{
text
:
'不接受物流单'
,
value
:
4
}
]
src/pages/content/tagsManagement/index.tsx
0 → 100644
View file @
a776c57b
import
React
,
{
useState
,
useEffect
}
from
'react'
;
import
{
Card
,
Input
,
Button
,
Table
,
Space
,
Popconfirm
}
from
'antd'
;
import
{
FilterTable
,
SchemaFlexRowLayout
}
from
'../components/FilterTable'
;
import
{
createVirtualBox
,
createFormActions
,
FormEffectHooks
,
createEffectHook
}
from
'@formily/antd'
;
import
{
history
,
Link
}
from
'umi'
;
import
{
PublicApi
}
from
'@/services/api'
;
import
StatusSwitch
from
'@/components/StatusSwitch'
;
import
tagsManagementSchema
from
'./schema'
;
import
TablePagination
from
'../components/TablePagination'
;
import
{
getTableDataSource
}
from
'../utils/utils'
;
import
CustomSearch
from
'../components/CustomSearch'
;
const
{
onFieldValueChange$
}
=
FormEffectHooks
const
{
Search
}
=
Input
;
const
SchemaButton
=
createVirtualBox
(
'button'
,
Button
);
const
SchemaTable
=
createVirtualBox
(
'SchemaTable'
,
Table
);
const
actions
=
createFormActions
();
const
getData
=
async
(
params
)
=>
{
const
res
=
await
PublicApi
.
getManageContentLabelPage
(
params
)
return
res
.
data
}
const
Tags
=
()
=>
{
const
tagEffects
=
()
=>
()
=>
{
onFieldValueChange$
(
'pagination'
).
subscribe
((
state
)
=>
{
handleSearch
({...
state
.
value
})
})
}
useEffect
(()
=>
{
const
params
=
{
current
:
1
,
pageSize
:
10
}
getTableDataSource
(
actions
,
params
,
getData
);
},
[])
// 修改状态
const
handleModify
=
(
value
)
=>
{
const
{
id
,
status
}
=
value
;
const
postData
=
{
id
:
id
,
enableStatus
:
(
status
^
1
),
}
//@ts-ignore
PublicApi
.
postManageContentLabelUpdateStatus
(
postData
).
then
((
data
)
=>
{
const
paginationValue
=
actions
.
getFieldValue
(
'pagination'
);
handleSearch
({...
paginationValue
})
})
}
// 栏目删除
const
handleRemove
=
(
id
:
number
)
=>
{
///manage/contentColumn/delete
PublicApi
.
postManageContentLabelDelete
({
id
:
id
})
.
then
(
async
(
data
)
=>
{
const
paginationValue
=
actions
.
getFieldValue
(
'pagination'
);
handleSearch
({...
paginationValue
})
})
}
const
handleSearch
=
async
(
params
)
=>
{
const
title
=
actions
.
getFieldValue
(
'search'
);
const
postData
=
{
name
:
title
||
''
,
current
:
1
,
pageSize
:
10
,
...
params
,
}
getTableDataSource
(
actions
,
postData
,
getData
);
}
// 重设页码
const
resetPagination
=
(
params
)
=>
{
const
paginationValue
=
actions
.
getFieldValue
(
'pagination'
);
actions
.
setFieldValue
(
'pagination'
,
{
...
paginationValue
,
...
params
})
}
return
(
<
div
>
<
Card
>
<
FilterTable
effects=
{
tagEffects
()
}
schema=
{
tagsManagementSchema
}
components=
{
{
CustomSearch
,
TablePagination
}
}
actions=
{
actions
}
expressionScope=
{
{
goToCreate
:
()
=>
{
history
.
push
(
`/content/tagsManagement/add`
)
},
search
:
(
value
)
=>
{
resetPagination
({
current
:
1
})
handleSearch
({
title
:
value
,
current
:
1
});
},
renderOperation
:
(
val
,
record
)
=>
{
return
(
<
Space
>
{
record
.
status
===
0
?
<>
<
Link
to=
{
`/content/tagsManagement/detail?id=${record.id}`
}
>
编辑
</
Link
>
<
Popconfirm
title=
"确定要执行这个操作?"
onConfirm=
{
()
=>
handleRemove
(
record
.
id
)
}
okText=
"是"
cancelText=
"否"
>
<
a
>
删除
</
a
>
</
Popconfirm
>
</>
:
null
}
</
Space
>
)
},
renderStatus
:
(
text
,
record
)
=>
{
return
(
<
StatusSwitch
handleConfirm=
{
()
=>
handleModify
(
record
)
}
record=
{
record
}
fieldNames=
"status"
/>
)
},
reset
:
()
=>
{
actions
.
setFieldValue
(
'search'
);
resetPagination
({
current
:
1
})
handleSearch
({
current
:
1
})
},
}
}
/>
</
Card
>
</
div
>
)
}
export
default
Tags
\ No newline at end of file
src/pages/content/tagsManagement/schema/index.tsx
0 → 100644
View file @
a776c57b
import
React
from
'react'
;
import
EyePreview
from
'@/components/EyePreview'
;
const
columns
=
[
{
title
:
'ID'
,
dataIndex
:
'id'
},
{
title
:
'标签名称'
,
dataIndex
:
'name'
,
render
:
(
text
:
string
,
record
:
any
)
=>
(
<
EyePreview
url=
{
`/content/tagsManagement/detail?id=${record.id}&preview=1`
}
>
{
text
}
</
EyePreview
>
)
},
{
title
:
'标签说明'
,
dataIndex
:
'explain'
},
{
title
:
'状态'
,
dataIndex
:
'status'
,
render
:
"{{renderStatus}}"
,
width
:
120
},
{
title
:
'操作'
,
render
:
"{{renderOperation}}"
,
width
:
150
}
];
const
schema
=
{
type
:
'object'
,
properties
:
{
layout
:
{
type
:
'object'
,
// 'x-component': 'mega-layout',
'x-component'
:
'CustomFlexRowLayout'
,
'x-component-props'
:
{
justify
:
'space-between'
},
properties
:
{
createBtn
:
{
type
:
"object"
,
name
:
"createBtn"
,
"x-component"
:
"button"
,
"x-component-props"
:
{
"onClick"
:
"{{goToCreate}}"
,
"children"
:
"新建"
,
"type"
:
'primary'
}
},
'right-layout'
:
{
type
:
'object'
,
name
:
'rigth-layout'
,
"x-component"
:
'CustomFlexRowLayout'
,
"x-component-props"
:
{
justify
:
'center'
},
properties
:
{
search
:
{
type
:
'string'
,
name
:
'search'
,
'x-component'
:
'CustomSearch'
,
'x-component-props'
:
{
placeholder
:
"请填写栏目名称"
,
"onSearch"
:
"{{search}}"
,
}
},
searchBtn
:
{
type
:
'string'
,
name
:
'searchBtn'
,
"x-component"
:
"button"
,
"x-component-props"
:
{
"onClick"
:
"{{reset}}"
,
"children"
:
"重置"
,
style
:
{
marginLeft
:
'15px'
}
}
},
}
}
}
},
"table"
:
{
"key"
:
"table"
,
"type"
:
"object"
,
"name"
:
"table"
,
"x-component"
:
"SchemaTable"
,
"x-component-props"
:
{
"dataSource"
:
[],
"columns"
:
columns
,
"rowKey"
:
"id"
,
"pagination"
:
false
}
},
pagination
:
{
type
:
'object'
,
'x-component'
:
"TablePagination"
,
'x-style'
:
{
display
:
'flex'
,
flexDirection
:
'row'
,
justifyContent
:
'flex-end'
},
'x-component-props'
:
{
showQuickJumper
:
true
,
pageSize
:
10
,
size
:
'small'
}
}
}
}
export
default
schema
;
\ No newline at end of file
src/pages/content/tagsManagement/tagsInfo.tsx
0 → 100644
View file @
a776c57b
import
React
,
{
useState
,
useEffect
}
from
'react'
;
import
{
SchemaForm
,
Submit
,
FormButtonGroup
,
Reset
}
from
'@formily/antd'
;
import
{
Card
,
Select
,
Input
,
Button
}
from
'antd'
;
import
{
PageHeaderWrapper
}
from
'@ant-design/pro-layout'
;
import
ReutrnEle
from
'@/components/ReturnEle'
;
import
{
usePageStatus
}
from
'@/hooks/usePageStatus'
;
import
{
history
,
Prompt
}
from
'umi'
;
import
{
useInitialValues
}
from
'../hooks/useInitialValues'
;
import
{
PublicApi
}
from
'@/services/api'
;
import
useCustomValidator
from
'../hooks/useValidator'
const
{
TextArea
}
=
Input
;
const
schema
=
{
type
:
'object'
,
properties
:
{
layout
:
{
name
:
'layout'
,
type
:
'boject'
,
'x-component'
:
'mega-layout'
,
'x-component-props'
:
{
"labelCol"
:
3
,
"wrapperCol"
:
10
,
"labelAlign"
:
"left"
},
properties
:
{
name
:
{
name
:
'name'
,
title
:
'标签名称'
,
'x-component'
:
'Input'
,
"required"
:
true
,
"x-rules"
:
[
{
"required"
:
true
,
"message"
:
"请填写标签名称"
},
{
limitByte
:
true
,
// 自定义校验规则
maxByte
:
20
,
}
],
},
explain
:
{
name
:
'explain'
,
title
:
'标签说明'
,
'x-component'
:
'TextArea'
,
'x-component-props'
:
{
rows
:
5
},
"x-rules"
:
[
{
limitByte
:
true
,
// 自定义校验规则
maxByte
:
80
,
}
],
},
}
}
}
}
const
TagInfo
=
()
=>
{
useCustomValidator
();
const
{
id
,
preview
}
=
usePageStatus
();
const
[
submitLoading
,
setSubmitLoading
]
=
useState
(
false
);
const
initialValues
=
useInitialValues
({
id
:
id
},
PublicApi
.
getManageContentLabelGet
);
const
isEdit
=
id
&&
!
preview
;
const
isAdd
=
!
id
&&
!
preview
;
const
[
unsaved
,
setUnsaved
]
=
useState
(
true
);
const
handleSubmit
=
(
value
)
=>
{
console
.
log
(
value
)
const
{
id
,
name
,
explain
}
=
value
;
const
serviceActions
=
isAdd
?
PublicApi
.
postManageContentLabelAdd
:
PublicApi
.
postManageContentLabelUpdate
let
tempData
=
{
name
,
explain
};
const
postData
=
isAdd
?
{...
tempData
,
id
:
0
}
:
{...
tempData
,
id
};
setSubmitLoading
(
true
)
setUnsaved
(
false
);
serviceActions
(
postData
).
then
((
data
)
=>
{
setSubmitLoading
(
false
);
if
(
data
.
code
===
1000
)
{
history
.
push
(
'/content/tagsManagement'
)
}
})
}
const
handleCancel
=
()
=>
{
history
.
push
(
'/content/tagsManagement'
)
}
return
(
<
div
>
<
PageHeaderWrapper
onBack=
{
()
=>
history
.
goBack
()
}
backIcon=
{
<
ReutrnEle
description=
"返回"
/>
}
title=
{
!
id
?
'新建标签'
:
'编辑标签'
}
>
<
Card
>
<
SchemaForm
initialValues=
{
initialValues
?.
data
}
onSubmit=
{
handleSubmit
}
editable=
{
isAdd
||
isEdit
}
schema=
{
schema
}
components=
{
{
Input
,
Select
,
Submit
,
TextArea
}
}
>
{
isAdd
||
isEdit
?
(
<
FormButtonGroup
offset=
{
3
}
>
<
Submit
loading=
{
submitLoading
}
>
提交
</
Submit
>
<
Button
onClick=
{
handleCancel
}
>
取消
</
Button
>
</
FormButtonGroup
>
)
:
<></>
}
</
SchemaForm
>
</
Card
>
<
Prompt
when=
{
unsaved
}
message=
"您还有未保存的内容,是否确定要离开?"
/>
</
PageHeaderWrapper
>
</
div
>
)
}
export
default
TagInfo
\ No newline at end of file
src/pages/content/utils/utils.tsx
0 → 100644
View file @
a776c57b
const
tagColorStyle
=
{
"1"
:
{
color
:
'#606266'
,
background
:
'#F4F5F7'
},
"2"
:
{
color
:
'#00B37A'
,
background
:
'#EBF7F2'
},
"3"
:
{
color
:
'#E63F3B'
,
background
:
'#FFEBE6'
},
}
// 设置Table 状态
const
setFormStatus
=
(
ctx
,
name
:
string
,
key
:
string
,
value
:
any
)
=>
{
ctx
.
setFieldState
(
name
,
state
=>
{
// @ts-ignore
state
.
props
[
'x-component-props'
][
key
]
=
value
})
}
// 设置table DataSource
const
setTableDataSource
=
(
ctx
,
{
dataSource
,
total
})
=>
{
ctx
.
setFieldState
(
"table"
,
state
=>
{
//@ts-ignore
state
.
props
[
"x-component-props"
][
"loading"
]
=
false
;
//@ts-ignore
state
.
props
[
"x-component-props"
][
"dataSource"
]
=
dataSource
;
if
(
state
.
props
[
"x-component-props"
][
"pagination"
])
{
state
.
props
[
"x-component-props"
][
"pagination"
][
"total"
]
=
total
}
})
ctx
.
setFieldState
(
'pagination'
,
state
=>
{
//@ts-ignore
state
.
props
[
"x-component-props"
][
"total"
]
=
total
;
})
}
// 获取 table DataSource,只是把loading 跟获取数据集合在一起
const
getTableDataSource
=
async
(
ctx
,
params
,
service
)
=>
{
setFormStatus
(
ctx
,
"table"
,
"loading"
,
true
);
const
res
=
await
service
(
params
);
setTableDataSource
(
ctx
,
{
dataSource
:
res
.
data
,
total
:
res
.
totalCount
})
}
interface
IOption
{
value
:
number
|
string
,
label
:
number
|
string
}
const
sortedList
=
(
start
,
end
)
=>
{
let
res
:
IOption
[]
=
[]
for
(
let
i
=
start
;
i
<
end
;
i
++
)
{
let
data
:
IOption
=
{
label
:
i
,
value
:
i
}
res
.
push
(
data
);
}
return
res
}
// 内容管理 - 广告栏目
const
ADVERTISE_WEB_COLUMN_TYPE
=
{
"1"
:
"会员首页-活动广告1"
,
"2"
:
"会员首页-活动广告2"
,
"3"
:
"会员首页-活动广告3"
,
"4"
:
"企业采购首页--轮播广告"
,
"5"
:
"企业采购首页--顶部广告栏"
,
"6"
:
"企业门户首页--轮播广告"
,
"7"
:
"采购商机页--右侧广告栏"
,
"8"
:
"渠道服务首页--轮播广告"
,
"9"
:
"物流服务首页--轮播广告"
,
"10"
:
"加工服务首页--轮播广告"
}
const
ADVERTISE_APP_COLUMN_TYPE
=
{
"51"
:
"找店铺--广告"
,
"52"
:
"人气店铺--广告"
,
"53"
:
"商品询价--广告"
,
"54"
:
"未开通电子签章推广页--广告"
,
"55"
:
"授信申请推广页广告"
}
// 内容管理 - 公告栏目
const
ANNOUNCE_COLUMN_TYPE
=
{
'1'
:
'会员首页公告'
,
'2'
:
'注册须知'
,
'3'
:
'入库须知'
}
// 内容管理 - 图片管理 - 使用场景
const
SCENE
=
{
"1"
:
'WEB'
,
"2"
:
'APP'
}
// 内容管理 - 图片管理 - 所在位置
const
POSITION
=
{
"1"
:
"WEB登录页面"
,
"2"
:
"平台后台登录页面"
,
"3"
:
"APP引导页"
,
"4"
:
"APP启动页"
}
/**
* 将字典转换成 {label: 'xx', value: 1}
* @param maps
*/
const
transfer2Options
=
(
maps
)
=>
{
const
res
=
Object
.
keys
(
maps
).
map
((
item
)
=>
{
return
{
label
:
maps
[
item
],
value
:
parseInt
(
item
)
}
})
return
res
}
export
{
tagColorStyle
,
setFormStatus
,
setTableDataSource
,
getTableDataSource
,
sortedList
,
ADVERTISE_WEB_COLUMN_TYPE
,
ADVERTISE_APP_COLUMN_TYPE
,
// ADVERTISE_COLUMN_TYPE,
ANNOUNCE_COLUMN_TYPE
,
transfer2Options
,
SCENE
,
POSITION
}
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