Commit 3df134d9 authored by 前端-李俊鑫's avatar 前端-李俊鑫

feat: 内容能力-》资讯等国际化

parent 4a6906cb
import React from 'react'
import { Popconfirm, Button } from 'antd'
import { PlayCircleOutlined,PauseCircleOutlined } from '@ant-design/icons'
import { useIntl } from 'umi';
export interface StatusSwitchProps {
record: any,
......@@ -11,14 +12,15 @@ export interface StatusSwitchProps {
}
const StatusSwitch:React.FC<StatusSwitchProps> = (props) => {
const intl = useIntl()
const { record, fieldNames = 'status', expectTrueValue = 1 } = props
return (
<Popconfirm
title="确定要执行这个操作?"
title={intl.formatMessage({ id: 'common.tip.option.confirm' })}
onConfirm={props.handleConfirm}
onCancel={props.handleCancel}
okText="是"
cancelText="否"
okText={intl.formatMessage({ id: 'common.button.yes' })}
cancelText={intl.formatMessage({ id: 'common.button.no' })}
>
<Button
type="link"
......@@ -28,7 +30,7 @@ const StatusSwitch:React.FC<StatusSwitchProps> = (props) => {
: { color: 'red' }
}
>
{record[fieldNames] === expectTrueValue ? '有效' : '无效'}
{record[fieldNames] === expectTrueValue ? intl.formatMessage({ id: 'common.status.effective' }) : intl.formatMessage({ id: 'common.status.invalid' })}
{record[fieldNames] === expectTrueValue ? (
<PlayCircleOutlined />
) : (
......@@ -41,4 +43,4 @@ const StatusSwitch:React.FC<StatusSwitchProps> = (props) => {
StatusSwitch.defaultProps = {}
export default StatusSwitch
\ No newline at end of file
export default StatusSwitch
......@@ -68,6 +68,7 @@
'common.form.endTime.placeholder': '结束时间',
'common.form.activity.startTime.placeholder': '活动开始时间',
'common.form.activity.endTime.placeholder': '活动结束时间',
'common.form.input.placeholder': '请输入',
}
......@@ -2,6 +2,12 @@
* 内容能力
*/
export default {
'content.common.up': '上架',
'content.common.down': '下架',
'content.common.waitUp': '待上架',
'content.common.hadUp': '已上架',
'content.common.hadDown': '已下架',
'content.columns.name': '栏目名称',
'content.columns.category': '栏目分类',
'content.columns.sort': '栏目排序',
......@@ -10,5 +16,22 @@
'content.columns.add': '新建栏目',
'content.columns.edit': '编辑栏目',
'content.category.name': '分类名称',
'content.category.type': '类型',
'content.category.recommend': '推荐分类',
'content.category.selectEditProject': '选择要编辑的项目',
'content.category.noCategoryTips': '暂无分类, 开始新增',
'content.category.handleTips': '只能同时对7个一级分类下的第三级分类设置推荐分类,且每个一级分类下最多只允许设置2个推荐分类',
'content.tag.name': '标签名称',
'content.tag.explain': '标签说明',
'content.tag.add': '新建标签',
'content.tag.edit': '编辑标签',
'content.info.title': '标题',
'content.info.column': '栏目',
'content.info.category': '分类',
'content.info.time': '发布时间',
'content.info.recommendTag': '推荐标签',
'content.info.sort': '排序',
}
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 React, { useEffect, useMemo } from 'react'
import { Popconfirm, Button, Card, Tooltip } from 'antd';
import TabTree, { createTreeActions } from '@/components/TabTree';
import { createFormActions, FormButtonGroup } from '@formily/antd';
import { Checkbox } from '@formily/antd-components';
import { useIntl } from 'umi';
import { classSchema } from './schema';
import { useTreeTabs } from '@/hooks/useTreeTabs';
import NiceForm from '@/components/NiceForm';
import styles from './index.less';
import { BorderOuterOutlined, QuestionCircleOutlined } from '@ant-design/icons';
import { QuestionCircleOutlined } from '@ant-design/icons';
import { getManageMemberCategoryAll, getManageMemberCategoryGet, postManageMemberCategoryAdd, postManageMemberCategoryDelete, postManageMemberCategoryUpdate } from '@/services/ManageV2Api';
const { ON_FORM_INPUT_CHANGE } = LifeCycleTypes
enum FormState {
FREE, // 空闲状态
EDIT, // 编辑状态
......@@ -69,6 +66,7 @@ const fetchClassTreeData = async (params?) => {
const ClassProperty: React.FC<{}> = () => {
const intl = useIntl()
const {
treeStatus,
setTreeStatus,
......@@ -164,7 +162,7 @@ const ClassProperty: React.FC<{}> = () => {
<div className={styles.page}>
<div className={styles.tree}>
<Card>
<h3 className="mb-30">选择要编辑的项目</h3>
<h3 className="mb-30">{intl.formatMessage({ id: 'content.category.selectEditProject' })}</h3>
{
treeData && treeData.length > 0
? <TabTree
......@@ -176,14 +174,14 @@ const ClassProperty: React.FC<{}> = () => {
customKey="id"
/>
:
<Button block type='primary' onClick={() => handleSelect()}>暂无菜单, 开始新增</Button>
<Button block type='primary' onClick={() => handleSelect()}>{intl.formatMessage({ id: 'content.category.noCategoryTips' })}</Button>
}
</Card>
</div>
<div className={styles.editPanel}>
{
treeStatus !== FormState.FREE && <>
<h3 className="commonPanelTitle mb-30">{treeStatus === FormState.ADD ? '新增' : '编辑'}</h3>
<h3 className="commonPanelTitle mb-30">{intl.formatMessage({ id: treeStatus === FormState.ADD ? 'common.button.add' : 'common.button.edit' })}</h3>
<NiceForm
value={formValue}
components={{
......@@ -194,10 +192,10 @@ const ClassProperty: React.FC<{}> = () => {
onSubmit={onFinish}
actions={formActions}
effects={($, action)=> {}}
schema={classSchema}
schema={classSchema()}
expressionScope={{
showWarn: (
<Tooltip placement="topLeft" title={"只能同时对7个一级分类下的第三级分类设置推荐分类,且每个一级分类下最多只允许设置2个推荐分类"}>
<Tooltip placement="topLeft" title={intl.formatMessage({ id: 'content.category.handleTips' })}>
<span style={{marginTop: '-12px', width: '50px'}}>
<QuestionCircleOutlined />
</span>
......@@ -207,12 +205,17 @@ const ClassProperty: React.FC<{}> = () => {
>
<FormButtonGroup>
<Button htmlType='submit' type="primary" >
保存
{intl.formatMessage({ id: 'common.button.save' })}
</Button>
<Popconfirm title="确定要删除吗?" okText="是" cancelText="否" onConfirm={handleDeleteMenu}>
<Popconfirm
title={intl.formatMessage({ id: 'common.tip.option.confirm' })}
okText={intl.formatMessage({ id: 'common.button.yes' })}
cancelText={intl.formatMessage({ id: 'common.button.no' })}
onConfirm={handleDeleteMenu}
>
{
treeStatus !== FormState.ADD && <Button >
删除
{intl.formatMessage({ id: 'common.button.delete' })}
</Button>
}
</Popconfirm>
......
import { ISchema } from '@formily/antd';
import { useIntl } from 'umi';
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: 20
}
]
export const classSchema = (): ISchema => {
const intl = useIntl()
return {
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,
},
describe: {
type: 'textarea',
title: '类型',
"x-component-props": {
placeholder: '最多100个字符,50个汉字'
},
"x-rules": [
{
limitByte: true,
maxByte: 100
}
]
"x-mega-props": {
span: 1
},
level: {
type: 'string',
visible: false,
'x-linkages': [
{
type: 'value:visible',
target: '*(inlineLayout)',
condition: '{{$value === 3}}'
properties: {
name: {
type: 'string',
title: intl.formatMessage({ id: 'content.category.name' }),
required: true,
"x-component-props": {
placeholder: `${intl.formatMessage({ id: 'common.form.input.placeholder' })}${intl.formatMessage({ id: 'content.category.name' })}`
},
]
},
inlineLayout: {
type: 'object',
"x-component": "mega-layout",
"x-component-props": {
inline: true,
"x-rules": [
{
limitByte: true,
maxByte: 20
}
]
},
properties: {
status: {
title: '',
'x-component': 'CheckboxGroup',
enum: [
{ label: '推荐分类', value: 1 },
],
"x-mega-props": {
"addonAfter": "{{showWarn}}",
// wrapperWidth: 130
describe: {
type: 'textarea',
title: intl.formatMessage({ id: 'content.category.type' }),
"x-component-props": {
placeholder: `100${intl.formatMessage({ id: 'common.unit.individual.character' })},50${intl.formatMessage({ id: 'common.unit.individual.chinese' })}`
},
"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: intl.formatMessage({ id: 'content.category.recommend' }), value: 1 },
],
"x-mega-props": {
"addonAfter": "{{showWarn}}",
// wrapperWidth: 130
},
},
}
}
}
// status1: {
// title: '',
// 'x-component': 'Children',
// "x-component-props": {
// "children": "{{renderCheckBox()}}"
// }
// }
}
},
// status1: {
// title: '',
// 'x-component': 'Children',
// "x-component-props": {
// "children": "{{renderCheckBox()}}"
// }
// }
}
},
}
}
}
}
......
import React, { useEffect, useState, useRef } from 'react';
import React, { useRef } from 'react';
import { Card, Button, Popconfirm, Row, Col } from 'antd';
import { createFormActions, ISchema } from '@formily/antd';
import { history, useIntl } from 'umi';
......@@ -6,7 +6,6 @@ import StatusSwitch from '@/components/StatusSwitch';
import { FORM_FILTER_PATH } from '@/formSchema/const';
import { PlusOutlined } from '@ant-design/icons'
import { ColumnType } from 'antd/lib/table/interface'
import { getTableDataSource } from '../utils/utils';
import { PageHeaderWrapper } from '@ant-design/pro-layout'
import NiceForm from '@/components/NiceForm';
import EyePreview from '@/components/EyePreview'
......@@ -15,12 +14,6 @@ import { useStateFilterSearchLinkageEffect } from '@/formSchema/effects/useFilte
import { getManageMemberColumnPage, postManageMemberColumnDelete, postManageMemberColumnUpdateStatus } from '@/services/ManageV2Api';
const formActions = createFormActions();
const actions = createFormActions();
const getData = async (params) => {
const res = await getManageMemberColumnPage(params)
return res.data
}
const columnList: React.FC<{}> = () => {
......
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={`/memberCenter/contentAbility/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
import React, { useEffect, useState, useRef } from 'react';
import { FilterTable, SchemaFlexRowLayout, SchemaFlexColumnLayout } from '../components/FilterTable';
import { Card, Input, Button, Table, Dropdown, Menu, Select, Space, Modal, Popconfirm } 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 { infomationSchema } from './schema';
import TablePagination from '../components/TablePagination';
import { getTableDataSource, setFormStatus } from '../utils/utils'
import { merge } from 'rxjs';
import CustomSearch from '../components/CustomSearch';
import { useRowSelectionTable } from '@/hooks/useRowSelectionTable';
import React, { useEffect, useRef } from 'react';
import { Row, Col, Card, Button, Dropdown, Menu, Space, Modal, Popconfirm } from 'antd';
import { createFormActions } from '@formily/antd';
import { history, Link, useIntl, getIntl } from 'umi';
import { DownOutlined } from '@ant-design/icons';
import { schema } from './schema';
import { StandardTable } from 'god';
import { useStateFilterSearchLinkageEffect } from '@/formSchema/effects/useFilterSearch';
import { FORM_FILTER_PATH } from '@/formSchema/const';
import NiceForm from '@/components/NiceForm';
import EyePreview from '@/components/EyePreview';
import { ColumnType } from 'antd/lib/table/interface';
import { COLUMN_CATEGORY } from '../constant';
import moment from 'moment';
import { PageHeaderWrapper } from '@ant-design/pro-layout'
import { getManageMemberColumnAll, getManageMemberInformationPage, postManageMemberInformationBatch, postManageMemberInformationDelete, postManageMemberInformationUpdateStatus } from '@/services/ManageV2Api';
const { onFormInit$, onFieldValueChange$ } = FormEffectHooks
const actions = createFormActions();
const formActions = createFormActions();
const tagColorStyle = {
"1": {color: '#606266', background: '#F4F5F7'},
......@@ -24,277 +23,199 @@ const tagColorStyle = {
"3": {color: '#E63F3B', background: '#FFEBE6'},
}
interface optionsType {
label: string,
value: string | number
const STATUS_MAP = {
"1": getIntl().formatMessage({ id: 'content.common.waitUp' }),
"2": getIntl().formatMessage({ id: 'content.common.hadUp' }),
"3": getIntl().formatMessage({ id: 'content.common.hadDown' })
}
const getData = async (params: any) => {
const res = await getManageMemberInformationPage(params);
return res.data
}
const STATUS_LIST = ["", getIntl().formatMessage({ id: 'content.common.up' }), getIntl().formatMessage({ id: 'content.common.down' }), getIntl().formatMessage({ id: 'content.common.up' })];
const CAN_MODIFY = [1, 3];
const Infomation = () => {
const [selectedRow, setSelectedRow] = useState<any[]>([]);
const selectedRowRef = useRef<any[]>([])
const columnsOptionsRef = useRef<any[]>([])
useEffect(() => {
const params = {
current: 1,
pageSize: 10
const intl = useIntl()
const ref = useRef<any>({})
const columns: ColumnType<any>[] = [
{ title: 'ID', dataIndex: 'id' },
{
title: intl.formatMessage({ id: 'content.columns.category' }),
dataIndex: 'type',
render: (text) => COLUMN_CATEGORY[text],
},
{ title: intl.formatMessage({ id: 'content.columns.name' }), dataIndex: 'columnName' },
{
title: intl.formatMessage({ id: 'content.info.title' }),
dataIndex: 'title',
render: (text: string, record: any) => (
<EyePreview
url={`/memberCenter/contentAbility/infomations/detail?id=${record.id}&preview=1`}
>
{text}
</EyePreview>
)
},
{ title: intl.formatMessage({ id: 'content.info.category' }), dataIndex: 'categoryName' },
{ title: intl.formatMessage({ id: 'content.info.recommendTag' }), dataIndex: 'labelNames' },
{
title: intl.formatMessage({ id: 'content.info.sort' }),
dataIndex: 'sort',
sorter: (a, b) => a.sort - b.sort,
},
{
title: intl.formatMessage({ id: 'content.info.time' }),
dataIndex: 'createTime',
sorter: (a, b) => a.createTime - b.createTime,
render: (text) => (
moment(text).format('YYYY-MM-DD HH:mm:ss')
)
},
{
title: intl.formatMessage({ id: 'common.table.status' }), dataIndex: 'status',
filters: [
{ text: intl.formatMessage({ id: 'content.common.waitUp' }), value: '1' },
{ text: intl.formatMessage({ id: 'content.common.hadUp' }), value: '2' },
{ text: intl.formatMessage({ id: 'content.common.hadDown' }), value: '3' },
],
onFilter: (value, record) => {
return record.status.toString().includes(value)
},
render: (text, record) => {
return (
<span style={{...tagColorStyle[record.status], padding: '3px 5px'}}>
{STATUS_MAP[record.status]}
</span>
)
}
},
{
title: intl.formatMessage({ id: 'common.table.action' }),
render: (val, record) => {
// 只有待上架, 下架才有删除
const menu = (
<Menu>
<Menu.Item>
<Link to={`/memberCenter/contentAbility/infomations/detail?id=${record.id}`}>
{intl.formatMessage({ id: 'common.button.edit' })}
</Link>
</Menu.Item>
<Menu.Item onClick={() => handleDelete(record.id)}>
<a>
{intl.formatMessage({ id: 'common.button.delete' })}
</a>
</Menu.Item>
</Menu>
)
return (
<Space>
<Popconfirm
title={intl.formatMessage({ id: 'common.tip.option.confirm' })}
onConfirm={() => handleUpdateState(record.id, STATUS_LIST[record.status] == intl.formatMessage({ id: 'content.common.up' }) ? 2 : 3)}
okText={intl.formatMessage({ id: 'common.button.yes' })}
cancelText={intl.formatMessage({ id: 'common.button.no' })}
>
<a href="#">{STATUS_LIST[record.status]}</a>
</Popconfirm>
{
CAN_MODIFY.includes(record.status)
? <Dropdown overlay={menu}>
<a>
{intl.formatMessage({ id: 'common.text.most' })} <DownOutlined />
</a>
</Dropdown>
: null
}
</Space>
)
}
}
getTableDataSource(actions, params, getData);
}, [])
];
// 获取列表
const fetchData = (params: any) => {
return new Promise((resolve) => {
getManageMemberInformationPage(params).then(res => {
resolve(res.data)
})
})
}
useEffect(() => {
getManageMemberColumnAll().then((res) => {
const { code, data } = res
console.log(res);
if (code === 1000) {
columnsOptionsRef.current = data.map((item) => ({label: item.name, value: item.id}));
const columnsList = data.map((item) => ({label: item.name, value: item.id}));
formActions.setFieldState('columnId', state => {
state.props.enum = columnsList
});
}
});
}, [])
const infomationEffects = () => () => {
onFormInit$().subscribe(() => {
actions.setFieldState('FILTERS', state => {
state.visible = false;
})
})
merge(
onFieldValueChange$('columns'),
onFieldValueChange$('status'),
onFieldValueChange$('time')
).subscribe((state) => {
if(state.active && state.value != null) {
handleSearch({})
}
})
onFieldValueChange$('pagination').subscribe((state) => {
handleSearch({...state.value})
})
}
const handleSearch = async (params) => {
const title = actions.getFieldValue('search');
const columnId = actions.getFieldValue("columns") ; // 栏目
const status = actions.getFieldValue('status'); // 状态
const time = actions.getFieldValue('time');
const { st, et } = timeRange(time);
const postData = {
title: title,
status: status != 0 ? status : '',
columnId: columnId,
startTime: st && st,
endTime: et && et,
current: 1,
pageSize: 10,
...params,
}
getTableDataSource(actions, postData, getData);
}
// 修改状态
const handleUpdateState = (id, status) => {
// 该方法是上下架 所以 enableStatus 无用,随意传
postManageMemberInformationUpdateStatus({id: id, shelfStatus: status, enableStatus: 0})
.then((data) => {
const paginationValue = actions.getFieldValue('pagination');
handleSearch({...paginationValue})
postManageMemberInformationUpdateStatus({id: id, shelfStatus: status, enableStatus: 0}).then((res) => {
if (res.code === 1000) {
ref.current.reload()
}
});
}
// 批量删除
const batchDelete = () => {
const rows = selectedRowRef.current
handleBatch(rows, 1);
}
// type 1-批量删除 2-批量上架 3-批量下架
const handleBatch = (row, type) => {
console.log(`handleBatch type`, type)
postManageMemberInformationBatch({ids: row, type: type})
.then((data) => {
const paginationValue = actions.getFieldValue('pagination');
handleSearch({...paginationValue})
})
}
const handleDelete = (id) => {
Modal.confirm({
title: '确定要执行这个操作?',
title: intl.formatMessage({ id: 'common.tip.option.confirm' }),
onOk: () => {
postManageMemberInformationDelete({id: id})
.then((data) => {
const paginationValue = actions.getFieldValue('pagination');
handleSearch({...paginationValue})
postManageMemberInformationDelete({id: id}).then((res) => {
if (res.code === 1000) {
ref.current.reload()
}
})
}
})
}
// 重设页码
const resetPagination = (params) => {
const paginationValue = actions.getFieldValue('pagination');
actions.setFieldValue('pagination', {
...paginationValue,
...params
})
}
return (
<Card>
<FilterTable
schema={infomationSchema}
components={{
CustomSearch,
// SchemaFlexRowLayout,
// SchemaDropDown,
SchemaFlexColumnLayout,
Select,
Table,
TablePagination
}}
actions={actions}
expressionScope={{
goToCreate: () => {
history.push(`/memberCenter/contentAbility/infomations/add`)
},
reset: () => {
actions.setFieldValue('search');
actions.setFieldValue("columns") ; // 栏目
actions.setFieldValue('status'); // 状态
actions.setFieldValue('time');
resetPagination({current: 1})
handleSearch({name: null, current: 1})
},
search: (value) => {
resetPagination({current: 1})
handleSearch({name: value, current: 1 });
},
renderOperation: (val, record) => {
const status = ["", "上架", "下架", "上架"];
const CAN_MODIFY = [1, 3];
// 只有待上架, 下架才有删除
const menu = (
<Menu>
<Menu.Item>
<Link to={`/memberCenter/contentAbility/infomations/detail?id=${record.id}`}>
编辑
</Link>
</Menu.Item>
<Menu.Item onClick={() => handleDelete(record.id)}>
<a>
删除
</a>
</Menu.Item>
</Menu>
)
return (
<Space>
{/* 这里反向操作, 上架的对应的是下架, 待上架,下架对应的是上架 */}
<Popconfirm
title="确定要执行这个操作吗"
onConfirm={() => handleUpdateState(record.id, status[record.status] == '上架' ? 2 : 3)}
okText="是"
cancelText="否"
>
<a href="#">{status[record.status]}</a>
</Popconfirm>
{
CAN_MODIFY.includes(record.status)
? <Dropdown overlay={menu}>
<a>
更多 <DownOutlined />
</a>
</Dropdown>
: null
}
</Space>
)
},
const controllerBtns = <Row>
<Col span={6}>
<Button
onClick={() => history.push('/memberCenter/contentAbility/infomations/add')}
type="primary"
>
{intl.formatMessage({ id: 'common.button.add' })}
</Button>
</Col>
</Row>
batchGrounding: () => {
console.log("批量上架");
const rows = selectedRowRef.current
handleBatch(rows, 2);
},
undercarriage: () => {
console.log("批量下架")
const rows = selectedRowRef.current
handleBatch(rows, 3);
},
menu: () => {
return (
<Menu onClick={batchDelete}>
<Menu.Item key="1" icon={<DeleteOutlined />}>
批量删除
</Menu.Item>
</Menu>
);
},
renderStatus: (text, record) => {
const STATUSMAP = {
"1": "待上架",
"2": "已上架",
"3": "已下架"
}
return (
<span style={{...tagColorStyle[record.status], padding: '3px 5px'}}>
{STATUSMAP[record.status]}
</span>
)
},
// rowSelection: roleSelection,
rowSelection: {
onSelect: (record, selected, selectedRows) => {
const selectedRowsKeys = selectedRows.filter((_item) => _item).map((item) => item.id);
let keys = Array.from(new Set([...selectedRowsKeys, ...selectedRow]))
if(!selected) {
keys = keys.filter((_item) => _item !== record.id);
}
setSelectedRow(keys)
selectedRowRef.current = keys
},
onSelectAll: (selected, checkedRows, changeRows) => {
const changeRowKey = changeRows.filter((_item) => _item).map((item) => item.id);
let keys = Array.from(new Set([...changeRowKey, ...selectedRow]))
if(selected) {
setSelectedRow(keys)
selectedRowRef.current = keys
} else {
const removeKeys = keys.filter((_item) => !changeRowKey.includes(_item));
setSelectedRow(removeKeys)
selectedRowRef.current = removeKeys
}
},
selectedRowKeys: selectedRow
},
toggleFilters: () => {
actions.setFieldState('FILTERS', state => {
const visible = !state.visible;
state.visible = visible;
if(visible) {
setFormStatus(actions, 'columns', "options", columnsOptionsRef.current);
}
actions.setFieldState('HIGHT_FILTER_BTN', (state) => {
//@ts-ignore
state.props['x-component-props'].children = (
<div>高级搜索 {visible ? <UpOutlined /> : <DownOutlined /> }</div>
return (
<PageHeaderWrapper>
<Card>
<StandardTable
columns={columns}
currentRef={ref}
tableProps={{ rowKey: 'id' }}
fetchTableData={(params: any) => fetchData(params)}
controlRender={
<NiceForm
actions={formActions}
onSubmit={values => ref.current.reload(values)}
expressionScope={{
controllerBtns,
}}
effects={($, actions) => {
useStateFilterSearchLinkageEffect(
$,
actions,
'title',
FORM_FILTER_PATH,
)
})
});
},
}}
effects={infomationEffects()}
/>
</Card>
}}
schema={schema}
/>
}
/>
</Card>
</PageHeaderWrapper>
)
}
......
import EyePreview from '@/components/EyePreview';
import { DownOutlined, DeleteOutlined, UpOutlined } from '@ant-design/icons';
import { timeRange } from '@/utils/index';
import { ISchema } from '@formily/antd';
import { TimeList } from '../../statusList';
import { COLUMN_CATEGORY } from '../../constant';
import moment from 'moment';
import React from 'react';
import { getIntl } from 'umi';
import { FORM_FILTER_PATH } from '@/formSchema/const';
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={`/memberCenter/contentAbility/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': {
export const schema: ISchema = {
type: 'object',
properties: {
mageLayout: {
type: 'object',
'x-component': 'mega-layout',
properties: {
topLayout: {
type: 'object',
name: 'left-layout',
'x-component': 'CustomFlexRowLayout',
'x-component': 'mega-layout',
'x-component-props': {
justify: 'start',
align: 'center'
grid: true,
},
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: {
ctl: {
type: 'object',
name: 'batchUpdata',
'x-component': 'button',
'x-component': 'Children',
'x-component-props': {
"onClick": "{{batchGrounding}}",
"children": "批量上架",
style: {
margin: '0 0 0 15px'
}
}
children: '{{controllerBtns}}',
},
},
undercarriage: {
type: 'object',
name: 'undercarriage',
'x-component': 'button',
title: {
type: 'string',
'x-component': 'Search',
'x-component-props': {
"onClick": "{{undercarriage}}",
"children": "批量下架",
style: {
margin: '0 15px'
}
}
placeholder: getIntl().formatMessage({id: 'content.info.title'}),
},
},
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',
[FORM_FILTER_PATH]: {
type: 'object',
'x-component': 'flex-layout',
'x-component-props': {
rowStyle: {
flexWrap: 'nowrap',
},
colStyle: {
marginLeft: 20,
},
},
properties: {
columnId: {
type: 'string',
enum: [],
'x-component-props': {
justify: 'end',
placeholder: `${getIntl().formatMessage({id: 'common.text.pleaseSelect'})}${getIntl().formatMessage({id: 'content.info.column'})}`,
style: { width: '174px' },
},
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',
status: {
type: 'string',
enum: [
{ label: '全部', value: '0' },
{ label: '待上架', value: '1' },
{ label: '已上架', value: '2' },
{ label: '已下架', value: '3' },
],
'x-component-props': {
justify: 'end'
placeholder: `${getIntl().formatMessage({id: 'common.text.pleaseSelect'})}${getIntl().formatMessage({id: 'common.table.status'})}`,
style: { width: '174px' },
},
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'
},
// time: {
// type: 'string',
// enum: CustomTimeList,
// 'x-component-props': {
// placeholder: getIntl().formatMessage({id: 'content.info.time'}),
// style: { width: '174px' },
// },
// },
submit: {
'x-component': 'Submit',
'x-mega-props': {
span: 1,
},
'x-component-props': {
children: getIntl().formatMessage({id: 'common.button.submit'}),
},
},
},
},
},
'x-component-props': {
showQuickJumper: true,
pageSize: 10,
size: 'small'
}
}
}
}
export {
infomationSchema
}
},
},
};
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 React, { useRef } from 'react';
import { Card, Button, Popconfirm, Row, Col } from 'antd';
import EyePreview from '@/components/EyePreview';
import NiceForm from '@/components/NiceForm';
import { ColumnType } from 'antd/lib/table/interface'
import { FORM_FILTER_PATH } from '@/formSchema/const';
import { createFormActions } from '@formily/antd';
import { history, useIntl } from 'umi';
import StatusSwitch from '@/components/StatusSwitch';
import tagsManagementSchema from './schema';
import TablePagination from '../components/TablePagination';
import { getTableDataSource } from '../utils/utils';
import CustomSearch from '../components/CustomSearch';
import { StandardTable } from 'god';
import { useStateFilterSearchLinkageEffect } from '@/formSchema/effects/useFilterSearch';
import { getManageMemberLabelPage, postManageMemberLabelDelete, postManageMemberLabelUpdateStatus } from '@/services/ManageV2Api';
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 getManageMemberLabelPage(params)
return res.data
}
const Tags = () => {
const tagEffects = () => () => {
onFieldValueChange$('pagination').subscribe((state) => {
handleSearch({...state.value})
})
}
const intl = useIntl()
const ref = useRef<any>({})
useEffect(() => {
const params = {
current: 1,
pageSize: 10
const columns: ColumnType<any>[] = [
{title: 'ID', dataIndex: 'id'},
{
title: intl.formatMessage({ id: 'content.tag.name' }), dataIndex: 'name',
render: (text: string, record: any) => (
<EyePreview
url={`/memberCenter/contentAbility/tagsManagement/detail?id=${record.id}&preview=1`}
>
{text}
</EyePreview>
)
},
{
title: intl.formatMessage({ id: 'content.tag.explain' }),
dataIndex: 'explain'
},
{
title: intl.formatMessage({ id: 'common.table.status' }),
align: 'center',
dataIndex: 'status',
key: 'status',
render: (text: any, record: any) => (
<StatusSwitch
fieldNames="status"
handleConfirm={() => handleModify(record)}
record={record}
/>
)
},
{
title: intl.formatMessage({ id: 'common.table.action' }),
align: 'center',
key: 'operate',
dataIndex: 'operate',
render: (_, record) => !record.status && (
<>
<Button type='link' onClick={() => history.push(`/memberCenter/contentAbility/tagsManagement/detail?id=${record.id}`)}>{intl.formatMessage({ id: 'common.button.modify' })}</Button>
<Popconfirm
title={intl.formatMessage({ id: 'common.tip.option.confirm' })}
onConfirm={() => handleRemove(record.id)}
>
<Button type='link'>{intl.formatMessage({ id: 'common.button.delete' })}</Button>
</Popconfirm>
</>
)
}
getTableDataSource(actions, params, getData);
}, [])
];
const schema = {
type: 'object',
properties: {
megalayout: {
type: 'object',
"x-component": 'mega-layout',
"x-component-props": {
grid: true
},
properties: {
ctl: {
type: 'object',
"x-component": "Children",
"x-component-props": {
children: "{{controllerBtns}}"
}
},
name: {
type: 'string',
"x-component": "Search",
"x-mega-props": {
},
"x-component-props": {
placeholder: intl.formatMessage({ id: 'content.tag.name' }),
advanced: false
}
}
}
}
}
}
// 获取列表
const fetchData = (params: any) => {
return new Promise((resolve) => {
getManageMemberLabelPage(params).then(res => {
resolve(res.data)
})
})
}
// 修改状态
const handleModify = (value) => {
......@@ -44,94 +114,54 @@ const Tags = () => {
id: id,
enableStatus: (status ^ 1),
}
postManageMemberLabelUpdateStatus(postData).
then((data) => {
const paginationValue = actions.getFieldValue('pagination');
handleSearch({...paginationValue})
postManageMemberLabelUpdateStatus(postData).then((res) => {
if (res.code === 1000) {
ref.current.reload()
}
})
}
// 栏目删除
const handleRemove = (id: number) => {
///manage/contentColumn/delete
postManageMemberLabelDelete({id: id})
.then(async (data) => {
const paginationValue = actions.getFieldValue('pagination');
handleSearch({...paginationValue})
postManageMemberLabelDelete({id: id}).then((res) => {
if (res.code === 1000) {
ref.current.reload()
}
})
}
const handleSearch = async (params) => {
const title = actions.getFieldValue('search');
const postData = {
name: title || '',
current: 1,
pageSize: 10,
...params,
}
getTableDataSource(actions, postData, getData);
}
const controllerBtns = <Row>
<Col span={6}>
<Button
onClick={() => history.push('/memberCenter/contentAbility/tagsManagement/add')}
type="primary"
>
{intl.formatMessage({ id: 'common.button.add' })}
</Button>
</Col>
</Row>
// 重设页码
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(`/memberCenter/contentAbility/tagsManagement/add`)
},
search: (value) => {
resetPagination({current: 1})
handleSearch({title: value, current: 1 });
},
renderOperation: (val, record) => {
return (
<Space>
{
record.status === 0
? <>
<Link to={`/memberCenter/contentAbility/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})
},
}}
<StandardTable
tableProps={{ rowKey: 'id' }}
columns={columns}
currentRef={ref}
fetchTableData={(params: any) => fetchData(params)}
controlRender={
<NiceForm
actions={actions}
expressionScope={{ controllerBtns }}
onSubmit={values => ref.current.reload(values)}
effects={($, actions) => {
useStateFilterSearchLinkageEffect($, actions, 'title', FORM_FILTER_PATH)
}}
schema={schema}
>
</NiceForm>
}
/>
</Card>
</div>
......
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={`/memberCenter/contentAbility/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;
......@@ -4,70 +4,71 @@ 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 { history, Prompt, useIntl } from 'umi';
import { useInitialValues } from '../hooks/useInitialValues';
import useCustomValidator from '../hooks/useValidator'
import { getManageMemberLabelGet, postManageMemberLabelAdd, postManageMemberLabelUpdate } from '@/services/ManageV2Api';
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 intl = useIntl()
const { id, preview } = usePageStatus();
const [ submitLoading, setSubmitLoading ] = useState(false);
const initialValues = useInitialValues({id:id}, getManageMemberLabelGet);
const isEdit = id && !preview;
const isAdd = !id && !preview;
const [unsaved, setUnsaved] = useState(true);
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: intl.formatMessage({ id: 'content.tag.name' }),
'x-component': 'Input',
"required": true,
"x-rules": [
{
"required": true,
"message": `${intl.formatMessage({ id: 'common.form.input.placeholder' })}${intl.formatMessage({ id: 'content.tag.name' })}`
},
{
limitByte: true, // 自定义校验规则
maxByte: 20,
}
],
},
explain: {
name: 'explain',
title: intl.formatMessage({ id: 'content.tag.explain' }),
'x-component': 'TextArea',
'x-component-props': {
rows: 5
},
"x-rules": [
{
limitByte: true, // 自定义校验规则
maxByte: 80,
}
],
},
}
}
}
}
const handleSubmit = (value) => {
console.log(value)
const { id, name, explain} = value;
......@@ -90,12 +91,13 @@ const TagInfo = () => {
const handleCancel = () => {
history.push('/memberCenter/contentAbility/tagsManagement')
}
return (
<div>
<PageHeaderWrapper
onBack={() => history.goBack()}
backIcon={<ReutrnEle description="返回" />}
title={!id ? '新建标签' : '编辑标签'}
backIcon={<ReutrnEle description={intl.formatMessage({ id: 'common.button.back' })} />}
title={!id ? intl.formatMessage({ id: 'content.tag.add' }) : intl.formatMessage({ id: 'content.tag.edit' })}
>
<Card>
<SchemaForm
......@@ -109,15 +111,15 @@ const TagInfo = () => {
isAdd || isEdit
? (
<FormButtonGroup offset={3}>
<Submit loading={submitLoading}>提交</Submit>
<Button onClick={handleCancel}>取消</Button>
<Submit loading={submitLoading}>{intl.formatMessage({ id: 'common.button.submit' })}</Submit>
<Button onClick={handleCancel}>{intl.formatMessage({ id: 'common.button.cancel' })}</Button>
</FormButtonGroup>
)
: <></>
}
</SchemaForm>
</Card>
<Prompt when={unsaved} message="您还有未保存的内容,是否确定要离开?" />
<Prompt when={unsaved} message={intl.formatMessage({ id: 'common.tip.save.confirm' })} />
</PageHeaderWrapper>
</div>
)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment