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

feat(): 优化货品选择

parent 532b2680
......@@ -37,6 +37,7 @@ const PurchasInfo: React.FC<PurchasInfoPropsType> = (props) => {
const [selectCategoryData, setSelectCategoryData] = useState<any>([defaultCategoryData])
const [companyPics, setCompanyPics] = useState([]) // 厂房照片
const [honorPics, setHonorPics] = useState([]) // 资质荣誉
const [advertPics, setAdvertPics] = useState([]) // 采购门户广告图
const [slideshowBOList, setSlideshowBOList] = useState([]) // 首页轮播图
const [logo, setLogo] = useState<string>("")
const [shopInfo, setShopInfo] = useState<any>()
......@@ -106,6 +107,7 @@ const PurchasInfo: React.FC<PurchasInfoPropsType> = (props) => {
setCompanyPics(data.companyPics || [])
setHonorPics(data.honorPics || [])
setSlideshowBOList(data.slideshowBOList || [])
setAdvertPics(data.advertPics || [])
if (data.albumName && data.albumUrl) {
setFile({
albumName: data.albumName,
......@@ -119,6 +121,7 @@ const PurchasInfo: React.FC<PurchasInfoPropsType> = (props) => {
companyPics: data.companyPics || [],
honorPics: data.honorPics || [],
slideshowBOList: data.slideshowBOList || [],
advertPics: data.advertPics || []
})
}
}
......@@ -186,6 +189,15 @@ const PurchasInfo: React.FC<PurchasInfoPropsType> = (props) => {
})
}
const handleDeleteAdvertPicsItem = (itemInfo: any) => {
let result = [...advertPics]
result = result.filter(item => item !== itemInfo)
setAdvertPics(result)
form.setFieldsValue({
advertPics: result
})
}
const handleDeleteIndexPicsItem = (itemInfo: any) => {
let result = [...slideshowBOList]
result = result.filter(item => item !== itemInfo)
......@@ -294,6 +306,17 @@ const PurchasInfo: React.FC<PurchasInfoPropsType> = (props) => {
}
/**
* 采购门户广告图
* @param url
*/
const handleAddadvertPics = (url: string) => {
setAdvertPics([...advertPics, url])
form.setFieldsValue({
advertPics: [...advertPics, url]
})
}
/**
* 添加首页轮播图
* @param url
*/
......@@ -317,65 +340,7 @@ const PurchasInfo: React.FC<PurchasInfoPropsType> = (props) => {
slideshowBOList: result
})
}
/**
const handleMallSelectChange = (mallId: number) => {
setShopId(mallId)
console.log(mallId, shopInfo)
if (!shopInfo) {
return null
}
if (shopInfo.shopId && shopInfo.memberId) {
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 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
}
*/
const handleFormValueChange = () => {
setFormIsHalfFilledOut(true)
}
......@@ -512,6 +477,33 @@ const PurchasInfo: React.FC<PurchasInfoPropsType> = (props) => {
</Form.Item>
<Form.Item
labelAlign="left"
name="advertPics"
label={<RequireItem label="采购门户广告图" />}
>
<div className={styles.form_item_wrap}>
<div className={styles.img_list}>
{
advertPics.map((item, index) => (
<div key={index} className={cx(styles.upload_btn, styles.large, styles.upload)}>
<div className={styles.delete_btn} onClick={() => handleDeleteAdvertPicsItem(item)}><DeleteOutlined /></div>
<div className={styles.upload_img}>
<Image width="100%" height="100%" src={item} />
</div>
</div>
))
}
<UploadImage
imgUrl={""}
large={true}
fileMaxSize={1024}
size="106x107"
onChange={(url) => handleAddadvertPics(url)}
/>
</div>
</div>
</Form.Item>
<Form.Item
labelAlign="left"
name="albumName"
label={<RequireItem label="宣传画册" />}
className={styles.revise_style}
......
......@@ -16,6 +16,7 @@ import DrawerWrite from '../modal/drawerWrite';
import { PublicApi } from '@/services/api';
import UploadImport from '@/components/UploadImport';
import EyePreview from '@/components/EyePreview';
import AnchorModal from '../modal';
const layout: any = {
colon: false,
......@@ -220,10 +221,10 @@ const Material: React.FC<Iprops> = (props: any) => {
)}
{materielMode === 1
&& (
<DrawerWrite
<AnchorModal
preview={isPreview}
edit={edit}
flag={flag}
visible={flag}
onClose={handleClose}
onConfirm={fetchTableList}
/>
......
......@@ -568,7 +568,6 @@ const DrawerWrite: React.FC<Iprops> = (props: any) => {
}
}}
/>
</>
)
}
......
......@@ -85,3 +85,96 @@
.marginTop {
margin-top: 48px;
}
.container {
display: flex;
height: 100%;
overflow: hidden;
.menu {
width: 200px;
height: 100%;
border-right: 1px solid #F4F5F7;
.menuItem {
padding: 18px 16px;
color: #606266;
}
.active {
position: relative;
font-weight: bold;
color: #303133;
&::after {
content: '';
height: 24px;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
border-left: 3px solid @main-color;
transform: scaleY(1);
opacity: 1;
transition: transform .15s cubic-bezier(.645,.045,.355,1),opacity .15s cubic-bezier(.645,.045,.355,1);
}
}
}
.content {
width: 100%;
padding: 24px 16px;
overflow-y: scroll;
.anchor {
color: #909399;
font-size: 14px;
position: relative;
padding-left: 6px;
&::after {
content: '';
height: 14px;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
border-left: 2px solid @main-color;
transform: scaleY(1);
opacity: 1;
transition: transform .15s cubic-bezier(.645,.045,.355,1),opacity .15s cubic-bezier(.645,.045,.355,1);
}
}
.upload_item {
padding: 5px 8px;
margin-bottom: 16px;
display: flex;
align-items: center;
justify-content: space-between;
background-color: #FAFBFC;
.upload_left {
display: flex;
align-items: center;
color: #303133;
:global {
.anticon-file-word {
color: #4279df;
font-size: 20px;
margin-right: 8px;
}
}
}
.upload_right {
color: @main-color;
cursor: pointer;
:global {
.anticon-delete {
margin-left: 19px;
color: #C0C4CC;
}
}
}
}
}
}
import React, { useEffect, useState } from 'react';
import { Drawer, Form, Input, Button, Cascader, Spin, InputNumber, Typography, Upload, message } from 'antd';
import style from './index.less';
import cx from 'classnames';
import { DeleteOutlined, LinkOutlined, UploadOutlined } from '@ant-design/icons';
import UploadProps from '@/pages/transaction/common/uploadProps';
import { isEmpty } from '@formily/shared';
import { PublicApi } from '@/services/api';
import { FORM_FILTER_PATH } from '@/formSchema/const';
import { useStateFilterSearchLinkageEffect } from '@/formSchema/effects/useFilterSearch';
import TableModal from '@/pages/transaction/components/TableModal';
import { ColumnType } from 'rc-table/lib/interface';
const layout: any = {
colon: false,
labelCol: { style: { width: '110px' } },
labelAlign: "left"
};
interface AnchorModalProps {
/** 显示隐藏 */
visible?: boolean,
/** 是否查看数据 */
preview?: boolean,
/** 是否编辑数据 */
edit?: any,
/** 关闭弹窗 */
onClose: () => void,
/** 确认 */
onConfirm?: (e: any) => void,
}
const AnchorModal: React.FC<AnchorModalProps> = (props: any) => {
const [form] = Form.useForm();
const { visible, preview, edit, onClose, onConfirm } = props;
const [loading, setloading] = useState<boolean>(false);
const [searchVisible, setSearchVisible] = useState<boolean>(false)
const [isSeleted, setIsSeleted] = useState<number>(1);
const [category, setcategory] = useState([]);
const [files, setFiles] = useState([]);
const [product, setProduct] = useState<any>({});
const [menu] = useState([
{ id: 1, label: '基本信息' },
{ id: 2, label: '采购数量' },
{ id: 3, label: '附件' },
])
const handleClick = (id, anchorName) => {
setIsSeleted(id)
if (anchorName) {
let anchorElement = document.getElementById(anchorName);
if (anchorElement) {
anchorElement.scrollIntoView(
{ behavior: 'smooth' }
);
}
}
}
/**判断文件类型和大小 */
const beforeDocUpload = (file: any) => {
const isLt20M = file.size / 1024 / 1024 < 20;
if (!isLt20M) {
message.error('上传文件大小不超过 20M!');
}
return isLt20M;
}
// 上传回调
const handleChange = ({ file }) => {
const arr: any = files;
setloading(true);
if (file.response) {
if (file.response.code === 1000) {
arr.push({
name: file.name,
url: file.response.data
})
setloading(false);
}
}
setFiles([...arr])
}
// 删除附件
const removeFiles = (index: any) => {
const arr = [...files];
arr.splice(index, 1);
setFiles(arr);
}
/**查询品类树 */
const searchCategoryTree = (id: any) => {
return new Promise(resolve => {
PublicApi.getProductPlatformGetCategoryTree({ rootNodeId: id }).then(res => {
if (res.code === 1000) {
resolve(res.data)
}
})
}).then((data: any) => {
console.log(data)
setcategory(data)
})
}
useEffect(() => {
form.resetFields();
setFiles([])
searchCategoryTree(null);
if (!isEmpty(edit)) {
console.log(edit)
form.setFieldsValue({
number: edit.number,
name: edit.name,
model: edit.model,
brand: edit.brand,
unit: edit.unit,
ids: edit.ids,
purchaseCount: edit.purchaseCount,
})
setFiles(edit.urls)
}
}, [visible]);
/** 选择货品点击 */
const confirm = (selectRowKeys: string[] | number[], selectRowRecord: any) => {
const selectRow = selectRowRecord;
if (selectRow.length > 0) {
const data: any = selectRow[0]
if (data.customerCategory.category) {
const fullId = data.customerCategory.category.fullId;
const ids = fullId.replace(/\b(0+)/gi, '').split('.');
form.setFieldsValue({
ids: ids.join(',').split(','),
})
} else {
form.setFieldsValue({
ids: data.ids
})
}
form.setFieldsValue({
number: data.code,
name: data.name,
model: data.type,
brand: data.brand && data.brand.name,
unit: data.unitName,
})
setProduct(data);
setSearchVisible(false);
} else {
message.error('请选择货品!')
}
}
/** 提交表单 */
const handleSubmit = () => {
form.validateFields().then((res: any) => {
const data = {
goodsId: Object.keys(product).length > 0 && product.id,
itemNo: Object.keys(product).length > 0 ? product.code : res.number,
number: Object.keys(product).length > 0 ? product.code : res.number,
name: Object.keys(product).length > 0 ? product.name : res.name,
category: Object.keys(product).length > 0 && product.customerCategory.name,
ids: res.ids,
brand: res.brand,
model: res.model,
purchaseCount: res.purchaseCount,
unit: res.unit,
urls: files
}
onConfirm(data)
form.resetFields();
setFiles([])
}).catch(error => {
console.log(error)
})
}
/** 取消提交 */
const handleClose = () => {
form.resetFields();
setFiles([])
onClose()
}
const fetchGoodsData = (params: any) => {
return new Promise(resolve => {
PublicApi.getProductGoodsGetGoodsList(params).then(res => {
const { data } = res
resolve(data)
})
})
}
const columns: ColumnType<any>[] = [
{
title: '货号',
key: 'code',
dataIndex: 'code'
},
{
title: '货品名称',
key: 'name',
dataIndex: 'name',
},
{
title: '规格型号',
key: 'type',
dataIndex: 'type'
},
{
title: '品类',
key: 'customerCategory',
dataIndex: 'customerCategory',
render: (text: any) => <span>{(text && Object.keys(text).length > 0) && text.name}</span>
},
{
title: '品牌',
key: 'brand',
dataIndex: 'brand',
render: (text: any) => <span>{(text && Object.keys(text).length > 0) && text.name}</span>
},
{
title: '单位',
key: 'unitName',
dataIndex: 'unitName'
},
]
return (
<Drawer
title="选择货品生成"
width="45%"
visible={visible}
placement="right"
onClose={handleClose}
bodyStyle={{ padding: '0px' }}
footer={
!preview ?
<div
style={{
textAlign: 'right',
}}
>
<Button onClick={handleClose} style={{ marginRight: 8 }}>
取消
</Button>
<Button onClick={handleSubmit} type="primary">
确定
</Button>
</div> : null
}
>
<div className={style.container}>
<div className={style.menu}>
{menu.map(item => (
<div key={item.id} className={cx(style.menuItem, isSeleted === item.id && style.active)} onClick={() => handleClick(item.id, `menu${item.id}`)}>
{item.label}
</div>
))}
</div>
<div className={style.content}>
<Form
{...layout}
form={form}
>
<div id="menu1">
<div className={style.anchor}>基本信息</div>
<div className={style.formItem}>
<Form.Item
label='货号'
name='number'
rules={[{ required: true, message: '请输入货号' }]}
>
<Input.Search
readOnly
enterButton={<Button disabled={preview}><LinkOutlined /> 选择</Button>}
onSearch={() => setSearchVisible(true)}
/>
</Form.Item>
<Form.Item
label='货品名称'
name='name'
rules={[{ required: true, message: '请输入货品名称' }]}
>
<Input disabled />
</Form.Item>
<Form.Item
label='规格型号'
name='model'
rules={[{ required: true, message: '请输入规格型号' }]}
>
<Input disabled />
</Form.Item>
<Form.Item
label='品类'
name='ids'
rules={[{ required: true, message: '请选择品类' }]}
>
<Cascader
disabled
options={category}
fieldNames={{ label: 'title', value: 'id', children: 'children' }}
placeholder="请选择品类"
notFoundContent={<Spin size="small" />}
/>
</Form.Item>
<Form.Item
label='品牌'
name='brand'
>
<Input disabled={preview} />
</Form.Item>
</div>
</div>
<div id="menu2">
<div className={style.anchor}>采购数量</div>
<div className={style.formItem}>
<Form.Item
label='单位'
name='unit'
rules={[{ required: true, message: '请选择单位' }]}
>
<Input disabled />
</Form.Item>
<Form.Item
label='采购数量'
name='purchaseCount'
rules={[{ required: true, message: '请输入采购数量' }]}
>
<InputNumber disabled={preview} min={1} style={{ width: '100%' }} />
</Form.Item>
</div>
</div>
<div id="menu3">
<div className={style.anchor}>附件</div>
<div className={style.formItem}>
<Form.Item
label='附件'
name='upload'
>
<div className={style.upload_data}>
{files.length > 0 && files.map((v, index) => (
<div key={index} className={style.upload_item}>
<div className={style.upload_left}>
<Typography.Link
style={{ display: 'block' }}
key={`link_${index + 1}`}
href={`/api/contract/contractTemplate/downloadContract?contractName=${v.name}&contractUrl=${v.url}`}
target="_blank"
>
<LinkOutlined style={{ marginRight: '5px' }} />
{v.name}
</Typography.Link>
</div>
{!preview && <div className={style.upload_right} onClick={() => removeFiles(index)}>
<DeleteOutlined />
</div>}
</div>
))}
</div>
<Upload
{...UploadProps}
showUploadList={false}
accept='.doc,.docx,.pdf,.ppt,.pptx,.xls,.xlsx'
beforeUpload={beforeDocUpload}
onChange={handleChange}
>
<Button disabled={preview} loading={loading} icon={<UploadOutlined />}>上传文件</Button>
<div style={{ marginTop: '8px' }}>一次上传一个文件,每个附件大小不能超过 20M</div>
</Upload>
</Form.Item>
</div>
</div>
</Form>
</div>
</div>
{/* 选择货品 */}
<TableModal
modalType="Drawer"
visible={searchVisible}
title="选择货品"
mode="radio"
tableProps={{
rowKey: 'id',
}}
fetchData={fetchGoodsData}
onClose={() => setSearchVisible(false)}
onOk={confirm}
columns={columns}
effects={($, actions) => {
actions.reset()
useStateFilterSearchLinkageEffect($, actions, "name", FORM_FILTER_PATH)
}}
schema={{
type: 'object',
properties: {
megalayout: {
type: 'object',
"x-component": 'mega-layout',
properties: {
name: {
type: 'string',
"x-component": "Search",
"x-mega-props": {
},
"x-component-props": {
placeholder: '货品名称',
align: 'flex-left',
}
}
}
},
[FORM_FILTER_PATH]: {
type: 'object',
"x-component": "flex-layout",
"x-component-props": {
rowStyle: {
justifyContent: 'flex-start',
flexWrap: 'nowrap'
},
colStyle: {//改变间隔
marginRight: 20
}
},
properties: {
PRO_LAYOUT: {
type: 'object',
"x-component": 'mega-layout',
"x-mega-props": {
span: 5
},
"x-component-props": {
inline: true
},
properties: {
code: {
type: 'string',
"x-component-props": {
placeholder: '货号'
}
},
customerCategoryId: {
type: 'string',
"x-component": 'SearchSelect',
"x-component-props": {
placeholder: '请选择品类',
className: 'fixed-ant-selected-down', // 该类强制将显示的下拉框出现在select下, 只有这里出现问题, ??
fetchSearch: PublicApi.getProductSelectGetSelectCustomerCategory,
style: {
width: 160
}
}
},
brandId: {
type: 'string',
"x-component": 'SearchSelect',
"x-component-props": {
placeholder: '请选择品牌',
fetchSearch: PublicApi.getProductSelectGetSelectBrand,
style: {
width: 160
}
}
},
type: {
type: 'string',
"x-component-props": {
placeholder: '规格型号'
}
},
}
},
sumbit: {
"x-component": 'Submit',
"x-mega-props": {
span: 1
},
"x-component-props": {
children: '查询'
}
}
}
}
}
}}
/>
</Drawer>
)
}
export default AnchorModal;
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