diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..4a6ca4d --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,154 @@ + +pipeline{ + agent any + parameters { + choice( + description: 'pztjwebi:开发环境1', + name: 'environment', + choices: ['pztj'] + ) + + choice( + description: '前端or后端', + name: 'projectqh', + choices: ['backend','frontend'] + ) + + choice( + description: '执行操作(发布|回滚)', + name: 'operation', + choices: ['develop', 'rollback'] + ) + + choice( + description: '分支名', + name: 'branchName', + choices: ['master'] + ) + + string( + name: 'tag', + defaultValue: '', + description: '版本tag' + ) + + } + + stages + { + stage('Prepare') { + steps { + script{ + echo "1.Prepare Stage" + echo "当前环境${params.environment}" + if(params.operation=='develop') + { + checkout scm + script { + build_tag = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim() + if (env.BRANCH_NAME != 'master') { + build_tag = "${env.BRANCH_NAME}-${build_tag}" + } + } + } + else{ + script { + if(params.branchName!= 'master') + { + build_tag = "${params.branchName}-${params.tag}" + } + else + { + build_tag="${params.tag}" + } + } + } + } + } + } + stage('Test') { + steps { + script{ + echo "2.Test Stage" + } + } + + } + stage('Build') { + steps { + script{ + echo "3.Build Docker Image Stage" + if(params.operation=='develop') + { + if(params.projectqh=='backend') + { + sh "cp -r backend/* ./" + sh "docker build -f backend/dockerfile -t 10.2.1.24:10242/bpa/pztjapi:${build_tag} ." + } + else if(params.projectqh=='frontend') + { + sh "docker build -f frontend/dockerfile -t 10.2.1.24:10242/bpa/pztjweb:${build_tag} ." + } + + } + } + } + } + + + stage('Push') { + steps { + script{ + echo "4.Push Docker Image Stage" + withCredentials([usernamePassword(credentialsId: 'harbor', passwordVariable: 'harborPassword', usernameVariable: 'harborUser')]) { + sh "docker login -u ${harborUser} -p ${harborPassword} 10.2.1.24:10242" + if(params.operation=='develop') + { + if(params.projectqh=='backend') + { + sh "docker push 10.2.1.24:10242/bpa/pztjapi:${build_tag}" + + } + else if(params.projectqh=='frontend') + { + sh "docker push 10.2.1.24:10242/bpa/pztjweb:${build_tag}" + } + + } + } + } + } + + + + } + stage('Deploy') { + + steps { + script{ + echo "5. Deploy Stage" + // if(params.environment=='test') + // { + // input "确认要部署线上环境吗?" + // } + if(params.projectqh=='backend') + { + + sh "sed -i 's//${build_tag}/' k8s_pztjapi.yaml" + sh "sed -i 's//${env.BRANCH_NAME}/' k8s_pztjapi.yaml" + sh "sed -i 's//${params.environment}/' k8s_pztjapi.yaml" + sh "kubectl apply -f k8s_pztjapi.yaml --record" + } + else if(params.projectqh=='frontend') + { + sh "sed -i 's//${build_tag}/' k8s_pztjweb.yaml" + sh "sed -i 's//${env.BRANCH_NAME}/' k8s_pztjweb.yaml" + sh "sed -i 's//${params.environment}/' k8s_pztjweb.yaml" + sh "kubectl apply -f k8s_pztjweb.yaml --record" + } + + } + } + } + } +} diff --git a/NuGet.config b/NuGet.config new file mode 100644 index 0000000..b149801 --- /dev/null +++ b/NuGet.config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/frontend/default.conf b/frontend/default.conf new file mode 100644 index 0000000..ad50602 --- /dev/null +++ b/frontend/default.conf @@ -0,0 +1,13 @@ +server { + listen 80; + server_name localhost; + + location / { + root /usr/share/nginx/html; + index index.html index.htm; + try_files $uri $uri/ /index.html; + } +} + + + diff --git a/frontend/dockerfile b/frontend/dockerfile new file mode 100644 index 0000000..dfe1554 --- /dev/null +++ b/frontend/dockerfile @@ -0,0 +1,4 @@ +FROM nginx:latest +COPY ./frontend/dist /usr/share/nginx/html/ +COPY ./frontend/default.conf /etc/nginx/conf.d/ +EXPOSE 80 diff --git a/frontend/src/pages/bucket/index.less b/frontend/src/pages/bucket/index.less new file mode 100644 index 0000000..12530e0 --- /dev/null +++ b/frontend/src/pages/bucket/index.less @@ -0,0 +1,16 @@ +*{ + margin: 0; + padding: 0; +} +.container{ + display: flex; + justify-content:space-around; + + +} +.left { + + display: flex; + flex-direction: column; + justify-content: space-around +} diff --git a/frontend/src/pages/bucket/index.tsx b/frontend/src/pages/bucket/index.tsx new file mode 100644 index 0000000..efaa95f --- /dev/null +++ b/frontend/src/pages/bucket/index.tsx @@ -0,0 +1,444 @@ +// 桶管理 +import './index.less' +import type { ActionType, ProColumns } from '@ant-design/pro-components'; +import { ProTable } from '@ant-design/pro-components'; +import { Button, Modal, Form, Input, message, Popconfirm, Tag, QRCode, Table } from 'antd'; +import { useRef, useState } from 'react'; +import type { ColumnsType } from 'antd/es/table'; +import DeviceInfoAPI from '@/api/DeviceInfo'; + + +const bucket = () => { + //表单 + // eslint-disable-next-line react-hooks/rules-of-hooks + const [typeForm] = Form.useForm(); + // 下拉列表 + // eslint-disable-next-line react-hooks/rules-of-hooks + const [modelTitle, setModelTitle] = useState(); + //编辑/新增弹窗 + // eslint-disable-next-line react-hooks/rules-of-hooks + const [isModalOpen, setIsModalOpen] = useState(false); + // eslint-disable-next-line react-hooks/rules-of-hooks + const actionRef = useRef(); + // 二维码下载弹窗 + // eslint-disable-next-line react-hooks/rules-of-hooks + const [isopenshow, setopenshow] = useState(false); + // 下载回显的数据 + // eslint-disable-next-line react-hooks/rules-of-hooks + const [information, setinformation] = useState(); + + // 桶记录弹窗 + + // eslint-disable-next-line react-hooks/rules-of-hooks + const [isrecord, setrecord] = useState(false) + + + + + const columns: ProColumns[] = [ + { + title: 'id', + dataIndex: 'id', + tip: '规则名称是唯一的 key', + hideInSearch: true, + hideInTable: true, + }, + { + title: '桶名称', + dataIndex: 'name', + ellipsis: true, + }, + + { + title: '桶编号', + dataIndex: 'code', + hideInSearch: true, + ellipsis: true, + }, + { + title: '当前原料', + dataIndex: 'des', + ellipsis: true, + hideInSearch: true, + + }, + { + title: '桶二维码', + dataIndex: 'type', + ellipsis: true, + hideInSearch: true, + + }, + + { + title: '操作', + valueType: 'option', + key: 'option', + align:'center', + render: (_, record) => [ + + + , + + , + + , + + { + + const EnablejsonData: DeviceTypes.Info = { + id: record.id, + name: '', + code: '' + }; + + DeviceInfoAPI.Del(EnablejsonData).then((r) => { + if (r.statusCode === 200) { + message.success(r.statusCode === 200 ? '删除成功' : r.message); + actionRef.current?.reload(); + } + }); + }} + onCancel={() => { + message.info('已取消删除'); + }} + okText="确认" + cancelText="关闭" + > + + + , + + + ], + }, + ]; + + + // 定义桶记录里面的列表 + const data:ColumnsType = [ + { + title: 'id', + dataIndex: 'id', + // tip: '规则名称是唯一的 key', + hideInSearch: true, + hideInTable: true, + }, + { + title: '工单ID', + dataIndex: 'name', + key: 'name', + align:'center' + }, + { + title: '工单名称', + dataIndex: 'age', + key: 'age', + align:'center', + + ellipsis: true, + }, + + { + title: '原料', + dataIndex: 'age1', + key: 'age1', + align:'center' + }, + { + title: '原料重量', + dataIndex: 'age2', + key: 'age2', + align:'center' + }, + { + title: '时间', + dataIndex: 'age3', + key: 'age3', + align:'center' + } + + ]; + + // eslint-disable-next-line react-hooks/rules-of-hooks + // const [aaadata, setaaadata] = useState() + + // 桶记录内的列表状态 + // eslint-disable-next-line react-hooks/rules-of-hooks + const [condition,setcondition] = useState() + + // 定义一个桶函数 + const chart =async ()=>{ +// 自定义属性 + const chartcheet: DeviceTypes.Page = { + pageIndex: 1, + pageSize: 10, + name: '', + id: '', + code: '' + }; + // const response = await DeviceInfoAPI.PagedList(bbbbbb);; + + // if (response.statusCode === 200) { + // setaaadata(response.data.items) + // } + try { + // 调用接口 + const response = await DeviceInfoAPI.PagedList(chartcheet); + // 如果调用成功 + if (response.statusCode === 200) { + // console.log(response); + // 将数据更新到列表最新状态 + setcondition(response.data.items); + + } + } catch (error) { + console.error('Error fetching data:', error); + } + + } + + // 表单提交 + const OnSubmit = async (values: DeviceTypes.Info) => { + + if (values.id) { + const response = await DeviceInfoAPI.Update(values); + if (response.statusCode === 200) { + message.success('修改成功'); + actionRef.current?.reload(); + setIsModalOpen(false); + } else { + message.error(JSON.stringify(response.errors) || '修改失败'); + } + } else { + const response = await DeviceInfoAPI.Add(values); + console.log('response', response); + if (response.statusCode === 200) { + message.success('添加成功'); + actionRef.current?.reload(); + setIsModalOpen(false); + } else { + message.error(JSON.stringify(response.errors) || '添加失败'); + } + } + }; + + return ( + <> + + key="myTable" + columns={columns} + actionRef={actionRef} + cardBordered + request={async (params = {}) => { + const jsonData: DeviceTypes.Page = { + pageIndex: params.current || 1, + pageSize: params.pageSize || 10, + name: params.name || '', + id: '', + code: '' + }; + const response = await DeviceInfoAPI.PagedList(jsonData); + if (response.statusCode === 200) { + return { + data: response.data.items, + success: true, + total: response.data.total, + }; + } else { + return { + data: [], + success: false, + total: 0, + }; + } + }} + rowKey="id" + pagination={{ + pageSize: 10, + }} + dateFormatter="string" + headerTitle="桶列表" + toolBarRender={() => [ + , + ]} + /> + {modelTitle}} + open={isModalOpen} + onCancel={() => { + setIsModalOpen(false); + }} + footer={[ + , + , + ]} + > +
+ + + + + + + + + + + + + + + + + + +
+
+ + {/* 下载二维码 */} + 二维码} + open={isopenshow} + + + onCancel={() => { + setopenshow(false); + + }} + footer={[ + , + + ]} + > +
+
+
桶编号 : {information?.code}
+
桶名称 : {information?.name}
+
当前原料 :
+
+
+
+ + +
+
+
+ +
+ {/* 桶记录 */} + 桶记录} + open={isrecord} + onCancel={() => { + setrecord(false) + }} + footer={[ + , + + ]} + > +
+
桶编号 : {information?.code}
+
桶名称 :{information?.name}
+ + + + + + + ); +}; + +export default bucket; diff --git a/frontend/src/pages/final/index.less b/frontend/src/pages/final/index.less new file mode 100644 index 0000000..afafd28 --- /dev/null +++ b/frontend/src/pages/final/index.less @@ -0,0 +1,4 @@ +*{ + margin: 0; + padding: 0; +} \ No newline at end of file diff --git a/frontend/src/pages/final/index.tsx b/frontend/src/pages/final/index.tsx new file mode 100644 index 0000000..c0c2170 --- /dev/null +++ b/frontend/src/pages/final/index.tsx @@ -0,0 +1,282 @@ +// 成品管理 + +import type { ActionType, ProColumns } from '@ant-design/pro-components'; +import { ProTable } from '@ant-design/pro-components'; +import { Button, Modal, Form, Input, message, Popconfirm, TreeSelect, Select, Tag, Dropdown, Space, MenuProps } from 'antd'; +import { useRef, useState } from 'react'; +import DeviceInfoAPI from '@/api/DeviceInfo'; +import { DownOutlined } from '@ant-design/icons'; +import FormItem from 'antd/lib/form/FormItem'; +import { ItemType } from 'rc-menu/lib/interface'; + +const final = () => { + + //定于表单 + const [typeForm] = Form.useForm(); + + // 定义新增弹窗 + const [isModalOpen, setIsModalOpen] = useState(false); + + // 定义编辑弹窗 + const actionRef = useRef(); + + // 定义title + const [modelTitle, setModelTitle] = useState(); + // 定义列表数据 + const columns: ProColumns[] = [ + { + title: 'id', + dataIndex: 'id', + tip: '规则名称是唯一的 key', + hideInSearch: true, + hideInTable: true, + }, + + { + title: '成品编号', + dataIndex: 'code', + hideInSearch: false, + ellipsis: true, + }, + { + title: '成品名称', + dataIndex: 'name', + hideInSearch: false, + ellipsis: true, + }, + { + title: '成品配方', + dataIndex: 'pf', + ellipsis: true, + hideInSearch: true, + }, + { + title: '成品工艺', + dataIndex: 'gy', + ellipsis: true, + hideInSearch: true, + }, + + { + title: '操作', + valueType: 'option', + key: 'option', + render: (_, record) => [ + , + + { + + const EnablejsonData: DeviceTypes.Info = { + id: record.id, + name: '', + code: '' + }; + + DeviceInfoAPI.Del(EnablejsonData).then((r) => { + if (r.statusCode === 200) { + message.success(r.statusCode === 200 ? '删除成功' : r.message); + actionRef.current?.reload(); + } + }); + }} + onCancel={() => { + message.info('已取消删除'); + }} + okText="确认" + cancelText="关闭" + > + + , + ], + }, + ]; + const OnSubmit = async (values: DeviceTypes.Info) => { + + if (values.id) { + const response = await DeviceInfoAPI.Update(values); + if (response.statusCode === 200) { + message.success('修改成功'); + actionRef.current?.reload(); + setIsModalOpen(false); + } else { + message.error(JSON.stringify(response.errors) || '修改失败'); + } + } else { + const response = await DeviceInfoAPI.Add(values); + console.log('response', response); + if (response.statusCode === 200) { + message.success('添加成功'); + actionRef.current?.reload(); + setIsModalOpen(false); + } else { + message.error(JSON.stringify(response.errors) || '添加失败'); + } + } + }; + + // 定义配方列表的数据 + // const item: MenuProps['items'] = [ + // { + // label: 'hini', + // key: '1', + // }, + // { + // label: 'eer ', + // key: '2', + // } + // ]; +// 定义工艺列表 + const areas = [ + { label: '工艺1', value: '工艺1' }, + { label: '工艺2', value: '工艺1' }, + ]; +// 定义配方列表 +const formula = [ + { label: '配方1', value: '配方1' }, + { label: '配方2', value: '配方1' }, +]; + return ( + <> + + key="myTable" + columns={columns} + actionRef={actionRef} + cardBordered + // 调用接口判断 + request={async (params = {}) => { + const jsonData: DeviceTypes.Page = { + pageIndex: params.current || 1, + pageSize: params.pageSize || 10, + name: params.name || '', + id: '', + code: '' + }; + const response = await DeviceInfoAPI.PagedList(jsonData); + if (response.statusCode === 200) { + return { + data: response.data.items, + success: true, + total: response.data.total, + }; + } else { + return { + data: [], + success: false, + total: 0, + }; + } + }} + rowKey="id" + pagination={{ + pageSize: 10, + }} + dateFormatter="string" + headerTitle="成品列表" + toolBarRender={() => [ + , + ]} + + + + + /> + {/* 新增成品的model弹窗 */} + {modelTitle}} + open={isModalOpen} + onCancel={() => { + setIsModalOpen(false); + }} + footer={[ + , + , + ]} + > + {/* 新增成品表单 */} + +
+ + + + + + + + + + + {/* 工艺列表 */} + + + + + + + + + + +
+ + + + ); +}; + +export default final; diff --git a/frontend/src/pages/group/index.tsx b/frontend/src/pages/group/index.tsx new file mode 100644 index 0000000..ed77a50 --- /dev/null +++ b/frontend/src/pages/group/index.tsx @@ -0,0 +1,247 @@ +// 分组页面 +import type { ActionType, ProColumns } from '@ant-design/pro-components'; +import { ProTable } from '@ant-design/pro-components'; +import { Button, Modal, Form, Input, message, Popconfirm, Tag, QRCode, Table } from 'antd'; +import { useRef, useState } from 'react'; +import type { ColumnsType } from 'antd/es/table'; +import DeviceInfoAPI from '@/api/DeviceInfo'; +const group = () => { + // 4.定义编辑/新增的弹窗 + // eslint-disable-next-line react-hooks/rules-of-hooks + const [isModalOpen, setIsModalOpen] = useState(false); + // 下拉 + // eslint-disable-next-line react-hooks/rules-of-hooks + const [modelTitle, setModelTitle] = useState(); + + // eslint-disable-next-line react-hooks/rules-of-hooks + const actionRef = useRef(); + + // 6.定义表单 + // eslint-disable-next-line react-hooks/rules-of-hooks + const [typeForm] = Form.useForm(); + + // 1.定义列 + const columns: ProColumns[] = [ + { + title: 'id', + dataIndex: 'id', + tip: '规则名称是唯一的 key', + hideInSearch: true, + hideInTable: true, + + }, + { + title: '分组名称', + dataIndex: 'name', + ellipsis: true, + align: 'center' + }, + + { + title: '分组描述', + dataIndex: 'code', + hideInSearch: true, + ellipsis: true, + align: 'center' + }, + + + + { + title: '操作', + valueType: 'option', + key: 'option', + align: 'center', + // 4.操作内有两个按钮 + render: (_, record) => [ + + , + + // 删除 + { + + const EnablejsonData: DeviceTypes.Info = { + id: record.id, + name: '', + code: '' + }; + + DeviceInfoAPI.Del(EnablejsonData).then((r) => { + if (r.statusCode === 200) { + message.success(r.statusCode === 200 ? '删除成功' : r.message); + actionRef.current?.reload(); + } + }); + }} + onCancel={() => { + message.info('已取消删除'); + }} + okText="确认" + cancelText="关闭" + > + + + , + ] + + }, + ]; + + // 7.定义表单提交 + // 表单提交 + const OnSubmit = async (values: DeviceTypes.Info) => { + + if (values.id) { + const response = await DeviceInfoAPI.Update(values); + if (response.statusCode === 200) { + message.success('修改成功'); + actionRef.current?.reload(); + setIsModalOpen(false); + } else { + message.error(JSON.stringify(response.errors) || '修改失败'); + } + } else { + const response = await DeviceInfoAPI.Add(values); + console.log('response', response); + if (response.statusCode === 200) { + message.success('添加成功'); + actionRef.current?.reload(); + setIsModalOpen(false); + } else { + message.error(JSON.stringify(response.errors) || '添加失败'); + } + } + }; + + + return ( + <> + {/* 2.列的展现 */} + + key="myTable" + columns={columns} + + actionRef={actionRef} + cardBordered + // 3.调用列接口 + request={async (params = {}) => { + const jsonData: DeviceTypes.Page = { + pageIndex: params.current || 1, + pageSize: params.pageSize || 10, + name: params.name || '', + id: '', + code: '' + }; + const response = await DeviceInfoAPI.PagedList(jsonData); + if (response.statusCode === 200) { + return { + data: response.data.items, + success: true, + total: response.data.total, + }; + } else { + return { + data: [], + success: false, + total: 0, + }; + } + }} + // 展示的页数 + rowKey="id" + pagination={{ + pageSize: 10, + }} + dateFormatter="string" + headerTitle="分组列表" + toolBarRender={() => [ + , + ]} + + /> + {/* 5.弹窗 */} + {modelTitle}} + open={isModalOpen} + onCancel={() => { + setIsModalOpen(false); + }} + footer={[ + , + , + ]} + > + {/* 弹窗内的表单 */} +
+ + + + + + + + + + + + + +
+ + ) +} + +export default group \ No newline at end of file diff --git a/frontend/src/pages/manufacturing/index.less b/frontend/src/pages/manufacturing/index.less new file mode 100644 index 0000000..47c4907 --- /dev/null +++ b/frontend/src/pages/manufacturing/index.less @@ -0,0 +1,37 @@ +@primary-color: '#13C2C2'; +.tag { + height: 100%; + width: 100%; + &_item { + padding: 0 5px 0 20px; + height: 72px; + position: relative; + cursor: pointer; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + &_active { + position: absolute; + width: 3px; + height: 72px; + left: 0; + top: 0; + background-color: #13C2C2; + + } + &_activeItem{ + background-color: #f7f8fa;; + } + &_editicon{ + position: absolute; + right: 0; + top: 0; + bottom: 0; + display: flex; + align-items: center; + + } +} +} + diff --git a/frontend/src/pages/manufacturing/index.tsx b/frontend/src/pages/manufacturing/index.tsx new file mode 100644 index 0000000..0f7e6d4 --- /dev/null +++ b/frontend/src/pages/manufacturing/index.tsx @@ -0,0 +1,1199 @@ +// 产线管理 + +import { ActionType, EditableFormInstance, EditableProTable, ProCard, ProColumns } from '@ant-design/pro-components'; +import { ProTable } from '@ant-design/pro-components'; +import { Button, Modal, Form, Input, message, Popconfirm, Upload, UploadProps, Spin, Tag, Col, Divider, Row, Card, Space, Select } from 'antd'; +import { useEffect, useRef, useState } from 'react'; +import RecipeInfoAPI from '@/api/recipeService' +// import MaterialsInfoAPI from '@/api/materialService' +import GroupInfoAPI from '@/api/groupService' +import { LoadingOutlined, RedoOutlined, PlusSquareOutlined, EditOutlined } from '@ant-design/icons'; +// import { RcFile, UploadChangeParam, UploadFile } from 'antd/es/upload'; +// import { history } from '@umijs/max'; +import styles from './index.less' +const { Option } = Select; + +const Index = () => { + //表单 + const [typeForm] = Form.useForm(); + // 料仓表单 + const [binForm] = Form.useForm() + + //编辑/新增弹窗 + const [isModalOpen, setIsModalOpen] = useState(false); + const [isModalGroupOpen, setIsModalGroupOpen] = useState(false); + + + // 料仓弹窗 + const [binModelopen, setbinModelopen] = useState(false) + + + + // const [spinStatus, setSpinStatus] = useState(false); + // const [isEditModalOpen, setIsEditModalOpen] = useState(false); + const [isModalGroupFormOpen, setIsModalGroupFormOpen] = useState(false); + const [selectGroup, setSelectGroup] = useState(0) + const [recipeparams, setRecipeparams] = useState(); + const [GroupList, setGroupList] = useState([{ + id: '-1', + name: '全部', + des: '全部' + }]); + // const [selectRowItem, setSelectRowItem] = useState(); + // const [materiallist, setMateriallist] = useState([]); + // const [selectMateriallist, setSelectMateriallist] = useState([]); + // const [imageUrl, setImageUrl] = useState(); + // const [loading, setLoading] = useState(false); + const actionRef = useRef(); + const [formRef] = Form.useForm(); + // const editactionformRef = useRef(); + // const editactionRef = useRef(); + const [groupForm] = Form.useForm(); + const [GroupEditForm] = Form.useForm(); + //设备成功方法 + const OnSubmit = async (values: RecipeTypes.Info) => { + // values.picUrl = imageUrl!; + if (values.id) { + const response = await RecipeInfoAPI.Update(values); + if (response.statusCode === 200) { + message.success('修改成功'); + actionRef.current?.reload(); + setIsModalOpen(false); + } else { + message.error(response.errors || '修改失败'); + } + } else { + const response = await RecipeInfoAPI.Add(values); + if (response.statusCode === 200) { + message.success('添加成功'); + + actionRef.current?.reload(); + setIsModalOpen(false); + } else { + message.error(response.errors || '添加失败'); + } + } + } + + // 料仓成功 + + const submission = async (values: RecipeTypes.Info) => { + // values.picUrl = imageUrl!; + if (values.id) { + const response = await RecipeInfoAPI.Update(values); + if (response.statusCode === 200) { + message.success('修改成功'); + + actionRef.current?.reload(); + setbinModelopen(false); + } else { + message.error(response.errors || '修改失败'); + } + } else { + const response = await RecipeInfoAPI.Add(values); + if (response.statusCode === 200) { + message.success('添加成功'); + actionRef.current?.reload(); + setbinModelopen(false); + } else { + message.error(response.errors || '添加失败'); + } + } + } + + + + // const beforeUpload = (file: RcFile) => { + // console.log('file', file); + // } + + // const handleChange: UploadProps['onChange'] = (info: UploadChangeParam) => { + // setLoading(true); + // if (info.file.status === 'uploading') { + // setLoading(true); + // return; + // } + // if (info.file.status === 'done') { + // console.log('info', info); + // // Get this url from response in real world. + // setLoading(false); + // const { statusCode, data } = info.file.response; + // if (statusCode === 200) { + // console.log('data', data); + // setImageUrl("http://162.14.105.138:8333/uploads" + data); + // } + // } + // } + // const uploadButton = ( + //
+ // {loading ? : ''} + //
+ // ) + //表单名 + const columns: ProColumns[] = [ + { + title: '设备名称', + dataIndex: 'code', + width: 200, + align: 'center', + hideInSearch: true, + // valueType: { + // type: 'image', + // width: 60, + // } + }, + { + title: '设备功能', + width: 200, + dataIndex: 'name', + align: 'center', + }, + { + title: '当前产线', + width: 200, + dataIndex: 'groupId', + hideInSearch: true, + renderText(text, record) { + return <>{GroupList.find(x => x.id === record.groupId)?.name} + }, + align: 'center', + }, + { + title: '设备类型', + dataIndex: 'code', + align: 'center', + width: 100, + hideInSearch: true + }, + { + title: '操作', + align: 'center', + width: 40, + valueType: 'option', + + + key: 'option', + render: (_, record) => [ + + {/* */} + {/* */} + + {/* {record.groupId ? + + + + : + + + } */} + + { + const delData: RecipeTypes.Info = { + id: record.id, + name: '', + code: '', + picUrl: '', + groupId: '' + }; + RecipeInfoAPI.Del(delData).then((r) => { + if (r.statusCode === 200) { + message.success(r.statusCode === 200 ? '删除成功' : r.message); + actionRef.current?.reload(); + } + }); + }} + onCancel={() => { + message.info('已取消删除'); + }} + okText="确认" + cancelText="关闭" + > + + + + ], + }, + ]; + + // 料仓列表 + const list: ProColumns[] = [ + { + title: '料仓名称', + dataIndex: 'code', + width: 200, + align: 'center', + // hideInSearch: true, + // valueType: { + // type: 'image', + // width: 60, + // } + }, + { + title: '料仓剩余', + width: 200, + dataIndex: 'name', + align: 'center', + hideInSearch: true, + + }, + { + title: '当前产线', + width: 200, + dataIndex: 'groupId', + hideInSearch: true, + renderText(text, record) { + return <>{GroupList.find(x => x.id === record.groupId)?.name} + }, + align: 'center', + }, + + + { + title: '操作', + align: 'center', + width: 10, + + valueType: 'option', + + key: 'option', + render: (_, record) => [ + + {/* */} + {/* */} + + {/* {record.groupId ? + + : + + } */} + + + + + { + const delData: RecipeTypes.Info = { + id: record.id, + name: '', + code: '', + picUrl: '', + groupId: '' + }; + RecipeInfoAPI.Del(delData).then((r) => { + if (r.statusCode === 200) { + message.success(r.statusCode === 200 ? '删除成功' : r.message); + actionRef.current?.reload(); + } + }); + }} + onCancel={() => { + message.info('已取消删除'); + }} + okText="确认" + cancelText="关闭" + > + + + + ], + }, + ]; + + + + + + + + + // 获取分组数据 + const GetGroupList = () => { + GroupInfoAPI.List().then((res: MyResponse.Content) => { + if (res.statusCode === 200) { + res.data.unshift( + { + id: '-1', + name: '全部', + des: '全部' + } + ) + setGroupList(res.data) + } + }) + } + // 更新分组 + const OnGroupSubmit = (value: any) => { + const jsonData: RecipeTypes.RecipesGroupInput = { + GroupId: value.groupId, + RecipesId: value.id + } + RecipeInfoAPI.ChangeGroup(jsonData).then((res: MyResponse.Content) => { + if (res.statusCode === 200) { + message.success("设置完成"); + setIsModalGroupOpen(false); + actionRef.current?.reload(); + } else { + message.error("设置失败"); + } + }); + } + // 修改分组数据 + const OnGroupEditSubmit = (value: GroupInfoTypes.Info) => { + if (value.id) { + GroupInfoAPI.Update(value).then((res: MyResponse.Content) => { + if (res.statusCode) { + message.success("修改成功"); + setIsModalGroupFormOpen(false); + GetGroupList(); + } else { + message.success("修改失败"); + } + }) + } else { + GroupInfoAPI.Add(value).then((res: MyResponse.Content) => { + if (res.statusCode) { + message.success("新增成功"); + setIsModalGroupFormOpen(false); + GetGroupList(); + + } else { + message.success("新增失败"); + } + }) + } + GroupEditForm.resetFields(); + } + useEffect(() => { + GetGroupList(); + }, []) + useEffect(() => { + const jsonData: RecipeTypes.Page = { + pageIndex: 1, + pageSize: 4, + picUrl: '', + id: '', + code: '', + groupId: GroupList[selectGroup].id === '-1' ? '' : GroupList[selectGroup].id + }; + setRecipeparams(jsonData); + }, [selectGroup]) + // const editcolumns: ProColumns[] = [ + // // { + // // title: '物料名称/wos', + // // dataIndex: 'materialId', + // // valueType: 'select', + // // tooltip:'wos为每秒出水量', + // // ellipsis: true, + // // request: async () => { + // // const res: MyResponse.Content = await MaterialsInfoAPI.List(); + // // const myData: any[] = []; + // // if (res.statusCode === 200) { + // // setSelectMateriallist(res.data) + // // res.data.map((item: MaterialsTypes.MaterialsInfo) => ( + // // myData.push({ + // // label: `${item.name}-[${item.wos}${item.unit}]`, + // // value: item.id, + // // }) + // // )) + // // } + // // return myData; + // // }, + // // formItemProps: (form, { rowIndex }) => { + // // return { + // // rules: [{ required: true, message: '此项为必填项' }] + // // }; + // // }, + // // }, + + // // { + // // title: '通道号', + // // dataIndex: 'outlet', + // // tooltip: "设备出料口编号", + // // valueType: 'text', + // // ellipsis: true, + // // formItemProps: (form, { rowIndex }) => { + // // return { + // // rules: [{ required: true, message: '此项为必填项' }] , + // // }; + // // }, + // // }, + // // { + // // title: '重量(g)', + // // dataIndex: 'time', + // // valueType: 'text', + // // ellipsis: true, + // // formItemProps: (form, { rowIndex }) => { + // // return { + // // rules: [{ required: true, message: '此项为必填项' }] , + // // }; + // // }, + // // }, + // // { + // // title: '步骤', + // // dataIndex: 'sort', + // // valueType: 'text', + // // tooltip: "步骤不可重复", + // // ellipsis: true, + // // formItemProps: (form, { rowIndex }) => { + // // return { + // // rules: [{ required: true, message: '此项为必填项' }] + // // // , + // // // () => ({ + // // // validator(_, value) { + // // // if (!materiallist[rowIndex]) { + // // // if (!materiallist.find(x => x.sort === value)) { + // // // return Promise.resolve(); + // // // } + // // // } else { + // // // if (materiallist.filter(x => x.sort === value && x.id !== materiallist[rowIndex].id).length < 1) { + // // // return Promise.resolve(); + // // // } + // // // } + // // // return Promise.reject(new Error('已存在步骤!')); + // // // }, + // // // }) + // // }; + // // }, + // // }, + // // { + // // title: '操作', + // // valueType: 'option', + // // render: (_, row) => [ + // // // , + // // // + // // ], + // // }, + // ]; + return ( + <> + { + /* + * 产线 + */} + +
+ + + + + + +
+ {GroupList.map((item, index) => ( +
{ + // 当前选中的设备 + setSelectGroup(index); + + + }} className={`${styles.tag_item} ${index === selectGroup ? styles.tag_item_activeItem : ''}`}> + +
{item.name}
+ {item.id === "-1" ? '' :
{ + e.stopPropagation(); + const copyFormData = JSON.parse(JSON.stringify(GroupList[index])); + GroupEditForm.setFieldsValue(copyFormData); + setIsModalGroupFormOpen(true) + }} twoToneColor="#eb2f96">
} +
+
+
+ ))} +
+
+ + + {/* 设备列表 */} + + key="myTable" + columns={columns} + actionRef={actionRef} + + + cardBordered + params={recipeparams} + request={async (params = {}) => { + console.log('params', params); + + const jsonData: RecipeTypes.Page = { + pageIndex: params.current || 1, + pageSize: params.pageSize || 4, + name: params.name || '', + id: params.id, + code: params.code, + picUrl: '', + groupId: params.groupId + }; + const response = await RecipeInfoAPI.PagedList(jsonData); + if (response.statusCode === 200) { + return { + data: response.data.items, + success: true, + total: response.data.total, + }; + } else { + return { + data: [], + success: false, + total: 0, + }; + } + }} + rowKey="id" + pagination={{ + pageSize: 4, + }} + dateFormatter="string" + headerTitle="设备列表" + toolBarRender={() => [ + , + ]} + /> + + {/* 料仓列表 */} + + key="myTable2" + columns={list} + actionRef={actionRef} + cardBordered + params={recipeparams} + request={async (params = {}) => { + console.log('params', params); + + const jsonData: RecipeTypes.Page = { + pageIndex: params.current || 1, + pageSize: params.pageSize || 4, + name: params.name || '', + id: params.id, + code: params.code, + picUrl: '', + groupId: params.groupId + }; + const response = await RecipeInfoAPI.PagedList(jsonData); + if (response.statusCode === 200) { + return { + data: response.data.items, + success: true, + total: response.data.total, + }; + } else { + return { + data: [], + success: false, + total: 0, + }; + } + }} + rowKey="id" + pagination={{ + pageSize: 4, + }} + dateFormatter="string" + headerTitle="料仓列表" + toolBarRender={() => [ + , + ]} + + + /> + + + + + + { + /* + * 设备绑定 + */} + 设备绑定} + open={isModalOpen} + onCancel={() => { + setIsModalOpen(false); + }} + footer={[ + , + , + ]} + > +
+ + + + + + + + + + + {/* + + */} + + + + {/* ({ + validator() { + if (!imageUrl) { + return Promise.reject(new Error('此项必填!')); + } else { + return Promise.resolve(); + } + }, + }) + , + ]} + > + + {imageUrl ? avatar : uploadButton} + +
+ {uploadButton} +
+
*/} + +
+ + + + + + + {/* 料仓绑定 */} + 料仓绑定} + + open={binModelopen} + onCancel={() => { + setbinModelopen(false); + }} + footer={[ + , + , + ]} + > +
+ + + + + + + + + + + +
+ + + + + + + + + { + /* + * 配置物料与工艺的弹框 + */} + {/* { + setIsEditModalOpen(false); + setMateriallist([]); + }} + onOk={() => { + const list: RecipeMaterialTypes.Info[] = JSON.parse(JSON.stringify(materiallist)); + list.map((item) => { + item.recipesId = selectRowItem.id; + item.id = ''; + }) + RecipeInfoAPI.BatchAdd(list).then((res: MyResponse.Content) => { + if (res.statusCode === 200) { + message.success("保存成功!"); + setIsEditModalOpen(false); + } else { + message.error("保存失败!"); + } + }); + }} + > + + +
+ + rowKey="id" + controlled + editableFormRef = {editactionformRef} + actionRef={editactionRef} + columns={editcolumns} + value={materiallist} + // onChange={setMateriallist} + recordCreatorProps={{ + record: () => ( + { + id: Date.now().toString(), + materialId: '', + recipesId: '', + outlet: '', + sort: '', + time: '', + wos:'', + }) + , + } + } + editable={{ + form: formRef, + type: 'single', + onValuesChange: (record, recordList:RecipeMaterialTypes.Info[]) => { + console.log(selectMateriallist); + + recordList.map((res) => { + if (!res.wos) { + res.wos = selectMateriallist.find((x) => x.id === res.materialId)?.wos; + } + }); + if (!recordList) { + record.wos = selectMateriallist.find((x) => x.id === record.materialId)?.wos; + materiallist.push(record); + setMateriallist(materiallist); + }else{ + setMateriallist(recordList); + } + console.log('materiallist',materiallist); + + }, + actionRender: (row, _, dom) => { + return [dom.delete, dom.save, dom.cancel]; + }, + }} + /> +
+
+
+ +
*/} + { + /* + * 新增产线的弹框 + */} + 新增产线} + onCancel={() => { + GroupEditForm.resetFields(); + setIsModalGroupFormOpen(false) + }} + footer={[ + { + console.log('sss', GroupEditForm.getFieldValue('id')); + const delJosnData: GroupInfoTypes.Info = { + id: GroupEditForm.getFieldValue('id'), + name: '', + des: '' + }; + GroupInfoAPI.Del(delJosnData).then((res: MyResponse.Content) => { + if (res.statusCode === 200) { + message.success("删除成功!"); + setIsModalGroupFormOpen(false); + GetGroupList(); + } + }) + }} + onCancel={() => { }} + > + + , + , + ]} + > + {/* 新增产线的表单 */} +
+ + + + + + + + + + + +
+ { + /* + * 修改产线的弹框 + */} + 修改产线} + centered + onCancel={() => setIsModalGroupOpen(false)} + destroyOnClose + footer={[ + , + , + ]} + > + + {/* 修改产线选择分类 */} +
+ + + + + + +
+ + {/* */} + + + + ) +} + +export default Index; diff --git a/frontend/src/pages/stock/index.tsx b/frontend/src/pages/stock/index.tsx new file mode 100644 index 0000000..c68aba4 --- /dev/null +++ b/frontend/src/pages/stock/index.tsx @@ -0,0 +1,268 @@ + +// 料仓基础信息 + +import type { ActionType, ProColumns } from '@ant-design/pro-components'; +import { ProTable } from '@ant-design/pro-components'; +import { Button, Modal, Form, Input, message, Popconfirm, Transfer, Tag, Col } from 'antd'; +import { useRef, useState, useEffect } from 'react'; +// import { history } from '@umijs/max'; +import DeviceInfoAPI from '@/api/DeviceInfo'; +// import RecipeAPI from '@/api/recipeService' +// import { TransferDirection } from 'antd/es/transfer'; + + +// interface RecordType { +// key: string; +// title: string; +// description: string; +// chosen: boolean; +// } +// let selectRecordId :string; +export default () => { + //表单 + const [typeForm] = Form.useForm(); + + //下拉列表 + // const [isMaterialModalOpen, setIsMaterialModalOpen] = useState(false); + const [modelTitle, setModelTitle] = useState(); + //编辑/新增弹窗 + const [isModalOpen, setIsModalOpen] = useState(false); + const actionRef = useRef(); + const columns: ProColumns[] = [ + { + title: 'id', + dataIndex: 'id', + tip: '规则名称是唯一的 key', + hideInSearch: true, + hideInTable: true, + }, + { + title: '料仓名称', + dataIndex: 'name', + ellipsis: true, + }, + { + title: '料仓原料', + dataIndex: 'code', + ellipsis: true, + hideInSearch: true, + }, + { + title: '料仓编号', + dataIndex: 'code', + hideInSearch: true, + ellipsis: true, + }, + { + title: '剩余', + dataIndex: 'des', + ellipsis: true, + hideInSearch: true, + }, + { + title: '料仓容积', + dataIndex: 'type', + ellipsis: true, + hideInSearch: true, + }, + + { + title: '操作', + valueType: 'option', + key: 'option', + render: (_, record) => [ + , + + { + + const EnablejsonData: DeviceTypes.Info = { + id: record.id, + name: '', + code: '' + }; + + DeviceInfoAPI.Del(EnablejsonData).then((r) => { + if (r.statusCode === 200) { + message.success(r.statusCode === 200 ? '删除成功' : r.message); + actionRef.current?.reload(); + } + }); + }} + onCancel={() => { + message.info('已取消删除'); + }} + okText="确认" + cancelText="关闭" + > + + , + ], + }, + ]; + + /* + 初始化 + */ + useEffect(() => { + // 下拉列表信息 + const RegionDataList = () => { + + }; + RegionDataList(); + }, []); + /* + *表单提交 + */ + const OnSubmit = async (values: DeviceTypes.Info) => { + + if (values.id) { + const response = await DeviceInfoAPI.Update(values); + if (response.statusCode === 200) { + message.success('修改成功'); + actionRef.current?.reload(); + setIsModalOpen(false); + } else { + message.error(JSON.stringify(response.errors) || '修改失败'); + } + } else { + const response = await DeviceInfoAPI.Add(values); + console.log('response', response); + if (response.statusCode === 200) { + message.success('添加成功'); + actionRef.current?.reload(); + setIsModalOpen(false); + } else { + message.error(JSON.stringify(response.errors) || '添加失败'); + } + } + }; + return ( + <> + + key="myTable" + columns={columns} + actionRef={actionRef} + cardBordered + request={async (params = {}) => { + const jsonData: DeviceTypes.Page = { + pageIndex: params.current || 1, + pageSize: params.pageSize || 10, + name: params.name || '', + id: '', + code: '' + }; + const response = await DeviceInfoAPI.PagedList(jsonData); + if (response.statusCode === 200) { + return { + data: response.data.items, + success: true, + total: response.data.total, + }; + } else { + return { + data: [], + success: false, + total: 0, + }; + } + }} + rowKey="id" + pagination={{ + pageSize: 10, + }} + dateFormatter="string" + headerTitle="料仓列表" + toolBarRender={() => [ + , + ]} + /> + {modelTitle}} + open={isModalOpen} + onCancel={() => { + setIsModalOpen(false); + }} + footer={[ + , + , + ]} + > +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + ); +}; diff --git a/k8s_pztjapi.yaml b/k8s_pztjapi.yaml new file mode 100644 index 0000000..fdd8267 --- /dev/null +++ b/k8s_pztjapi.yaml @@ -0,0 +1,64 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: pztjapi + namespace: kube- +spec: + + selector: + matchLabels: + app: pztjapi + replicas: 1 + template: + metadata: + labels: + app: pztjapi + spec: + containers: + - image: 10.2.1.24:10242/bpa/pztjapi: + imagePullPolicy: IfNotPresent + name: pztjapi + env: + - name: branch + value: + - name: TZ + value: Asia/Shanghai + ports: + - containerPort: 80 + protocol: TCP + volumeMounts: + - mountPath: "/app/appsettings.json" + name: pztjapi-config + readOnly: true + subPath: appsettings + - mountPath: "/etc/localtime" + name: timezone + resources: + requests: + cpu: "100m" + memory: "112Mi" + limits: + cpu: "500m" + memory: "512Mi" + volumes: + - name: pztjapi-config + configMap: + name: pztjapi-config + - name: timezone + hostPath: + path: /usr/share/zoneinfo/Asia/Shanghai +--- +kind: Service +apiVersion: v1 +metadata: + labels: + app: pztjapi + name: pztjapi + namespace: kube- +spec: + type: ClusterIP + ports: + - port: 80 + name: http + selector: + app: pztjapi diff --git a/k8s_pztjweb.yaml b/k8s_pztjweb.yaml new file mode 100644 index 0000000..37824df --- /dev/null +++ b/k8s_pztjweb.yaml @@ -0,0 +1,55 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: pztjweb + namespace: kube- +spec: + + selector: + matchLabels: + app: pztjweb + replicas: 1 + template: + metadata: + labels: + app: pztjweb + spec: + containers: + - image: 10.2.1.24:10242/bpa/pztjweb: + imagePullPolicy: IfNotPresent + name: pztjweb + env: + - name: branch + value: + ports: + - containerPort: 80 + protocol: TCP + volumeMounts: + - mountPath: "/etc/localtime" + name: timezone + resources: + requests: + cpu: "100m" + memory: "112Mi" + limits: + cpu: "500m" + memory: "512Mi" + volumes: + - name: timezone + hostPath: + path: /usr/share/zoneinfo/Asia/Shanghai +--- +kind: Service +apiVersion: v1 +metadata: + labels: + app: pztjweb + name: pztjweb + namespace: kube- +spec: + type: ClusterIP + ports: + - port: 80 + name: http + selector: + app: pztjweb