@@ -131,7 +131,14 @@ export default [ | |||
path: '/database', | |||
routes: [ | |||
{ | |||
name: '商品类型', | |||
name: '商品分类', | |||
icon: 'smile', | |||
path: '/database/goods/goodsclassify', | |||
component: './database/goods/goodsclassify', | |||
access: 'k7', | |||
}, | |||
{ | |||
name: '工艺分类', | |||
icon: 'smile', | |||
path: '/database/goods/goodstypemanage', | |||
component: './database/goods/goodstypemanage', | |||
@@ -230,7 +230,7 @@ export async function getInitialState() { | |||
routes:[ | |||
{ | |||
code: 'goods-type', | |||
name: '商品类型', | |||
name: '工艺分类', | |||
icon: 'smile', | |||
path: '/database/goods/goodstypemanage', | |||
component: './database/goods/goodstypemanage', | |||
@@ -237,7 +237,7 @@ const Advanced = (props) => { | |||
<Form.Item name="id" hidden={true}> | |||
<Input /> | |||
</Form.Item> | |||
<Form.Item name="goodsTypeId" label="商品分类" rules={[{ required: true }]}> | |||
<Form.Item name="goodsTypeId" label="工艺分类" rules={[{ required: true }]}> | |||
<TreeSelect | |||
allowClear | |||
showSearch | |||
@@ -247,7 +247,7 @@ const Advanced = (props) => { | |||
onChange={onChange} | |||
filterTreeNode={filterOption} | |||
value={goodsTypeIdvalue} | |||
placeholder="请选择商品类型" | |||
placeholder="请选择工艺分类" | |||
treeDefaultExpandAll | |||
/> | |||
@@ -74,7 +74,7 @@ const headleOk=()=>{ | |||
<Input /> | |||
</Form.Item> | |||
{/* <Form.Item name="goodsTypeId" label="商品类型" rules={[{ required: true }]}> | |||
{/* <Form.Item name="goodsTypeId" label="工艺分类" rules={[{ required: true }]}> | |||
<TreeSelect | |||
allowClear | |||
showSearch | |||
@@ -84,7 +84,7 @@ const headleOk=()=>{ | |||
style={{ width: '100%' }} | |||
dropdownStyle={{ maxHeight: 400, overflow: 'auto' }} | |||
treeData={props.treeDatas} | |||
placeholder="请选择商品类型" | |||
placeholder="请选择工艺分类" | |||
treeDefaultExpandAll | |||
/> | |||
</Form.Item> */} | |||
@@ -143,7 +143,7 @@ const handleUpdate = async (fields) => { | |||
}, | |||
// { | |||
// title: '商品类型', | |||
// title: '工艺分类', | |||
// dataIndex: 'goodsTypeName', | |||
// valueType: 'treeSelect', | |||
// fieldProps: { | |||
@@ -232,7 +232,7 @@ const onresetsubmit=()=>{ | |||
<Card> | |||
<span><span style={{color:'red',marginRight: 3}}>*</span>商品属性</span> | |||
{ | |||
goodsAttriburteData==undefined || goodsAttriburteData.length ==0 ? ( <div style={{fontSize: '12px',marginLeft:10}}>当前商品分类还未配置属性点击跳转 <a | |||
goodsAttriburteData==undefined || goodsAttriburteData.length ==0 ? ( <div style={{fontSize: '12px',marginLeft:10}}>当前商品的工艺分类还未配置属性点击跳转 <a | |||
key="primary" | |||
type="primary" | |||
onClick={() => { | |||
@@ -244,7 +244,7 @@ const GoodsbomFrom = (props) => { | |||
> | |||
<span><span style={{color:'red',marginRight: 3}}>*</span>商品属性</span> | |||
{ | |||
props.goodsAttriburteData == undefined || props.goodsAttriburteData.length==0 ? ( <div style={{fontSize: '12px',marginLeft:10}}>当前商品分类还未配置属性点击跳转 <a | |||
props.goodsAttriburteData == undefined || props.goodsAttriburteData.length==0 ? ( <div style={{fontSize: '12px',marginLeft:10}}>当前商品的工艺分类还未配置属性点击跳转 <a | |||
key="primary" | |||
type="primary" | |||
onClick={() => { | |||
@@ -0,0 +1,51 @@ | |||
import React from 'react'; | |||
import { Modal, Form, Input, Button, InputNumber } from 'antd'; | |||
const CreateForm = (props) => { | |||
return ( | |||
<Modal | |||
title={props.values.id ? '编辑' : '新建'} | |||
width={640} | |||
visible={props.goodsClassifyVisible} | |||
bodyStyle={{ padding: '32px 40px 1px 48px' }} | |||
footer={null} | |||
onCancel={() => { | |||
props.onCancel(); | |||
}} | |||
maskClosable={false} | |||
destroyOnClose={true} | |||
> | |||
<Form | |||
labelCol={{ span: 4 }} | |||
layout="horizontal" | |||
preserve={false} | |||
initialValues={props.values} | |||
onFinish={props.onFinish} | |||
> | |||
<Form.Item name="id" hidden={true}> | |||
<Input /> | |||
</Form.Item> | |||
<Form.Item name="name" label="分类名称" rules={[{ required: true, max: 50 }]}> | |||
<Input /> | |||
</Form.Item> | |||
<Form.Item name="remark" label="备注" > | |||
<Input /> | |||
</Form.Item> | |||
<Form.Item name="sort" label="排序" > | |||
<InputNumber /> | |||
</Form.Item> | |||
<Form.Item> | |||
<Button htmlType="button" style={{ float: 'right', left: 10 }} onClick={props.onCancel} > | |||
取消 | |||
</Button> | |||
<Button type="primary" htmlType="submit" style={{ float: 'right' }} > | |||
保存 | |||
</Button> | |||
</Form.Item> | |||
</Form> | |||
</Modal> | |||
); | |||
}; | |||
export default CreateForm; |
@@ -0,0 +1,329 @@ | |||
import { Button, message, Popconfirm, Modal, Transfer } from 'antd'; | |||
import { PlusOutlined } from '@ant-design/icons'; | |||
import CreateForm from './components/CreateForm'; | |||
import React, { useState, useRef, useEffect } from 'react'; | |||
import { PageContainer } from '@ant-design/pro-layout'; | |||
import ProTable from '@ant-design/pro-table'; | |||
import { getGoodsClassifyPage, updateGoodsClassify, deleteGoodsClassify, getgoodslist, getRelation, setRelation } from './service'; | |||
const GoodsClassify = () => { | |||
const [goodsClassifyVisible, setGoodsClassifyVisible] = useState(false); | |||
const actionRef = useRef(); | |||
const [currentRow, setCurrentRow] = useState(); | |||
const [selectedRowsState, setSelectedRows] = useState([]); | |||
const [targetKeys, setTargetKeys] = useState([]); | |||
const [isModalOpen, setIsModalOpen] = useState(false); | |||
const [mockData, setMockData] = useState([]); | |||
const [classifyId, setClassifyId] = useState([]); | |||
useEffect(() => { | |||
getgoodslist().then((item) => { | |||
var data = item.data; | |||
const tempMockData = []; | |||
data.forEach((item) => { | |||
tempMockData.push({ | |||
key: item.id, | |||
title: item.name, | |||
description: item.name, | |||
}); | |||
}) | |||
setMockData(tempMockData); | |||
}); | |||
}, []); | |||
/** | |||
* 添加节点 | |||
* | |||
* @param fields | |||
*/ | |||
const handleAdd = async (fields) => { | |||
const hide = message.loading('正在添加'); | |||
try { | |||
await updateGoodsClassify(JSON.stringify(fields)).then((r) => { | |||
if (r.succeeded) { | |||
message.success('添加成功'); | |||
} else { | |||
message.error(r.errors); | |||
} | |||
}); | |||
hide(); | |||
return true; | |||
} catch (error) { | |||
hide(); | |||
message.error('添加失败请重试!'); | |||
return false; | |||
} | |||
}; | |||
/** | |||
* 更新节点去 | |||
* | |||
* @param fields | |||
*/ | |||
const handleUpdate = async (fields) => { | |||
const hide = message.loading('正在修改'); | |||
try { | |||
await updateGoodsClassify(JSON.stringify(fields)).then((r) => { | |||
if (r.succeeded) { | |||
message.success('修改成功'); | |||
} else { | |||
message.error(r.errors); | |||
} | |||
}); | |||
hide(); | |||
return true; | |||
} catch (error) { | |||
hide(); | |||
message.error('修改失败请重试!'); | |||
return false; | |||
} | |||
}; | |||
const BatchDeletion = () => { | |||
return ( | |||
selectedRowsState?.length > 0 && | |||
( | |||
<Popconfirm | |||
title="确认删除吗?" | |||
onConfirm={onClickdele} | |||
okText="确定" | |||
cancelText="取消" | |||
> | |||
<Button type="primary">批量删除</Button> | |||
</Popconfirm> | |||
)) | |||
} | |||
const onClickdele = () => { | |||
handleRemove(selectedRowsState); | |||
setSelectedRows([]); | |||
actionRef.current?.reloadAndRest?.(); | |||
} | |||
/** | |||
* 批量删除 | |||
* | |||
* @param selectedRows | |||
*/ | |||
const handleRemove = async (selectedRows) => { | |||
if (!selectedRows) return true; | |||
await deleteGoodsClassify(selectedRows.map((row) => row.id)).then((r) => { | |||
if (r.succeeded) { | |||
message.success('删除成功'); | |||
actionRef.current.reload(); | |||
} else { | |||
message.error(r.errors); | |||
} | |||
}); | |||
return true; | |||
}; | |||
const editGoodsClassify = async () => { | |||
const tempMockData = []; | |||
targetKeys.forEach(function (item, index, array) { | |||
tempMockData.push({ | |||
"goodsId": item | |||
}); | |||
}) | |||
var data = { | |||
"classifyId": classifyId, | |||
"goodsIdList": tempMockData | |||
} | |||
setRelation(data).then((r) => { | |||
console.log(r); | |||
if (r.succeeded) { | |||
message.success('编辑成功'); | |||
} else { | |||
message.error(r.errors) | |||
} | |||
}); | |||
setIsModalOpen(false); | |||
actionRef.current.reload(); | |||
}; | |||
const getGoodsList = async (classifyId) => { | |||
var list = []; | |||
getRelation(classifyId).then((item) => { | |||
item.data.forEach(function (item) { | |||
list.push(item.goodsId); | |||
}) | |||
setTargetKeys(list); | |||
}); | |||
}; | |||
const handleChange = (newTargetKeys) => { | |||
setTargetKeys(newTargetKeys); | |||
}; | |||
const columns = [ | |||
{ | |||
title: '主键', | |||
dataIndex: 'id', | |||
hideInSearch: true, | |||
hideInTable: true, | |||
tip: '规则名称是唯一的 key', | |||
render: (dom, entity) => { | |||
return ( | |||
<a | |||
onClick={() => { | |||
setCurrentRow(entity); | |||
}} | |||
> | |||
{dom} | |||
</a> | |||
); | |||
}, | |||
}, | |||
{ | |||
title: '名称', | |||
dataIndex: 'name', | |||
valueType: 'textarea', | |||
ellipsis: true, | |||
}, | |||
{ | |||
title: '备注', | |||
dataIndex: 'remark', | |||
ellipsis: true, | |||
hideInForm: true, | |||
hideInSearch: true, | |||
}, | |||
{ | |||
title: '排序', | |||
dataIndex: 'sort', | |||
hideInSearch: true, | |||
}, | |||
{ | |||
title: '操作', | |||
dataIndex: 'option', | |||
valueType: 'option', | |||
render: (_, record) => [ | |||
<a | |||
key="config" | |||
onClick={() => { | |||
setGoodsClassifyVisible(true); | |||
setCurrentRow(record); | |||
}} | |||
> | |||
更新 | |||
</a>, | |||
<Popconfirm | |||
type="primary" | |||
key="primary" | |||
title="确认删除吗?" | |||
okText="是" | |||
cancelText="否" | |||
onConfirm={async () => { | |||
await deleteGoodsClassify(record.id).then((r) => { | |||
if (r.succeeded) { | |||
message.success('删除成功'); | |||
actionRef.current.reload(); | |||
} else { | |||
message.error(r.errors); | |||
} | |||
}); | |||
}} | |||
onCancel={() => { }} | |||
> | |||
<a href="#">删除</a> | |||
</Popconfirm>, | |||
<a | |||
key="edit" | |||
onClick={() => { | |||
getGoodsList(record.id); | |||
setClassifyId(record.id); | |||
setIsModalOpen(true); | |||
}} | |||
> | |||
设置设备商品 | |||
</a>, | |||
], | |||
}, | |||
]; | |||
return ( | |||
<PageContainer host header={{ | |||
title: '', | |||
breadcrumb: {}, | |||
}}> | |||
<ProTable | |||
headerTitle="" | |||
actionRef={actionRef} | |||
rowKey="id" | |||
pagination={{ defaultPageSize: 10 }} | |||
search={{ | |||
labelWidth: 120, | |||
}} | |||
toolBarRender={() => [ | |||
<Button | |||
type="primary" | |||
key="primary" | |||
onClick={() => { | |||
setGoodsClassifyVisible(true); | |||
}} | |||
> | |||
<PlusOutlined /> 新建 | |||
</Button>, | |||
<BatchDeletion /> | |||
]} | |||
request={async (params) => { | |||
var goodsClassifyData = []; | |||
var total = 0; | |||
await getGoodsClassifyPage(params).then((r) => { | |||
goodsClassifyData = r.data.data; | |||
total = r.data.total; | |||
}); | |||
return { | |||
data: goodsClassifyData, | |||
success: true, | |||
total: total | |||
}; | |||
}} | |||
columns={columns} | |||
rowSelection={{ | |||
onChange: (_, selectedRows) => { | |||
setSelectedRows(selectedRows); | |||
} | |||
}} | |||
/> | |||
<CreateForm | |||
key={Date.now()} | |||
onFinish={async (value) => { | |||
var success = false; | |||
if (value.id) { | |||
success = await handleUpdate(value); | |||
} else { | |||
success = await handleAdd(value); | |||
} | |||
if (success) { | |||
setGoodsClassifyVisible(false); | |||
setCurrentRow(undefined); | |||
actionRef.current.reload(); | |||
} | |||
}} | |||
onCancel={() => { | |||
setGoodsClassifyVisible(false); | |||
setCurrentRow(undefined); | |||
}} | |||
goodsClassifyVisible={goodsClassifyVisible} | |||
values={currentRow || {}} | |||
/> | |||
<Modal | |||
width={600} | |||
title="编辑设备商品" | |||
open={isModalOpen} | |||
destroyOnClose | |||
onOk={() => { editGoodsClassify() }} | |||
onCancel={() => { setIsModalOpen(false) }}> | |||
<Transfer | |||
className="tree-transfer" | |||
listStyle={{ | |||
width: 250, | |||
height: 300, | |||
}} | |||
dataSource={mockData} | |||
targetKeys={targetKeys} | |||
onChange={handleChange} | |||
onSearch={() => { }} | |||
render={(item) => item.title} | |||
/> | |||
</Modal> | |||
</PageContainer> | |||
); | |||
} | |||
export default GoodsClassify; |
@@ -0,0 +1,41 @@ | |||
import { request } from 'umi'; | |||
import { getDataBaseUrl } from '@/global_data'; | |||
export async function getGoodsClassifyPage(data) { | |||
return request(getDataBaseUrl() + `/api/goodsClassify/getGoodsClassifyPage`, { | |||
method: 'POST', | |||
data: data | |||
}); | |||
} | |||
export async function updateGoodsClassify(data) { | |||
return request(getDataBaseUrl() + `/api/goodsClassify/updateGoodsClassify`, { | |||
method: 'POST', | |||
data: data | |||
}); | |||
} | |||
export async function deleteGoodsClassify(data) { | |||
return request(getDataBaseUrl() + `/api/goodsClassify/deleteGoodsClassify?ids=${data}`, { | |||
method: 'Get' | |||
}); | |||
} | |||
export async function getgoodslist() { | |||
return request(getDataBaseUrl() + `/api/goods/getgoodslist`, { | |||
method: 'Get', | |||
}); | |||
} | |||
export async function getRelation(classifyId) { | |||
return request(getDataBaseUrl() + `/api/goodsClassify/getRelation?classifyId=${classifyId}`, { | |||
method: 'Get', | |||
}); | |||
} | |||
export async function setRelation(data) { | |||
return request(getDataBaseUrl() + `/api/goodsClassify/setRelation`, { | |||
method: 'POST', | |||
data: data | |||
}); | |||
} |
@@ -81,7 +81,7 @@ const From = (props) => { | |||
{ | |||
props.propsdata.length > 0 ? | |||
props.propsdata.map((x, index) => { | |||
let value=props.optiondata.find(p=>p.id==x.technologyactionId && p.actionName==x.actionName).actionValue; | |||
let value=props.optiondata.find(p=>p.id==x.technologyactionId && p.actionName==x.actionName)?.actionValue; | |||
if (x.actionType == "text") { | |||
return <> | |||
<div style={{width:'100%',height: '40px'}}> | |||
@@ -116,7 +116,7 @@ const goodstechnologymaken = (props) => { | |||
// {key:'1',label:'',children:(<div><img style={{width:100,height:100}} src={res.data.imgUrl}></img></div>)}, | |||
{ key: '1', label: '商品名称', children: res.data.name }, | |||
{ key: '2', label: '商品价格', children: res.data.price }, | |||
{ key: '3', label: '商品类型', children: res.data.goodsTypeName }, | |||
{ key: '3', label: '工艺分类', children: res.data.goodsTypeName }, | |||
{ key: '4', label: '商品单位', children: res.data.goodsUintName }, | |||
] | |||
setItems(it) | |||
@@ -618,7 +618,7 @@ const goodstechnologymaken = (props) => { | |||
<Card bodyStyle={{ padding: 15 }} > | |||
<div style={{ fontSize: 16, marginBottom: 5, color: '#1890ff', fontWeight: 600 }}>商品属性</div> | |||
{ | |||
goodsinfo.goodsAttributeList == undefined || goodsinfo.goodsAttributeList == "" ? (<div style={{ fontSize: '12px', marginLeft: 10 }}>当前商品分类还未配置属性点击跳转 <a | |||
goodsinfo.goodsAttributeList == undefined || goodsinfo.goodsAttributeList == "" ? (<div style={{ fontSize: '12px', marginLeft: 10 }}>当前商品的工艺分类还未配置属性点击跳转 <a | |||
key="primary" | |||
type="primary" | |||
onClick={() => { | |||
@@ -136,7 +136,7 @@ const handleUpdate = async (fields) => { | |||
}, | |||
// { | |||
// title: '商品类型', | |||
// title: '工艺分类', | |||
// dataIndex: 'goodsTypeName', | |||
// valueType: 'treeSelect', | |||
// fieldProps: { | |||
@@ -38,7 +38,7 @@ const CreateForm = (props) => { | |||
treeDefaultExpandAll | |||
/> | |||
</Form.Item> | |||
<Form.Item name="name" label="类型名称" rules={[{ required: true,max:50 }]}> | |||
<Form.Item name="name" label="分类名称" rules={[{ required: true,max:50 }]}> | |||
<Input /> | |||
</Form.Item> | |||
@@ -3,7 +3,7 @@ | |||
/* eslint-disable */ | |||
import { request } from 'umi'; | |||
import { getDataBaseUrl } from '@/global_data'; | |||
/** 获取商品类型 sdsa GET /kitchen/api/rule */ | |||
/** 获取工艺分类 sdsa GET /kitchen/api/rule */ | |||
export async function goodsType(data) { | |||
return request(getDataBaseUrl()+`/api/goodstype/page`, { | |||
method: 'POST', | |||
@@ -12,7 +12,7 @@ export async function goodsType(data) { | |||
// ...(options || {}), | |||
}); | |||
} | |||
/** 新建商品类型 POST /kitchen/api/rule */ | |||
/** 新建工艺分类 POST /kitchen/api/rule */ | |||
export async function GetDicList(TypeCode) { | |||
return request(getDataBaseUrl()+`/api/dict-data/dic-list/${TypeCode}`, { | |||
method: 'Get', | |||
@@ -29,7 +29,7 @@ export async function addGoodsType(data) { | |||
}); | |||
} | |||
/** 更新商品类型 PUT /kitchen/api/rule */ | |||
/** 更新工艺分类 PUT /kitchen/api/rule */ | |||
export async function updateGoodsType(data) { | |||
return request(getDataBaseUrl()+'/api/goodstype/update', { | |||
@@ -39,7 +39,7 @@ export async function updateGoodsType(data) { | |||
}); | |||
} | |||
/** 删除商品类型 DELETE /kitchen/api/rule */ | |||
/** 删除工艺分类 DELETE /kitchen/api/rule */ | |||
export async function DeleteGoodsType(data) { | |||
return request(getDataBaseUrl()+`/api/goodstype/delete?id=${data}`, { | |||
@@ -0,0 +1,56 @@ | |||
import React, { useRef, useState, useEffect } from 'react'; | |||
import { message, Modal, Form, Input, Button, Upload, Select, InputNumber, TreeSelect, Switch, Divider, Space } from 'antd'; | |||
import { } from '../service'; | |||
const ChooseForm = (props) => { | |||
const inputRef = useRef(); | |||
return ( | |||
<Modal | |||
title='以下商品重复,请选择覆盖或跳过' | |||
width={500} | |||
visible={props.showChooseForm} | |||
onCancel={props.onCancel} | |||
footer={null} | |||
maskClosable={false} | |||
destroyOnClose | |||
> | |||
<Form | |||
layout="inline" | |||
preserve={false} | |||
form={props.form} | |||
onFinish={props.onFinish} | |||
> | |||
{Array.isArray(props.values) && props.values.map((t, index) => ( | |||
<div key={index} style={{ marginBottom: '10px', clear: 'both' }}> | |||
<div style={{ float: 'left', marginRight: '10px' }}> | |||
<Form.Item name={t.goodsName} label="商品名称"> | |||
<span>{t.goodsName}</span> | |||
</Form.Item> | |||
</div> | |||
<div style={{ float: 'left' }}> | |||
<Form.Item | |||
name={t.goodsName} | |||
label="覆盖或跳过" | |||
valuePropName="checked" | |||
> | |||
<Switch checkedChildren="覆盖" unCheckedChildren="跳过" defaultChecked={false} /> | |||
</Form.Item> | |||
</div> | |||
</div> | |||
))} | |||
<Form.Item style={{ textAlign: 'right', marginTop: '10px', float: 'right', width: '100%' }}> | |||
<Button htmlType="button" style={{ marginRight: '10px' }} onClick={props.onCancel}> | |||
取消 | |||
</Button> | |||
<Button type="primary" htmlType="submit"> | |||
保存 | |||
</Button> | |||
</Form.Item> | |||
</Form> | |||
</Modal> | |||
); | |||
}; | |||
export default ChooseForm; |
@@ -9,17 +9,14 @@ const CreateForm = (props) => { | |||
const [goodsTypeIdvalue, setgoodsTypeIdvalue] = useState(); | |||
const inputRef = useRef(); | |||
const [unitname, setunitname] = useState(''); | |||
const [url, setUrl] = useState(props.values ? props.values.imgUrl : null); | |||
const [url, setUrl] = useState(null); | |||
const [hovered, setHovered] = useState(false); | |||
const [imageError, setImageError] = useState(false); | |||
useEffect(() => { | |||
initGoodsUnit(); | |||
initGoodsType(); | |||
if (props.values) { | |||
setUrl(props.values.imgUrl); | |||
} else { | |||
setUrl(null); | |||
} | |||
props.form.setFieldsValue(props.values); | |||
setUrl(props.values.imgUrl); | |||
}, [props.values]) | |||
function initGoodsUnit() { | |||
unitList().then((r) => { | |||
@@ -29,7 +26,6 @@ const CreateForm = (props) => { | |||
list.push({ text: item.name, value: item.id, label: item.name }); | |||
}); | |||
} | |||
console.log("list", list) | |||
setGoodsUnit(list); | |||
}); | |||
} | |||
@@ -94,8 +90,10 @@ const CreateForm = (props) => { | |||
} | |||
}; | |||
const handleDeleteImage = () => { | |||
props.values.imgUrl = null; | |||
setUrl(null); | |||
}; | |||
props.form.setFieldsValue({ imgUrl: props.values.imgUrl }); | |||
}; | |||
const handleImageError = () => { | |||
setImageError(true); | |||
}; | |||
@@ -116,12 +114,12 @@ const CreateForm = (props) => { | |||
labelCol={{ span: 4 }} | |||
layout="horizontal" | |||
preserve={false} | |||
initialValues={props.values} | |||
form={props.form} | |||
onFinish={props.onFinish}> | |||
<Form.Item name="id" hidden={true}> | |||
<Input /> | |||
</Form.Item> | |||
<Form.Item name="goodsTypeId" label="商品分类" rules={[{ required: true }]}> | |||
<Form.Item name="goodsTypeId" label="工艺分类" rules={[{ required: true }]}> | |||
<TreeSelect | |||
allowClear | |||
showSearch | |||
@@ -131,7 +129,7 @@ const CreateForm = (props) => { | |||
onChange={onChange} | |||
filterTreeNode={filterOption} | |||
value={goodsTypeIdvalue} | |||
placeholder="请选择商品类型" | |||
placeholder="请选择工艺分类" | |||
treeDefaultExpandAll | |||
/> | |||
</Form.Item> | |||
@@ -169,7 +167,7 @@ const CreateForm = (props) => { | |||
)} | |||
/> | |||
</Form.Item> | |||
<Form.Item name="price" label="商品价格" rules={[{ required: true }]}> | |||
<Form.Item name="price" label="商品价格"> | |||
<InputNumber style={{ width: '100%' }} placeholder="价格" min={0} /> | |||
</Form.Item> | |||
<Form.Item name="isWeigh" label="是否称重" valuePropName="checked" > | |||
@@ -1,14 +1,15 @@ | |||
import { PlusOutlined, UploadOutlined, QuestionCircleOutlined, DownloadOutlined } from '@ant-design/icons'; | |||
import { Button, message, Input, Drawer, Popconfirm, Upload, Spin, Tooltip, Modal, Select } from 'antd'; | |||
import { Button, message, Input, Drawer, Popconfirm, Upload, Spin, Tooltip, Modal, Select, Form } from 'antd'; | |||
import React, { useState, useRef, useEffect } from 'react'; | |||
import { PageContainer } from '@ant-design/pro-layout'; | |||
import ProTable from '@ant-design/pro-table'; | |||
import ProDescriptions from '@ant-design/pro-descriptions'; | |||
import { history } from 'umi'; | |||
import CreateForm from './components/CreateForm'; | |||
import ChooseForm from './components/ChooseForm'; | |||
import { getDataBaseUrl } from '@/global_data'; | |||
import { gettree, goods, removeGoods, addGoods, updateGoods, GetDeviceTechnology, TechnologyTemplateExport, GoodsTechnologyExport, GetgoodsWithIds, Getgoodslist, GoodsSimpleExport } from './service'; | |||
import { getdevicegoods } from '../../../device/deviceInfo/services' | |||
import { gettree, goods, removeGoods, addGoods, updateGoods, GetDeviceTechnology, GetgoodsWithIds, Getgoodslist, GoodsExport } from './service'; | |||
import axios from 'axios'; | |||
const aliyunHostUrl = 'https://bpa.oss-cn-chengdu.aliyuncs.com/hkerp/test/goods/'; | |||
@@ -17,29 +18,30 @@ const GoodsManage = () => { | |||
/** 新建/更新窗口的弹窗 */ | |||
const [createModalVisible, handleModalVisible] = useState(false); | |||
/** 分布更新窗口的弹窗 */ | |||
const [form] = Form.useForm(); | |||
const [showDetail, setShowDetail] = useState(false); | |||
//表单 | |||
const myformRef = useRef(); | |||
//列表 | |||
const actionRef = useRef(); | |||
const [currentRow, setCurrentRow] = useState(); | |||
const [selectedRowsState, setSelectedRows] = useState([]); | |||
const [treeData, setTreeData] = useState(); | |||
const [treeData, setTreeData] = useState([]); | |||
const [loading, setLoading] = useState(false); | |||
const [isModalOpen, setIsModalOpen] = useState(false); | |||
const [deviceData, setDeviceData] = useState([]); | |||
const [goodData, setGoodData] = useState([]); | |||
const [deviceGoodData, setDeviceGoodData] = useState([]); | |||
const [deviceId, setDeviceId] = useState(''); | |||
const [deviceName, setDeviceName] = useState(''); | |||
const [goodsId, setGoodsId] = useState([]); | |||
const [isDataModalOpen, setIsDataModalOpen] = useState(false); | |||
const [ids, setIds] =useState(''); | |||
const [importFile, setImportFile] = useState(); | |||
const [showChooseForm, setShowChooseForm] = useState(false); | |||
const [chooseFormData, setChooseFormData] = useState([]); | |||
/** 国际化配置 */ | |||
useEffect(() => { | |||
gettree().then((r) => { | |||
setTreeData(r.data); | |||
}); | |||
initGetDeviceTechnology(); | |||
initGetgoodslist(); | |||
}, []); | |||
const initGetDeviceTechnology = () =>{ | |||
@@ -57,46 +59,6 @@ const GoodsManage = () => { | |||
} | |||
}); | |||
} | |||
const initGetgoodslist = () =>{ | |||
Getgoodslist().then((r)=>{ | |||
var arr = r.data; | |||
if (r.succeeded) { | |||
var list = []; | |||
arr.forEach((item) => { | |||
list.push({ | |||
value: item.id, | |||
label: item.name | |||
}); | |||
}); | |||
setGoodData(list); | |||
} | |||
}); | |||
} | |||
const initGetdevicegoodsList = async (deviceId) => { | |||
getdevicegoods(deviceId).then((r) => { | |||
var arr = r.data; | |||
if (r.succeeded) { | |||
var idList = []; | |||
arr.forEach((item) => { | |||
idList.push(item.goodsId); | |||
}); | |||
setIds(idList); | |||
GetgoodsWithIds(idList).then((t) => { | |||
var a = t.data; | |||
if (t.succeeded) { | |||
var list = []; | |||
a.forEach((i) => { | |||
list.push({ | |||
value: i.id, | |||
label: i.name | |||
}) | |||
}) | |||
setDeviceGoodData(list); | |||
} | |||
}) | |||
} | |||
}); | |||
}; | |||
/** | |||
* 添加节点 | |||
@@ -104,7 +66,7 @@ const GoodsManage = () => { | |||
* @param fields | |||
*/ | |||
const handleAdd = async (fields) => { | |||
fields.createBy = 'admin'; | |||
fields.price = fields.price ? fields.price : 0; | |||
fields.isAttrubute = true; | |||
fields.ImgUrl = fields.imgUrl1 ? aliyunHostUrl + fields.imgUrl1.file.name : null; | |||
await addGoods(JSON.stringify(fields)).then((r) => { | |||
@@ -130,10 +92,10 @@ const GoodsManage = () => { | |||
goodsTypeId: fields.goodsTypeId, | |||
name: fields.name, | |||
goodsUintId: fields.goodsUintId, | |||
price: fields.price, | |||
price: fields.price ? fields.price : 0, | |||
isWeigh: fields.isWeigh, | |||
descritption: fields.descritption, | |||
imgUrl: fields.imgUrl1 ? aliyunHostUrl + fields.imgUrl1.file.name : null | |||
imgUrl: fields.imgUrl1 ? aliyunHostUrl + fields.imgUrl1.file.name : fields.imgUrl | |||
}).then((r) => { | |||
if (r.succeeded) { | |||
message.success('修改成功'); | |||
@@ -208,15 +170,36 @@ const GoodsManage = () => { | |||
renderText: (val) => `${val}¥`, | |||
hideInSearch: true, | |||
}, | |||
{ | |||
title: '商品类型', | |||
title: '设备', | |||
dataIndex: 'deviceId', | |||
valueType: 'treeSelect', | |||
hideInTable: true, | |||
fieldProps: { | |||
showSearch:true, | |||
allowClear:true, | |||
options: deviceData, | |||
treeNodeFilterProp: 'label', | |||
onChange: (val, row) => { | |||
setDeviceId(val) | |||
setDeviceName(row[0]) | |||
myformRef.current.submit() | |||
} | |||
}, | |||
}, | |||
{ | |||
title: '工艺分类', | |||
dataIndex: 'goodsTypeName', | |||
valueType: 'treeSelect', | |||
fieldProps: { | |||
showSearch:true, | |||
allowClear:true, | |||
options: treeData | |||
fieldNames: { | |||
children: 'children', | |||
label: 'title', | |||
}, | |||
options: treeData, | |||
treeNodeFilterProp: 'title', | |||
}, | |||
}, | |||
{ | |||
@@ -286,23 +269,32 @@ const GoodsManage = () => { | |||
> | |||
工艺配置 | |||
</a>, | |||
<a | |||
key="primary" | |||
type="primary" | |||
onClick={() => { | |||
history.push({ | |||
pathname: '/database/goods/goodsattributeprice', | |||
query: { | |||
isAdd: false, | |||
values: record, | |||
}, | |||
}); | |||
// handleModalVisible(true); | |||
// setCurrentRow(record); | |||
}} | |||
> | |||
价格配置 | |||
</a> | |||
// <a | |||
// key="primary" | |||
// type="primary" | |||
// onClick={() => { | |||
// history.push({ | |||
// pathname: '/database/goods/goodsattributeprice', | |||
// query: { | |||
// isAdd: false, | |||
// values: record, | |||
// }, | |||
// }); | |||
// // handleModalVisible(true); | |||
// // setCurrentRow(record); | |||
// }} | |||
// > | |||
// 价格配置 | |||
// </a> | |||
<a | |||
key="primary" | |||
type="primary" | |||
onClick={()=>{ | |||
handleDownload(record.id) | |||
}} | |||
> | |||
下载商品 | |||
</a> | |||
, | |||
<Popconfirm | |||
type="primary" | |||
@@ -328,6 +320,27 @@ const GoodsManage = () => { | |||
}, | |||
]; | |||
const importMessage = (json) =>{ | |||
const formDataAll = new FormData(); | |||
formDataAll.append('file', importFile); | |||
formDataAll.append('json', json); | |||
formDataAll.append('deviceId', deviceId); | |||
const headers = { | |||
'Content-Type': 'application/json', | |||
'Authorization': 'Bearer ' + localStorage.getItem('token') | |||
}; | |||
axios.post(getDataBaseUrl() + '/api/goods/goodsImport', formDataAll, { headers }).then(r => { | |||
if(r.data.succeeded == true){ | |||
message.success("导入成功"); | |||
actionRef.current.reload(); | |||
}else{ | |||
message.error(r.data.errors); | |||
} | |||
}).catch(error => { | |||
message.error(error); | |||
}); | |||
} | |||
/** | |||
* 删除节点 | |||
* | |||
@@ -345,182 +358,95 @@ const GoodsManage = () => { | |||
}); | |||
return true; | |||
}; | |||
const props = { | |||
const importProps = { | |||
beforeUpload: (file) => { | |||
setLoading(true); | |||
if ( | |||
file.type !== 'application/vnd.ms-excel' && | |||
file.type !== 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' | |||
) { | |||
message.error(`${file.name} 不是 exelce 文件`); | |||
} | |||
return file.type == 'application/vnd.ms-excel' || | |||
file.type == 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' | |||
? true | |||
: Upload.LIST_IGNORE; | |||
}, | |||
name: 'file', | |||
action: getDataBaseUrl()+'/api/goods/GoodsImport', | |||
headers: { | |||
// authorization: 'authorization-text', | |||
Authorization: 'Bearer ' + localStorage.getItem('token') | |||
}, | |||
onChange(info) { | |||
if (info.file.status !== 'uploading') { | |||
console.log(info.file, info.fileList); | |||
setImportFile(file); | |||
if (deviceName == '' || deviceId == undefined) { | |||
message.error('请选择一个设备!'); | |||
return Upload.LIST_IGNORE; | |||
} | |||
if (info.file.status === 'done') { | |||
setLoading(false); | |||
message.success(`${info.file.name}导入成功`); | |||
actionRef.current.reload(); | |||
} else if (info.file.status === 'error') { | |||
setLoading(false); | |||
message.error(`${info.file.name}:${info.file.response} `); | |||
} | |||
} | |||
}; | |||
const technologprops = { | |||
beforeUpload: (file) => { | |||
if ( | |||
file.type !== 'application/vnd.ms-excel' && | |||
file.type !== 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' | |||
file.type !== 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' && | |||
file.type !== 'application/x-zip-compressed' | |||
) { | |||
message.error(`${file.name} 不是 exelce 文件`); | |||
message.error(`${file.name} 不是excel或zip文件`); | |||
} | |||
return file.type == 'application/vnd.ms-excel' || | |||
file.type == 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' | |||
file.type == 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' || | |||
file.type == 'application/x-zip-compressed' | |||
? true | |||
: Upload.LIST_IGNORE; | |||
}, | |||
name: 'file', | |||
action: getDataBaseUrl() + '/api/goods/goodsTechnologyImport', | |||
action: getDataBaseUrl() + '/api/goods/getFileToChoose', | |||
headers: { | |||
// authorization: 'authorization-text', | |||
Authorization: 'Bearer ' + localStorage.getItem('token') | |||
}, | |||
onChange(info) { | |||
setLoading(true); | |||
if (info.file.status !== 'uploading') { | |||
console.log(info.file, info.fileList); | |||
} | |||
if (info.file.status === 'done') { | |||
setLoading(false); | |||
message.success(`${info.file.name}导入成功`); | |||
actionRef.current.reload(); | |||
} else if (info.file.status === 'error') { | |||
setLoading(false); | |||
message.error(`${info.file.name}:${info.file.response} `); | |||
if(info.file.response.data.length > 0){ | |||
setChooseFormData(info.file.response.data); | |||
setShowChooseForm(true); | |||
} | |||
else{ | |||
importMessage([]); | |||
myformRef.current.submit() | |||
} | |||
} | |||
// setLoading(true); | |||
// if (info.file.status !== 'uploading') { | |||
// console.log(info.file, info.fileList); | |||
// } | |||
// if (info.file.status === 'done') { | |||
// setLoading(false); | |||
// message.success(`${info.file.name}导入成功`); | |||
// actionRef.current.reload(); | |||
// } else if (info.file.status === 'error') { | |||
// setLoading(false); | |||
// message.error(`${info.file.name}:${info.file.response} `); | |||
// } | |||
} | |||
}; | |||
const handleDataDeviceChange = (value, option) => { | |||
setDeviceId(option?.value); | |||
setDeviceName(option?.label); | |||
initGetdevicegoodsList(option?.value); | |||
} | |||
const handleDeviceChange = (value, option) => { | |||
setDeviceId(option?.value); | |||
setDeviceName(option?.label); | |||
} | |||
const handleGoodChange = (value, option) => { | |||
setGoodsId(value); | |||
} | |||
const handleDataDownload = async()=>{ | |||
if(deviceName == '') | |||
{ | |||
message.error('请选择一个设备!'); | |||
return; | |||
} | |||
if(goodsId == '') | |||
{ | |||
message.error('请选择至少一个商品!'); | |||
return; | |||
} | |||
const base64String = await GoodsSimpleExport({ goodsId: goodsId, deviceId: deviceId, ids: ids }); | |||
// 解码 Base64 数据 | |||
const binaryString = atob(base64String); | |||
// 转换为 Uint8Array | |||
const bytes = new Uint8Array(binaryString.length); | |||
for (let i = 0; i < binaryString.length; i++) { | |||
bytes[i] = binaryString.charCodeAt(i); | |||
} | |||
// 创建 Blob 对象 | |||
const blob = new Blob([bytes], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }); | |||
// 创建一个临时的 URL,指向 Blob 对象 | |||
const url = window.URL.createObjectURL(blob); | |||
// 创建 <a> 元素,用于下载文件 | |||
const link = document.createElement('a'); | |||
const fileName = "商品.xlsx"; | |||
link.href = url; | |||
link.setAttribute('download', fileName); | |||
// 将 <a> 元素添加到页面中 | |||
document.body.appendChild(link); | |||
// 模拟用户点击下载链接,触发文件下载 | |||
link.click(); | |||
// 下载完成后,移除 <a> 元素 | |||
document.body.removeChild(link); | |||
setDeviceId(''); | |||
setDeviceName(''); | |||
setGoodsId([]); | |||
setIds(''); | |||
setIsDataModalOpen(false); | |||
} | |||
const handleDownload = async () => { | |||
if(deviceName == '') | |||
{ | |||
const handleDownload = async (goodId) => { | |||
if (deviceName == '' || deviceId == undefined) { | |||
message.error('请选择一个设备!'); | |||
return; | |||
} | |||
try { | |||
// 第一次下载操作 | |||
const r = await TechnologyTemplateExport(deviceId); | |||
if (!r) { | |||
message.error('未能获取第一个文件下载链接'); | |||
return; | |||
} | |||
const fileName1 = r.substring(r.lastIndexOf('/') + 1); | |||
const link1 = document.createElement('a'); | |||
link1.href = r; | |||
link1.setAttribute('download', fileName1); | |||
document.body.appendChild(link1); | |||
link1.click(); | |||
document.body.removeChild(link1); | |||
// 第二次下载操作 | |||
const base64String = await GoodsTechnologyExport({ goodsId: goodsId, deviceId: deviceId, fileName: fileName1 }); | |||
if (!base64String) { | |||
message.error('未能获取第二个文件Base64数据'); | |||
return; | |||
} | |||
// 解码 Base64 数据 | |||
const binaryString = atob(base64String); | |||
// 转换为 Uint8Array | |||
const bytes = new Uint8Array(binaryString.length); | |||
for (let i = 0; i < binaryString.length; i++) { | |||
bytes[i] = binaryString.charCodeAt(i); | |||
} | |||
// 创建 Blob 对象 | |||
const blob = new Blob([bytes], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }); | |||
// 创建一个临时的 URL,指向 Blob 对象 | |||
const url = window.URL.createObjectURL(blob); | |||
// 创建第二个 <a> 元素,用于下载第二个文件 | |||
const link2 = document.createElement('a'); | |||
const fileName2 = "商品.xlsx"; | |||
link2.href = url; | |||
link2.setAttribute('download', fileName2); | |||
// 将第二个 <a> 元素添加到页面中 | |||
document.body.appendChild(link2); | |||
// 模拟用户点击下载链接,触发第二个文件下载 | |||
link2.click(); | |||
// 下载完成后,移除第二个 <a> 元素 | |||
document.body.removeChild(link2); | |||
setDeviceId(''); | |||
setDeviceName(''); | |||
setGoodsId([]); | |||
setIsModalOpen(false); | |||
} catch (error) { | |||
message.error('下载过程中发生错误:', error); | |||
} | |||
await GoodsExport({ goodId: goodId, deviceId: deviceId, goodsId: goodsId }).then((r) => { | |||
if (r.succeeded) { | |||
const base64String = r.data; | |||
// 解码 Base64 数据 | |||
const binaryString = atob(base64String); | |||
// 转换为 Uint8Array | |||
const bytes = new Uint8Array(binaryString.length); | |||
for (let i = 0; i < binaryString.length; i++) { | |||
bytes[i] = binaryString.charCodeAt(i); | |||
} | |||
// 创建 Blob 对象 | |||
const blob = new Blob([bytes], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }); | |||
// 创建一个临时的 URL,指向 Blob 对象 | |||
const url = window.URL.createObjectURL(blob); | |||
// 创建 <a> 元素,用于下载文件 | |||
const link = document.createElement('a'); | |||
const fileName = "商品.zip"; | |||
link.href = url; | |||
link.setAttribute('download', fileName); | |||
// 将 <a> 元素添加到页面中 | |||
document.body.appendChild(link); | |||
// 模拟用户点击下载链接,触发文件下载 | |||
link.click(); | |||
// 下载完成后,移除 <a> 元素 | |||
document.body.removeChild(link); | |||
message.success("下载成功"); | |||
}else{ | |||
message.error(r.errors); | |||
} | |||
}) | |||
} | |||
return ( | |||
<PageContainer host header={{ | |||
title: '', | |||
@@ -529,6 +455,7 @@ const GoodsManage = () => { | |||
<Spin spinning={loading} tip="上传中..."> | |||
<ProTable | |||
headerTitle="" | |||
formRef={myformRef} | |||
actionRef={actionRef} | |||
rowKey="id" | |||
pagination={{ defaultPageSize: 10 }} | |||
@@ -555,64 +482,40 @@ const GoodsManage = () => { | |||
</Button>, | |||
<Button | |||
key="primary" | |||
onClick={async () => { | |||
const link = document.createElement('a'); | |||
link.href = "https://bpa.oss-cn-chengdu.aliyuncs.com/hkerp/test/goods/商品导入模版.xlsx"; | |||
link.click(); | |||
}} | |||
onClick={() => handleDownload(null)} | |||
> | |||
<DownloadOutlined /> 下载商品导入模板 | |||
<DownloadOutlined />下载商品 | |||
<Tooltip placement="top" title="下载后请使用wps进行编辑"><QuestionCircleOutlined /></Tooltip> | |||
</Button>, | |||
<Upload {...props} showUploadList={false} > | |||
<Button icon={<UploadOutlined />} >导入商品</Button> | |||
<Upload {...importProps} showUploadList={false}> | |||
<Button icon={<UploadOutlined />}>导入商品</Button> | |||
</Upload>, | |||
<Button | |||
key="primary" | |||
onClick={async () => { | |||
initGetgoodslist(); | |||
setIsModalOpen(true); | |||
}} | |||
> | |||
<DownloadOutlined /> 下载工艺模板 | |||
<Tooltip placement="top" title="下载后请使用wps进行编辑"><QuestionCircleOutlined /></Tooltip> | |||
</Button>, | |||
<Upload {...technologprops} showUploadList={false}> | |||
<Button icon={<UploadOutlined />}>导入工艺</Button> | |||
</Upload>, | |||
<Button | |||
key="primary" | |||
onClick={async () => { | |||
setIsDataModalOpen(true); | |||
}} | |||
> | |||
<DownloadOutlined /> 下载商品工艺 | |||
</Button>, | |||
<BatchDeletion /> | |||
]} | |||
request={async (params) => { | |||
var goodsData = []; | |||
var goodsIds = []; | |||
if (params.goodsTypeId != undefined) { | |||
params.goodsTypeId = goodsTypes[params.goodsTypeId].goodsTypeId; | |||
} | |||
var total = 0; | |||
await goods(params).then((r) => { | |||
goodsData = r.data.data; | |||
console.log(goodsData) | |||
goodsData.forEach((x) => { | |||
goodsIds.push(x.id); | |||
if (x.defaultMate != null) { | |||
x.defaultMate = x.defaultMate.split(","); | |||
} | |||
}); | |||
console.log(goodsData) | |||
total = r.data.total; | |||
}); | |||
setGoodsId(goodsIds); | |||
return { | |||
data: goodsData, | |||
success: true, | |||
total: total, | |||
}; | |||
}} | |||
columns={columns} | |||
rowSelection={{ | |||
@@ -644,125 +547,34 @@ const GoodsManage = () => { | |||
}} | |||
createModalVisible={createModalVisible} | |||
values={currentRow || {}} | |||
form={form} | |||
/> | |||
<Modal | |||
title="下载设备工艺及商品工艺模版" | |||
open={isModalOpen} | |||
footer={false} | |||
width={450} | |||
maskClosable={false} | |||
destroyOnClose={true} | |||
onCancel={() => { | |||
setDeviceId('') | |||
setDeviceName('') | |||
setIsModalOpen(false) | |||
}}> | |||
<div style={{ marginBottom: 10 }}> | |||
<span style={{ marginRight: 10 }}><span style={{color:'red',marginRight: 3}}>*</span>选择设备:</span> | |||
<Select | |||
showSearch | |||
allowClear | |||
style={{ | |||
width: 300, | |||
marginRight: 10 | |||
}} | |||
placeholder="请选择设备下载该设备的工艺模版" | |||
optionFilterProp="children" | |||
filterOption={(input, option) => (option?.label ?? '').includes(input)} | |||
filterSort={(optionA, optionB) => | |||
(optionA?.label ?? '').toLowerCase().localeCompare((optionB?.label ?? '').toLowerCase()) | |||
} | |||
onChange={async (value, option) => { handleDeviceChange(value, option) }} | |||
options={deviceData} | |||
required | |||
/> | |||
</div> | |||
<div style={{ marginBottom: 10 }}> | |||
<span style={{ marginLeft: 9, marginRight: 10 }}>选择商品:</span> | |||
<Select | |||
mode='multiple' | |||
showSearch | |||
allowClear | |||
style={{ | |||
width: 300, | |||
marginRight: 10 | |||
}} | |||
placeholder="选择商品下载模版" | |||
optionFilterProp="children" | |||
filterOption={(input, option) => (option?.label ?? '').includes(input)} | |||
filterSort={(optionA, optionB) => | |||
(optionA?.label ?? '').toLowerCase().localeCompare((optionB?.label ?? '').toLowerCase()) | |||
} | |||
onChange={async (value, option) => { handleGoodChange(value, option) }} | |||
options={goodData} | |||
/> | |||
</div> | |||
<Button | |||
icon={<DownloadOutlined />} | |||
style={{ marginLeft: '22.2%' }} | |||
onClick = {handleDownload} | |||
>下载</Button> | |||
</Modal> | |||
<Modal | |||
title="下载商品工艺" | |||
open={isDataModalOpen} | |||
footer={false} | |||
width={450} | |||
destroyOnClose={true} | |||
<ChooseForm | |||
onFinish={async (data) => { | |||
const transformedData = Object.entries(data).map(([key, value]) => ({ | |||
key, | |||
value | |||
})); | |||
var list = []; | |||
transformedData.forEach((item) => { | |||
list.push({ | |||
key: item.key, | |||
value: item.value == true ? true : false | |||
}); | |||
}); | |||
importMessage(JSON.stringify(list)); | |||
setShowChooseForm(false); | |||
setChooseFormData(undefined); | |||
myformRef.current.submit() | |||
}} | |||
onCancel={() => { | |||
setDeviceGoodData([]) | |||
setDeviceId('') | |||
setDeviceName('') | |||
setGoodsId([]) | |||
setIds('') | |||
setIsDataModalOpen(false) | |||
}}> | |||
<div style={{ marginBottom: 10 }}> | |||
<span style={{ marginRight: 10 }}><span style={{color:'red',marginRight: 3}}>*</span>选择设备:</span> | |||
<Select | |||
showSearch | |||
allowClear | |||
style={{ | |||
width: 300, | |||
marginRight: 10 | |||
}} | |||
placeholder="请选择设备" | |||
optionFilterProp="children" | |||
filterOption={(input, option) => (option?.label ?? '').includes(input)} | |||
filterSort={(optionA, optionB) => | |||
(optionA?.label ?? '').toLowerCase().localeCompare((optionB?.label ?? '').toLowerCase()) | |||
} | |||
onChange={async (value, option) => { handleDataDeviceChange(value, option) }} | |||
options={deviceData} | |||
required | |||
/> | |||
</div> | |||
<div style={{ marginBottom: 10 }}> | |||
<span style={{ marginLeft: 9, marginRight: 10 }}>选择商品:</span> | |||
<Select | |||
mode='multiple' | |||
showSearch | |||
allowClear | |||
style={{ | |||
width: 300, | |||
marginRight: 10 | |||
}} | |||
placeholder="选择商品下载工艺" | |||
optionFilterProp="children" | |||
filterOption={(input, option) => (option?.label ?? '').includes(input)} | |||
filterSort={(optionA, optionB) => | |||
(optionA?.label ?? '').toLowerCase().localeCompare((optionB?.label ?? '').toLowerCase()) | |||
} | |||
onChange={async (value, option) => { handleGoodChange(value, option) }} | |||
options={deviceGoodData} | |||
/> | |||
</div> | |||
<Button | |||
icon={<DownloadOutlined />} | |||
style={{ marginLeft: '22.2%' }} | |||
onClick = {handleDataDownload} | |||
>下载</Button> | |||
</Modal> | |||
setShowChooseForm(false); | |||
setChooseFormData(undefined); | |||
}} | |||
showChooseForm={showChooseForm} | |||
values={chooseFormData || {}} | |||
form={form} | |||
/> | |||
<Drawer | |||
width={600} | |||
visible={showDetail} | |||
@@ -68,7 +68,7 @@ export async function removeGoods(data) { | |||
}); | |||
} | |||
/** 获取商品类型 sdsa GET /kitchen/api/rule */ | |||
/** 获取工艺分类 sdsa GET /kitchen/api/rule */ | |||
export async function goodsType(data) { | |||
return request(getDataBaseUrl()+`/api/goods-type/goods-types`, { | |||
method: 'POST', | |||
@@ -170,6 +170,19 @@ export async function GoodsSimpleExport(data) { | |||
return request(getDataBaseUrl()+`/api/goods/goodsSimpleExport`, { | |||
method: 'post', | |||
data: data | |||
// responseType: 'blob' | |||
}); | |||
} | |||
export async function GoodsExport(data) { | |||
return request(getDataBaseUrl()+`/api/goods/goodsExport`, { | |||
method: 'post', | |||
data: data | |||
}); | |||
} | |||
export async function GoodsImport(data) { | |||
return request(getDataBaseUrl()+`/api/goods/goodsImport`, { | |||
method: 'post', | |||
data: data | |||
}); | |||
} |
@@ -258,7 +258,7 @@ const GoodsTypeManage = () => { | |||
dataIndex: 'option', | |||
valueType: 'option', | |||
fixed: 'right', | |||
width: 400, | |||
width: 300, | |||
render: (_, record) => [ | |||
<a | |||
key="update" | |||
@@ -344,16 +344,16 @@ const GoodsTypeManage = () => { | |||
导出工艺模版 | |||
</a>, | |||
<a | |||
key="edit" | |||
onClick={() => { | |||
GetdevicegoodsList(record.id); | |||
setCurrentRow(record); | |||
setIsModalOpen(true); | |||
}} | |||
> | |||
设置设备商品 | |||
</a>, | |||
// <a | |||
// key="edit" | |||
// onClick={() => { | |||
// GetdevicegoodsList(record.id); | |||
// setCurrentRow(record); | |||
// setIsModalOpen(true); | |||
// }} | |||
// > | |||
// 设置设备商品 | |||
// </a>, | |||
], | |||
}, | |||
@@ -2,11 +2,10 @@ import React, { useRef, useState, useEffect } from 'react'; | |||
import { Modal, Form, Input, Button, Select, Upload, InputNumber, message } from 'antd'; | |||
import { PlusOutlined, UploadOutlined, DeleteOutlined } from '@ant-design/icons'; | |||
import { GetAliyunRequestURL } from '../services'; | |||
import $ from 'jquery'; | |||
const CreateForm = (props) => { | |||
const [modalVisible, setModalVisible] = useState(false); | |||
const [modalContent, setModalContent] = useState(''); | |||
const [url, setUrl] = useState(props.values ? props.values.productUrl : null); | |||
const [url, setUrl] = useState(null); | |||
const [hovered, setHovered] = useState(false); | |||
const [imageError, setImageError] = useState(false); | |||
const uploadProp = { | |||
@@ -53,7 +52,9 @@ const CreateForm = (props) => { | |||
props.onCancel(); | |||
}; | |||
const handleDeleteImage = () => { | |||
props.values.productUrl = null; | |||
setUrl(null); | |||
props.form.setFieldsValue({ productUrl: props.values.productUrl }); | |||
}; | |||
const handleImageError = () => { | |||
setImageError(true); | |||
@@ -73,7 +74,6 @@ const CreateForm = (props) => { | |||
layout="vertical" | |||
preserve={false} | |||
form={props.form} | |||
// initialValues={props.values} | |||
onFinish={props.onFinish} > | |||
<Form.Item name="id" hidden={true}> | |||
<Input /> | |||
@@ -95,6 +95,9 @@ const CreateForm = (props) => { | |||
<Form.Item label={"仓位数量"} name="productNumber" rules={[{ required: true, }]} > | |||
<InputNumber min={1} /> | |||
</Form.Item> | |||
<Form.Item label={"备注"} name="remark"> | |||
<Input /> | |||
</Form.Item> | |||
<Form.Item name="productUrl" hidden={true}> | |||
<Input /> | |||
</Form.Item> | |||
@@ -42,7 +42,7 @@ const GoodsTypeManage = () => { | |||
file.type !== 'application/vnd.ms-excel' && | |||
file.type !== 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' | |||
) { | |||
message.error(`${file.name} 不是 exelce 文件`); | |||
message.error(`${file.name} 不是 excel 文件`); | |||
} | |||
return file.type == 'application/vnd.ms-excel' || | |||
file.type == 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' | |||
@@ -96,7 +96,7 @@ const handleAdd = async (fields) => { | |||
//修改 | |||
const handleUpdate = async (fields) => { | |||
try { | |||
fields.productUrl = fields.productUrl1 ? aliyunHostUrl + fields.productUrl1.file.name : null; | |||
fields.productUrl = fields.productUrl1 ? aliyunHostUrl + fields.productUrl1.file.name : fields.productUrl; | |||
message.loading('正在修改', key); | |||
message.destroy(key); | |||
await UpdateDeviceVesion(JSON.stringify(fields)).then((r) => { | |||
@@ -165,6 +165,12 @@ const handleRemove = async (selectedRows) => { | |||
valueType: 'textarea', | |||
hideInSearch: true, | |||
}, | |||
{ | |||
title: '备注', | |||
dataIndex: 'remark', | |||
valueType: 'textarea', | |||
hideInSearch: true, | |||
}, | |||
{ | |||
title: '图片', | |||
dataIndex: 'productUrl', | |||
@@ -30,7 +30,7 @@ const props = { | |||
file.type !== 'application/vnd.ms-excel' && | |||
file.type !== 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' | |||
) { | |||
message.error(`${file.name} 不是 exelce 文件`); | |||
message.error(`${file.name} 不是 excel 文件`); | |||
} | |||
return file.type == 'application/vnd.ms-excel' || | |||
file.type == 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' | |||
@@ -0,0 +1,38 @@ | |||
import React, {} from 'react'; | |||
import { Modal, Form, Input, Button } from 'antd'; | |||
const CreateRemarkForm = (props) => { | |||
return ( | |||
<Modal | |||
width={400} | |||
title="编辑备注" | |||
open={props.remarkModalOpen} | |||
footer={null} | |||
maskClosable={false} | |||
destroyOnClose | |||
onCancel={props.onCancel} | |||
> | |||
<Form | |||
layout="horizontal" | |||
preserve={false} | |||
initialValues={props.values} | |||
onFinish={props.onFinish} | |||
> | |||
<Form.Item name="id" hidden={true}> | |||
<Input /> | |||
</Form.Item> | |||
<Form.Item label={"备注"} name="remark"> | |||
<Input /> | |||
</Form.Item> | |||
<Form.Item> | |||
<Button type="primary" htmlType="submit" style={{ float: 'right' }}> | |||
保存 | |||
</Button> | |||
</Form.Item> | |||
</Form> | |||
</Modal> | |||
); | |||
}; | |||
export default CreateRemarkForm; |
@@ -1,14 +1,14 @@ | |||
import { Modal, Button, message, Form, Upload, Select ,Popconfirm} from 'antd'; | |||
import { Modal, Button, message, Form, Upload, Select ,Popconfirm, Input} from 'antd'; | |||
import React, { useState, useRef, useEffect } from 'react'; | |||
import { PageContainer, FooterToolbar } from '@ant-design/pro-layout'; | |||
import { PlusOutlined, UploadOutlined } from '@ant-design/icons'; | |||
import ProTable from '@ant-design/pro-table'; | |||
import {GetTechnologyPage,GetProductList,GetDeviceVesionList,DeleteTechnology,GetAliyunRequestURL,GoodsTemplateExport } from "./services" | |||
import {GetTechnologyPage,GetProductList,GetDeviceVesionList,DeleteTechnology,GetAliyunRequestURL,GoodsTemplateExport,UpdateRecodeRemark } from "./services" | |||
import { history } from 'umi'; | |||
import { getDataBaseUrl } from '@/global_data'; | |||
import Technologylist from './components/technologylist' | |||
import useFetchData from '@ant-design/pro-descriptions/lib/useFetchData'; | |||
import CreateRemarkForm from './components/CreateRemarkForm'; | |||
const key = 'message'; | |||
import $ from 'jquery'; | |||
import { set } from 'lodash'; | |||
@@ -26,6 +26,8 @@ const GoodsTypeManage = () => { | |||
const [deviceTypeKey, setdeviceTypeKey] = useState(''); | |||
const [version, setversion] = useState(''); | |||
const [url, setUrl] = useState(''); | |||
const [remarkModalOpen, setRemarkModalOpen] = useState(false); | |||
const [remarkData, setRemarkData] = useState(); | |||
let aliyunHostUrl = 'https://bpa.oss-cn-chengdu.aliyuncs.com/hkerp/test/technology/'; | |||
const props = { | |||
beforeUpload: (file) => { | |||
@@ -35,7 +37,7 @@ const GoodsTypeManage = () => { | |||
file.type !== 'application/vnd.ms-excel' && | |||
file.type !== 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' | |||
) { | |||
message.error(`${file.name} 不是 exelce 文件`); | |||
message.error(`${file.name} 不是 excel 文件`); | |||
} | |||
if(ProductVesionId.length==0){ | |||
message.error(`请选择版本`); | |||
@@ -129,6 +131,12 @@ const GoodsTypeManage = () => { | |||
valueType: 'textarea', | |||
search:false | |||
}, | |||
{ | |||
title: '备注', | |||
dataIndex: 'remark', | |||
valueType: 'textarea', | |||
search:false | |||
}, | |||
// { | |||
// title: '是否存在模板', | |||
// dataIndex: 'templatePath', | |||
@@ -197,7 +205,12 @@ const GoodsTypeManage = () => { | |||
// href={record.templatePath} | |||
// > 下载工艺模板</a>, | |||
<a | |||
key="config" | |||
onClick={() => { | |||
setRemarkModalOpen(true); | |||
setRemarkData(record); | |||
}} > 编辑备注</a> | |||
], | |||
}, | |||
]; | |||
@@ -250,6 +263,26 @@ const GoodsTypeManage = () => { | |||
setDeviceVesionData([]) | |||
handleModalVisible(false); | |||
} | |||
const handleUpdate = async (fields) => { | |||
try { | |||
message.loading('正在修改', key); | |||
message.destroy(key); | |||
await UpdateRecodeRemark(JSON.stringify(fields)).then((r) => { | |||
message.destroy(key); | |||
if (r.data) { | |||
message.success('修改成功',); | |||
actionRef.current?.reloadAndRest?.(); | |||
return true; | |||
} else { | |||
message.error(r.errors); | |||
return false; | |||
} | |||
}); | |||
} catch (error) { | |||
message.error('修改失败请重试!'); | |||
return false; | |||
} | |||
}; | |||
return ( | |||
<PageContainer host header={{ | |||
title: '', | |||
@@ -321,12 +354,12 @@ const GoodsTypeManage = () => { | |||
</Button> | |||
</FooterToolbar> | |||
)} | |||
<Modal title="上传工艺模版" open={isModalOpen} footer={null} maskClosable={false} | |||
<Modal title="上传工艺模版" open={isModalOpen} footer={null} maskClosable={false} width={400} | |||
destroyOnClose onCancel={() => { setDeviceVesionData();setdeviceTypeKey(""); | |||
setProductVesionId('');setIsModalOpen(false) }}> | |||
<div style={{marginBottom:10}}> | |||
<span style={{marginRight:10}}>选择产品</span> | |||
<Select style={{width: '60%'}} onChange={handleChange}> | |||
<Select style={{width: '80%'}} onChange={handleChange}> | |||
{DictData?.map((item, index) => { | |||
return ( | |||
<Select.Option index={index} value={item.id} key={item.id}> | |||
@@ -338,7 +371,7 @@ const GoodsTypeManage = () => { | |||
</div> | |||
<div style={{marginBottom:10}}> | |||
<span style={{marginRight:10}}>选择版本</span> | |||
<Select style={{width: '60%'}} onChange={handleVisChange}> | |||
<Select style={{width: '80%'}} onChange={handleVisChange}> | |||
{DeviceVesionData?.map((item, index) => { | |||
return ( | |||
<Select.Option index={index} value={item.id} key={item.id}> | |||
@@ -349,12 +382,29 @@ const GoodsTypeManage = () => { | |||
</Select> | |||
</div> | |||
<Upload | |||
// {...uploadProp} | |||
{...props} | |||
maxCount={1}> | |||
<Button icon={<UploadOutlined />} style={{marginLeft:'48%'}}>导入工艺模版</Button> | |||
</Upload> | |||
</Modal> | |||
<CreateRemarkForm | |||
onFinish={async (value) => { | |||
var success = handleUpdate(value); | |||
if (success) { | |||
setRemarkModalOpen(false); | |||
setRemarkData(undefined); | |||
} | |||
actionRef.current.reload(); | |||
}} | |||
onCancel={() => { | |||
setRemarkModalOpen(false); | |||
setRemarkData(undefined); | |||
}} | |||
remarkModalOpen={remarkModalOpen} | |||
values={remarkData || {}} | |||
> | |||
</CreateRemarkForm> | |||
<Technologylist createModalVisible={createModalVisible} dataSource={currentRow} onCancel={onCancel}/> | |||
</PageContainer> | |||
); | |||
@@ -32,4 +32,10 @@ export async function GetTechnologyPage(data) { | |||
method: 'POST', | |||
data: data, | |||
}); | |||
} | |||
export async function UpdateRecodeRemark(data) { | |||
return request(getDataBaseUrl() + `/api/technology/UpdateRecodeRemark`, { | |||
method: 'POST', | |||
data: data, | |||
}); | |||
} |
@@ -1,5 +1,5 @@ | |||
import React, {useState,useEffect } from 'react'; | |||
import { Modal, Form, Input, Button, Select,Image } from 'antd'; | |||
import { Modal, Form, Input, Button, Select,Image, InputNumber } from 'antd'; | |||
import { | |||
EditableProTable | |||
} from '@ant-design/pro-table'; | |||
@@ -15,6 +15,7 @@ const CreateForm = (props) => { | |||
form.setFieldsValue({ | |||
id: props.values.id, | |||
templateName:props.values.templateName, | |||
sort:props.values.sort, | |||
deviceId:props.values.deviceId, | |||
}); | |||
var data=props.values.warehousePostion.map(x=>{ | |||
@@ -138,8 +139,9 @@ const CreateForm = (props) => { | |||
(optionA?.label ?? '').toLowerCase().localeCompare((optionB?.label ?? '').toLowerCase()) | |||
} | |||
onChange={handleChange} options={options}/> | |||
</Form.Item> | |||
<Form.Item label={"序号"} name="sort"> | |||
<InputNumber style={{width: '100%'}}/> | |||
</Form.Item> | |||
<Form.Item label={"设备仓位图"} name="productUrl" rules={[{ required: false,max:50}]} > | |||
<Image | |||
@@ -74,7 +74,7 @@ GetFlowExport(data) { | |||
}); | |||
}, | |||
/** | |||
* 查询商品类型 | |||
* 查询工艺分类 | |||
*/ | |||
goodsTypeList(data) { | |||
return request(`/kitchen/api/goodstype/list`, { | |||
@@ -76,7 +76,7 @@ const PushFrom = (props) => { | |||
valueType: 'textarea', | |||
}, | |||
{ | |||
title: '商品类型', | |||
title: '工艺分类', | |||
dataIndex: 'goodsTypeName', | |||
valueType: 'treeSelect', | |||
fieldProps: { | |||
@@ -88,7 +88,7 @@ const handleStopChange=(value)=>{ | |||
valueType: 'textarea', | |||
}, | |||
{ | |||
title: '商品类型', | |||
title: '工艺分类', | |||
dataIndex: 'goodsTypeName', | |||
valueType: 'treeSelect', | |||
fieldProps: { | |||
@@ -37,7 +37,7 @@ const FoodMenuGoods = (props) => { | |||
tip: '规则名称是唯一的 key', | |||
}, | |||
{ | |||
title: '商品类型', | |||
title: '工艺分类', | |||
dataIndex: 'goodsTypeName', | |||
valueType: 'treeSelect', | |||
hideInTable: true, | |||