Commit 0f2cce04 authored by 前端-李俊鑫's avatar 前端-李俊鑫

自营商城SEO设置,自营商城关于我们-初步

parent e76a0bc9
......@@ -48,6 +48,22 @@ const ownMallRoute: RouterChild = {
icon: 'smile',
component: '@/pages/ownMall/ownMallManager/ownMallSeo/add',
},
// 自营商城SEO设置-修改
{
path: '/memberCenter/ownMallAbility/ownMallManager/ownMallSeo/edit',
name: 'editOwnMallSeo',
hideInMenu: true,
icon: 'smile',
component: '@/pages/ownMall/ownMallManager/ownMallSeo/add',
},
// 自营商城SEO设置-查看
{
path: '/memberCenter/ownMallAbility/ownMallManager/ownMallSeo/view',
name: 'viewOwnMallSeo',
hideInMenu: true,
icon: 'smile',
component: '@/pages/ownMall/ownMallManager/ownMallSeo/add',
},
// 自营商城关于我们信息设置
{
path: '/memberCenter/ownMallAbility/ownMallManager/ownMallAboutUs',
......
......@@ -20,6 +20,8 @@
&:hover {
opacity: .8;
border-color: @primary-color;
color: @primary-color;
}
&.add {
......@@ -29,3 +31,19 @@
}
}
}
.add_line {
display: flex;
align-items: center;
justify-content: center;
height: 32px;
border: 1px solid #E3E4E5;
border-radius: 4px;
font-size: 12px;
color: #5C626A;
cursor: pointer;
&:hover {
color: @primary-color;
border-color: @primary-color;
}
}
\ No newline at end of file
......@@ -17,13 +17,14 @@ interface CitySelectPropsType {
onAdd: Function;
onReduce: Function;
onChange: Function;
showUnderAddBtn?: Boolean;
}
const { Option } = Select;
const CityCascader: React.FC<CitySelectPropsType> = (props) => {
const { selectData, onAdd, onReduce, onChange } = props
const { selectData, onAdd, onReduce, onChange, showUnderAddBtn = false } = props
const [provinceData, setProvinceData] = useState([])
const [cityData, setCityData] = useState({})
const [cities, setCities] = useState([])
......@@ -165,28 +166,29 @@ const CityCascader: React.FC<CitySelectPropsType> = (props) => {
)) : null}
</Select>
{
index === selectData.length - 1 && (
!showUnderAddBtn && index === selectData.length - 1 && (
<div className={cx(styles.opration_btn, styles.add)} onClick={() => handleAddNewSelect()}>
<PlusOutlined />
</div>
)
}
<div className={styles.opration_btn} onClick={() => handleReduceSelect(item.index)}>
<div className={styles.opration_btn} style={showUnderAddBtn ? { marginRight: 0 } : {}} onClick={() => handleReduceSelect(item.index)}>
<MinusOutlined />
</div>
</div>
))
}
{showUnderAddBtn && <div className={styles.add_line} onClick={() => handleAddNewSelect()}><PlusOutlined />添加</div>}
</Fragment>
)
}
const CitySelect: React.FC<CitySelectPropsType> = forwardRef((props, ref) => {
const { selectData, onAdd, onReduce, onChange } = props
const { selectData, onAdd, onReduce, onChange, showUnderAddBtn } = props
return (
<div className={styles.city_select}>
<CityCascader selectData={selectData} onAdd={onAdd} onReduce={onReduce} onChange={onChange} />
<CityCascader selectData={selectData} onAdd={onAdd} onReduce={onReduce} onChange={onChange} showUnderAddBtn={showUnderAddBtn} />
</div>
)
})
......
.tips {
color: #909399;
font-size: 12px;
}
import { useState, useImperativeHandle, forwardRef } from 'react'
import { PlusOutlined } from '@ant-design/icons'
import { Upload, message, UploadProps, Modal, Space } from 'antd'
import styles from './index.less'
export interface IProps extends Omit<UploadProps, 'onChange'> {
// maxNameLength?: number // 图片名字最大长度
maxSize?: number // 图片大小(默认单位:MB)
fileType?: string[] // 图片类型
unit?: 'MB' | 'KB' // 图片大小单位
onChange?: (imgData: string[] | string, fileList?: any[]) => void // 结果回调
tips?: string | boolean // 上传提示
disabled?: boolean // 是否禁用
imgSizeText?: string // 图片尺寸
}
export interface imgUploadRefProps {
setData: (x: string[]) => void // 设置图片数据
}
/**
* 图片上传
* @param {IProps} props
* @param ref
* * props 参数说明:
* + nameLength {number} - 图片名字最大长度, 默认 64,图片名字长度过长会导致上传失败
* + maxCount {number} - 图片数量, 默认 1
* + maxSize {number} - 图片大小, 默认 10
* + unit {'MB' | 'KB'} - 图片大小单位
* + fileType - 图片类型, 默认 ['image/jpeg', 'image/png', 'image/jpg', 'image/gif']
* + onChange - 结果回调
* + tips {string} - 提示语
* + disabled {boolean} - 是否禁用
* + imgSizeText {string} - 图片尺寸
* @returns
*/
const ZImgUpload = forwardRef((props: IProps, ref: any) => {
const {
// maxNameLength = 64, // 图片名字最大长度
maxCount = 1, // 图片数量
maxSize = 10, // 图片大小(单位:M)
imgSizeText = '???', // 图片尺寸
fileType = ['image/jpeg', 'image/png', 'image/jpg', 'image/gif'], // 图片类型
unit = 'MB',
onChange,
tips = true,
disabled = false,
...rest
} = props
const [fileList, setFileList] = useState<any[]>([])
const [showImage, setShowImage] = useState<boolean>(false)
const [previewImage, setPreviewImage] = useState<string>()
useImperativeHandle(ref, () => ({
setData(imgs: string[]) {
const newFileList = imgs.map((item, index) => {
return {
uid: `uid${index}`,
name: 'image.png',
status: 'done',
url: item,
}
})
setFileList(newFileList)
},
}))
// 图片上传限制验证
const beforeUpload = (file: any) => {
let { type, size, name } = file
// let fileNameOutcome = true
// name.length <= maxNameLength
let fileTypeOutcome = fileType.includes(type)
let fileTypeTips = fileType.map((item) => item.replace('image/', '').toLocaleUpperCase()).join('/')
let fileSizeOutcome = unit === 'MB' ? size / 1024 / 1024 <= maxSize : size / 1024 <= maxSize
// 图片名字长度校验
// if (!fileNameOutcome) {
// message.error(`图片名字过长,请控制名字长度在${maxNameLength}位以下`)
// }
// 图片类型校验
if (!fileTypeOutcome) {
message.error(`仅支持上传 ${fileTypeTips} 类型!`)
}
// 图片大小校验
if (!fileSizeOutcome) {
message.error(`上传图片不超过 ${maxSize} ${unit}!`)
}
return fileTypeOutcome && fileSizeOutcome
}
// 上传结果回调
const handleChange = ({ file, fileList }: any) => {
// 若上传受条件限制,则不做数据存储
if (!file.status) return
// upload受控模式需始终setState fileList, 保证所有状态同步到upload
setFileList(fileList)
if (file.status === 'error') {
return message.error(`文件上传失败`)
}
let imgData: string[] = []
fileList.map((item: any) => {
if (item.url || (item.response && item.response.data)) {
imgData.push(item.url || item.response.data)
}
})
onChange && onChange(maxCount === 1 ? imgData[0] : imgData, fileList)
}
// 查看图片
const handlePreview = (file: any) => {
if (file.status === 'done') {
setPreviewImage(file.url || file.response.data)
setShowImage(true)
}
}
// 上传框按钮样式
const uploadButtonElement = (
<div>
<PlusOutlined />
<div className="ant-upload-text">上传图片</div>
</div>
)
return (
<div>
<Space size={16}>
<Upload
name="file"
action="/api/file/file/upload"
listType="picture-card"
maxCount={maxCount}
fileList={fileList}
beforeUpload={beforeUpload}
onChange={handleChange}
onPreview={handlePreview}
disabled={disabled}
{...rest}
>
{fileList.length >= maxCount || disabled ? null : uploadButtonElement}
</Upload>
{
tips &&
<div className={styles.tips}>
<div>支持 {fileType.map(item => item.split('/')[1]).join('/')}</div>
<div>最大不超过 {maxSize} {unit}</div>
<div>尺寸: {imgSizeText}</div>
{typeof tips === 'string' && tips}
</div>
}
</Space>
<Modal visible={showImage} title="图片查看" footer={null} onCancel={() => setShowImage(false)}>
<img alt="example" style={{ width: '100%' }} src={previewImage} />
</Modal>
</div>
)
})
export default ZImgUpload
.tabAnchor {
margin: -16px -16px 0;
height: 48px;
.tabLink {
height: 48px;
}
:global {
.ant-anchor-wrapper {
margin-left: 0;
padding: 0 16px;
.ant-anchor {
padding-left: 0;
.ant-anchor-ink {
display: none;
}
.ant-anchor-link {
display: inline-block;
height: 48px;
line-height: 48px;
padding: 0 16px;
font-size: 14px;
color: #91959B;
}
}
}
}
}
\ No newline at end of file
import React, { useEffect, useState } from 'react';
import { Anchor } from 'antd';
import styles from './index.less';
const activeAnchorClassName = 'ant-anchor-link-active'
export type tabLink = {
id: string,
title: string
}
export interface IProps {
/** 返回按钮 */
onBack?: boolean,
/** 单号 */
no?: string | React.ReactNode,
/** 详情描述 */
detail?: string,
/** 锚点Link */
tabLink?: Array<tabLink>,
/** 审核操作按钮放这 */
effect?: React.ReactNode,
/** 页面的组件 */
components?: React.ReactNode,
/** 隐藏头部分割线 */
hideBreak?: boolean,
}
const TabAnchor: React.FC<IProps> = (props: any) => {
const {
tabLink = [],
} = props;
/** the argument */
const [targetOffset, setTargetOffset] = useState<number | undefined>(undefined);
const [currLink, setCurrLink] = useState(activeAnchorClassName)
/** the event */
const onChange = (link) => {
if (link && currLink) {
setCurrLink('')
} else if (!link && !currLink) {
setCurrLink(activeAnchorClassName)
}
}
const onClick = (e) => {
e.preventDefault();
}
useEffect(() => {
setTargetOffset(window.innerHeight / 6);
}, [])
return (
<div className={styles.tabAnchor}>
<Anchor
targetOffset={targetOffset}
onChange={onChange}
onClick={onClick}
>
{/* 头部信息 */}
<div className={styles.tabLink}>
{
tabLink.map((item) => (
<Anchor.Link
key={item.id}
href={`#${item.id}`}
title={item.title}
/>
))
}
</div>
</Anchor>
</div>
)
}
export default TabAnchor
export const PAGE_TYPE = {
1: '首页',
2: '关于我们',
3: '行情资讯'
}
export const PAGE_TYPE_OPTIONS = [
{ label: '首页', value: 1 },
{ label: '关于我们', value: 2 },
{ label: '行情资讯', value: 3 },
]
\ No newline at end of file
.container {
:global {
.ant-form-item-label > label.ant-form-item-required:not(.ant-form-item-required-mark-optional)::before {
display: none;
}
}
.mallLink {
font-size: 12px;
color: #91959B;
& > span {
color: #252D37;
}
}
}
\ No newline at end of file
import React from 'react'
import { useEffect, useState, useRef } from 'react';
import { Tabs, Form, Button, Card, Select, Input, Tooltip, Typography, Row, Col, Anchor } from 'antd';
import RequireItem from '@/components/RequireItem';
import { history, Prompt } from 'umi';
import { PublicApi } from '@/services/api';
import { QuestionCircleOutlined, SaveOutlined } from '@ant-design/icons';
import PeripheralLayout from '@/pages/transaction/components/detailLayout';
import { validatorByte } from '@/utils/regExp';
import ReutrnEle from '@/components/ReturnEle';
import { PageHeaderWrapper } from '@ant-design/pro-layout'
import { PAGE_TYPE, PAGE_TYPE_OPTIONS } from './constant'
import TabAnchor from '@/components/TabAnchor'
import CitySelect from '@/components/CitySelect'
import ImgUpload, { imgUploadRefProps } from '@/components/ImgUpload'
import UploadFiles from '@/pages/transaction/components/uploadFiles'
import styles from './index.less'
export default function index() {
return (
<div>
</div>
const layout: any = {
colon: false,
labelCol: { span: 4 },
wrapperCol: { span: 20 },
labelAlign: "left"
}
const otherLayout: any = {
labelCol: { span: 2 },
wrapperCol: { span: 22 },
}
const tabLink = [
{ id: '1', title: '基本信息' },
{ id: '2', title: '厂房照片' },
{ id: '3', title: '资质荣誉' },
{ id: '4', title: '宣传画册' },
]
const defaultCityData = { index: 0, provinceCode: 0, province: '', cityCode: 0, city: '' }
const OwnMallAboutUs = () => {
const { query: { id } } = history.location;
const workshopImgRef = useRef<imgUploadRefProps>()
const honorImgRef = useRef<imgUploadRefProps>()
const [form] = Form.useForm()
const [saveLoading, setSaveLoading] = useState<boolean>(false)
const [isFormChange, setIsFormChange] = useState<boolean>(false)
const [albumUrls, setAlbumUrls] = useState<any[]>([])
const [allMallList, setAllMallList] = useState<any[]>([])
const [selectCityData, setSelectCityData] = useState<any>([defaultCityData])
const getAlbumUrls = (data) => {
setAlbumUrls(data);
form.setFieldsValue({
"albumUrls": data
})
}
const removeAlbumUrls = (index) => {
const files = [...albumUrls];
files.splice(index, 1);
setAlbumUrls(files);
form.setFieldsValue({
"albumUrls": files
})
}
const handleAddNewCitySelect = (item: any) => {
const temp = [...selectCityData]
temp.push(item)
setSelectCityData(temp)
form.setFieldsValue({
city: temp
})
}
const handleReduceCitySelect = (index: number) => {
let temp = JSON.parse(JSON.stringify(selectCityData))
temp = temp.filter((item: any) => item.index !== index)
setSelectCityData(temp)
form.setFieldsValue({
city: temp
})
}
const handleCityChange = (data: any) => {
setSelectCityData(data)
form.setFieldsValue({
city: data
})
}
// 提交
const onSave = () => {
form.validateFields().then(values => {
console.log(`values`, values)
return
const params = {
id,
...values,
}
setSaveLoading(true)
const requestApi = id ? PublicApi.postManageActivityShopSeoUpdate : PublicApi.postManageActivityShopSeoAdd
requestApi(params).then(res => {
if (res.code === 1000) {
setIsFormChange(false)
setTimeout(() => {
history.goBack()
}, 500)
}
}).finally(() => {
setSaveLoading(false)
})
})
}
// 根据站点获取商城信息
const getAllMallList = () => {
PublicApi.getManageShopFindByDoorType({ doorType: 1 }).then(res => {
if (res.code === 1000) {
const data = res.data.map(item => {
return {
label: item.name,
value: item.id,
url: item.url,
type: item.type,
}
})
setAllMallList(data)
}
})
}
// 获取关于我们详情
const getAboutUsInfo = () => {
}
useEffect(() => {
getAllMallList()
}, [])
return (
<PageHeaderWrapper
onBack={() => history.goBack()}
backIcon={<ReutrnEle description="返回" />}
title={'自营商城'}
className={styles.container}
extra={[<Button key="1" type="primary" icon={<SaveOutlined />} onClick={onSave} loading={saveLoading}> 保存 </Button>]}
>
<TabAnchor tabLink={tabLink} />
<Form {...layout} form={form} onValuesChange={() => setIsFormChange(true)}>
<Card id='1' title='基本信息' style={{ marginBottom: 16, marginTop: 16 }}>
<Row gutter={24}>
<Col span={12}>
<Form.Item
name='introduction'
label={<RequireItem label="公司简介" isRequire={true}/>}
rules={[
{ required: true, message: "请输公司简介" },
{ validator: (r, v, c) => validatorByte(r, v, c, 400) }
]}
>
<Input.TextArea rows={1} placeholder="最长400个字符,200个汉字"/>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
name='city'
label={<RequireItem label="业务覆盖地市" isRequire={true}/>}
>
<CitySelect
selectData={selectCityData}
onAdd={handleAddNewCitySelect}
onReduce={handleReduceCitySelect}
onChange={handleCityChange}
showUnderAddBtn={true}
/>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item label='自营商城链接'>
<Form.Item name='mallLink'>
<Select allowClear options={allMallList}/>
</Form.Item>
<div className={styles.mallLink}>当前自营商城链接: <span>https://www.shushangyun.com/B2B/index.html?id=11011</span></div>
</Form.Item>
</Col>
</Row>
</Card>
<Card id='2' title='厂房照片' style={{ marginBottom: 16 }}>
<Form.Item
name='workshop'
label='厂房照片'
{...otherLayout}
>
<ImgUpload
ref={workshopImgRef}
maxCount={10}
maxSize={100}
unit='KB'
fileType={['image/jpeg', 'image/png', 'image/jpg']}
/>
</Form.Item>
</Card>
<Card id='3' title='资质荣誉' style={{ marginBottom: 16 }}>
<Form.Item
name='honor'
label='资质荣誉'
{...otherLayout}
>
<ImgUpload
ref={honorImgRef}
maxCount={10}
maxSize={1}
fileType={['image/jpeg', 'image/png', 'image/jpg']}
/>
</Form.Item>
</Card>
<Card id='4' title='宣传画册' style={{ marginBottom: 16 }}>
<Form.Item
name='albumUrls'
label='宣传画册'
{...otherLayout}
wrapperCol={{ span: 12 }}
>
<UploadFiles
accept=".pdf"
size={50}
fileList={albumUrls}
onChange={getAlbumUrls}
onRemove={removeAlbumUrls}
/>
</Form.Item>
</Card>
</Form>
<Prompt when={isFormChange} message="您还有未保存的内容,是否确定要离开?" />
</PageHeaderWrapper>
)
}
export default OwnMallAboutUs
\ No newline at end of file
......@@ -17,6 +17,10 @@
}
}
.right {
width: ~'calc(100% - 56px)';
}
.name {
margin-bottom: 8px;
font-size: 16px;
......
......@@ -77,7 +77,7 @@ const OwnMallConfigure = () => {
}
// 获取商城列表
const getMallList = (isInit: boolean) => {
const getMallList = (isInit?: boolean) => {
isInit && setLoading(true)
PublicApi.getManageActivityShopRuleList().then(res => {
if (res.code === 1000) {
......@@ -105,7 +105,8 @@ const OwnMallConfigure = () => {
return (
<Row key={item.id} className={styles.mallItem} gutter={16}>
<Col span={6}>
<Space size={16} style={{ width: '100%' }}>
<Row gutter={16}>
<Col>
{
item.isEdit ?
<Form.Item
......@@ -125,7 +126,8 @@ const OwnMallConfigure = () => {
:
<Image src={item.logoUrl} width={40} style={{ borderRadius: 4 }} />
}
<div>
</Col>
<Col className={styles.right}>
{
item.isEdit ?
<Form.Item
......@@ -146,8 +148,8 @@ const OwnMallConfigure = () => {
{MALL_ENV[item.environment]}
</div>
</Space>
</div>
</Space>
</Col>
</Row>
</Col>
<Col span={6}>
<div className={styles.title}>商城描述:</div>
......
import React from 'react'
import { useEffect, useState, useRef } from 'react';
import { Tabs, Form, Button, Card, Select, Input, Tooltip, Typography, Row, Col, Anchor } from 'antd';
import RequireItem from '@/components/RequireItem';
import { history, Prompt } from 'umi';
import { PublicApi } from '@/services/api';
import { QuestionCircleOutlined, SaveOutlined } from '@ant-design/icons';
import PeripheralLayout from '@/pages/transaction/components/detailLayout';
import { validatorByte } from '@/utils/regExp';
import ReutrnEle from '@/components/ReturnEle';
import { PageHeaderWrapper } from '@ant-design/pro-layout'
import { PAGE_TYPE, PAGE_TYPE_OPTIONS } from './constant'
import TabAnchor from '@/components/TabAnchor'
import styles from './index.less'
export default function index() {
return (
<div>
</div>
const layout: any = {
colon: false,
labelCol: { span: 5 },
wrapperCol: { span: 18 },
labelAlign: "left"
}
const tabLink = [
{ id: '1', title: '基本信息' },
{ id: '2', title: 'SEO设置' },
]
const SeoAdd = () => {
const { query: { id }, pathname } = history.location;
const isView = pathname.indexOf('view') > 0
const title = id ? isView ? '查看SEO' : '修改SEO' : '新增SEO'
const [form] = Form.useForm()
const [saveLoading, setSaveLoading] = useState<boolean>(false)
const [isFormChange, setIsFormChange] = useState<boolean>(false)
// 提交
const onSave = () => {
form.validateFields().then(values => {
const params = {
id,
name: PAGE_TYPE[values.type],
...values,
}
setSaveLoading(true)
const requestApi = id ? PublicApi.postManageActivityShopSeoUpdate : PublicApi.postManageActivityShopSeoAdd
requestApi(params).then(res => {
if (res.code === 1000) {
setIsFormChange(false)
setTimeout(() => {
history.goBack()
}, 500)
}
}).finally(() => {
setSaveLoading(false)
})
})
}
useEffect(() => {
if (id) {
PublicApi.getManageActivityShopSeoGet({ id }).then(res => {
if (res.code === 1000) {
form.setFieldsValue(res.data)
}
})
}
}, [])
return (
<PageHeaderWrapper
onBack={() => history.goBack()}
backIcon={<ReutrnEle description="返回" />}
title={title}
className={styles.container}
extra={
!isView ?
[<Button key="1" type="primary" icon={<SaveOutlined />} onClick={onSave} loading={saveLoading}> 保存 </Button>]
:
null
}
>
<TabAnchor tabLink={tabLink} />
<Form {...layout} form={form} onValuesChange={() => setIsFormChange(true)}>
<Card id='1' title='基本信息' style={{ marginBottom: 16, marginTop: 16 }}>
<Row gutter={16}>
<Col span={12}>
<Form.Item
name='type'
label={<RequireItem label="页面名称" isRequire={true} />}
rules={[{ required: true, message: "请选择页面名称" }]}
>
<Select options={PAGE_TYPE_OPTIONS} disabled={isView} />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
name='link'
label={<RequireItem label="访问链接" brief={<Tooltip placement="top" title="访问该页面的链接"><QuestionCircleOutlined /></Tooltip>} />}
>
<Input addonBefore={<Typography.Text type='secondary'>http://</Typography.Text>} disabled={isView} />
</Form.Item>
</Col>
</Row>
</Card>
<Card id='2' title='SEO设置'>
<Row gutter={16}>
<Col span={12}>
<Form.Item
name='title'
label={<RequireItem label="标题" isRequire={true} brief={<Tooltip placement="top" title="用于显示在页面title标签的内容,便于搜索引擎抓取"><QuestionCircleOutlined /></Tooltip>} />}
rules={[
{ required: true, message: "请输入标题" },
{ validator: (r, v, c) => validatorByte(r, v, c, 100) }
]}
>
<Input placeholder='最长100个字符,50个汉字' disabled={isView} />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
name='description'
label={<RequireItem label="描述" isRequire={true} brief={<Tooltip placement="top" title="用于显示在页面Description标签的内容,便于搜索引擎抓取"><QuestionCircleOutlined /></Tooltip>} />}
rules={[
{ required: true, message: "请输入描述" },
{ validator: (r, v, c) => validatorByte(r, v, c, 400) }
]}
>
<Input.TextArea rows={1} placeholder="最长400个字符,200个汉字" disabled={isView} />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
name='keywords'
label={<RequireItem label="关键字" isRequire={true} brief={<Tooltip placement="top" title="用于显示在页面Keywords标签的内容,便于搜索引擎通过关键词搜索时抓取页面,多个关键词用豆号分隔"><QuestionCircleOutlined /></Tooltip>} />}
rules={[
{ required: true, message: "请输入关键字" },
{ validator: (r, v, c) => validatorByte(r, v, c, 200) }
]}
>
<Input.TextArea rows={1} placeholder="最长200个字符,100个汉字" disabled={isView} />
</Form.Item>
</Col>
</Row>
</Card>
</Form>
<Prompt when={isFormChange} message="您还有未保存的内容,是否确定要离开?" />
</PageHeaderWrapper>
)
}
export default SeoAdd
\ No newline at end of file
export const PAGE_TYPE = {
1: '首页',
2: '关于我们',
3: '行情资讯'
}
export const PAGE_TYPE_OPTIONS = [
{ label: '首页', value: 1 },
{ label: '关于我们', value: 2 },
{ label: '行情资讯', value: 3 },
]
\ No newline at end of file
.container {
:global {
.ant-form-item-label > label.ant-form-item-required:not(.ant-form-item-required-mark-optional)::before {
display: none;
}
}
}
\ No newline at end of file
import React from 'react'
import React, { useRef } from 'react';
import { Card, Button, Popconfirm, Row, Col, message } from 'antd'
import { ISchema } from '@formily/antd';
import { createFormActions } from '@formily/antd';
import { useStateFilterSearchLinkageEffect } from '@/formSchema/effects/useFilterSearch';
import { FORM_FILTER_PATH } from '@/formSchema/const';
import { history } from 'umi'
import { StandardTable } from 'god'
import { ColumnType } from 'antd/lib/table/interface'
import EyePreview from '@/components/EyePreview'
import StatusSwitch from '@/components/StatusSwitch'
import NiceForm from '@/components/NiceForm';
import { PlusOutlined } from '@ant-design/icons'
import { PublicApi } from '@/services/api'
import { PageHeaderWrapper } from '@ant-design/pro-layout'
export default function index() {
return (
<div>
const formActions = createFormActions();
const schema: ISchema = {
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: '页面名称',
advanced: false
}
}
}
}
}
}
const controllerBtns = <Row>
<Col span={6}>
<Button
onClick={() => history.push('/memberCenter/ownMallAbility/ownMallManager/ownMallSeo/add')}
type="primary"
icon={<PlusOutlined />}
>
新建
</Button>
</Col>
</Row>
const SeoList: React.FC<{}> = () => {
const ref = useRef<any>({})
const columns: ColumnType<any>[] = [
{
title: 'ID',
dataIndex: 'id',
key: 'id',
},
{
title: '页面名称',
dataIndex: 'name',
key: 'name',
render: (text: any, record: any) => (
<EyePreview url={`/memberCenter/ownMallAbility/ownMallManager/ownMallSeo/view?id=${record.id}`}>
{text}
</EyePreview>
)
},
{
title: '访问链接',
align: 'center',
dataIndex: 'link',
key: 'link',
render: (text) => `http://${text}`
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
render: (text: any, record: any) => (
<StatusSwitch
fieldNames="status"
handleConfirm={() => handleModify(record)}
record={record}
/>
)
},
{
title: '操作',
key: 'operate',
dataIndex: 'operate',
render: (_, record) => !record.status && (
<>
<Button type='link' onClick={() => history.push(`/memberCenter/ownMallAbility/ownMallManager/ownMallSeo/edit?id=${record.id}`)}>修改</Button>
<Popconfirm
title="确定要执行这个操作?"
onConfirm={() => handleDelete(record.id)}
>
<Button type='link'>删除</Button>
</Popconfirm>
</>
)
}
]
// 停用/启用
const handleModify = async (record: any) => {
await PublicApi.postManageActivityShopSeoUpdateStatus({
id: record.id,
enableStatus: record.status === 1 ? 0 : 1
})
ref.current.reload()
}
// 删除
const handleDelete = async (id) => {
const res = await PublicApi.getManageActivityShopSeoDelete({ id })
if (res.code === 1000) {
message.success('删除成功')
ref.current.reload()
}
}
</div>
// 获取列表
const fetchData = (params: any) => {
return new Promise((resolve) => {
PublicApi.getManageActivityShopSeoPage({ ...params }).then(res => {
resolve(res.data)
})
})
}
return (
<PageHeaderWrapper>
<Card>
<StandardTable
tableProps={{ rowKey: 'id' }}
columns={columns}
currentRef={ref}
fetchTableData={(params: any) => fetchData(params)}
controlRender={
<NiceForm
actions={formActions}
expressionScope={{ controllerBtns }}
onSubmit={values => ref.current.reload(values)}
effects={($, actions) => {
useStateFilterSearchLinkageEffect($, actions, 'name', FORM_FILTER_PATH)
}}
schema={schema}
>
</NiceForm>
}
/>
</Card>
</PageHeaderWrapper>
)
}
export default SeoList
......@@ -98,7 +98,7 @@ const UploadFiles: React.FC<UploadFilesProps> = (props: any) => {
onChange={handleFilesChange}
>
<Button loading={loading} icon={<UploadOutlined />}>上传文件</Button>
<div style={{ marginTop: '8px' }}>一次上传一个文件,每个附件大小不能超过 {size}M</div>
<div style={{ marginTop: '8px', color: '#909399' }}>一次上传一个文件,每个附件大小不能超过 {size}M</div>
</Upload>
)}
</>
......
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