diff --git a/config/routes.js b/config/routes.js index 8af9561..fba28a1 100644 --- a/config/routes.js +++ b/config/routes.js @@ -216,6 +216,13 @@ export default [ component: './device/productmanage', access: 'k14', }, + { + name: '设备工艺', + icon: 'smile', + path: '/device/technology', + component: './device/technology', + access: 'k14', + }, // { // name: '设备工艺信息', // icon: 'smile', diff --git a/src/pages/database/bom/components/BomBatching.jsx b/src/pages/database/bom/components/BomBatching.jsx new file mode 100644 index 0000000..bcade1e --- /dev/null +++ b/src/pages/database/bom/components/BomBatching.jsx @@ -0,0 +1,147 @@ +import React, { useState,useRef,useEffect } from 'react'; +import { PlusOutlined} from '@ant-design/icons'; +import { Modal, Form, Input, Button, Select,Radio,message,Tag,Divider,Space } from 'antd'; +import { GetByidBomList } from '../services'; +import { + EditableProTable, + ProTable +} from '@ant-design/pro-table'; +const GoodsbomFrom = (props) => { + const { Option, OptGroup } = Select; + const [dataSource, setDataSource] = useState([]); + const [editableKeys, setEditableRowKeys] = useState([]); + const [form] = Form.useForm(); + + useEffect(() => { + let soredata=[]; + if(props.BomId){ + GetByidBomList(props.BomId).then((t)=>{ + var data=t.data + if(data.bomEntry.length>0){ + data.bomEntry.map(x=>{ + var item={ + id:x.id, + bomId:x.bomId, + batchingId:x.batchingId, + dosage:x.bomQty + } + console.log("item",item) + soredata.push(item) + }) + } + console.log("soredata",soredata) + if(soredata.length>0){ + setEditableRowKeys(soredata.map((item) => item.id)) + setDataSource(soredata); + } + }) + } + + },[props]) + const columns=[ + { + title: '主键', + dataIndex: 'id', + key: 'id', + hideInTable: true, + hideInSearch: true, + tip: '规则名称是唯一的 key', + }, + { + title: '配方', + dataIndex: 'bomId', + hideInTable: true, + hideInSearch: true, + }, + { + title: '物料名称', + dataIndex: 'batchingId', + formItemProps: (form, { rowIndex }) => { + return { + rules: + rowIndex > 1 ? [{ required: true, message: '此项为必填项' }] : [], + }; + }, + valueType: 'select', + fieldProps: { + showSearch:true, + options: props.matedata.map((item, index) => {return {label:item.name,value:item.id}}) + }, + width: '25%', + }, + { + title: '用量', + dataIndex: 'dosage', + valueType:'digit', + width: '15%', + }, + { + title: '操作', + valueType: 'option', + width: '15%', + render: () => { + return null; + }, + }, +] + const headleOk=()=>{ + if(dataSource.length==0){ + check=false; + message.error("请选择物料") + }else{ + props.onBomBatchingFinish(dataSource); + //setDataSource([]) + } + + + } + return ( + { + props.onBomBatchingCancel(); + }} + destroyOnClose + > + ({ + id: Date.now(), + bomId:props.BomId + }), + }} + + editable={{ + type: 'multiple', + editableKeys, + actionRender: (row, config, defaultDoms) => { + return [defaultDoms.delete,defaultDoms.Button]; + }, + onValuesChange: (record, recordList) => { + setDataSource(recordList); + }, + onDelete:async (key, row) =>{ + console.log(key) + console.log(row) + + }, + onChange: setEditableRowKeys, + }}/> + + + //vessels + ); +}; + +export default GoodsbomFrom; diff --git a/src/pages/database/bom/components/CreateBom.jsx b/src/pages/database/bom/components/CreateBom.jsx index 0e88c7f..b47800d 100644 --- a/src/pages/database/bom/components/CreateBom.jsx +++ b/src/pages/database/bom/components/CreateBom.jsx @@ -6,12 +6,11 @@ import { AddBomType } from '../services'; const App = (props) => { - const [form] = Form.useForm(); const inputRef = useRef(null); const [typename, settypename] = useState(''); const [dataSource, setDataSource] = useState([]); const [editableKeys, setEditableRowKeys] = useState([]); - + const onNameChange = (event) => { settypename(event.target.value); } @@ -69,13 +68,39 @@ const App = (props) => { } + const headleOk = () => { + props.form.validateFields().then((values) => { + var check = true; + var data = values; + debugger + if (dataSource.length == 0) { + check = false; + message.error("请选择物料") + } else { + data.mate = dataSource.map(x => { return { batchingId: x.batchingId, dosage: x.dosage } }); + } + if (check) { + props.form.resetFields(); + props.onFinish(data); + setDataSource([]) + } + + }).catch((info) => { + message.error("请填写必填信息") + }); + } + return ( <> - - + + diff --git a/src/pages/database/bom/components/UpdateBom.jsx b/src/pages/database/bom/components/UpdateBom.jsx new file mode 100644 index 0000000..9d4b2e5 --- /dev/null +++ b/src/pages/database/bom/components/UpdateBom.jsx @@ -0,0 +1,96 @@ +import React, { useState, useEffect, useRef } from 'react'; +import { Modal, Form, Input, Button, Select, Switch, InputNumbe, Divider, Space } from 'antd'; +import { PlusOutlined } from '@ant-design/icons'; + +const UpdateBom = (props) => { + const { Option, OptGroup } = Select; + const [typename, settypename] = useState(''); + const inputRef = useRef(null); + + + const onNameChange = (event) => { + settypename(event.target.value); + } + + const addItem = (e) => { + e.preventDefault(); + + if (typename == 0) { + message.error("请输入名称"); + } else { + var parm = { name: typename } + AddBomType(parm).then((r) => { + if (r.succeeded) { + message.success('添加成功'); + props.initTypeList(); + settypename(''); + } else { + message.error(r.errors); + } + }) + } + + } + + const headleOk = () => { + props.onUpdateBomSave() + } + + + return ( + { + props.onCancel(); + }} + onOk={headleOk} + destroyOnClose + > + + + + + + + + + ( + <> + {menu} + + + e.stopPropagation()} + /> + } onClick={addItem}> + 新增 + + + > + )} + /> + + + + ); +}; + +export default UpdateBom; diff --git a/src/pages/database/bom/index.jsx b/src/pages/database/bom/index.jsx index 3da88cb..22647fd 100644 --- a/src/pages/database/bom/index.jsx +++ b/src/pages/database/bom/index.jsx @@ -1,20 +1,31 @@ import { PlusOutlined } from '@ant-design/icons'; -import { Button, message, Input, Drawer, Modal, Space, Tag, Popconfirm } from 'antd'; +import { Button, message, Input, Drawer, Modal, Space, Tag, Popconfirm, Form } from 'antd'; import React, { useState, useRef, useEffect } from 'react'; import { PageContainer, FooterToolbar } from '@ant-design/pro-layout'; import ProTable from '@ant-design/pro-table'; -import { bomPage, getproductpage,GetbomTypelist } from './services'; +import { bomPage, getproductpage, GetbomTypelist, AddBom, UpdateBomInfo, UpdateBomBatcing,DelBom } from './services'; import CreateBom from './components/CreateBom'; +import UpdateBom from './components/UpdateBom'; +import BomBatching from './components/BomBatching' + const GoodsBomsManage = (props) => { const actionRef = useRef(); const [modalVisible, setModalVisible] = useState(false); + const [updateModalVisible, setupdateModalVisible] = useState(false); const [matedata, setMatedata] = useState([]); - const [bomTypeData,setbomTypeData]= useState([]); + const [bomTypeData, setbomTypeData] = useState([]); + const [selectedRowsState, setSelectedRows] = useState([]); + const [BomId, setBomId] = useState(); + const [form] = Form.useForm(); + const [form2] = Form.useForm(); + const [currentRow, setCurrentRow] = useState(); + const [BomBatchingVisible, setBomBatchingVisible] = useState(false); + useEffect(() => { + initGetbomType(); intBatching();//默认原料 - }, []); function intBatching() { @@ -37,8 +48,8 @@ const GoodsBomsManage = (props) => { }) } - function initGetbomType(){ - GetbomTypelist().then((r)=>{ + function initGetbomType() { + GetbomTypelist().then((r) => { var list = []; if (r.data.length > 0) { r.data.forEach((item) => { @@ -47,60 +58,79 @@ const GoodsBomsManage = (props) => { } setbomTypeData(list) }) - + } const columns = [ { title: '主键', dataIndex: 'id', - key: 'id', hideInTable: true, hideInSearch: true, tip: '规则名称是唯一的 key', + render: (dom, entity) => { + return ( + { + setCurrentRow(entity); + setShowDetail(true); + }} + > + {dom} + + ); + }, }, { title: '配方名称', - key: 'name', dataIndex: 'name', - valueType: 'textarea', + width: 300, + hideInForm: true, + hideInSearch: false, }, { - title: '配方类型', - dataIndex: 'isMain', - hideInForm: true, - valueEnum: { - false: { - text: '辅料', - status: 'Processing', - }, - true: { - text: '主料', - status: 'Success', - }, - }, + title: '配方分类', + dataIndex: 'bomTypeList', + search: false, + + render: (_, record) => ( + + { + bomTypeData.filter((x) => { + let findId = record.bomTypeList.find((findItem) => findItem === x.value); + let findBomType = bomTypeData.find((bomItem) => bomItem.value === findId); + return findBomType != null || undefined; + }).map((item) => ( + + {item.text} + + ))} + + ), }, { title: '操作', dataIndex: 'option', valueType: 'option', + width: 250, render: (_, record) => [ { - setUpdateBomVisible(true); - setBomId(record.bomId) + setCurrentRow(record); + form2.setFieldsValue(record); + setupdateModalVisible(true); }} > 更新 , { setBomBatchingVisible(true); - setBomId(record.bomId) + setBomId(record.id) }} > 配方详情 @@ -108,19 +138,72 @@ const GoodsBomsManage = (props) => { { - + const hide = message.loading('正在删除'); + try { + DelBom(record.id); + hide(); + message.success('删除成功,即将刷新'); + actionRef.current.reloadAndRest(); + return true; + } catch (error) { + hide(); + message.error('删除失败,请重试'); + actionRef.current.reloadAndRest(); + return false; + } }} onCancel={() => { }} > 删除 , + ], - } - ] + }, + ]; + + const onUpdateBomSave = () => { + form2 + .validateFields() + .then((values) => { + console.log(values) + var parm = { id: values.id, name: values.bomName, IsMain: values.bomType == '1' ? true : false, bomTypeIds: values.bomTypeList } + UpdateBomInfo(parm).then((r) => { + if (r.data) { + message.success('修改成功'); + setupdateModalVisible(false); + actionRef.current.reload(); + setBomId('') + } else { + message.error(r.errors || "修改失败"); + } + }) + }) + } + + + const onBomBatchingCancel = () => { + setBomBatchingVisible(false); + setBomId('') + } + + const onBomBatchingFinish = (form) => { + console.log("form", form) + var parm = { bomId: BomId, bomEntry: form }; + UpdateBomBatcing(parm).then((r) => { + if (r.succeeded) { + message.success('修改成功'); + setBomBatchingVisible(false); + actionRef.current.reload(); + setBomId('') + } else { + message.error(r.errors); + } + }) + } return ( @@ -167,10 +250,46 @@ const GoodsBomsManage = (props) => { {/* 新增菜谱 */} { setModalVisible(false); }} + onFinish={async (value) => { + await AddBom(value).then((r) => { + if (r.data) { + message.success("添加成功") + setModalVisible(false); + } else { + message.error("添加失败") + } + actionRef.current.reloadAndRest(); + }) + }} + onCancel={() => { setModalVisible(false); form.resetFields(); }} /> + {/* 修改菜谱 */} + { + + }} + onCancel={() => { + setupdateModalVisible(false); + setCurrentRow(undefined); + }} + /> + + {/* 配方详情 */} + + ); diff --git a/src/pages/database/bom/services.js b/src/pages/database/bom/services.js index 2120a38..f3e713a 100644 --- a/src/pages/database/bom/services.js +++ b/src/pages/database/bom/services.js @@ -7,6 +7,14 @@ export async function bomPage(data) { data:data, }); } + export async function AddBom(data) { + return request(getDataBaseUrl()+'/api/bom/AddBom', { + method: 'POST', + data:data, + }); + } + + export async function AddBomType (data) { return request(getDataBaseUrl()+`/api/bom/addbomtype`, { @@ -31,3 +39,32 @@ export async function bomPage(data) { }); } + + export async function GetByidBomList(data) { + return request(getDataBaseUrl()+`/api/bom/getbyidbomlist?bomId=`+data, { + method: 'Get', + }); + } + + export async function UpdateBomInfo(data) { + return request(getDataBaseUrl()+`/api/bom/update`, { + method: 'Post', + data: data, + }); + } + + export async function UpdateBomBatcing(data) { + return request(getDataBaseUrl()+`/api/bom/updatebombatcing`, { + method: 'Post', + data: data, + }); + } + + export async function DelBom (data) { + return request(getDataBaseUrl()+`/api/bom/DelBom?id=${data}`, { + method: 'post', + //data: data, + }); + } + + diff --git a/src/pages/database/goods/goodsbom/components/CreateBom.jsx b/src/pages/database/goods/goodsbom/components/CreateBom.jsx index dd289f3..93392d6 100644 --- a/src/pages/database/goods/goodsbom/components/CreateBom.jsx +++ b/src/pages/database/goods/goodsbom/components/CreateBom.jsx @@ -19,6 +19,10 @@ const GoodsbomFrom = (props) => { const [arttue,setarttue]=useState(1); const [arttuename,setarttuename]=useState(""); const [arttuename11,setarttuename1]=useState(""); + const [checked,setchecked]=useState(false); + const [bomNameRules,setbomNameRules]=useState([]) + const [bomTypeListRules,setbomTypeListRules]=useState([]) + const [bomcheckRules,setbomcheckRules]=useState([]) const [recordCreatorProps,setrecordCreatorProps]=useState(false) const onNameChange=(event)=>{ settypename(event.target.value); @@ -46,7 +50,8 @@ const GoodsbomFrom = (props) => { console.log("props.Bomdata",props.Bomdata) console.log(props.goodsname) setdisaenumbled('block') - setdisnewd("none") + setdisnewd("none"); + setbomcheckRules([{ required: true, message: '请选择配方' }]) // form.setFieldsValue({ // bomName: props.goodsname, // // bomType:1 @@ -66,7 +71,7 @@ const GoodsbomFrom = (props) => { setEditableRowKeys(soredata.map((item) => item.id)) setDataSource(soredata); } - },[props]) + },[]) const columns=[ { title: '物料名称', @@ -133,7 +138,7 @@ const GoodsbomFrom = (props) => { data.bomName=values.bomName+"("+arttuename11+")" props.onFinish(data); setDataSource([]) - setCheckvalue([]) + //setCheckvalue([]) setarttuename("") } @@ -199,14 +204,20 @@ const GoodsbomFrom = (props) => { const onchagetype= (e) => { console.log(form) setarttue(e.target.value) - setCheckvalue([]) + //setCheckvalue([]) setDataSource([]) + setchecked(false) if(e.target.value==1){//选择配方 setrecordCreatorProps(false); setdisaenumbled("block") setdisnewd("none") - + setbomcheckRules([{ required: true, message: '请选择配方' }]) + setbomNameRules( [{ required: false}]) + setbomTypeListRules([{ required: false}]) }else{ + setbomcheckRules([{ required: false }]) + setbomNameRules( [{ required: true, message: '请输入配方名称!' }]) + setbomTypeListRules([{ required: true, message: '配方分类' }]) setrecordCreatorProps({ newRecordType: 'dataSource', record: () => ({ @@ -244,7 +255,7 @@ const GoodsbomFrom = (props) => { { item.goodsAttributeValueList.map((item, index)=>{ return ( - {item.attributeValue} + {item.attributeValue} ) }) } @@ -264,10 +275,9 @@ const GoodsbomFrom = (props) => { - + @@ -282,11 +292,11 @@ const GoodsbomFrom = (props) => { - - + + - + { onClick={async () => { await handleRemove(selectedRowsState); setSelectedRows([]); - actionRef.current?.reloadAndRest?.(); + actionRef.current?.AndRest?.(); }} > 删除 diff --git a/src/pages/database/goods/newgoods/index.jsx b/src/pages/database/goods/newgoods/index.jsx index 53bd205..5dc9e84 100644 --- a/src/pages/database/goods/newgoods/index.jsx +++ b/src/pages/database/goods/newgoods/index.jsx @@ -378,7 +378,7 @@ const GoodsManage = () => { // cancelText="否" // onConfirm={() => { // handleRemove([record.id]); - // actionRef.current?.reloadAndRest(); + // actionRef.current?.AndRest(); // }} // onCancel={() => {}} // > @@ -444,7 +444,7 @@ const GoodsManage = () => { onClick={async () => { await handleRemove(selectedRowsState); setSelectedRows([]); - actionRef.current?.reloadAndRest?.(); + actionRef.current?.AndRest?.(); }} > 删除 diff --git a/src/pages/device/technology/index.jsx b/src/pages/device/technology/index.jsx new file mode 100644 index 0000000..3550e15 --- /dev/null +++ b/src/pages/device/technology/index.jsx @@ -0,0 +1,312 @@ + +import { Modal, Button, message, Form, Upload, Select ,Popconfirm} from 'antd'; +import React, { useState, useRef, useEffect } from 'react'; +import { PageContainer, FooterToolbar } from '@ant-design/pro-layout'; +import { PlusOutlined } from '@ant-design/icons'; +import ProTable from '@ant-design/pro-table'; +import {GetTechnologyPage,GetProductList,GetDeviceVesionList } from "./services" +import { history } from 'umi'; +const key = 'message'; + + + + +const GoodsTypeManage = () => { + const [createModalVisible, handleModalVisible] = useState(false); + const actionRef = useRef(); + const [DictData, setDictData] = useState([]); + const [DeviceVesionData, setDeviceVesionData] = useState([]); + const [currentRow, setCurrentRow] = useState(); + const [selectedRowsState, setSelectedRows] = useState([]); + const [isModalOpen, setIsModalOpen] = useState(false); + const [isAddGoodsTemplate,setIsAddGoodsTemplate]=useState(false); + const [form] = Form.useForm(); + const props = { + beforeUpload: (file) => { + 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', + data: { "id": currentRow?.id, "deviceClientType": currentRow?.deviceTypeKey, "version": currentRow?.vesion,"isAddGoodsTemplate":isAddGoodsTemplate}, + action: '/saasbase/api/goods/goodstemplateexport', + headers: { + Authorization: 'Bearer ' + localStorage.getItem('token') + }, + onChange(info) { + if (info.file.status !== 'uploading') { + console.log(info.file, info.fileList); + } + setIsAddGoodsTemplate(false); + if (info.file.status === 'done') { + setIsModalOpen(false); + actionRef.current.reload(); + message.success(`${info.file.name} 文件上传成功.`); + } else if (info.file.status === 'error') { + message.error(`${info.file.name} 文件上载失败.`); + } + } + }; + const columns = [ + { + title: '主键', + dataIndex: 'id', + hideInSearch: true, + hideInTable: true, + tip: '规则名称是唯一的 key' + }, + { + title: '所属产品', + dataIndex: 'productName', + valueType: 'textarea', + }, + { + title: '版本号', + dataIndex: 'vesion', + valueType: 'textarea', + }, + { + title: '时间', + dataIndex: 'createTime', + valueType: 'textarea', + }, + // { + // title: '是否存在模板', + // dataIndex: 'templatePath', + // valueType: 'textarea', + // hideInSearch: true, + // render: (_, record) => [ + // + // 存在模板 + // 无模板 + // ], + // }, + { + title: '操作', + dataIndex: 'option', + valueType: 'option', + fixed: 'right', + width: 700, + render: (_, record) => [ + { + handleModalVisible(true); + setCurrentRow(record); + // form.setFielsValue(record) + }} > 详情, + { + handleModalVisible(true); + setCurrentRow(record); + // form.setFielsValue(record) + }} > 下载, + { + DelDeviceVesion([record.id]).then((r) => { + + if (r.data) { + message.success('删除成功'); + actionRef.current.reload(); + } else { + message.error(r.errors); + } + + }); + }} + onCancel={() => { }} + > + 删除 + , + // { + // setCurrentRow(record); + // setIsModalOpen(true); + // setIsAddGoodsTemplate(false); + // }} > 上传设备工艺模型, + // { + // setCurrentRow(record); + // setIsModalOpen(true); + // setIsAddGoodsTemplate(true); + // }} > 上传商品工艺模版, + // 下载工艺模板, + { + history.push({ + pathname: '/device/productmanage', + query: { + isAdd: false, + values: record, + tabStatus: 'basis' + }, + }); + }} > 管理, + ], + }, + ]; + useEffect(() => { + GetProductList().then((r) => { + var arr = r.data; + if (r.succeeded) { + var list = []; + arr.forEach((item) => { + list.push({ + label: item.name, + text:item.name, + id: item.id, + }); + }); + //setDicDataAny(data); + setDictData(list); + } + }); + }, []) + const handleChange = (value) => { + console.log(`selected ${value}`); + GetDeviceVesionList(value).then((r)=>{ + var arr = r.data; + if (r.succeeded) { + var list = []; + arr.forEach((item) => { + list.push({ + label: item.vesion, + text:item.vesion, + id: item.id, + }); + }); + //setDicDataAny(data); + setDeviceVesionData(list); + } + }) + }; + const handleVisChange=(value)=>{ + console.log(`selected ${value}`); + } + return ( + + [ + { + // form.setFielsValue(currentRow) + setIsModalOpen(true); + }} > + 导入工艺模版 + , + ]} + request={async (params) => { + var data = []; + var total = 0; + await GetTechnologyPage(params).then((r) => { + data = r.data.data; + total = r.data.total; + }); + return { + data: data, + success: true, + total: total, + }; + }} + columns={columns} + rowSelection={{ + onChange: (_, selectedRows) => { + setSelectedRows(selectedRows); + }, + }} + /> + {selectedRowsState?.length > 0 && ( + + 已选择{' '} + + {selectedRowsState.length} + {' '} + 项 + + } + > + { + await handleRemove(selectedRowsState); + setSelectedRows([]); + actionRef.current?.reloadAndRest?.(); + }} + > + 删除 + + + )} + { setIsModalOpen(false) }}> + + 选择产品 + + {DictData.map((item, index) => { + return ( + + {item.label} + + ); + })} + + + + 选择版本 + + {DeviceVesionData.map((item, index) => { + return ( + + {item.label} + + ); + })} + + + + 导入工艺模版 + + + + + ); +}; + +export default GoodsTypeManage; diff --git a/src/pages/device/technology/services.js b/src/pages/device/technology/services.js new file mode 100644 index 0000000..2fe9f05 --- /dev/null +++ b/src/pages/device/technology/services.js @@ -0,0 +1,18 @@ +import { request } from 'umi'; +import { getDataBaseUrl } from '@/global_data'; +export async function GetTechnologyPage(data) { + return request(getDataBaseUrl()+`/api/technology/page`, { + method: 'POST', + data: data, + }); + } + export async function GetProductList() { + return request(getDataBaseUrl()+`/api/product/list`, { + method: 'Get', + }); + } + export async function GetDeviceVesionList(data) { + return request(getDataBaseUrl()+`/api/devicevesion/getdevicevesion?productId=`+data, { + method: 'Get', + }); + } \ No newline at end of file