...
 
Commits (59)
......@@ -302,4 +302,53 @@ export default [
},
],
},
{
name: '租赁管理',
path: '/lease',
icon: 'laptop',
routes: [
{
name: '租户管理',
path: '/lease/custom',
icon: '',
component: './lease/custom',
},
{
name: '设备台账',
path: '/lease/ledger',
icon: '',
component: './lease/ledger',
},
{
name: '供应商管理',
path: '/lease/supplier',
icon: '',
component: './lease/supplier',
},
{
name: '设备查看',
path: '/lease/devicedata',
icon: '',
component: './lease/devicedata',
},
{
name: '租赁合同',
path: '/lease/contract',
icon: '',
component: './lease/contract',
},
{
name: '租赁营收',
path: '/lease/costanalysis',
icon: '',
component: './lease/costanalysis',
},
{
name: '设备OEE',
path: '/lease/leasedevice',
icon: '',
component: './lease/leasedevice',
},
],
},
];
/*
* @Author: wuhao930406 1148547900@qq.com
* @Date: 2023-09-19 08:36:54
* @LastEditors: wuhao930406 1148547900@qq.com
* @LastEditTime: 2023-09-19 08:54:01
* @FilePath: /ems3.3/config/config.js
* @Description:
*
* Copyright (c) 2023 by ${git_name_email}, All Rights Reserved.
*/
// https://umijs.org/config/
import { defineConfig } from '@umijs/max';
import { join } from 'path';
......
/*
* @Author: wuhao930406 1148547900@qq.com
* @Date: 2023-09-19 08:36:54
* @LastEditors: wuhao930406 1148547900@qq.com
* @LastEditTime: 2023-09-19 10:10:58
* @FilePath: /ems3.3/config/proxy.js
* @Description:
*
* Copyright (c) 2023 by ${git_name_email}, All Rights Reserved.
*/
/**
* 在生产环境 代理是无法生效的,所以这里没有生产环境的配置
* -------------------------------
......@@ -13,7 +23,7 @@ export default {
dev: {
[defaultSetting.proxypath]: {
// 要代理的地址
target: 'http://192.168.40.64:28000', //jf哥
target: 'http://192.168.40.110:8000', //jf哥
// target: 'http://192.168.40.248:8080', //jf哥
// target: 'http://192.168.40.64:28000', //gc哥
// target: 'http://192.168.40.203:8000', //dj哥
......@@ -22,7 +32,7 @@ export default {
},
'/token': {
// 要代理的地址
target: 'http://192.168.40.64:8000',
target: 'http://192.168.40.110:8000',
changeOrigin: true,
},
'/staticfile/': {
......
......@@ -45,7 +45,7 @@
],
"dependencies": {
"@ant-design/icons": "^4.7.0",
"@ant-design/pro-components": "^2.3.52",
"@ant-design/pro-components": "2.5.2",
"@umijs/route-utils": "^2.0.0",
"ahooks": "^3.7.0",
"antd": "^4.23.1",
......@@ -54,6 +54,13 @@
"browserslist": "^4.21.4",
"classnames": "^2.3.0",
"crypto-js": "^4.1.1",
"dayjs": "^1.11.9",
"decimal.js": "^10.4.3",
"echarts": "^5.4.3",
"echarts-for-react": "^3.0.2",
"fabric": "^5.3.0",
"file-saver": "^2.0.5",
"jszip": "^3.10.1",
"lodash": "^4.17.21",
"moment": "^2.29.4",
"omit.js": "^2.0.2",
......@@ -67,6 +74,7 @@
"react-dom": "^17.0.0",
"react-helmet-async": "^1.2.0",
"react-resizable": "^3.0.4",
"socket.io-client": "2.2.0",
"umi-request": "^1.4.0"
},
"devDependencies": {
......
<svg width="130" height="80" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient x1="52.348%" y1="74.611%" x2="52.348%" y2="-17.635%" id="a"><stop stop-color="#DEDEDE" stop-opacity="0" offset="0%"/><stop stop-color="#A9A9A9" stop-opacity=".3" offset="100%"/></linearGradient><linearGradient x1="44.79%" y1="100%" x2="44.79%" y2="0%" id="b"><stop stop-color="#FFF" stop-opacity="0" offset="0%"/><stop stop-color="#96A1C5" stop-opacity=".373" offset="100%"/></linearGradient><linearGradient x1="50%" y1="100%" x2="50%" y2="-19.675%" id="c"><stop stop-color="#FFF" stop-opacity="0" offset="0%"/><stop stop-color="#919191" stop-opacity=".15" offset="100%"/></linearGradient><linearGradient x1="50%" y1="0%" x2="50%" y2="44.95%" id="d"><stop stop-color="#5389F5" offset="0%"/><stop stop-color="#416FDC" offset="100%"/></linearGradient><linearGradient x1="63.345%" y1="100%" x2="63.345%" y2="-5.316%" id="e"><stop stop-color="#DCE9FF" offset="0%"/><stop stop-color="#B6CFFF" offset="100%"/></linearGradient><linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="f"><stop stop-color="#7CA5F7" offset="0%"/><stop stop-color="#C4D6FC" offset="100%"/></linearGradient></defs><g transform="translate(-1.866 .364)" fill="none" fill-rule="evenodd"><path d="M27.94 14.864c1.326-4.192 2.56-6.802 3.7-7.831 3.157-2.848 7.522-1.298 8.45-1.076 3.26.782 2.2-4.364 4.997-5.41 1.864-.697 3.397.155 4.6 2.556C50.752.863 52.375-.163 54.556.02c3.272.277 4.417 11.328 8.913 8.909 4.497-2.42 10.01-2.973 12.365.623.509.778.704-.429 4.166-4.55C83.462.88 86.914-.936 93.996 1.464c3.22 1.09 5.868 4.045 7.947 8.864 0 6.878 5.06 10.95 15.178 12.213 15.179 1.895 3.397 18.214-15.178 22.993-18.576 4.78-61.343 7.36-84.551-4.716C1.92 32.769 5.436 24.117 27.939 14.864z" fill="url(#a)" opacity=".8"/><ellipse fill="url(#b)" cx="66" cy="69.166" rx="27.987" ry="6.478"/><path d="M113.25 77.249c-21.043 5.278-92.87-.759-100.515-3.516-3.721-1.343-7.075-3.868-10.061-7.576a2.822 2.822 0 0 1 2.198-4.593h125.514c2.605 6.938-3.107 12.166-17.136 15.685z" fill="url(#c)" opacity=".675"/><g fill-rule="nonzero"><path d="M43.396 12.098L33.825.906a2.434 2.434 0 0 0-1.837-.86h-20.58c-.706 0-1.377.324-1.837.86L0 12.098v6.144h43.396v-6.144z" fill="url(#d)" transform="translate(44.08 39.707)"/><path d="M40.684 18.468L32.307 8.72a2.136 2.136 0 0 0-1.622-.725H12.711c-.617 0-1.22.256-1.622.725l-8.377 9.748v5.354h37.972v-5.354z" fill="url(#e)" transform="translate(44.08 39.707)"/><path d="M43.396 25.283c0 .853-.384 1.62-.99 2.134l-.123.1a2.758 2.758 0 0 1-1.67.56H2.784c-.342 0-.669-.062-.971-.176l-.15-.06A2.802 2.802 0 0 1 0 25.282V12.165h10.529c1.163 0 2.1.957 2.1 2.118v.015c0 1.162.948 2.099 2.111 2.099h13.916a2.113 2.113 0 0 0 2.111-2.107c0-1.166.938-2.125 2.1-2.125h10.53z" fill="url(#f)" transform="translate(44.08 39.707)"/></g></g></svg>
\ No newline at end of file
......@@ -25,6 +25,21 @@ function strToHump(str) {
return res + 'Outlined';
}
function getChildren(data) {
let arr = [];
function loop(data) {
data.map(it => {
if (it.routes?.length > 0) {
loop(it.routes);
} else {
arr.push(it);
}
});
}
loop(data);
return arr;
}
export async function getInitialState() {
let token = localStorage.getItem('TOKENES');
const fetchUserInfo = async () => {
......@@ -98,11 +113,11 @@ export const layout = ({ initialState, setInitialState }) => {
},
links: isDev
? [
<Link key="openapi" to="/umi/plugin/openapi" target="_blank">
<LinkOutlined />
<span>OpenAPI 文档</span>
</Link>,
]
<Link key="openapi" to="/umi/plugin/openapi" target="_blank">
<LinkOutlined />
<span>OpenAPI 文档</span>
</Link>,
]
: [],
//接口获取菜单数据
menu: {
......@@ -112,8 +127,8 @@ export const layout = ({ initialState, setInitialState }) => {
},
request: (params, defaultMenuData) => {
let lastArr = initialState?.newMenu?.userHavePermList
? JSON.parse(JSON.stringify(initialState?.newMenu?.userHavePermList))
: [],
? JSON.parse(JSON.stringify(initialState?.newMenu?.userHavePermList))
: [],
newArr = [
{
path: '/welcome',
......@@ -152,11 +167,28 @@ export const layout = ({ initialState, setInitialState }) => {
noFound: <div>noFound</div>,
// 增加一个 loading 的状态
childrenRender: (children, props) => {
// if (initialState?.loading) return <PageLoading />;
let home, items = getChildren(initialState?.newMenu?.userHavePermList ?? []);
items?.unshift({
path: "/welcome",
name: "首页",
icon: "smile",
component: "./Welcome",
haveChildren: false,
key: "000000",
parentKey: "0",
routes: [],
children: null,
title: null,
});
if (history.location.pathname != "/welcome" && history.location.pathname != "/") {
home = history.location.pathname
} else {
home = items?.length > 0 ? items[0].path.indexOf("/") > -1 ? items[0].path : items[0]?.children?.length > 0 ? items[0]?.children[0]?.path : "" : "";
}
return (
<>
{initialState?.currentUser && location.pathname !== loginPath ? (
<TagView home="/welcome">{children}</TagView>
<TagView home={home}>{children}</TagView>
) : (
children
)}
......
......@@ -16,19 +16,8 @@ export default (props) => {
childposition = childposition ?? 'left';
const actionbtn = {
add: <PremButton {...props?.addconfig}>{props?.addconfig?.name || '新增'}</PremButton>,
export: (
<PremButton
{...props?.exportconfig}
btn={{
...props.exportconfig,
icon: <ExportOutlined />,
}}
>
导出
</PremButton>
),
export: <PremButton {...props?.exportconfig}>{props?.exportconfig?.name || '导出'}</PremButton>,
};
//右上角 pageextra 类型 1.reactDom 2.string 以逗号隔开 为none时不显示
const renderextra = () => {
if (props.pageextra && !isString(props.pageextra)) {
......@@ -78,7 +67,7 @@ export default (props) => {
};
});
}
}, [props.tabList]);
}, [props.tabList, props.extraparams]);
return (
<div className="diycard">
{props.withCard === false ? (
......@@ -120,7 +109,7 @@ export default (props) => {
{props.childposition == 'bottom' && props.children}
</Card>
) : (
<div className="tabsTable">
<div className="tabstable">
<div style={{ display: 'flex', justifyContent: 'space-between', padding: '16px 20px 0' }}>
<div style={{ fontSize: 16, fontWeight: 500 }}>{props.pagetitle}</div>
<div className="center">{renderextra()}</div>
......@@ -129,7 +118,7 @@ export default (props) => {
items={items}
onChange={props.onTabChange}
destroyInactiveTabPane
activeTabKey={props.activeTabKey}
activeKey={props.activeTabKey}
/>
</div>
)}
......
......@@ -37,12 +37,15 @@ const Mtable = (props) => {
pageSize, //修改默认pageSize
pagination = true, //分页设置
x, //横向滚动
y,
activeTabKey, //激活的tabKey 拖拽表格唯一标识使用 其他情况用不到
refreshDep, //依赖刷新 (已废弃)
getDefaultSelected, //存在默认选中向上返回选中值
resizeable = false,
dataSource,
iscurrent = true,
toolBarRender = false,
dataSourceFieldsChange
} = props;
const actionRefs = actionRef ?? useRef(),
formRefs = formRef ?? useRef(),
......@@ -51,13 +54,20 @@ const Mtable = (props) => {
[valueColumns, setvalueColumns] = useState({});
const [columnes, setcolumnes] = useState(columns ?? []);
const [newparames, setnewparams] = useState({});
//调用接口
const request = async (params, sort, filter) => {
if (!path) return;
for (let i in params) {
let itemType = columns.filter(it => it.key == i)?.[0]?.valueType ?? '';
if (itemType && (itemType == 'dateTimeRange' || itemType == 'dateRange' || itemType == 'timeRange' || itemType == 'checkbox')) {
if (params[i] === '') {
params[i] = undefined;
}
}
}
let newparams = {
...params,
...extraparams, //父组件传参
...params,
pageIndex: params.current,
pageSize: params.pageSize || pageSize,
};
......@@ -66,6 +76,7 @@ const Mtable = (props) => {
delete newparams.pageIndex;
delete newparams.pageSize;
}
const result = await doFetch({ url: path, params: newparams });
//分页结果
let data = result?.data?.page?.list,
......@@ -92,10 +103,10 @@ const Mtable = (props) => {
let itemwidth = valueColumns[it.key]?.width
? valueColumns[it.key].width
: it.width
? it.width
: resizeable
? 160
: 'auto';
? it.width
: resizeable
? 160
: 'auto';
let options = {},
faoptopns = it?.searchOptions ?? it?.options;
if (['select', 'treeSelect', 'radio', 'checkbox', 'cascader'].includes(it?.valueType)) {
......@@ -283,83 +294,82 @@ const Mtable = (props) => {
//缩放表格
const handleResize =
(index) =>
(e, { size }) => {
e.stopImmediatePropagation();
setcolumnes((s) => {
const nextColumns = [...s];
nextColumns[index] = {
...nextColumns[index],
width: size.width,
};
return nextColumns;
});
};
(e, { size }) => {
e.stopImmediatePropagation();
setcolumnes((s) => {
const nextColumns = [...s];
nextColumns[index] = {
...nextColumns[index],
width: size.width,
};
return nextColumns;
});
};
//更新表格缩放
const handleResizeStop =
(index) =>
(e, { size }) => {
e.stopImmediatePropagation();
let submitdata = { ...valueColumns } ?? {},
curkey = Object.keys(submitdata)[index];
submitdata[curkey].width = parseInt(size.width);
setvalueColumns(submitdata);
doFetch({
url: '/ngic-base-business/paFieldScene/save',
params: {
sceneMark: activeTabKey ? path + activeTabKey : path,
controList: Object.keys(submitdata).map((it, i) => {
return {
fieldKey: it,
fieldWidth: i == index ? parseInt(size.width) : submitdata[it].width,
fieldOrder: submitdata[it].order,
fieldFixed: submitdata[it].fixed,
fieldShow: submitdata[it].show,
};
}),
},
});
};
(e, { size }) => {
e.stopImmediatePropagation();
let submitdata = { ...valueColumns } ?? {},
curkey = Object.keys(submitdata)[index];
submitdata[curkey].width = parseInt(size.width);
setvalueColumns(submitdata);
doFetch({
url: '/ngic-base-business/paFieldScene/save',
params: {
sceneMark: activeTabKey ? path + activeTabKey : path,
controList: Object.keys(submitdata).map((it, i) => {
return {
fieldKey: it,
fieldWidth: i == index ? parseInt(size.width) : submitdata[it].width,
fieldOrder: submitdata[it].order,
fieldFixed: submitdata[it].fixed,
fieldShow: submitdata[it].show,
};
}),
},
});
};
const components = resizeable
? {
components: {
header: {
cell: Resizecell,
},
components: {
header: {
cell: Resizecell,
},
columnsState: {
value: valueColumns,
onChange: (val, state) => {
setvalueColumns((s) => {
let submitdata = {
...s,
...val,
};
doFetch({
url: '/ngic-base-business/paFieldScene/save',
params: {
sceneMark: activeTabKey ? path + activeTabKey : path,
controList: Object.keys(submitdata).map((it) => {
return {
fieldKey: it,
fieldWidth: submitdata[it].width,
fieldOrder: submitdata[it].order,
fieldFixed: submitdata[it].fixed,
fieldShow: submitdata[it].show,
};
}),
},
});
return submitdata;
},
columnsState: {
value: valueColumns,
onChange: (val, state) => {
setvalueColumns((s) => {
let submitdata = {
...s,
...val,
};
doFetch({
url: '/ngic-base-business/paFieldScene/save',
params: {
sceneMark: activeTabKey ? path + activeTabKey : path,
controList: Object.keys(submitdata).map((it) => {
return {
fieldKey: it,
fieldWidth: submitdata[it].width,
fieldOrder: submitdata[it].order,
fieldFixed: submitdata[it].fixed,
fieldShow: submitdata[it].show,
};
}),
},
});
},
return submitdata;
});
},
}
},
}
: {};
const datas = dataSource ? { dataSource, toolBarRender: false } : { request };
const datas = dataSource ? { dataSource, toolBarRender: toolBarRender == false ? false : () => { } } : { request };
return (
<ProTable
{...props}
......@@ -386,6 +396,15 @@ const Mtable = (props) => {
...newparams,
}));
}
for (let i in params) {
let itemType = columns.filter(it => it.key == i)?.[0]?.valueType ?? '';
if (itemType && (itemType == 'dateTimeRange' || itemType == 'dateRange' || itemType == 'timeRange' || itemType == 'checkbox')) {
if (params[i] === '') {
params[i] = undefined;
}
}
}
dataSourceFieldsChange && dataSourceFieldsChange(params)
}}
onSizeChange={(size) => {
localStorage.setItem('size', size); //设置全局表格规格缓存
......@@ -402,26 +421,27 @@ const Mtable = (props) => {
rowKey={rowKey ?? 'id'} //表格每行数据的key
dateFormatter="string"
scroll={
x
x || y
? {
x: x,
}
x: x,
y: y
}
: {}
}
pagination={
pagination
? {
showTotal: (total, range) => <span>{total}</span>,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: [5, 10, 15, 30, 50, 100, 200],
defaultPageSize: pageSize || 15,
}
showTotal: (total, range) => <span>{total}</span>,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: [5, 10, 15, 30, 50, 100, 200],
defaultPageSize: pageSize || 15,
}
: false
}
search={{
filterType: 'light', //轻量模式
placement: 'bottomLeft',
placement: 'bottomLeft'
}}
/>
);
......
......@@ -72,13 +72,11 @@ function DetailPro(props) {
: {};
if (it.valueType == 'split') {
return (
<>
<Col span={24}>
<div className={styles.title} style={{ borderWidth: i == 0 ? 0 : 1 }}>
{it?.render ? it?.render?.(curitem[it.dataIndex], curitem) : it.title}
</div>
</Col>
</>
<Col span={24} key={i}>
<div className={styles.title} style={{ borderWidth: i == 0 ? 0 : 1, '--before': !(it.title || it?.render) ? 'none' : 'block', '--after': !(it.title || it?.render) ? '100%' : 'calc(100% - 160px)', '--padb': !(it.title || it?.render) ? '20px' : '0' }}>
{it?.render ? it?.render?.(curitem[it.dataIndex], curitem) : it.title}
</div>
</Col>
);
}
return (
......
@import '~antd/es/style/variable.less';
.title {
position: relative;
width: 100%;
padding-top: 8px;
padding-left: 12px;
font-weight: bolder;
padding-bottom: var(--padb);
&::before {
position: absolute;
top: 11px;
......@@ -14,15 +17,17 @@
background-color: @primary-color;
border-radius: 4px;
content: '';
display: var(--before);
}
&::after {
position: absolute;
top: 18px;
right: 0px;
width: calc(100% - 160px);
width: var(--after);
height: 1px;
border-bottom: 1px dotted rgba(0, 0, 0, 0.1);
border-radius: 4px;
content: '';
}
}
}
\ No newline at end of file
......@@ -15,14 +15,13 @@ function DrawerPro(props) {
fields: props.fields,
detailData: props.detailData,
};
return (
<Drawer
maskClosable={false}
placement="right"
closable={true}
getContainer={false}
style={{ position: 'absolute', transform: 'translateX(0)', maxWidth: '100%' }}
style={{ position: 'absolute', transform: 'translateX(0)', zIndex: 10 }}
width={'100%'}
destroyOnClose={true}
{...props}
......@@ -37,7 +36,11 @@ function DrawerPro(props) {
{props?.children}
</div>
) : (
<InitForm {...newProps} />
<>
{props.childrenposition == 'top' && props.children}
<InitForm {...newProps} />
{props.childrenposition == 'bottom' && props.children}
</>
)}
{pushSettingFlag ? (
......
......@@ -15,14 +15,15 @@ const App = ({
onFinish,
drawer,
formRef,
columns,
columns = [],
urlParams,
formId,
defaultFormValue,
onValuesChange,
}) => {
const [value, setValue] = useState('');
const [fieldscolumns, setfieldscolumns] = useState(columns);
const [fieldscolumns, setfieldscolumns] = useState([]);
const [otherFields, cot] = useState([]);
const selectValueType = (type, options) => {
switch (type) {
case 1:
......@@ -52,7 +53,6 @@ const App = ({
break;
}
};
useEffect(() => {
const fn = async () => {
let res = await doFetch({
......@@ -76,11 +76,14 @@ const App = ({
key: el.id,
});
});
setfieldscolumns(fieldscolumns.concat(column));
cot(column);
}
};
fn();
}, []);
useEffect(() => {
setfieldscolumns(columns.concat(otherFields));
}, [columns, otherFields])
const selectextendField = (type) => {
switch (Number(type)) {
......
import React from 'react';
const Filedetail = ({ files }) => {
return <div style={{ display: "flex", flexFlow: "row wrap", width: "100%" }}>
{
files && typeof (files) == "string" ?
<a href={files} download={files} style={{ margin: '0 20px 0 0', display: 'block' }}>{urlName ? urlName : "下载"}</a>
: files && Array.isArray(files) && files?.length ?
files?.map(el => {
return <a title={el.name} key={el.url} href={el.url} download={el.name} style={{ margin: '0 20px 0 0', display: 'block' }}>{el.name}</a>
})
:
"-"
}
</div>
}
export default Filedetail;
\ No newline at end of file
This diff is collapsed.
......@@ -33,14 +33,14 @@ let FormRender = memo(({ fields = [], colProps, proformRef }) => {
item.formItemProps = item.formItemProps ?? { rules: [] };
if (item.valueType == 'split') {
return (
<div className={styles.title} style={{ borderWidth: index == 0 ? 0 : 1 }}>
<div key={index} className={styles.title} style={{ borderWidth: index == 0 ? 0 : 1 }}>
{item.title}
</div>
);
}
if (item?.valueType == 'nosubmit') {
return (
<Col {...(item.colProps ?? { span: 12 })} style={{ marginBottom: 24 }}>
<Col key={index} {...(item.colProps ?? { span: 12 })} style={{ marginBottom: 24 }}>
<label style={{ marginBottom: 8, display: 'block' }}>{item?.title}</label>
<Input disabled value={item?.initialValue} />
</Col>
......@@ -49,7 +49,7 @@ let FormRender = memo(({ fields = [], colProps, proformRef }) => {
if (hideInForm && Object.keys(hideInForm)) {
return (
<ProFormDependency name={Object.keys(hideInForm)}>
<ProFormDependency key={index} name={Object.keys(hideInForm)}>
{(params) => {
let ifs = true;
let res = Object.keys(hideInForm).map((its) => {
......@@ -64,31 +64,23 @@ let FormRender = memo(({ fields = [], colProps, proformRef }) => {
if (ifs) {
return;
} else {
return (
<>
{createElement(FormItems[key], {
item: item,
colProps: colProps,
key: item.dataIndex,
formRef: proformRef,
})}
</>
);
return createElement(FormItems[key], {
item: item,
colProps: colProps,
key: item.dataIndex,
formRef: proformRef,
});
}
}}
</ProFormDependency>
);
} else {
return (
<>
{createElement(FormItems[key], {
item: item,
colProps: colProps,
key: item.dataIndex,
formRef: proformRef,
})}
</>
);
return createElement(FormItems[key], {
item: item,
colProps: colProps,
key: item.dataIndex,
formRef: proformRef,
});
}
})}
</>
......@@ -117,16 +109,50 @@ function InitForm(props) {
style = {},
} = props;
const { run } = useDebounceFn(onFinish, { wait: 400 });
// const { run } = useDebounceFn(onFinish, { wait: 400 });
let proformRef = useRef();
proformRef = formRef ?? proformRef;
function formartData(item, val) {
let formartValue = val;
if (item?.valueType == 'uploadBtn' || item?.valueType == "uploadImage" || item?.valueType == "uploadDragger") {
let stepval = val?.filter(it => {
if (!it?.response) {
return it;
} else {
if (it?.response?.code == "0000") {
return it;
}
}
}) ?? [];
formartValue = stepval.map((it) => {
if (it.response) {
if (it.response.code != "0000") {
return undefined;
}
return it?.response?.data?.dataList[0] ?? undefined;
} else {
return it ? it : undefined;
}
});
}
return formartValue;
}
return fields?.length == 0 ? (
<ColumnsTrans />
) : (
<ProForm
style={{ overflow: 'hidden', ...style }}
formRef={proformRef}
onFinish={run}
onFinish={async (values) => {
let newAllvalues = {};
for (let i in values) {
newAllvalues[i] = formartData(fields?.find(it => it.key == i), values[i]);
}
await onFinish(newAllvalues);
}}
formKey={formKey ?? parseInt(Math.random() * 1000000)}
params={params}
submitter={submitter ?? true}
......@@ -160,24 +186,24 @@ function InitForm(props) {
//反填参数 格式化
const relationSupplierList = res?.data?.data?.relationSupplierList
? {
relationSupplierList: res?.data?.data?.relationSupplierList?.map?.((it, i) => {
return {
...it,
id: it?.supplierId,
};
}),
}
relationSupplierList: res?.data?.data?.relationSupplierList?.map?.((it, i) => {
return {
...it,
id: it?.supplierId,
};
}),
}
: {};
const supplierList = res?.data?.data?.supplierList
? {
supplierList: res?.data?.data?.supplierList?.map?.((it, i) => {
return {
...it,
id: it?.supplierId,
};
}),
}
supplierList: res?.data?.data?.supplierList?.map?.((it, i) => {
return {
...it,
id: it?.supplierId,
};
}),
}
: {};
let result = res?.data?.data;
......@@ -187,7 +213,6 @@ function InitForm(props) {
return it;
});
}
return {
...defaultFormValue,
...(result ?? {}),
......
import React, { useCallback, useState, useMemo } from 'react';
import React, { useCallback, useState, useMemo, useEffect } from 'react';
import { LogoutOutlined, LockOutlined } from '@ant-design/icons';
import { Menu, Spin, Button, Form, Modal, message, Avatar, Select } from 'antd';
import { history, useModel } from '@umijs/max';
......@@ -14,6 +14,14 @@ import ECB from 'crypto-js/mode-ecb';
import Pkcs7 from 'crypto-js/pad-pkcs7';
import Utf8 from 'crypto-js/enc-utf8';
import moment from 'moment';
import io from 'socket.io-client';
const { NODE_ENV } = process.env;
const websocketUrl = NODE_ENV == "development" ? "ws://192.168.40.111:9933" : `${window.location.protocol == "http:" ? "ws" : "wss"}://${window.location.host}`;
const socket = io(websocketUrl, {
reconnectionDelay: 4000,
transports: ['websocket'],
autoConnect: true,
});
/**
* 退出登录,并且将当前的 url 保存
*/
......@@ -31,6 +39,7 @@ const AvatarDropdown = ({ menu }) => {
return res?.data || {};
});
const { initialState, setInitialState } = useModel('@@initialState');
const { allWebsocket, changeWebsocket } = useModel('useGlobal');
const [visible, cv] = useState(false),
[formRef] = Form.useForm(),
{ run, loading } = useRequest(doFetch, {
......@@ -50,6 +59,14 @@ const AvatarDropdown = ({ menu }) => {
}
},
});
useEffect(() => {
changeWebsocket((s) => ({ ...s, commonWebsocket: socket }));
socket.on('iotData', (data) => {
changeWebsocket((s) => ({ ...s, commonWebmsg: data }));
});
}, []);
const fields = useMemo(() => {
return {
password: {
......@@ -133,9 +150,9 @@ const AvatarDropdown = ({ menu }) => {
padding: Pkcs7,
}).toString();
let newPassword = AES.encrypt(values.newPassword, Utf8.parse(timestamp), {
mode: ECB,
padding: Pkcs7,
}).toString(),
mode: ECB,
padding: Pkcs7,
}).toString(),
password = AES.encrypt(values.password, Utf8.parse(timestamp), {
mode: ECB,
padding: Pkcs7,
......@@ -184,7 +201,7 @@ const AvatarDropdown = ({ menu }) => {
formRef={formRef}
fields={fields}
col={{ span: 24 }}
onChange={(changedValues, allValues) => {}}
onChange={(changedValues, allValues) => { }}
submitData={(values, fn) => {
saveData(values, fn);
}}
......
......@@ -21,42 +21,42 @@ function strToHump(str) {
}
let CardItems = (datav, i, getstar, addHistory) => {
let name = datav.name,
collected = datav.isExist == '1',
icon = datav.icon ? strToHump(datav.icon) : 'ToolOutlined',
ItemIcon = icon ? Ant4Icons[icon] : Ant4Icons['ToolOutlined'];
return (
<div
key={i}
className={styles.carditem}
onClick={async () => {
history.push(datav.path);
await addHistory(datav.key);
}}
>
<a className={styles.diylink}>
{' '}
{React.createElement(Ant4Icons[icon], { style: { marginRight: 6 } })}
{name}
</a>
{collected ? (
<Ant4Icons.StarFilled
className={styles.collected}
onClick={async (e) => {
getstar(e, collected, datav.key);
}}
/>
) : (
<Ant4Icons.StarOutlined
className={styles.tocollect}
onClick={async (e) => {
getstar(e, collected, datav.key);
}}
/>
)}
</div>
);
},
let name = datav.name,
collected = datav.isExist == '1',
icon = datav.icon ? strToHump(datav.icon) : 'ToolOutlined',
ItemIcon = icon ? Ant4Icons[icon] : Ant4Icons['ToolOutlined'];
return (
<div
key={i}
className={styles.carditem}
onClick={async () => {
history.push(datav.path);
await addHistory(datav.key);
}}
>
<a className={styles.diylink}>
{' '}
{React.createElement(Ant4Icons[icon], { style: { marginRight: 6 } })}
{name}
</a>
{collected ? (
<Ant4Icons.StarFilled
className={styles.collected}
onClick={async (e) => {
getstar(e, collected, datav.key);
}}
/>
) : (
<Ant4Icons.StarOutlined
className={styles.tocollect}
onClick={async (e) => {
getstar(e, collected, datav.key);
}}
/>
)}
</div>
);
},
coles = { xs: 24, sm: 24, md: 12, lg: 8, xl: 6, xxl: 4 };
function SiderMenu({ logo, collapsed, onCollapse, fixSiderbar, theme, isMobile, name, menuData }) {
......@@ -169,7 +169,6 @@ function SiderMenu({ logo, collapsed, onCollapse, fixSiderbar, theme, isMobile,
};
});
}, [collectPerm]);
return (
<Sider
trigger={null}
......@@ -237,6 +236,12 @@ function SiderMenu({ logo, collapsed, onCollapse, fixSiderbar, theme, isMobile,
label: '产品与服务',
type: 'sub1',
},
{
key: '/welcome',
label: '首页',
type: 'sub1',
icon: <Ant4Icons.HomeOutlined />
},
...collectList,
]}
/>
......
import React, { useState, useMemo, useEffect } from 'react';
import { Card, Form, Divider, Empty, Spin, Button } from 'antd';
import ReactEcharts from 'echarts-for-react';
import { useRequest, useAsyncEffect } from "ahooks";
import { doFetch } from '@/utils/doFetch';
import * as echarts from "echarts";
import moment from 'moment';
const Statuschart = ({ statusData = [], statusColorList = [], barStyle }) => {
const [datas, cdatas] = useState([]);
useEffect(() => {
cdatas([]);
statusData?.map((it, i) => {
let arrs = resetData(it.value, i, it.name);
cdatas(datas => [...datas, ...arrs]);
})
}, [statusData]);
function resetData(data, index, parentName) {
let reslist = data?.map((it, i) => {
let time = it.value[0],
endtime = it.value[1];
let typeItem = statusColorList.filter((item) => it.name == item.type)[0];
let baseTime = moment(time).valueOf(),
endTime = moment(endtime).valueOf(),
duration = moment(endtime).diff(moment(time), 'milliseconds');
return {
name: typeItem?.name,
value: [
index,
baseTime,
endTime,
duration
],
itemStyle: {
color: typeItem?.color
},
parentName: parentName
}
}) ?? [];
return reslist;
}
function renderItem(params, api) {
var categoryIndex = api.value(0);
var start = api.coord([api.value(1), categoryIndex]);
var end = api.coord([api.value(2), categoryIndex]);
var height = api.size([0, 1])[1] * 0.8;
var rectShape = echarts.graphic.clipRectByRect({
x: start[0],
y: start[1] - height / 2,
width: end[0] - start[0],
height: height
}, {
x: params.coordSys.x,
y: params.coordSys.y,
width: params.coordSys.width,
height: params.coordSys.height * 0.8
});
return rectShape && {
type: 'rect',
shape: rectShape,
style: api.style(),
transition: ['shape']
};
};
const options = useMemo(() => {
let xAxisoption = {
min: 'dataMin',
max: 'dataMax',
scale: true,
axisLine: {
show: false
},
axisTick: {
show: false
},
splitLine: {
show: false
},
axisLabel: {
formatter: (val) => {
let item = moment(val).format("YYYY-MM-DD HH:mm:ss").split(" ")[1];
return item;
},
// rotate: 25
}
}, yAxisoption = {
data: statusData?.map(it => it.name) ?? [],
axisLine: {
show: false
},
axisTick: {
show: false
},
splitLine: {
show: false
},
axisLabel: {
formatter: (params) => {
let newParamsName = '';
const paramsNameNumber = params.length;
const provideNumber = 10;
const rowNumber = Math.ceil(paramsNameNumber / provideNumber);
if (paramsNameNumber > provideNumber) {
for (let p = 0; p < rowNumber; p++) {
let tempStr = '';
const start = p * provideNumber;
const end = start + provideNumber;
if (p == rowNumber - 1) {
tempStr = params.substring(start, paramsNameNumber);
} else {
tempStr = params.substring(start, end) + '\n';
}
newParamsName += tempStr;
}
} else {
newParamsName = params;
}
return newParamsName;
},
// rotate:15
}
};
return {
grid: {
left: 10,
right: "2%",
bottom: 40,
containLabel: true
},
tooltip: {
formatter: function (params) {
return `设备:${params?.data?.parentName}
<br />
设备状态:${params.name}
<br />
开始时间:${moment(params.value[1]).format("YYYY-MM-DD HH:mm:ss")}
<br />
结束时间:${moment(params.value[2]).format("YYYY-MM-DD HH:mm:ss")}
`
}
},
dataZoom: [{
type: 'slider',
filterMode: 'weakFilter',
showDataShadow: true,
labelFormatter: '',
bottom: "1%"
},
{
type: 'inside',
filterMode: 'weakFilter'
}],
xAxis: xAxisoption,
yAxis: yAxisoption,
series: [{
type: 'custom',
renderItem: renderItem,
itemStyle: {
opacity: 0.8
},
encode: {
x: [1, 2],
y: 0
},
data: datas
}]
}
}, [datas, statusData]);
return <div className='screenwh center'>
<ReactEcharts
style={{ height: "100%", width: "100%" }}
option={options}
/>
</div>
}
export default Statuschart;
\ No newline at end of file
......@@ -56,7 +56,7 @@ const Tags = ({ tagList, closeTag, closeAllTag, closeOtherTag, refreshTag, home
key={item.path}
className={item.active ? `${styles.item} ${styles.active}` : styles.item}
onClick={() => history.push({ pathname: item.path, query: item.query })}
onContextMenu={(e) => openContextMenu(e, item)}
onContextMenu={(e) => openContextMenu(e, { ...item, currentIndex: i })}
>
<span>{item.title}</span>
{i !== 0 && (
......
/* eslint-disable react/jsx-key */
import React, { useState, useEffect, useRef, memo } from 'react';
import React, { useState, useEffect, useRef, memo, cloneElement, createElement } from 'react';
import { RouteContext } from '@ant-design/pro-layout';
import { history } from '@umijs/max';
import { Outlet, history } from '@umijs/max';
import Tags from './Tags';
import styles from './index.less';
import { Scrollbars } from 'react-custom-scrollbars';
......@@ -13,7 +13,7 @@ function treeForeach(tree, func) {
});
}
const TagView = ({ children, home }) => {
const TagView = ({ home }) => {
const [tagList, setTagList] = useState([]);
const [currentPath, setCurrentPath] = useState();
......@@ -30,11 +30,8 @@ const TagView = ({ children, home }) => {
// console.log(routeContext);
const { menuData } = routeContext;
if (tagList.length === 0 && menuData) {
const allarr = [];
treeForeach(menuData, (node) => {
allarr.push(node);
});
const firstTag = allarr.filter((el) => el.path === location?.hash?.replace('#', ''))[0];
const allarr = getChildren(menuData);
const firstTag = allarr.filter((el) => el.path === home)[0];
if (firstTag) {
const title = firstTag.name;
const path = firstTag.path;
......@@ -54,7 +51,7 @@ const TagView = ({ children, home }) => {
};
// 监听路由改变
const handleOnChange = (routeContext) => {
const handleOnChange = async (routeContext) => {
const { currentMenu } = routeContext;
// console.log(tagList);
// tags初始化
......@@ -64,7 +61,7 @@ const TagView = ({ children, home }) => {
// 判断是否已打开过该页面
let hasOpen = false;
if (currentMenu.path) {
const tagsCopy = tagList.map((item) => {
let tagsCopy = tagList.map((item) => {
if (currentMenu?.path === item.path) {
//console.log(item);
hasOpen = true;
......@@ -83,7 +80,7 @@ const TagView = ({ children, home }) => {
tagsCopy.push({
title,
path,
children,
children: <Outlet />,
refresh: 0,
active: true,
});
......@@ -123,21 +120,41 @@ const TagView = ({ children, home }) => {
setTagList(tagsCopy);
};
const [refresh, setrefresh] = useState(true);
// 刷新选择的标签
const handleRefreshTag = async (tag) => {
// const tagsCopy = tagList.map((item) => {
// if (item.path === tag.path) {
// history.push({ pathname: tag?.path, query: tag?.query });
// return { ...item, refresh: item.refresh + 1, active: true };
// }
// return { ...item, active: false };
// });
// setTagList(tagsCopy);
await setrefresh(false);
setrefresh(true);
const tagsCopy0 = tagList.map((item) => {
if (item.path === tag.path) {
history.push({ pathname: tag?.path, query: tag?.query });
return { ...item, refresh: item.refresh + 1, active: true, children: null };
}
return { ...item, active: false };
});
const tagsCopy = tagList.map((item) => {
if (item.path === tag.path) {
history.push({ pathname: tag?.path, query: tag?.query });
return { ...item, refresh: item.refresh + 1, active: true, children: <Outlet /> };
}
return { ...item, active: false };
});
setTagList(tagsCopy0);
setTimeout(() => {
setTagList(tagsCopy);
}, 10);
};
function getChildren(data) {
let arr = [];
function loop(data) {
data.map(it => {
if (it.children?.length > 0) {
loop(it.children);
} else {
arr.push(it);
}
});
}
loop(data);
return arr;
}
return (
<>
<RouteContext.Consumer>
......@@ -161,16 +178,27 @@ const TagView = ({ children, home }) => {
/>
</div>
</div>
<div className={styles.child}>
{/* <div className={styles.child}>
<div className={styles.contianbox}>
<Scrollbars
thumbMinSize={10}
autoHide
style={{ width: '100%', height: '100%' }}
hideTracksWhenNotNeeded={true}
>
{refresh && children}
</Scrollbars>
<div style={{ width: '100%', height: '100%' }}> {refresh && children}</div>
</div>
</div> */}
<div className={styles.child}>
<div className={`${styles.contianbox} boxcontianbox`}>
{tagList.map((item) => {
return (
<div
key={item.path}
style={{
display: item.active ? 'block' : 'none',
width: '100%',
height: '100%',
}}
>
{item.children}
</div>
);
})}
</div>
</div>
</>
......
......@@ -42,6 +42,8 @@ const getParentKey = (key, tree) => {
}
function TreeRender({
isSelectFirst = false,
dataSource,
url,
deleteurl,
saveurl,
......@@ -58,10 +60,28 @@ function TreeRender({
visible: false,
});
const [expandall, setexpandall] = useState(false);
const [expandedKeys, onExpand] = useState();
const { data, loading, refresh } = useRequest(() => {
const [expandedKeys, onExpand] = useState(),
[selectedKeys, cselectedKeys] = useState([]),
[treeDataArr, cta] = useState([]);
const { loading, refresh, run } = useRequest(() => {
return doFetch({ url, params: params ?? {} });
}, {
manual: true,
onSuccess: (res, params) => {
if (res.code == '0000') {
cta(res?.data?.dataList ?? []);
}
}
});
useEffect(() => {
if (dataSource) {
cta(dataSource);
} else if (url && !dataSource) {
run();
}
}, [url, dataSource]);
const [autoExpandParent, setAutoExpandParent] = useState(true);
const allkeys = useMemo(() => {
......@@ -72,9 +92,9 @@ function TreeRender({
el.children && el.children.length > 0 ? fn(el.children) : ''; // 子级递归
});
};
fn(data?.data?.dataList ?? []);
fn(treeDataArr);
return res.filter((it) => it.children).map((it) => it.key);
}, [data]);
}, [treeDataArr]);
const alldata = useMemo(() => {
let res = [];
const fn = (source) => {
......@@ -83,19 +103,23 @@ function TreeRender({
el.children && el.children.length > 0 ? fn(el.children) : ''; // 子级递归
});
};
fn(data?.data?.dataList ?? []);
fn(treeDataArr);
return res;
}, [data]);
}, [treeDataArr]);
const treeData = useMemo(() => {
let res = data?.data?.dataList ?? [];
let res = treeDataArr;
if (isSelectFirst) {
cselectedKeys(res?.[0]?.key ? [res?.[0]?.key] : []);
}
return [
{
title: '全部类型',
key: '',
title: '全部',
key: '00000000',
children: res,
disabled: true
},
];
}, [data]);
}, [treeDataArr]);
const onChange = (e) => {
const { value } = e.target;
const dataLists = getAllList();
......@@ -124,7 +148,7 @@ function TreeRender({
const afterStr = item.title.substr(index + search.length);
let title =
index > -1 ? (
<Tooltip title={item.title} placement="bottom">
<span title={item.title} style={{ display: 'inherit' }}>
<span
style={{
display: 'inline-block',
......@@ -139,9 +163,9 @@ function TreeRender({
<span style={{ color: '#f50' }}>{search}</span>
{afterStr}
</span>
</Tooltip>
</span>
) : (
<Tooltip title={item.title} placement="bottom">
<span title={item.title} style={{ display: 'inherit' }}>
<span
style={{
display: 'inline-block',
......@@ -154,7 +178,7 @@ function TreeRender({
>
{item.title}
</span>
</Tooltip>
</span>
);
const actiontitle = (
......@@ -225,7 +249,6 @@ function TreeRender({
okText="删除"
cancelText="取消"
onConfirm={(e) => {
console.log(111);
doFetch({ url: deleteurl, params: { id: item.key } }).then((res) => {
if (res.code == '0000') {
message.success('操作成功');
......@@ -238,7 +261,6 @@ function TreeRender({
<Tooltip title="删除">
<MinusSquareOutlined
onClick={(e) => {
// console.log(e);
e.stopPropagation();
doFetch({ url: deleteurl, params: { id: item.key } }).then((res) => {
if (res.code == '0000') {
......@@ -287,7 +309,7 @@ function TreeRender({
setAutoExpandParent(!expandall);
}}
>
{expandall ? <ArrowDownOutlined /> : <ArrowRightOutlined />}
{expandall ? <ArrowDownOutlined style={{ color: 'rgba(0,0,0,0.85)' }} /> : <ArrowRightOutlined style={{ color: 'rgba(0,0,0,0.85)' }} />}
</Tooltip>
</div>
);
......@@ -300,6 +322,7 @@ function TreeRender({
children: loop(item.children),
level: item.level,
type: item.type,
disabled: item.disabled
};
}
return {
......@@ -307,6 +330,7 @@ function TreeRender({
key: item.key,
level: item.level,
type: item.type,
disabled: item.disabled
};
});
useEffect(() => {
......@@ -329,7 +353,7 @@ function TreeRender({
return dataLists;
}
return (
<div style={{ ...style }}>
<div style={{ ...style }} className='treenode'>
<Modal
{...modal}
onCancel={() => {
......@@ -424,27 +448,30 @@ function TreeRender({
onChange={onChange}
/>
<Tree
onSelect={(selectedKeys, e) => {
// //console.log(selectedKeys);
onselected?.(selectedKeys, e, alldata);
}}
autoExpandParent={autoExpandParent}
defaultExpandAll={true}
expandedKeys={expandedKeys}
onExpand={(expandedKeys, { expanded: bool, node }) => {
onExpand(expandedKeys);
setAutoExpandParent(false);
if (!bool && node.key == '00000000') {
setexpandall(false);
} else {
setexpandall(true);
}
}}
treeData={loop(treeData ?? [])}
>
{/* {loop(treeData ? treeData : [])} */}
</Tree>
<div className='boxcontianbox'>
<Tree
onSelect={(selectedKeys, e) => {
cselectedKeys(selectedKeys);
onselected?.(selectedKeys, e, alldata);
}}
autoExpandParent={autoExpandParent}
defaultExpandAll={true}
expandedKeys={expandedKeys}
selectedKeys={selectedKeys}
onExpand={(expandedKeys, { expanded: bool, node }) => {
onExpand(expandedKeys);
setAutoExpandParent(false);
if (!bool && node.key == '00000000') {
setexpandall(false);
} else {
setexpandall(true);
}
}}
treeData={loop(treeData ?? [])}
>
{/* {loop(treeData ? treeData : [])} */}
</Tree>
</div>
</div>
);
}
......
......@@ -50,6 +50,13 @@ ol {
padding-bottom: 24px !important;
}
.statuspage {
.ant-pro-table-list-toolbar-container {
padding-top: 0 !important;
padding-bottom: 0 !important;
}
}
.ant-pro-table-list-toolbar-right {
flex: 1 !important;
flex-direction: row !important;
......@@ -57,6 +64,10 @@ ol {
justify-content: space-between !important;
}
.ant-pro-table-list-toolbar-left {
display: none;
}
@media (max-width: @screen-xs) {
.ant-table {
width: 100%;
......@@ -124,7 +135,7 @@ ol {
font-size: 16px !important;
.ant-tabs-tab-btn {
color: @primary-color !important;
color: @primary-color !important;
}
}
......@@ -256,12 +267,12 @@ ol {
}
}
.ant-pro .ant-layout-header.ant-pro-layout-header {
.ant-layout-header.ant-pro-layout-header {
height: 48px !important;
line-height: 48px !important;
}
.ant-pro .ant-pro-layout .ant-pro-layout-content {
.ant-pro-layout .ant-pro-layout-content {
margin: 0 !important;
padding: 0 !important;
}
......@@ -357,7 +368,7 @@ ol {
}
}
.tabsTable {
.tabstable {
background: #fff;
.ant-tabs-nav {
......@@ -399,6 +410,10 @@ ol {
width: 100%;
}
.ant-popover {
z-index: 9999;
}
.ant-drawer-wrapper-body {
.diycard {
height: unset;
......@@ -411,6 +426,44 @@ ol {
}
}
.runtime-keep-alive-layout,
.ant-table-content,
.ant-drawer-body,
.boxcontianbox,
.ant-table-body {
&::-webkit-scrollbar {
/*滚动条整体样式*/
width: 5px;
/*高宽分别对应横竖滚动条的尺寸*/
height: 8px;
}
&::-webkit-scrollbar-thumb {
/*滚动条里面小方块*/
// border-radius: 5px;
-webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
background: #c1c1c1;
}
&::-webkit-scrollbar-track {
/*滚动条里面轨道*/
-webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
border-radius: 0;
background: #fff;
}
}
.page-title {
margin-bottom: 0;
font-weight: 700;
......@@ -450,9 +503,10 @@ ol {
.runtime-keep-alive-layout,
.runtime-keep-alive-layout-no {
height: auto !important;
min-height: 100% !important;
overflow: hidden !important;
// height: auto !important;
// min-height: 100% !important;
// overflow: hidden !important;
position: static !important;
>div {
height: 100%;
......@@ -537,8 +591,66 @@ ol {
}
}
.contianbox___W4bW5 {
.boxcontianbox {
.ant-descriptions {
margin-bottom: 24px;
}
}
.treenode {
.ant-tree-title {
display: flex !important;
align-items: center;
}
}
.ledgerf {
.ant-card-head {
display: none !important;
}
.ant-card-body {
padding: 0 !important;
}
}
.formlist {
>div {
overflow-x: auto;
>div {
>div {
>div {
>div:last-child {
border: var(--bordered);
padding: 12px;
}
}
}
}
}
.ant-col .ant-form-item-label {
padding-bottom: 12px !important;
}
.ant-form-item {
margin-bottom: 12px !important;
}
.ant-pro-form-group {
>div {
>.ant-row {
flex-flow: row nowrap !important;
align-items: baseline !important;
}
}
}
}
.screenwh {
width: 100%;
height: 100%;
}
\ No newline at end of file
import { useState, useCallback } from 'react';
export default function useGlobal() {
const [alive, setAlive] = useState(false),
[newMenus, setMenu] = useState({});
[newMenus, setMenu] = useState({}),
[allWebsocket, setAllWebsocket] = useState({});
const changealive = useCallback((parser) => {
setAlive(parser);
......@@ -10,11 +11,16 @@ export default function useGlobal() {
const setMenuFn = useCallback((val) => {
setMenu(val);
}, []);
const changeWebsocket = useCallback((parser) => {
setAllWebsocket(parser)
}, []);
return {
alive,
changealive,
newMenus,
setMenuFn,
allWebsocket,
changeWebsocket
};
}
......@@ -248,7 +248,7 @@ function Order(props) {
}, [drawer?.val, drawer?.item?.id]);
return (
<div style={{ position: 'relative' }}>
<div>
<AutoTable
pagetitle={<h3 className="page-title">点检接单</h3>}
columns={columns}
......
......@@ -15,8 +15,8 @@ function Plan(props) {
let actionRef = useRef(),
formRef = useRef();
const [drawer, setdrawer] = useState({
open: false,
}),
open: false,
}),
[activeTabKey, setactiveTabKey] = useState(1);
const { run, loading, runAsync } = useRequest(doFetch, {
......@@ -123,75 +123,75 @@ function Plan(props) {
let defpath = getcolumns(setdrawer).filter((it) => it.key == activeTabKey)[0]?.pathconfig ?? {};
return activeTabKey == 1
? defcolumn.concat([
{
title: '启用/停用',
dataIndex: 'checkEnable',
key: 'checkEnable',
hideInForm: true,
hideInSearch: true,
valueType: 'switch',
render: (text, row, _, action) => {
//"1停用 2启用 *"
return row.checkEnable == 1 ? (
<Popconfirm
title="是否开启或停用?"
onConfirm={async () => {
if (row.checkEnable == 1) {
await runAsync({
url: '/check/umEquipmentCheckPlan/enable',
params: { id: row.id, checkEnable: 2 },
});
}
}}
okText="确定"
cancelText="取消"
disabled={!(row.status == 1 || (row.status == 2 && row.checkLoop == 2))}
>
<Switch
checked={row.checkEnable == 1 ? true : false}
checkedChildren="开启"
unCheckedChildren="停用"
defaultChecked={false}
disabled={!(row.status == 1 || (row.status == 2 && row.checkLoop == 2))}
/>
</Popconfirm>
) : (
{
title: '启用/停用',
dataIndex: 'checkEnable',
key: 'checkEnable',
hideInForm: true,
hideInSearch: true,
valueType: 'switch',
render: (text, row, _, action) => {
//"1停用 2启用 *"
return row.checkEnable == 1 ? (
<Popconfirm
title="是否开启或停用?"
onConfirm={async () => {
if (row.checkEnable == 1) {
await runAsync({
url: '/check/umEquipmentCheckPlan/enable',
params: { id: row.id, checkEnable: 2 },
});
}
}}
okText="确定"
cancelText="取消"
disabled={!(row.status == 1 || (row.status == 2 && row.checkLoop == 2))}
>
<Switch
checked={row.checkEnable == 1 ? true : false}
checkedChildren="开启"
unCheckedChildren="停用"
defaultChecked={false}
disabled={!(row.status == 1 || (row.status == 2 && row.checkLoop == 2))}
onChange={(checked) => {
if (checked) {
setdrawer((s) => ({
...s,
open: true,
item: row,
title: '启用点检计划',
val: 'detailaddon',
type: 'delay',
id: row?.id,
}));
}
}}
/>
);
},
hideInDescriptions: true,
},
{
title: '操作',
valueType: 'option',
width: 150,
render: (text, row, _, action) => [
(row.status == 1 || (row.status == 2 && row.checkLoop == 2)) &&
editDate(text, row, _, action),
row.status == 2 && close(text, row, _, action),
defpath?.enabledelete && row.status == 1 && remove(text, row, _, action),
],
</Popconfirm>
) : (
<Switch
checked={row.checkEnable == 1 ? true : false}
checkedChildren="开启"
unCheckedChildren="停用"
defaultChecked={false}
disabled={!(row.status == 1 || (row.status == 2 && row.checkLoop == 2))}
onChange={(checked) => {
if (checked) {
setdrawer((s) => ({
...s,
open: true,
item: row,
title: '启用点检计划',
val: 'detailaddon',
type: 'delay',
id: row?.id,
}));
}
}}
/>
);
},
])
hideInDescriptions: true,
},
{
title: '操作',
valueType: 'option',
width: 150,
render: (text, row, _, action) => [
(row.status == 1 || (row.status == 2 && row.checkLoop == 2)) &&
editDate(text, row, _, action),
row.status == 2 && close(text, row, _, action),
defpath?.enabledelete && row.status == 1 && remove(text, row, _, action),
],
},
])
: defcolumn;
}, [activeTabKey]);
......@@ -450,7 +450,7 @@ function Plan(props) {
});
};
return (
<div style={{ position: 'relative' }}>
<div>
<AutoTable
pagetitle={<h3 className="page-title">点检计划</h3>}
columns={columns}
......@@ -485,8 +485,8 @@ function Plan(props) {
drawer?.val == 'detailaddon'
? editDateColumns
: drawer?.val == 'detail'
? detailsColumns
: columns
? detailsColumns
: columns
}
detailpath={pathconfig?.detail || null}
defaultFormValue={drawer?.item}
......
......@@ -110,7 +110,7 @@ function Project({ equipmentCheckStandardId }) {
}, [drawer?.id]);
return (
<div style={{ position: 'relative' }}>
<div>
<AutoTable
columns={columns}
actionRef={actionRef}
......
......@@ -133,7 +133,7 @@ function Standard(props) {
}, [drawer?.id]);
return (
<div style={{ position: 'relative' }}>
<div>
<AutoTable
pagetitle={<h3 className="page-title">点检标准</h3>}
columns={columns}
......
This diff is collapsed.
This diff is collapsed.
.ledgerbox {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
.ledgerheader {
width: 100%;
border-bottom: 1px solid #f0f0f0;
flex-shrink: 0;
}
.ledgercontent {
background-color: #fff;
flex: 1;
width: 100%;
overflow: hidden;
display: flex;
justify-content: space-between;
.ledgerleft {
width: 300px;
display: flex;
flex-direction: column;
height: 100%;
overflow-y: auto;
padding: 0 16px;
flex-shrink: 0;
}
.ledgerright {
padding: 0 16px;
flex: 1;
border-left: 1px solid #f0f0f0;
overflow: hidden;
overflow-y: auto;
}
}
}
\ No newline at end of file
......@@ -132,7 +132,7 @@ function Model(props) {
}, []);
return (
<div style={{ position: 'relative' }}>
<div>
<AutoTable
pagetitle={<h3 className="page-title">设备型号</h3>}
columns={columns}
......
......@@ -191,25 +191,25 @@ function Supplier(props) {
const [request, setrequest] = useState();
useEffect(() => {
const fn = async () => {
let res = await doFetch({
url: '/base/paFormField/queryList',
params: {
formId: '3',
},
});
if (res?.data?.dataList) {
let column = [];
res?.data?.dataList?.forEach?.((el) => {
column.push({
...selectValueType(el.fieldChar, el.valueList),
title: el.fieldName,
dataIndex: el.id,
key: el.id,
});
let res = await doFetch({
url: '/base/paFormField/queryList',
params: {
formId: '3',
},
});
if (res?.data?.dataList) {
let column = [];
res?.data?.dataList?.forEach?.((el) => {
column.push({
...selectValueType(el.fieldChar, el.valueList),
title: el.fieldName,
dataIndex: el.id,
key: el.id,
});
setnewfieldscolumns(column);
}
},
});
setnewfieldscolumns(column);
}
},
fn2 = async () => {
const res = await doFetch({
url: urlParams.detail,
......@@ -420,7 +420,7 @@ function Supplier(props) {
}
};
return (
<div style={{ position: 'relative' }}>
<div>
<AutoTable
pagetitle={<h3 className="page-title">设备供应商</h3>}
columns={columns}
......
......@@ -193,7 +193,7 @@ function Type(props) {
}, [drawer?.val]);
return (
<div style={{ position: 'relative' }}>
<div>
<AutoTable
pagetitle={<h3 className="page-title">设备类型</h3>}
columns={columns}
......
This diff is collapsed.
import React, { useMemo } from 'react';
import { Tooltip, Tabs } from 'antd';
import Filedetail from "@/components/Filedetail";
import DetailPro from '@/components/DetailPro';
import AutoTable from '@/components/AutoTable/mtable';
const statusColors = {
1: '#7ac143',
2: 'orange',
3: '#6a737b',
4: '#fa4659'
};
const columns = [
{
title: '设备编号',
dataIndex: 'equipmentNo',
key: 'equipmentNo'
},
{
title: '设备名称',
dataIndex: 'equipmentName',
key: 'equipmentName',
},
{
title: '设备类型',
dataIndex: 'equipmentTypeName',
key: 'equipmentType',
hideInSearch: true,
// valueType: 'select',
// options: [
// { label: '设备', value: 1 },
// { label: '智能单元', value: 2 },
// ]
},
{
title: '设备型号',
dataIndex: 'equipmentModelName',
key: 'equipmentModelName',
},
{
title: '开始租赁时间',
dataIndex: 'startLeaseDate',
key: 'startLeaseDateList',
valueType: 'dateRange'
},
{
title: '结束租赁时间',
dataIndex: 'endLeaseDate',
key: 'endLeaseDateList',
valueType: 'dateRange'
},
{
title: '实际结束时间',
dataIndex: 'realEndDate',
key: 'realEndDateList',
valueType: 'dateRange'
},
{
title: '采集状态',
dataIndex: 'collectStatusName',
key: 'collectStatus',
valueType: 'select',
options: [
{ label: '工作', value: 1 },
{ label: '待机', value: 2 },
{ label: '关机', value: 3 },
{ label: '报警', value: 4 }
],
render: (_, row) => {
return <span style={{ color: statusColors[row.collectStatus] }}>{row.collectStatusName}</span>
}
},
];
const Devices = ({ drawer }) => {
return <div>
<AutoTable
columns={columns}
path={'/lease/umContractEquipment/queryByContractId'}
resizeable={false}
pageextra="none"
bordered={false}
extraparams={{ contractId: drawer?.item?.id }}
pagination={'false'}
/>
</div>
}
export default Devices;
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
import React, { useMemo, useState } from 'react';
import DrawerPro from '@/components/DrawerPro';
import AutoTable from '@/components/AutoTable/mtable';
import PremButton from '@/components/PremButton';
import { Tooltip } from "antd";
import Filedetail from "@/components/Filedetail";
import { doFetch, exportFetch } from '@/utils/doFetch';
import { message } from "antd";
const statusColor = {
1: '#00bce4',
2: '#7ac143',
3: '#6a737b'
}
const commona = [
{
title: '当期金额',
dataIndex: 'thisPrice',
key: 'thisPrice',
search: false
},
{
title: '回款日期',
dataIndex: 'collectionDate',
key: 'collectionDate',
search: false
},
{
title: '预警日期',
dataIndex: 'warnDate',
key: 'warnDate',
search: false
},
{
title: '状态',
dataIndex: 'statusName',
key: 'statusName',
search: false,
render: (_, row) => {
return <span style={{ color: statusColor[row.status] }}>{row.statusName}</span>
}
}
],
commonb = [
{
title: '是否回款',
dataIndex: 'isCollectionName',
key: 'isCollectionName',
search: false
},
{
title: '回款时间',
dataIndex: 'collectionTime',
key: 'collectionTime',
search: false
},
{
title: '回款形式',
dataIndex: 'collectionTypeName',
key: 'collectionTypeName',
search: false
}
],
columnsc = [
{
title: '基本信息',
valueType: 'split'
},
{
title: '期数',
dataIndex: 'thisTenancy',
key: 'thisTenancy'
},
{
title: '当期开始时间',
dataIndex: 'tenancyStartDate',
key: 'tenancyStartDate'
},
{
title: '当期结束时间',
dataIndex: 'tenancyEndDate',
key: 'tenancyEndDate'
},
...commona,
{
title: '回款信息',
valueType: 'split'
},
...commonb,
{
title: '回款确认人',
dataIndex: 'collectionUserName',
key: 'collectionUserName'
},
{
title: '是否逾期',
dataIndex: 'isOverdueName',
key: 'isOverdueName'
},
{
title: '减免租金信息',
valueType: 'split'
},
{
title: '当期租金减免金额',
dataIndex: 'reducePrice',
key: 'reducePrice'
},
{
title: '最近租金减免时间',
dataIndex: 'reduceTime',
key: 'reduceTime'
},
{
title: '最近租金减免人',
dataIndex: 'reduceUserName',
key: 'reduceUserName'
},
{
title: '减免情况说明',
dataIndex: 'reduceRemark',
key: 'reduceRemark'
},
{
title: '相关文件',
dataIndex: 'reduceFileList',
key: 'reduceFileList',
render: (_, row) => {
return <Filedetail files={row?.['reduceFileList']} />
}
},
{
title: '开票信息',
valueType: 'split'
},
{
title: '是否开票',
dataIndex: 'isOpenName',
key: 'isOpenName'
},
{
title: '开票时间',
dataIndex: 'openTime',
key: 'openTime'
},
{
title: '开票记录人',
dataIndex: 'openUserName',
key: 'openUserName'
},
];
const Leaseterminformation = ({ drawer, boxRef }) => {
const [detail, cd] = useState({
open: false,
});
const columns = [
{
title: '期数',
dataIndex: 'thisTenancy',
key: 'thisTenancy',
search: false
},
...commona,
...commonb,
{
title: '是否逾期',
dataIndex: 'isOverdueName',
key: 'isOverdueName',
search: false
},
{
title: '租金减免金额',
dataIndex: 'reducePrice',
key: 'reducePrice',
search: false
},
{
title: '租金情况说明',
dataIndex: 'reduceRemark',
key: 'reduceRemark',
search: false
},
{
title: '是否开票',
dataIndex: 'isOpenName',
key: 'isOpenName',
search: false
},
{
title: '操作',
valueType: 'option',
width: 80,
render: (text, row, _, action) => rightExtra(text, row, _, action),
}
];
const rightExtra = (text, row, _, action) => {
return [
<PremButton
key='confirm'
btn={{
size: 'small',
onClick: () => {
cd((s) => ({
...s,
open: true,
item: row,
title: '租期详情',
val: 'detail'
}));
},
}}
>
详情
</PremButton>
]
}
return <div style={{ position: "relative" }}>
<div style={{ display: 'flex', justifyContent: 'flex-end' }}>
<PremButton
key='export'
btn={{
type: 'primary',
onClick: async () => {
message.warning('导出中,请稍后');
await exportFetch({ url: '/lease/umContractEquipmentTenancy/exportExcelTenancy', params: { id: drawer?.item?.id } });
}
}}
>
导出
</PremButton>
</div>
<AutoTable
columns={columns}
path={'/lease/umContractEquipmentTenancy/queryByContractEquipmentId'}
resizeable={false}
bordered={false}
extraparams={{ id: drawer?.item?.id }}
options={false}
pagination='false'
/>
<DrawerPro
{...detail}
fields={columnsc}
params={{ id: detail?.item?.id }}
detailpath='/lease/umContractEquipmentTenancy/queryDetail'
placement="right"
onClose={() => {
cd((s) => ({
...s,
open: false,
}));
}}
getContainer={() => boxRef.current}
>
</DrawerPro>
</div>
}
export default Leaseterminformation;
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
import React, { useMemo } from 'react';
import DetailPro from '@/components/DetailPro';
import getcolumns from './columns';
import { doFetch } from '@/utils/doFetch';
import { useRequest } from 'ahooks';
const Basemsg = ({ drawer, activeKey, setdrawer }) => {
const columns = useMemo(() => {
let defcolumn = getcolumns(setdrawer, activeKey)?.columns ?? [];
return defcolumn;
}, [activeKey]);
const detailData = useRequest(async () => {
let res = await doFetch({ url: '/lease/umLeaseLedger/detail', params: { id: drawer?.item?.id } });
return res?.data?.data ?? {};
}, {
refreshDeps: [drawer?.item?.id]
});
return <DetailPro
fields={columns}
detailData={detailData?.data ?? {}}
params={{ id: drawer?.item?.id }}
/>
}
export default Basemsg;
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
.ledgerbox {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
.ledgerheader {
width: 100%;
border-bottom: 1px solid #f0f0f0;
flex-shrink: 0;
}
.ledgercontent {
background-color: #fff;
flex: 1;
width: 100%;
overflow: hidden;
display: flex;
justify-content: space-between;
.ledgerleft {
width: var(--flagw);
display: flex;
flex-direction: column;
height: 100%;
overflow-y: auto;
padding: 0 16px;
flex-shrink: 0;
}
.ledgerright {
padding: 0 16px;
flex: 1;
border-left: 1px solid #f0f0f0;
overflow: hidden;
overflow-y: auto;
}
}
}
\ No newline at end of file
This diff is collapsed.
.rowClass {
background-color: #e6f4ff;
}
\ No newline at end of file
import React, { useMemo } from 'react';
import DetailPro from '@/components/DetailPro';
import getcolumns from './columns';
const Basemsg = ({ drawer }) => {
const columns = useMemo(() => {
let defcolumn = getcolumns()?.columns ?? [];
return defcolumn;
}, []);
return <DetailPro
fields={columns}
detailpath="/lease/umLeaseLedger/detail"
params={{ id: drawer?.item?.id }}
/>
}
export default Basemsg;
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -212,7 +212,7 @@ function Warning(props) {
}, []);
return (
<div style={{ position: 'relative' }}>
<div>
<AutoTable
pagetitle={<h3 className="page-title">寿命件台账</h3>}
columns={columns}
......
......@@ -118,7 +118,7 @@ function Criterion(props) {
}, []);
return (
<div style={{ position: 'relative' }}>
<div>
<AutoTable
pagetitle={<h3 className="page-title">寿命件标准</h3>}
columns={columns}
......
......@@ -205,7 +205,7 @@ function Warning(props) {
}, []);
return (
<div style={{ position: 'relative' }}>
<div>
<AutoTable
pagetitle={<h3 className="page-title">寿命件预警</h3>}
columns={columns}
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.