ylj20011123 59c2d7d5bd update
2025-07-11 21:09:14 +08:00

687 lines
30 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 点餐类别管理 点餐分类管理
import React, { useRef, useState, Suspense } from 'react';
import moment from 'moment'; // 时间相关引用,没有使用可以删除
import numeral from "numeral"; // 数字相关引用,没有使用可以删除
import { connect } from 'umi';
import useRequest from '@ahooksjs/use-request'; // 请求数据的引用
import Draggable from 'react-draggable';
import SubMenu from "antd/lib/menu/SubMenu";
import ProTable from '@ant-design/pro-table';
import ProDescriptions from '@ant-design/pro-descriptions';
import ProForm, { ProFormDatePicker, ProFormDateTimePicker, ProFormDateTimeRangePicker, ProFormDigit, ProFormMoney, ProFormSelect, ProFormText, ProFormTextArea, ProFormTreeSelect, ProFormUploadButton } from '@ant-design/pro-form';
import { MenuFoldOutlined, PlusOutlined, ExclamationCircleOutlined } from '@ant-design/icons';
import { PageContainer } from '@ant-design/pro-layout';
import { Button, Col, Drawer, message, Row, Popconfirm, Space, Image, Modal, Form, Switch, Upload, Tooltip, Descriptions, TreeSelect } from 'antd';
import type { CurrentUser } from "umi";
import type { ConnectState } from '@/models/connect';
import type { ActionType, ProColumns } from '@ant-design/pro-table';
import type { ProDescriptionsItemProps } from '@ant-design/pro-descriptions';
import type { FormInstance } from 'antd';
import { getFieldEnumTree, getFieldEnumName } from "@/services/options"; // 枚举的引用,没有使用可以删除
import { handlDeleteUSERDEFINEDTYPE, handlGetUSERDEFINEDTYPEList, handlSynchroUSERDEFINEDTYPE } from '../service';
import PageTitleBox from '@/components/PageTitleBox';
import { uploadPicture } from '@/services/picture';
import defaultIcon from '../../../assets/brand/defaultIcon.png'
import classNames from 'classnames';
import ModalFooter from '../scenicSpotConfig/component/modalFooter';
const beforeUpload = (file: any) => {
const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
if (!isJpgOrPng) {
message.error('请上传JPEG、jpg、png格式的图片文件!');
}
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isLt2M) {
message.error('图片大小不超过 2MB!');
}
return isJpgOrPng && isLt2M;
}
const OrderCategoryManage: React.FC<{ currentUser: CurrentUser | undefined }> = (props) => {
const { currentUser } = props
const { confirm } = Modal;
const actionRef = useRef<ActionType>();
const formRef = useRef<FormInstance>();
const [currentRow, setCurrentRow] = useState<any>();
const [showDetail, setShowDetail] = useState<boolean>();
const [modalVisible, handleModalVisible] = useState<boolean>();
const [confirmLoading, handleConfirmLoading] = useState<boolean>(false) // 弹出框的内容表单是否在提交
const [searchParams, setSearchParams] = useState<any>();
// 分类的树形结构数据
const [typeTreeData, setTypeTreeData] = useState<any>()
// 表单里面的是否预售
const [formPRESALE_TYPE, setFormPRESALE_TYPE] = useState<boolean>(false)
// 弹出框拖动效果
const [bounds, setBounds] = useState<{ left: number, right: number, top: number, bottom: number }>() // 移动的位置
const [disabled, setDraggleDisabled] = useState<boolean>() // 是否拖动
const draggleRef = React.createRef<any>()
// 文件列表
const [fileList, setFileList] = useState<any>([])
const [imagePreviewVisible, setImagePreviewVisible] = useState<boolean>(false) // 预览图片
const onDraggaleStart = (event, uiData) => {
const { clientWidth, clientHeight } = window.document.documentElement;
const targetRect = draggleRef.current?.getBoundingClientRect();
if (!targetRect) {
return;
}
setBounds({
left: -targetRect.left + uiData.x,
right: clientWidth - (targetRect.right - uiData.x),
top: -targetRect.top + uiData.y,
bottom: clientHeight - (targetRect.bottom - uiData.y),
});
};
// 定义列表字段内容
const columns: any = [
// {
// title: '上级类别',
// align: 'center',
// width: 150,
// ellipsis: true,
// dataIndex: 'USERDEFINEDTYPE_PID',
// hideInSearch: true,
// hideInDescriptions: true,
// },
{
dataIndex: 'USERDEFINEDTYPE_NAME',
title: '类别名称',
align: 'center',
width: 300,
ellipsis: true,
hideInSearch: true,
hideInDescriptions: true,
render: (_, record) => {
return <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'flex-start' }}>
<img style={{ width: '30px', height: '30px', marginRight: '5px', borderRadius: '50%' }} src={record?.USERDEFINEDTYPE_ICO || defaultIcon} />
<a style={{ width: '240px', display: "inline-block", whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', textAlign: 'left' }}
onClick={() => {
if (record?.USERDEFINEDTYPE_ICO) {
setFileList([{
name: "",
url: record?.USERDEFINEDTYPE_ICO
}])
}
if (record?.PRESALE_TYPE) {
setFormPRESALE_TYPE(true)
}
setCurrentRow({ ...record });
handleModalVisible(true);
}}
>{record?.USERDEFINEDTYPE_NAME}</a>
</div>
}
},
{
dataIndex: 'USERDEFINEDTYPE_INDEX',
title: '类别索引',
align: 'center',
width: 120,
ellipsis: true,
hideInSearch: true,
},
{
dataIndex: 'USERDEFINEDTYPE_STATE',
title: '有效状态',
align: 'center',
width: 120,
ellipsis: true,
valueType: "select",
valueEnum: {
"1": "有效",
"0": "无效"
},
initialValue: "1"
},
{
dataIndex: 'SCANCODE_ORDER',
title: '上架状态',
align: 'center',
width: 120,
ellipsis: true,
hideInSearch: true,
valueType: "select",
valueEnum: {
"1": "上架",
"0": "下架"
}
},
{
dataIndex: "PRESALE_TYPE",
title: "是否预售",
align: 'center',
hideInSearch: true,
width: 120,
ellipsis: true,
valueType: "select",
valueEnum: {
"0": "否",
"1": "是"
}
},
{
dataIndex: 'OWNERUNIT_NAME',
title: '业主单位',
align: 'center',
width: 180,
ellipsis: true,
hideInSearch: true,
},
// {
// dataIndex: 'option',
// title: '操作',
// width: 100,
// ellipsis: true,
// valueType: 'option',
// align: 'center',
// hideInSearch: true,
// render: (_, record) => {
// return (
// <Space>
// <a
// onClick={() => {
// console.log('recordrecordrecord', record);
// if (record?.USERDEFINEDTYPE_ICO) {
// setFileList([{
// name: "",
// url: record?.USERDEFINEDTYPE_ICO
// }])
// }
// if (record?.PRESALE_TYPE) {
// setFormPRESALE_TYPE(true)
// }
// setCurrentRow({ ...record });
// handleModalVisible(true);
// }}
// >
// 编辑
// </a>
// <Popconfirm
// title="确认删除该点餐自定义类别列表信息吗?"
// onConfirm={async () => {
// handelDelete(record.USERDEFINEDTYPE_ID);
// }}
// >
// <a>删除</a>
// </Popconfirm>
// </Space>
// );
// },
// },
];
// 预览上传后的图片
const handlePreview = async () => {
setFileList(fileList)
setImagePreviewVisible(true)
};
const handleChangePreview = (val: any) => {
setImagePreviewVisible(val)
}
// 删除点餐类别
const handelDelete = async (id: any) => {
const req: any = {
USERDEFINEDTYPEId: id
}
const result = await handlDeleteUSERDEFINEDTYPE(req)
if (result.Result_Code !== 100) {
message.error(`${result.Result_Desc}` || `${result.Result_Code}:删除失败`);
} else {
message.success('删除成功!');
actionRef.current?.reload()
handleConfirmLoading(false)
handleModalVisible(false)
setFormPRESALE_TYPE(false)
setFileList([])
}
}
// 同步点餐列表
const handleAddUpdate = async (res: any) => {
let req: any = {}
if (currentRow?.USERDEFINEDTYPE_ID) {
req = {
...currentRow,
...res,
GOODSTYPE: 3000,
USERDEFINEDTYPE_ICO: fileList && fileList.length > 0 ? fileList[0].url : "",
PRESALE_STARTTIME: res.PRESALE_TIME && res.PRESALE_TIME.length > 0 ? res.PRESALE_TIME[0] : "",
PRESALE_ENDTIME: res.PRESALE_TIME && res.PRESALE_TIME.length > 0 ? res.PRESALE_TIME[1] : "",
PROVINCE_CODE: currentUser?.ProvinceCode,
STAFF_ID: currentUser?.ID,
STAFF_NAME: currentUser?.Name,
OPERATE_DATE: moment().format('YYYY-MM-DD HH:mm:ss'),
}
} else {
req = {
...res,
GOODSTYPE: 3000,
USERDEFINEDTYPE_ICO: fileList && fileList.length > 0 ? fileList[0].url : "",
PRESALE_STARTTIME: res.PRESALE_TIME && res.PRESALE_TIME.length > 0 ? res.PRESALE_TIME[0] : "",
PRESALE_ENDTIME: res.PRESALE_TIME && res.PRESALE_TIME.length > 0 ? res.PRESALE_TIME[1] : "",
PROVINCE_CODE: currentUser?.ProvinceCode,
STAFF_ID: currentUser?.ID,
STAFF_NAME: currentUser?.Name,
OPERATE_DATE: moment().format('YYYY-MM-DD HH:mm:ss'),
USERDEFINEDTYPE_DATE: moment().format('YYYY-MM-DD HH:mm:ss'),
}
}
const data = await handlSynchroUSERDEFINEDTYPE(req)
handleConfirmLoading(false)
if (data.Result_Code === 100) {
message.success("新增成功!")
setCurrentRow(undefined)
formRef?.current?.resetFields()
handleModalVisible(false)
setFormPRESALE_TYPE(false)
setFileList([])
actionRef.current?.reload()
} else {
message.error(data.Result_Desc)
}
}
return (
<PageContainer header={{
title: '',
breadcrumb: {}
}}>
<ProTable
style={{ height: 'calc(100vh - 135px)', background: '#fff' }}
scroll={{ y: 'calc(100vh - 410px)' }}
rowKey={(record) => {
return `${record?.USERDEFINEDTYPE_PID}-${record?.USERDEFINEDTYPE_ID}`
}}
formRef={formRef}
headerTitle={<PageTitleBox props={props} />} // 列表表头
actionRef={actionRef}
search={{ span: 6, labelWidth: 'auto' }}
bordered
// 请求数据
request={async (params, sorter) => {
const req = {
OWNERUNIT_ID: currentUser?.OwnerUnitId,
PROVINCE_CODE: "",
GOODSTYPE: 3000,
USERDEFINEDTYPE_STATE: params?.USERDEFINEDTYPE_STATE
// SearchKey: ""
}
const data = await handlGetUSERDEFINEDTYPEList(req);
console.log('datadatadatadatadata', data);
if (data && data.length > 0) {
setTypeTreeData(data)
return { data: data, success: true, total: data.length }
}
return { data: [], success: true }
}}
columns={columns}
toolbar={{
actions: [
// 新增按钮
<Button
key="new"
icon={<PlusOutlined />}
type="primary"
onClick={() => {
handleModalVisible(true);
}}
>
</Button>,
],
}}
/>
{/* 图片预览组件 */}
{fileList && fileList.length > 0 && <div style={{ display: 'none' }}>
<Image.PreviewGroup
preview={{
visible: imagePreviewVisible,
onVisibleChange: vis => {
handleChangePreview(vis)
}
}}>
{
fileList.map((n) => <Image src={n.url} key={n.url} />)
}
</Image.PreviewGroup>
</div>}
<Modal
title={
<div
className='orderCategoryModal'
style={{
width: '100%',
cursor: 'move',
}}
onMouseOver={() => {
if (disabled) {
setDraggleDisabled(false)
}
}}
onMouseOut={() => {
setDraggleDisabled(true)
}}
onFocus={() => { }}
onBlur={() => { }}
>
{currentRow ? '更新点餐自定义类别' : '新建点餐自定义类别'}
</div>
}
destroyOnClose={true}
width={900}
visible={modalVisible}
confirmLoading={confirmLoading}
afterClose={() => {
formRef.current?.resetFields();
setCurrentRow(undefined);
}}
bodyStyle={{
maxHeight: '700px', // 你可以根据需要调整高度
overflowY: 'auto',
}}
onCancel={() => {
handleConfirmLoading(false)
handleModalVisible(false)
setFormPRESALE_TYPE(false)
setFileList([])
}}
footer={
<ModalFooter
hideDelete={!currentRow?.USERDEFINEDTYPE_ID}
handleDelete={async () => {
await handelDelete(currentRow?.USERDEFINEDTYPE_ID)
}}
handleCancel={() => {
handleConfirmLoading(false)
handleModalVisible(false)
setFormPRESALE_TYPE(false)
setFileList([])
}}
handleOK={() => {
formRef?.current?.validateFields().then(() => {
handleConfirmLoading(true)
formRef?.current?.submit()
})
}}
/>
}
onOk={async () => { // 提交框内的数据
formRef?.current?.validateFields().then(() => {
handleConfirmLoading(true)
formRef?.current?.submit()
})
}}
modalRender={(modal) => {
return <Draggable
disabled={disabled}
bounds={bounds}
onStart={(event, uiData) => onDraggaleStart(event, uiData)}
handle='.orderCategoryModal'
>
<div ref={draggleRef}>{modal}</div>
</Draggable>
}}
>
<ProForm
layout={'horizontal'}
formRef={formRef}
autoFocusFirstInput
submitter={false}
labelCol={{ style: { width: 80 } }}
preserve={false}
initialValues={currentRow ? {
...currentRow,
PRESALE_TIME: currentRow?.PRESALE_TYPE ? [currentRow?.PRESALE_STARTTIME, currentRow?.PRESALE_ENDTIME] : ""
} : {
USERDEFINEDTYPE_STATE: 1,
USERDEFINEDTYPE_DATE: moment().format('YYYY-MM-DD HH:mm:ss'),
OWNERUNIT_NAME: currentUser?.OwnerUnitName
}}
onFinish={async (values) => {
let newValue = { ...values };
if (currentRow) {
// 编辑数据
newValue = { ...values, USERDEFINEDTYPE_ID: currentRow.USERDEFINEDTYPE_ID };
}
console.log('fileListfileList', fileList);
console.log('newValuenewValuenewValue', newValue);
// 如果有开关,要把开关的代码写进去
await handleAddUpdate(newValue);
handleConfirmLoading(false)
setFormPRESALE_TYPE(false)
}}
>
<Row gutter={8}>
<Col span={12}>
<ProFormTreeSelect
name="USERDEFINEDTYPE_PID"
label="上级类别"
request={async () => {
if (typeTreeData && typeTreeData.length > 0) {
let list: any = [{ USERDEFINEDTYPE_NAME: "默认类别", USERDEFINEDTYPE_ID: -1 }, ...typeTreeData]
return list
} else {
const req = {
OWNERUNIT_ID: currentUser?.OwnerUnitId,
PROVINCE_CODE: "",
GOODSTYPE: 3000,
}
const data = await handlGetUSERDEFINEDTYPEList(req);
console.log('datadatadatadatadata', data);
if (data.List && data.List.length > 0) {
data.List.unshirft({ USERDEFINEDTYPE_NAME: "默认类别", USERDEFINEDTYPE_ID: -1 })
setTypeTreeData(data.List)
return data.List
} else {
return [{ USERDEFINEDTYPE_NAME: "默认类别", USERDEFINEDTYPE_ID: -1 }]
}
}
}}
fieldProps={{
fieldNames: {
label: 'USERDEFINEDTYPE_NAME',
value: 'USERDEFINEDTYPE_ID',
children: 'children'
},
showSearch: true,
filterTreeNode: (input, node) =>
(node.USERDEFINEDTYPE_NAME || '').toLowerCase().includes(input.toLowerCase())
}}
rules={[
{
required: true,
message: "请选择上级类别"
}
]}
/>
</Col>
<Col span={12}>
<ProFormText
name="USERDEFINEDTYPE_NAME"
label="类别名称"
rules={[
{
required: true,
message: "请输入类别名称"
}
]}
/>
</Col>
<Col span={12}>
<ProFormDigit
name="USERDEFINEDTYPE_INDEX"
label="类别索引"
rules={[
{
required: true,
message: "请输入类别索引"
}
]}
/>
</Col>
<Col span={12}>
<ProFormSelect
name="SCANCODE_ORDER"
label="上架状态"
options={[{ label: "上架", value: 1 }, { label: "下架", value: 0 }]}
/>
</Col>
<Col span={12}>
<ProFormSelect
name="USERDEFINEDTYPE_STATE"
label="有效状态"
options={[{ label: "有效", value: 1 }, { label: "无效", value: 0 }]}
rules={[
{
required: true,
message: "请选择有效状态"
}
]}
/>
</Col>
<Col span={12}>
<ProFormSelect
name="PRESALE_TYPE"
label="是否预售"
options={[{ label: "是", value: 1 }, { label: "否", value: 0 }]}
fieldProps={{
onChange: (e: any) => {
setFormPRESALE_TYPE(e)
}
}}
/>
</Col>
{
formPRESALE_TYPE ?
<Col span={12}>
<ProFormDateTimeRangePicker
width={'lg'}
name="PRESALE_TIME"
label="预售时间"
rules={[
{
required: true,
message: "请选择预售时间"
}
]}
/>
</Col>
: ""
}
<Col span={12}>
<ProFormUploadButton
name="USERDEFINEDTYPE_ICO"
label="图标地址"
fileList={fileList || []}
listType="picture-card"
accept="image/*"
fieldProps={{
beforeUpload,
maxCount: 1,
onPreview: handlePreview,
customRequest: async (info) => {
const formData = new FormData();
formData.append('files', info.file);
formData.append('TableType', '1215');
formData.append('ImageName', typeof info.file !== 'string' ? info.file?.name : '');
if (info.filename) {
const success = await uploadPicture(formData)
if (success) {
const list = [{
// uid: `${success.ImageId}`, // 注意这个uid一定不能少否则上传失败
name: success.Result_Data.ImageName,
// status: 'done',
url: success.Result_Data.ImageUrl, // url 是展示在页面上的绝对链接
// imgUrl: success.ImagePath // + success.ImageUrl,
}]
setFileList(list)
}
} else {
message.error("您上传的图片不存在.")
}
},
onChange: async (info: any) => {
if (info.file.status === 'removed') {
confirm({
title: '确认删除该图片吗?',
icon: <ExclamationCircleOutlined rev={undefined} />,
async onOk() {
setFileList([])
// const deleteLoading = message.loading('正在删除...')
// try {
// const deleteIndex = fileList?.findIndex((n: any) => n.uid === info.file.uid)
// const success = await deletePicture(info.file?.ImagePath, info.file?.ImageId, '1208')
// if (deleteIndex !== -1) {
// const files = [...fileList]
// files.splice(deleteIndex, 1)
// setFileList(files)
// }
// deleteLoading()
// return true
// } catch (error) {
// deleteLoading()
// return false
// }
}
});
}
}
}}
/>
</Col>
<Col span={12}>
<ProFormText
name="USERDEFINEDTYPE_DATE"
label="添加时间"
disabled
/>
</Col>
<Col span={12}>
<ProFormText
name="OWNERUNIT_NAME"
label="业主单位"
disabled
/>
</Col>
<Col span={24}>
<ProFormTextArea
name="USERDEFINEDTYPE_DESC"
label="备注"
/>
</Col>
</Row>
</ProForm>
</Modal>
</PageContainer >
);
};
export default connect(({ user }: ConnectState) => ({
currentUser: user.currentUser
}))(OrderCategoryManage);