Commit 8c6192c7 authored by 前端-黄佳鑫's avatar 前端-黄佳鑫

feat: 新增采购门户设置

parent 7c7b3729
......@@ -42,6 +42,10 @@ const memberCenterRoute = {
redirect: '/memberCenter/handling/infoManage',
},
{
path: '/memberCenter/procurementAbility',
redirect: '/memberCenter/procurementAbility/purchasDoor/purchasInfo',
},
{
path: '/memberCenter/channelAbility',
redirect: '/memberCenter/channelAbility/infoManage',
},
......
......@@ -7,6 +7,7 @@ import { purchaseBidRoute } from './purchaseBid';
import { onlineBidRoute } from './onlineBid';
import { demandPlanRoute } from './demamdPlan';
import { purchasePlanRoute } from './purchasePlan';
import { PurchasDoorRoute } from './purchasDoor';
/**
* 采购能力路由
......@@ -16,6 +17,8 @@ const ProcurementRoute = {
name: "采购能力",
icon: "commodity",
routes: [
/** 采购门户管理 */
...PurchasDoorRoute,
/** 需求采购计划 */
...demandPlanRoute,
/** 采购需求计划 */
......
/**
* @description: 采购能力 采购门户管理
* @param {type}
* @return {type}
*/
export const PurchasDoorRoute = [
/** 采购门户管理 */
{
path: '/memberCenter/procurementAbility/purchasDoor',
name: '采购门户管理',
routes: [
{
/** 创建采购门户 */
path: '/memberCenter/procurementAbility/purchasDoor/purchasInfo',
name: '创建采购门户',
component: '@/pages/transaction/purchaseAbility/purchasDoor/purchasInfo',
},
{
/**采购门户SEO设置 */
path: '/memberCenter/procurementAbility/purchasDoor/purchasSeo',
name: '采购门户SEO设置',
component: '@/pages/transaction/purchaseAbility/purchasDoor/purchasSeo',
},
{
/**新增采购门户SEO */
path: '/memberCenter/procurementAbility/purchasDoor/purchasSeo/add',
name: '新增采购门户SEO',
component: '@/pages/transaction/purchaseAbility/purchasDoor/purchasSeo/add',
hideInMenu: true,
noMargin: true,
},
{
/**编辑采购门户SEO */
path: '/memberCenter/procurementAbility/purchasDoor/purchasSeo/edit',
name: '编辑采购门户SEO',
component: '@/pages/transaction/purchaseAbility/purchasDoor/purchasSeo/add',
hideInMenu: true,
noMargin: true,
},
{
/**采购门户SEO详情 */
path: '/memberCenter/procurementAbility/purchasDoor/purchasSeo/detail',
name: '采购门户SEO详情',
component: '@/pages/transaction/purchaseAbility/purchasDoor/purchasSeo/add',
hideInMenu: true,
noMargin: true,
}
]
}
]
import React, { useState } from 'react';
import { Form, DatePicker, Row, Col } from 'antd';
import moment from 'moment';
interface DatePickerSelectPropsType {
/** 开始时间name */
startTimeName: string,
/** 结束时间name */
endTimeName: string,
}
const DatePickerSelect: React.FC<DatePickerSelectPropsType> = (props) => {
const { startTimeName, endTimeName } = props;
const [timeList, setTimeList] = useState<Array<any>>([]);
/**
* 1. 开始时间选择: 只能选择当日的
* 2. 结束时间选择: 只能选择大于开始时间的
* 3. 结束时间先选: 大于单日
* 4. 结束时间先选然后在选开始时间: 只能选当日时间并且不能选择大于结束时间
*/
const startDisabledDate = current => {
const startTime = timeList[0] && current < timeList[0]
const endTime = timeList[1] && current > timeList[1]
return startTime || endTime || current && current < moment().startOf('day');
};
const endDisabledDate = current => {
const startTime = timeList[0] && current < timeList[0]
const endTime = timeList[1] && current >= timeList[1]
return startTime || endTime || current && current < moment().endOf('day');
};
const startTimeChange = (val) => {
let time = [...timeList]
time[0] = val
setTimeList(time)
}
const endStartTimeChange = (val) => {
let time = [...timeList]
time[1] = val
setTimeList(time)
}
return (
<Row>
<Col span={11}>
<Form.Item
name={startTimeName}
rules={[{ required: true, message: '请选择开始日期' }]}
>
<DatePicker
style={{ width: '100%' }}
placeholder='选择开始日期'
format="YYYY-MM-DD"
onChange={(val) => startTimeChange(val)}
disabledDate={startDisabledDate}
/>
</Form.Item>
</Col>
<Col span={2}>
<span style={{
display: 'flex',
textAlign: 'center',
height: '45%',
width: '100%',
alignItems: 'center',
justifyContent: 'space-evenly',
}}>~</span>
</Col>
<Col span={11}>
<Form.Item
name={endTimeName}
rules={[{ required: true, message: '请选择结束日期' }]}
>
<DatePicker
style={{ width: '100%' }}
format="YYYY-MM-DD"
placeholder='选择结束日期'
disabledDate={endDisabledDate}
onChange={(val) => endStartTimeChange(val)}
/>
</Form.Item>
</Col>
</Row>
)
}
DatePickerSelect.displayName = 'DatePicker';
export default DatePickerSelect
import React from 'react';
import { Card, Tabs, Button } from 'antd';
import React, { useRef, useState } from 'react';
import { Card, Tabs, Button, Badge, message } from 'antd';
import { history } from 'umi';
import BasicInfo from './components/basicInfo';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import ReutrnEle from '@/components/ReturnEle';
import Material from './components/material';
import moment from 'moment'
import { PublicApi } from '@/services/api';
import { isEmpty } from 'lodash';
const { TabPane } = Tabs;
const DemandPlanAddedForm = () => {
/** 基本信息 */
const [basic, setBasic] = useState<any>({});
const [material, setMaterial] = useState<any>([]);
const [badge, setbadge] = useState<any>([0, 0]);
const [loading, setLoading] = useState<boolean>(false);
const TabFormErrors = (props) => {
return (
<Badge size="small" count={props.dot} offset={[6, -5]}>
{props.children}
</Badge>
)
}
/** 拿表单数据的 */
const currentBasic = useRef<any>({});
const currentMaterial = useRef<any>({});
/**必填没填写出现角标 */
const getError = (num: number, idx: number) => {
const data = [...badge];
data[idx] = num;
setbadge(data);
if (num !== 0) {
setLoading(false);
}
}
const handleSubmit = async () => {
setLoading(true);
const basicRef = await currentBasic.current.get();
const materialRef = await currentMaterial.current.get();
if (basicRef.state && materialRef.state) {
const params = {
summary: basicRef.data.summary,
startTime: basicRef.data.startTime.format('x'),
endTime: basicRef.data.endTime.format('x'),
...materialRef.data,
}
if (isEmpty(materialRef.data)) {
message.error('请添加采购物物料')
setLoading(false);
return
}
await PublicApi.postPurchaseNeedPlanAdd({ ...params }).then(res => {
if (res.code !== 1000) {
setLoading(false);
return
}
history.goBack();
setLoading(false);
})
console.log(params)
} else {
setLoading(false);
}
}
return (
<PageHeaderWrapper
onBack={() => history.goBack()}
backIcon={<ReutrnEle description="返回" />}
extra={
<Button type="primary"> 保存</Button>
<Button loading={loading} type="primary" onClick={handleSubmit}> 保存</Button>
}
>
<Card>
<Tabs>
<TabPane tab="基本信息" key="1">
<BasicInfo />
<Tabs type='card'>
<TabPane tab={<TabFormErrors dot={badge[0]}>基本信息</TabFormErrors>} key="1" forceRender>
<BasicInfo
currentRef={currentBasic}
fetchdata={basic}
onBadge={getError}
/>
</TabPane>
<TabPane tab="采购物料" key="2">
<Material />
<TabPane tab={<TabFormErrors dot={badge[1]}>采购物料</TabFormErrors>} key="2" forceRender>
<Material
currentRef={currentMaterial}
fetchdata={material}
onBadge={getError}
/>
</TabPane>
</Tabs>
</Card>
......
import React from 'react';
import { Form, Input, DatePicker, Row, Col, Typography } from 'antd';
import React, { useEffect } from 'react';
import { Form, Input, Typography } from 'antd';
import DatePicker from '@/components/DatePicker';
import moment from 'moment';
const layout: any = {
colon: false,
......@@ -8,42 +10,50 @@ const layout: any = {
labelAlign: "left"
}
const BasicInfo = () => {
interface BasicInfoprops {
currentRef: any,
fetchdata: any,
onBadge?: Function
}
const BasicInfo: React.FC<BasicInfoprops> = (props: any) => {
const { currentRef, fetchdata, onBadge } = props;
const format = (text) => {
return <>{moment(text).format("YYYY-MM-DD HH:mm:ss")}</>
}
const [form] = Form.useForm();
useEffect(() => {
currentRef.current = {
get: () => new Promise((resolve: any) => {
form.validateFields().then(res => {
resolve({
state: true,
name: 'basic',
data: {
...res,
},
})
onBadge(0, 0)
}).catch(error => {
if (error && error.errorFields) {
onBadge(error.errorFields.length, 0)
}
})
})
}
})
return (
<Form {...layout} form={form}>
<Form.Item label="需求计划摘要" rules={[{ required: true, message: '请输入需求计划摘要' }]} name="summary">
<Input />
</Form.Item>
<Form.Item required label="需求计划周期" rules={[{ required: true, message: '请输入需求计划摘要' }]} style={{ marginBottom: 0 }}>
<Row>
<Col span={11}>
<Form.Item
name="startTime"
rules={[{ required: true }]}
>
<DatePicker style={{ width: '100%' }} placeholder='选择开始日期' />
</Form.Item>
</Col>
<Col span={2}>
<span style={{
display: 'flex',
textAlign: 'center',
height: '45%',
width: '100%',
alignItems: 'center',
justifyContent: 'space-evenly',
}}>~</span>
</Col>
<Col span={11}>
<Form.Item
name="endTime"
rules={[{ required: true }]}
>
<DatePicker style={{ width: '100%' }} placeholder='选择结束日期' />
</Form.Item>
</Col>
</Row>
<Form.Item required label="需求计划周期" style={{ marginBottom: 0 }}>
<DatePicker
startTimeName='startTime'
endTimeName='endTime'
/>
</Form.Item>
<Form.Item label="需求计划编号" name="needPlanNo">
<Typography.Text>X2020025008</Typography.Text>
......
import React, { useState } from 'react';
import { Form, Radio, Button, Table } from 'antd';
import React, { useEffect, useState } from 'react';
import { Form, Radio, Button, Table, message, Space, Typography, DatePicker, InputNumber, Popconfirm } from 'antd';
import { PlusOutlined } from '@ant-design/icons';
import { ColumnType } from 'antd/lib/table/interface';
import SelectProduct from './selectProduct';
import { isEmpty } from 'lodash';
import moment from 'moment';
const layout: any = {
colon: false,
......@@ -11,13 +13,26 @@ const layout: any = {
labelAlign: "left"
}
const Material = () => {
interface Materialprops {
currentRef: any,
fetchdata: { [key: string]: any },
onBadge?: Function
}
const Material: React.FC<Materialprops> = (props: any) => {
const { currentRef, fetchdata, onBadge } = props;
const [form] = Form.useForm();
const columns: ColumnType<Object>[] = [
{
title: '物料编号/名称',
key: 'number',
dataIndex: 'number'
dataIndex: 'number',
render: (text: any, record: any) => (
<Space direction='vertical' size={0}>
<Typography.Text>{text}</Typography.Text>
<Typography.Text type='secondary'>{record.name}</Typography.Text>
</Space>
)
},
{
title: '规格型号',
......@@ -42,35 +57,162 @@ const Material = () => {
{
title: '需求数量',
key: 'needCount',
dataIndex: 'needCount'
dataIndex: 'needCount',
render: (text: any, _rcod: any, index: number) => (
<Form.Item
style={{ marginBottom: 0 }}
name={`needCount${index}`}
rules={[
{
required: true,
message: '请正确输入需求数量',
},
{
pattern: /^\d+(\.\d{1,3})?$/,
message: '需求数量为数字格式,最长保留3位小数',
}
]}
>
<InputNumber min={1} onChange={(val) => handleNeedCount(val, index)} />
</Form.Item>
)
},
{
title: '成本价',
key: 'costPrice',
dataIndex: 'costPrice'
dataIndex: 'costPrice',
render: (text: any) => (
<Typography.Text>{`¥${text.toFixed(2)}`}</Typography.Text>
)
},
{
title: '需求金额',
key: 'needPrice',
dataIndex: 'needPrice'
dataIndex: 'needPrice',
render: (text: any) => (
<Typography.Text>{text ? `¥${text.toFixed(2)}` : `¥0`}</Typography.Text>
)
},
{
title: '到货日期',
key: 'arriveTime',
dataIndex: 'arriveTime'
dataIndex: 'arriveTime',
render: (text: any, _rcod: any, index: number) => (
<Form.Item
style={{ marginBottom: 0 }}
name={`arriveTime${index}`}
>
<DatePicker
style={{ width: '100%' }}
placeholder='选择开始日期'
format="YYYY-MM-DD"
disabledDate={disabledDate}
onChange={(val) => handleArriveTime(val, index)}
/>
</Form.Item>
)
},
{
title: '操作',
key: 'operate',
dataIndex: 'operate'
dataIndex: 'operate',
render: (_text: any, _record: any, index: number) => (
<Popconfirm
title="确定要执行这个操作?"
onConfirm={() => handleRemove(index)}
okText="是"
cancelText="否"
>
<Button type='link'>删除</Button>
</Popconfirm>
)
}
]
const [visible, setVisible] = useState<boolean>(false);
const [dataSource, setDataSource] = useState<Array<any>>([])
const disabledDate = (current) => {
// Can not select days before today and today
return current && current < moment().endOf('day');
}
const handleArriveTime = (val, index) => {
const data = [...dataSource];
data[index].arriveTime = val.format('x');
setDataSource(data)
}
const handleConfirm = (e: any) => {
console.log(e, 98)
if (isEmpty(e.selectRow)) {
message.warning('请选择货品')
return
}
setDataSource(e.selectRow.map((item: any) => {
return {
id: item.id,
number: item.code,
name: item.name,
model: item.type,
category: !isEmpty(item.customerCategory) && item.customerCategory.name,
brand: !isEmpty(item.brand) && item.brand.name,
unit: item.unitName,
needCount: null,
costPrice: item.costPrice,
needPrice: null,
arriveTime: null,
}
}))
setVisible(false)
}
const handleNeedCount = (val, index) => {
const data = [...dataSource];
data[index].needCount = val;
data[index].needPrice = (Number(val) * Number(data[index].costPrice))
setDataSource(data);
}
const handleRemove = (index: number) => {
const data = [...dataSource];
data.splice(index, 1);
message.success('删除成功')
setDataSource(data)
}
useEffect(() => {
currentRef.current = {
get: () => new Promise((resolve: any) => {
form.validateFields().then(_res => {
resolve({
state: true,
name: 'material',
data: {
details: dataSource,
},
})
onBadge(0, 1)
}).catch(error => {
if (error && error.errorFields) {
onBadge(error.errorFields.length, 1)
}
})
})
}
})
useEffect(() => {
/**编辑回显数据 */
if (!isEmpty(fetchdata)) {
const data = [...fetchdata];
setDataSource(data.map(item => {
return {
arriveTime: moment(item.arriveTime)
}
}))
}
}, [fetchdata])
return (
<Form {...layout} form={form}>
<Form.Item
......@@ -95,8 +237,9 @@ const Material = () => {
添加
</Button>
<Table
rowKey="id"
columns={columns}
dataSource={[]}
dataSource={dataSource}
/>
{/* 选择货品 */}
<SelectProduct
......
......@@ -22,9 +22,9 @@ const DemandPlanAdded = () => {
key: 'needPlanNo',
dataIndex: 'needPlanNo',
render: (text: any, record: any) => (
<Space direction='vertical'>
<Space direction='vertical' size={0}>
<EyePreview url={`/memberCenter/procurementAbility/offter/auditOffterOne/view?id=${record.id}&number=${record.quotedPriceNo}&turn=${record.turn}`}>{text}</EyePreview>
<Text type='secondary'>{record.summary}</Text>
<Text>{record.summary}</Text>
</Space>
)
}, {
......@@ -32,9 +32,9 @@ const DemandPlanAdded = () => {
key: 'startTime',
dataIndex: 'startTime',
render: (text: any, record: any) => (
<Space direction='vertical'>
<Text type='secondary'><PlayCircleOutlined />{format(text)}</Text>
<Text type='secondary'><PoweroffOutlined />{format(record.endTime)}</Text>
<Space direction='vertical' size={0}>
<Text><PlayCircleOutlined style={{ marginRight: 5 }} />{format(text)}</Text>
<Text><PoweroffOutlined style={{ marginRight: 5 }} />{format(record.endTime)}</Text>
</Space>
)
}, {
......@@ -49,7 +49,7 @@ const DemandPlanAdded = () => {
title: '编制时间',
key: 'createTime',
dataIndex: 'createTime',
render: (text: any, record: any) => <Text type='secondary'>{format(text)}</Text>
render: (text: any, record: any) => format(text)
}, {
title: '内部状态',
key: 'innerStatus',
......@@ -76,12 +76,12 @@ const DemandPlanAdded = () => {
schemaType="DEMANDPLANADDED_SECHEMA"
columns={columns}
effects="needPlanNo"
fetch={PublicApi.getPurchaseNeedPlanList}
fetch={PublicApi.getPurchaseNeedPlanToBeAddList}
controllerBtns={
<Row>
<Col span={6}>
<Button
onClick={() => history.push('/memberCenter/procurementAbility/purchaseInquiry/add')}
onClick={() => history.push('/memberCenter/procurementAbility/demandPlan/demandPlanAdded/add')}
type="primary"
icon={<PlusOutlined />}
>
......
......@@ -76,7 +76,7 @@ const DemandPlanOne = () => {
schemaType="DEMANDPLAN_SECHEMA"
columns={columns}
effects="needPlanNo"
fetch={PublicApi.getPurchaseNeedPlanList}
fetch={PublicApi.getPurchaseNeedPlanToBeFirstExamList}
/>
)
}
......
......@@ -62,7 +62,7 @@ const DemandPlanSearch = () => {
schemaType="DEMANDPLANSERCH_SECHEMA"
columns={columns}
effects="needPlanNo"
fetch={PublicApi.getPurchaseNeedPlanList}
fetch={PublicApi.getPurchaseNeedPlanAllList}
/>
)
}
......
......@@ -76,7 +76,7 @@ const DemandPlanSubmit = () => {
schemaType="DEMANDPLAN_SECHEMA"
columns={columns}
effects="needPlanNo"
fetch={PublicApi.getPurchaseNeedPlanList}
fetch={PublicApi.getPurchaseNeedPlanToBeSubmitList}
/>
)
}
......
......@@ -76,7 +76,7 @@ const DemanPlanTwo = () => {
schemaType="DEMANDPLAN_SECHEMA"
columns={columns}
effects="needPlanNo"
fetch={PublicApi.getPurchaseNeedPlanList}
fetch={PublicApi.getPurchaseNeedPlanToBeSecondExamList}
/>
)
}
......
.handling_info {
background-color: #ffffff;
padding: 32px 24px;
border-radius: 8px;
.add_template_form {
:global {
.ant-form-item-label>label::after {
display: none;
}
}
}
.form_item {
width: 572px;
resize: none;
}
.form_item_wrap {
display: flex;
flex-wrap: wrap;
align-items: center;
.size_require {
color: #C0C4CC;
}
}
.img_list {
display: flex;
flex-wrap: wrap;
}
.index_pics_list {
display: flex;
align-items: center;
}
.jump_link {
flex: 1;
}
.shop_url {
width: 572px;
color: #909399;
margin-top: 16px;
font-size: 12px;
display: flex;
&>label {
flex: 1;
width: 0;
display: block;
color: #303133;
margin-left: 8px;
margin-right: 15px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.copy_icon {
cursor: pointer;
}
}
.upload_btn {
position: relative;
width: 104px;
height: 104px;
display: flex;
align-items: center;
justify-content: center;
color: #909399;
flex-direction: column;
background: rgba(250, 251, 252, 1);
border-radius: 2px;
border: 1px dashed rgba(223, 225, 230, 1);
cursor: pointer;
margin-right: 24px;
overflow: hidden;
margin-bottom: 12px;
&.upload {
border: 1px solid rgba(223, 225, 230, 1);
background: #ffffff;
}
.upload_img {
height: 100%;
width: 100%;
display: block;
margin: 0 auto;
background-size: auto 100%;
background-position: center center;
background-repeat: no-repeat;
}
&>img {
width: 100%;
height: 100%;
}
&.large {
width: 175px;
height: 120px;
}
&>p {
margin-top: 12px;
}
.delete_btn {
position: absolute;
width: 24px;
height: 24px;
border-radius: 4px;
background: rgba(0, 0, 0, 0.45);
top: 8px;
right: 8px;
color: #ffffff;
text-align: center;
line-height: 24px;
&:hover {
cursor: pointer;
opacity: .8;
}
}
}
}
.revise_style {
.upload_data {
width: 575px;
.upload_item {
padding: 5px 8px;
margin-bottom: 16px;
display: flex;
align-items: center;
justify-content: space-between;
background-color: #ecf7ff;
.upload_left {
display: flex;
align-items: center;
color: #303133;
:global {
.anticon-file-word {
color: #4279df;
font-size: 20px;
margin-right: 8px;
}
}
}
.upload_right {
color: #00B37A;
cursor: pointer;
:global {
.anticon-delete {
margin-left: 19px;
color: #C0C4CC;
}
}
}
}
}
}
import React, { useState, useEffect } from 'react'
import { PageHeaderWrapper } from '@ant-design/pro-layout'
import { Form, Input, Button, Tooltip, Select, message, Upload, Typography, Tabs } from 'antd'
import { Prompt } from 'umi'
import { inject } from 'mobx-react'
import { QuestionCircleOutlined, DeleteOutlined, CopyOutlined, UploadOutlined, LinkOutlined } from '@ant-design/icons'
import CitySelect from '@/components/CitySelect'
import RequireItem from '@/components/RequireItem'
import { PublicApi } from '@/services/api'
import UploadImage from '@/components/UploadImage'
import copy from 'copy-to-clipboard'
import cx from 'classnames'
import styles from './index.less'
import { getAuth } from '@/utils/auth'
import { isEmpty } from '@formily/antd/esm/shared'
import { UPLOAD_TYPE } from '@/constants'
import CategorySelect from '@/components/CategorySelect'
import { yearProcessAmount, plantArea, staffNum } from '@/constants';
interface PurchasInfoPropsType {
SiteStore: {
siteUrl: string;
siteId: number;
}
}
const { TabPane } = Tabs;
const defaultCityData = { index: 0, provinceCode: 0, province: '', cityCode: 0, city: '' }
const defaultCategoryData = { index: 0, firstId: 0, secondId: 0, thirdlyId: 0, firstName: '', secondName: '', thirdlyName: '' }
const PurchasInfo: React.FC<PurchasInfoPropsType> = (props) => {
const { siteUrl, siteId } = props.SiteStore
const [formIsHalfFilledOut, setFormIsHalfFilledOut] = useState(false)
const [form] = Form.useForm()
const [allMallList, setAllMallList] = useState([])
const [selectCityData, setSelectCityData] = useState<any>([defaultCityData])
const [selectCategoryData, setSelectCategoryData] = useState<any>([defaultCategoryData])
const [companyPics, setCompanyPics] = useState([]) // 厂房照片
const [honorPics, setHonorPics] = useState([]) // 资质荣誉
const [slideshowBOList, setSlideshowBOList] = useState([]) // 首页轮播图
const [logo, setLogo] = useState<string>("")
const [shopInfo, setShopInfo] = useState<any>()
const [shopId, setShopId] = useState<number>()
const [confirmLoading, setConfirmLoading] = useState<boolean>(false)
/** 上传公司画册 */
const [file, setFile] = useState<any>({});
const [fileLoading, setFileLoading] = useState<boolean>(false);
const beforeDocUpload = (file: any) => {
const isLt50M = file.size / 1024 / 1024 < 50;
if (!isLt50M) {
message.error('上传文件大小不超过 50M!');
}
return isLt50M;
}
const handleChange = ({ file }) => {
setFileLoading(true);
if (file.response) {
if (file.response.code !== 1000) {
setFileLoading(false);
return
}
setFileLoading(false);
setFile({
albumName: file.name,
albumUrl: file.response.data,
})
}
}
const fileRemove = () => {
setFile({})
}
useEffect(() => {
fetchShopInfo()
fetchAllShop()
}, [])
// 根据站点获取商城信息
const fetchAllShop = () => {
const param: any = {
siteId,
type: 1
}
PublicApi.getManageShopFindShopsBySiteId(param).then(res => {
if (res.code === 1000) {
setAllMallList(res.data)
}
})
}
/**
* 获取店铺信息
*/
const fetchShopInfo = () => {
const { memberId, memberRoleId } = getAuth() || {}
const param: any = {
memberId,
roleId: memberRoleId
}
PublicApi.getTemplateWebMemberPurchaseWebFindCurrMemberPurchase().then(res => {
const data: any = res.data
if (res.code === 1000) {
if (data) {
setSelectCityData(initMemberShopArea(data.areaBOList))
setLogo(data.logo)
setCompanyPics(data.companyPics || [])
setHonorPics(data.honorPics || [])
setSlideshowBOList(data.slideshowBOList || [])
if (data.albumName && data.albumUrl) {
setFile({
albumName: data.albumName,
albumUrl: data.albumUrl
})
}
form.setFieldsValue({
describe: data.describe,
logo: data.logo,
areaBOList: initMemberShopArea(data.areaBOList),
companyPics: data.companyPics || [],
honorPics: data.honorPics || [],
slideshowBOList: data.slideshowBOList || [],
})
}
}
})
}
const initMemberShopArea = (data) => {
if (!isEmpty(data)) {
return data.map((item, index) => {
item.index = index
return item
})
} else {
return [defaultCityData]
}
}
const handleAddNewCitySelect = (item: any) => {
const temp = [...selectCityData]
temp.push(item)
setSelectCityData(temp)
form.setFieldsValue({
areaBOList: temp
})
}
const handleReduceCitySelect = (index: number) => {
let temp = JSON.parse(JSON.stringify(selectCityData))
temp = temp.filter((item: any) => item.index !== index)
setSelectCityData(temp)
form.setFieldsValue({
areaBOList: temp
})
}
const handleCityChange = (data: any) => {
setSelectCityData(data)
form.setFieldsValue({
areaBOList: data
})
}
const handleCategoryChang = (data: any) => {
setSelectCategoryData(data);
form.setFieldsValue({
categoryBOList: data
})
}
const handleDeleteWorkShopImgItem = (itemInfo: any) => {
let result = [...companyPics]
result = result.filter(item => item !== itemInfo)
setCompanyPics(result)
form.setFieldsValue({
companyPics: result
})
}
const handleDeleteHonorPicsItem = (itemInfo: any) => {
let result = [...honorPics]
result = result.filter(item => item !== itemInfo)
setHonorPics(result)
form.setFieldsValue({
honorPics: result
})
}
const handleDeleteIndexPicsItem = (itemInfo: any) => {
let result = [...slideshowBOList]
result = result.filter(item => item !== itemInfo)
setSlideshowBOList(result)
form.setFieldsValue({
slideshowBOList: result
})
}
const handleSave = (e: any) => {
e.preventDefault()
form.validateFields().then((value: any) => {
if (!checkareaBOList(value.areaBOList)) {
return
}
value.albumName = file.albumName;
value.albumUrl = file.albumUrl;
delete value.slideshowBOList
value.slideshowBOList = slideshowBOList
delete value.title
delete value.keywords
delete value.description
setConfirmLoading(true)
PublicApi.postTemplateWebMemberPurchaseWebSaveCurrMemberPurchase(value).then(res => {
if (res.code === 1000) {
fetchShopInfo()
setFormIsHalfFilledOut(false)
}
setConfirmLoading(false)
}).catch(() => {
setConfirmLoading(false)
})
})
}
const checkareaBOList = (shopAreas) => {
if (isEmpty(shopAreas)) {
message.destroy()
message.error('请选择归属地市')
return false
}
return shopAreas.every(item => {
if (isEmpty(item.provinceCode)) {
message.destroy()
message.error('请选择归属地市')
return false
} else {
return true
}
})
}
const checkcategoryBOList = (categoryBOList) => {
if (isEmpty(categoryBOList)) {
message.destroy()
message.error('请选择主要加工种类')
return false
}
return categoryBOList.every(item => {
console.log(item)
if (isEmpty(item)) {
message.destroy()
message.error('请选择主要加工种类')
return false
} else {
return true
}
})
}
const handleCopyLinke = (link: string) => {
if (copy(link)) {
message.success('复制成功!')
}
}
/**
* 添加厂房照片
* @param url
*/
const handleAddworkshopPics = (url: string) => {
setCompanyPics([...companyPics, url])
form.setFieldsValue({
companyPics: [...companyPics, url]
})
}
/**
* 添加荣誉图片
* @param url
*/
const handleAddhonorPics = (url: string) => {
setHonorPics([...honorPics, url])
form.setFieldsValue({
honorPics: [...honorPics, url]
})
}
/**
* 添加首页轮播图
* @param url
*/
const handleAddIndexPics = (url: string) => {
const params = {
imgPath: url,
link: '',
}
setSlideshowBOList([...slideshowBOList, params])
form.setFieldsValue({
slideshowBOList: [...slideshowBOList, params]
})
}
const handleInputIndexPicsItem = (e: any, index: number) => {
const { value } = e.target;
const result = [...slideshowBOList];
result[index].link = value;
console.log(result)
setSlideshowBOList(result)
form.setFieldsValue({
slideshowBOList: result
})
}
const handleMallSelectChange = (mallId: number) => {
setShopId(mallId)
if (!shopInfo) {
return null
}
if (shopInfo.shopId && shopInfo.memberId) {
const resUrl = getMallItemAndSetUrl(mallId)
}
}
const getMallItemAndSetUrl = (mallId) => {
let result = ""
const mallItem = allMallList.filter(item => item.id === mallId)[0]
if (!mallItem) {
return ""
}
if (mallItem.environment === 1) {
let newSiteUrl = siteUrl
if (newSiteUrl.indexOf('http') < 0) {
newSiteUrl = `http://` + newSiteUrl
}
switch (mallItem.type) {
case 1:
result = `${newSiteUrl}/shop?shopId=${btoa(JSON.stringify({ shopId: shopInfo.id, memberId: shopInfo.memberId, roleId: shopInfo.roleId }))}`
break
case 2:
result = `${newSiteUrl}/shop/pointsMall?shopId=${btoa(JSON.stringify({ shopId: shopInfo.id, memberId: shopInfo.memberId, roleId: shopInfo.roleId }))}`
break
default:
result = ""
break
}
} else {
result = ""
}
return result
}
const handleFormValueChange = () => {
setFormIsHalfFilledOut(true)
}
const getSelectMallStoreUrl = () => {
if (!shopInfo) {
return null
}
if (shopId && shopInfo.memberId) {
const resUrl = getMallItemAndSetUrl(shopId)
return resUrl ? (
<div className={styles.shop_url}>
<span>当前店铺链接:</span>
<label>{resUrl}</label>
<CopyOutlined className={styles.copy_icon} onClick={() => handleCopyLinke(resUrl)} />
</div>
) : null
}
return null
}
return (
<PageHeaderWrapper
extra={
<Button type="primary" loading={confirmLoading} onClick={handleSave}>保存</Button>
}
>
<Prompt when={formIsHalfFilledOut} message="您还有未保存的内容,是否确定要离开?" />
<div className={styles.handling_info}>
<Form
form={form}
className={styles.add_template_form}
hideRequiredMark={true}
onValuesChange={handleFormValueChange}
>
<Tabs
type='card'
>
<TabPane tab='基本信息' key='1' forceRender>
<Form.Item
labelAlign="left"
name="areaBOList"
label={<RequireItem label="归属地市" isRequire={true} />}
rules={[{ required: true, message: "请选择归属地市" }]}
>
<CitySelect
selectData={selectCityData}
onAdd={handleAddNewCitySelect}
onReduce={handleReduceCitySelect}
onChange={handleCityChange}
/>
</Form.Item>
<Form.Item
labelAlign="left"
name="logo"
label={<RequireItem label="公司LOGO" isRequire={true} />}
rules={[{ required: true, message: "请上传公司LOGO" }]}
>
<UploadImage
imgUrl={logo}
fileMaxSize={50}
size="275*50"
onChange={(val) => {
setLogo(val)
form.setFieldsValue({
logo: val
})
}}
/>
</Form.Item>
<Form.Item
labelAlign="left"
name="describe"
label={<RequireItem label="公司简介" isRequire={true} />}
rules={[{ required: true, message: "请输入公司简介" }]}
>
<Input.TextArea rows={5} className={styles.form_item} placeholder="请输入公司简介" maxLength={200} />
</Form.Item>
<Form.Item
labelAlign="left"
name="companyPics"
label={<RequireItem label="公司照片" />}
>
<div className={styles.form_item_wrap}>
<div className={styles.img_list}>
{
companyPics.map((item, index) => (
<div key={index} className={cx(styles.upload_btn, styles.large, styles.upload)}>
<div className={styles.delete_btn} onClick={() => handleDeleteWorkShopImgItem(item)}><DeleteOutlined /></div>
<div className={styles.upload_img} style={{ backgroundImage: `url(${item})` }} />
</div>
))
}
<UploadImage
imgUrl={""}
large={true}
fileMaxSize={1024}
size="600x400"
onChange={(url) => handleAddworkshopPics(url)}
/>
</div>
</div>
</Form.Item>
<Form.Item
labelAlign="left"
name="honorPics"
label={<RequireItem label="资质荣誉" brief={<Tooltip placement="top" title="如商标注册证书、品牌授权证书等证明材料"><QuestionCircleOutlined /></Tooltip>} />}
>
<div className={styles.form_item_wrap}>
<div className={styles.img_list}>
{
honorPics.map((item, index) => (
<div key={index} className={cx(styles.upload_btn, styles.large, styles.upload)}>
<div className={styles.delete_btn} onClick={() => handleDeleteHonorPicsItem(item)}><DeleteOutlined /></div>
<img className={styles.upload_img} src={item} />
</div>
))
}
<UploadImage
imgUrl={""}
large={true}
fileMaxSize={1024}
size="106x107"
onChange={(url) => handleAddhonorPics(url)}
/>
</div>
</div>
</Form.Item>
<Form.Item
labelAlign="left"
name="albumName"
label={<RequireItem label="宣传画册" />}
className={styles.revise_style}
>
<div className={styles.upload_data}>
{Object.keys(file).length > 0 && (
<div className={styles.upload_item}>
<div className={styles.upload_left}>
<LinkOutlined style={{ marginRight: '5px' }} />
<Typography.Link
href={`/api/contract/contractTemplate/downloadContract?contractName=${file.albumName}&contractUrl=${file.albumURL}`}
target="_blank"
>
{file.albumName}
</Typography.Link>
</div>
<div className={styles.upload_right} onClick={fileRemove}>
<DeleteOutlined />
</div>
</div>
)}
</div>
{Object.keys(file).length === 0 && (
<Upload
action="/api/file/file/upload"
data={{ fileType: UPLOAD_TYPE }}
showUploadList={false}
accept='.pdf'
beforeUpload={beforeDocUpload}
onChange={handleChange}
>
<Button loading={fileLoading} icon={<UploadOutlined />}>上传文件</Button>
<div style={{ marginTop: '8px' }}>一次上传一个文件,每个附件大小不能超过 50M</div>
</Upload>
)}
</Form.Item>
<Form.Item
labelAlign="left"
name="shopId"
label={<RequireItem label="门户链接" />}
>
<Select allowClear value={shopId} className={styles.form_item} onChange={handleMallSelectChange}>
{
allMallList.map(item => (
<Select.Option key={item.id} value={item.id}>{item.name}</Select.Option>
))
}
</Select>
{
getSelectMallStoreUrl()
}
</Form.Item>
</TabPane>
<TabPane tab='首页轮播图' key='2' forceRender>
<Form.Item
labelAlign="left"
name="slideshowBOList"
label={<RequireItem label="首页轮播图" />}
>
<div>
<div className={styles.form_item_wrap}>
{
slideshowBOList.map((item, index) => (
<div className={cx(styles.index_pics_list, styles.form_item)} >
<div key={index} className={cx(styles.upload_btn, styles.large, styles.upload)}>
<div className={styles.delete_btn} onClick={() => handleDeleteIndexPicsItem(item)}><DeleteOutlined /></div>
<img className={styles.upload_img} src={item.imgPath} />
</div>
<div className={styles.jump_link}>
<Typography.Text type='secondary'>跳转链接:</Typography.Text>
<Input addonBefore={<Typography.Text type='secondary'>http://</Typography.Text>} onChange={(value) => handleInputIndexPicsItem(value, index)} value={item.link} placeholder='轮播图跳转链接' />
</div>
</div>
))
}
</div>
<UploadImage
imgUrl={""}
large={true}
fileMaxSize={1024}
size="xxxxx"
onChange={(url) => handleAddIndexPics(url)}
/>
</div>
</Form.Item>
</TabPane>
</Tabs>
</Form>
</div>
</PageHeaderWrapper>
)
}
export default inject('SiteStore')(PurchasInfo)
import React, { useEffect, useState } from 'react';
import { history, Prompt } from 'umi';
import { Card, Button, Tabs, Form, Select, Tooltip, Input, Typography } from 'antd';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import ReutrnEle from '@/components/ReturnEle';
import RequireItem from '@/components/RequireItem';
import { QuestionCircleOutlined } from '@ant-design/icons';
import { SELECT_NAME, DOORTYPE } from '@/constants';
import { PublicApi } from '@/services/api';
const { TabPane } = Tabs
const layout: any = {
colon: false,
labelCol: { style: { width: '174px' } },
wrapperCol: { span: 9 },
labelAlign: "left"
}
const PurchasSeoAdded = () => {
const { query: { id }, pathname } = history.location;
const link = pathname.split('/')[pathname.split('/').length - 1];
console.log(link)
const [form] = Form.useForm()
const [confirmLoading, setConfirmLoading] = useState<boolean>(false);
const [formIsHalfFilledOut, setFormIsHalfFilledOut] = useState<boolean>(false);
const handleFormValueChange = () => {
setFormIsHalfFilledOut(true)
}
const handleSave = (e: any) => {
e.preventDefault()
const fetch = (link === 'add' ? PublicApi.postTemplateWebSeoWebAdd : PublicApi.postTemplateWebSeoWebUpdate);
form.validateFields().then((value: any) => {
const type: number = value.type;
const link: string = value.link;
const params = {
id,
...value,
link: `http://${link}`,
doorType: DOORTYPE.STORE_DOORTYPE,
name: SELECT_NAME[type]
}
setConfirmLoading(true)
fetch(params).then(res => {
if (res.code !== 1000) {
setConfirmLoading(false);
return
}
setConfirmLoading(false)
setFormIsHalfFilledOut(false)
history.goBack();
}).catch(() => {
setConfirmLoading(false)
})
})
}
useEffect(() => {
if (id) {
PublicApi.getTemplateWebSeoWebGet({ id }).then(res => {
if (res.code !== 1000) {
return
}
form.setFieldsValue({...res.data})
})
}
}, [])
return (
<PageHeaderWrapper
onBack={() => history.goBack()}
backIcon={<ReutrnEle description="返回" />}
extra={
link !== 'detail' && <Button type="primary" loading={confirmLoading} onClick={handleSave}> 保存</Button>
}
>
<Prompt when={formIsHalfFilledOut} message="您还有未保存的内容,是否确定要离开?" />
<Card>
<Tabs
type="card"
>
<TabPane tab='基本信息' key='1'>
<Form
{...layout}
form={form}
hideRequiredMark={true}
onValuesChange={handleFormValueChange}
>
<Form.Item
name='type'
label={<RequireItem label="页面名称" isRequire={true} />}
rules={[{ required: true, message: "请选择页面名称" }]}
>
<Select disabled={link === 'detail'}>
<Select.Option value={1}>店铺首页</Select.Option>
<Select.Option value={2}>关于我们</Select.Option>
</Select>
</Form.Item>
<Form.Item
name='link'
label={<RequireItem label="访问链接" brief={<Tooltip placement="top" title="访问该页面的链接"><QuestionCircleOutlined /></Tooltip>} />}
>
<Input disabled={link === 'detail'} addonBefore={<Typography.Text type='secondary'>http://</Typography.Text>} />
</Form.Item>
<Form.Item
name='title'
label={<RequireItem label="标题" isRequire={true} brief={<Tooltip placement="top" title="用于显示在页面title标签的内容,便于搜索引擎抓取"><QuestionCircleOutlined /></Tooltip>} />}
rules={[{ required: true, message: "请输入标题" }]}
>
<Input disabled={link === 'detail'} placeholder='最长100个字符,50个汉字' />
</Form.Item>
<Form.Item
name='description'
label={<RequireItem label="描述" isRequire={true} brief={<Tooltip placement="top" title="用于显示在页面Description标签的内容,便于搜索引擎抓取"><QuestionCircleOutlined /></Tooltip>} />}
rules={[{ required: true, message: "请输入描述" }]}
>
<Input.TextArea disabled={link === 'detail'} rows={5} placeholder="最长200个字符,100个汉字" maxLength={200} />
</Form.Item>
<Form.Item
name='keywords'
label={<RequireItem label="关键字" isRequire={true} brief={<Tooltip placement="top" title="用于显示在页面Keywords标签的内容,便于搜索引擎通过关键词搜索时抓取页面,多个关键词用豆号分隔"><QuestionCircleOutlined /></Tooltip>} />}
rules={[{ required: true, message: "请输入关键字" }]}
>
<Input.TextArea disabled={link === 'detail'} rows={5} placeholder="最长200个字符,100个汉字" maxLength={200} />
</Form.Item>
</Form>
</TabPane>
</Tabs>
</Card>
</PageHeaderWrapper>
)
}
export default PurchasSeoAdded;
import React, { ReactNode, useRef } from 'react';
import { ISchema } from '@formily/antd';
import { history } from 'umi';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import { Card, Row, Col, Button, Popconfirm, Typography } from 'antd';
import { StandardTable } from 'god';
import { ColumnType } from 'antd/lib/table/interface';
import { PublicApi } from '@/services/api';
import NiceForm from '@/components/NiceForm';
import { FORM_FILTER_PATH } from '@/formSchema/const';
import { createFormActions, FormEffectHooks } from '@formily/antd';
import { useStateFilterSearchLinkageEffect } from '@/formSchema/effects/useFilterSearch';
import { searchSelectGetSelectCategoryOptionEffect } from '@/pages/transaction/effect/index';
import { PauseCircleOutlined, PlayCircleOutlined, PlusOutlined } from '@ant-design/icons';
const PurchasSeo = () => {
const ref = useRef<any>({});
const formActions = createFormActions();
/** 修改状态 */
const confirm = (e: any) => {
const status = e.status === 1 ? 0 : 1;
PublicApi.postTemplateWebSeoWebUpdateStatus({ id: e.id, status }).then(res => {
if (res.code !== 1000) {
return
}
ref.current.reload();
})
}
/** 删除 */
const handleDelete = (id: number) => {
PublicApi.postTemplateWebSeoWebDelete({ id }).then(res => {
if (res.code !== 1000) {
return
}
ref.current.reload();
})
}
const columns: ColumnType<any>[] = [
{
title: 'ID',
key: 'id',
dataIndex: 'id',
width: 128,
},
{
title: '页面名称',
key: 'name',
dataIndex: 'name',
render: (text: any,record: any) => <Typography.Link href={`/memberCenter/procurementAbility/purchasDoor/purchasSeo/detail?id=${record.id}`}>{text}</Typography.Link>
},
{
title: '访问链接',
key: 'link',
dataIndex: 'link',
},
{
title: '状态',
key: 'status',
dataIndex: 'status',
width: 256,
render: (text: any, record: any) => {
let component: ReactNode = null
component = (
<Popconfirm
title="确定要执行这个操作?"
onConfirm={() => confirm(record)}
okText="是"
cancelText="否"
>
<Button
type="link"
style={record.status === 1 ? { color: '#00B37A' } : { color: 'red' }}>
{record.status === 1 ? <>有效 <PlayCircleOutlined /></> : <>无效 <PauseCircleOutlined /></>}
</Button>
</Popconfirm>
)
return component
}
},
{
title: '操作',
key: 'action',
dataIndex: 'action',
width: 256,
render: (_text: any, record: any) => (
<>
<Popconfirm
title="确定要执行这个操作?"
onConfirm={() => handleDelete(record.id)}
disabled={record.status === 1}
okText="是"
cancelText="否"
>
<Button disabled={record.status === 1} type='link'>删除</Button>
</Popconfirm>
<Button disabled={record.status === 1} type='link' onClick={() => history.push(`/memberCenter/procurementAbility/purchasDoor/purchasSeo/edit?id=${record.id}`)}>修改</Button>
</>
)
}
]
// 搜索
const search = (values: any) => {
ref.current.reload(values)
}
const fetchData = (params: any) => {
return new Promise(resolve => {
PublicApi.getTemplateWebSeoWebPage({ ...params, doorType: 3 }).then(res => {
resolve(res.data)
})
})
}
const controllerBtns = <Row>
<Col span={6}>
<Button
onClick={() => history.push('/memberCenter/procurementAbility/purchasDoor/purchasSeo/add')}
type="primary"
icon={<PlusOutlined />}
>
新建
</Button>
</Col>
</Row>
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
}
}
}
}
}
}
return (
<PageHeaderWrapper>
<Card>
<StandardTable
tableProps={{
rowKey: 'id',
}}
columns={columns}
currentRef={ref}
fetchTableData={(params: any) => fetchData(params)}
controlRender={
<NiceForm
actions={formActions}
expressionScope={{ controllerBtns }}
onSubmit={values => search(values)}
effects={($, actions) => {
useStateFilterSearchLinkageEffect($, actions, 'name', FORM_FILTER_PATH)
FormEffectHooks.onFieldChange$('category').subscribe(state => {
searchSelectGetSelectCategoryOptionEffect(actions, 'category')
})
}}
schema={schema}
>
</NiceForm>
}
/>
</Card>
</PageHeaderWrapper >
)
}
export default PurchasSeo;
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