first commit

master
李神峰 2025-11-22 11:00:19 +08:00
commit a8d4ad8a1a
104 changed files with 50348 additions and 0 deletions

1
.env.development Normal file
View File

@ -0,0 +1 @@
PUBLIC_URL=/yjtgq

2
.env.production Normal file
View File

@ -0,0 +1,2 @@
GENERATE_SOURCEMAP=false
PUBLIC_URL=/yjtgq

25
.gitignore vendored Normal file
View File

@ -0,0 +1,25 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
yarn.lock
build.7z

46
README.md Normal file
View File

@ -0,0 +1,46 @@
# Getting Started with Create React App
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
## Available Scripts
In the project directory, you can run:
### `npm start`
Runs the app in the development mode.\
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
The page will reload if you make edits.\
You will also see any lint errors in the console.
### `npm test`
Launches the test runner in the interactive watch mode.\
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
### `npm run build`
Builds the app for production to the `build` folder.\
It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.\
Your app is ready to be deployed!
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
### `npm run eject`
**Note: this is a one-way operation. Once you `eject`, you cant go back!**
If you arent satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point youre on your own.
You dont have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldnt feel obligated to use this feature. However we understand that this tool wouldnt be useful if you couldnt customize it when you are ready for it.
## Learn More
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
To learn React, check out the [React documentation](https://reactjs.org/).

28
craco.config.js Normal file
View File

@ -0,0 +1,28 @@
const CracoLessPlugin = require('craco-less');
module.exports = {
plugins: [
{
plugin: CracoLessPlugin,
options: {
lessLoaderOptions: {
lessOptions: {
modifyVars: {
'@primary-color': '#3B7CFF',
'@error-color': '#F55E55',
'@text-color': '#3B4859',
'@menu-dark-bg': '#3773C5',
'@layout-body-background': '#eeeeee',
'@form-vertical-label-padding': '0 0 10px',
'@normal-color': '#EFF1F5',
'@label-color': '#3B4859',
'@card-background': '#fbfbfb',
'@heading-color': '#3B4859',
},
javascriptEnabled: true,
},
},
},
},
],
};

30713
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

56
package.json Normal file
View File

@ -0,0 +1,56 @@
{
"name": "yjtgq-web",
"version": "0.1.0",
"private": true,
"dependencies": {
"@ant-design/icons": "^4.7.0",
"@craco/craco": "7.0.0-alpha.7",
"@dnd-kit/core": "^6.0.8",
"@dnd-kit/sortable": "^7.0.2",
"@panzoom/panzoom": "^4.5.1",
"@react-hook/resize-observer": "^1.2.6",
"@rematch/core": "^2.2.0",
"@types/geojson": "^7946.0.8",
"@types/node": "^16.11.45",
"@types/react": "^18.0.15",
"@types/react-dom": "^18.0.6",
"antd": "^4.21.7",
"axios": "^0.27.2",
"craco-less": "2.1.0-alpha.0",
"echarts": "^5.3.3",
"echarts-for-react": "^3.0.2",
"http-proxy-middleware": "^2.0.6",
"moment": "^2.29.4",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-konva": "^18.2.3",
"react-redux": "^8.0.2",
"react-router": "^6.3.0",
"react-router-dom": "^6.3.0",
"react-scripts": "5.0.1",
"redux": "^4.2.0",
"typescript": "^4.7.4",
"xlsx": "^0.18.5"
},
"scripts": {
"start": "craco start",
"build": "craco build"
},
"eslintConfig": {
"extends": [
"react-app"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}

BIN
public/assets/decst.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

BIN
public/assets/icons2/bz.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 689 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 B

BIN
public/assets/icons2/hz.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 858 B

BIN
public/assets/icons2/sx.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
public/assets/icons2/wx.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
public/assets/u945.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 443 KiB

3411
public/data/gateFlow.json Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,276 @@
{
"success": true,
"message": "操作成功!",
"extMessage": "",
"code": 200,
"result": {
"records": [
{
"idElement": "svg_1678158955703",
"levelShow": "2",
"officeCode": "A06A22",
"stroke": null,
"transform": null,
"stcd": "4211223304",
"width": "36",
"x": "5854",
"y": "372",
"isWindowShow": 1,
"style": null,
"id": "1632915412385660929",
"height": "36"
},
{
"idElement": "svg_1679969744692",
"levelShow": "1",
"officeCode": "A07",
"stroke": null,
"transform": null,
"stcd": "42000003",
"width": "36",
"x": "4931",
"y": "571",
"isWindowShow": 1,
"style": null,
"id": "1640537692418736130",
"height": "36"
},
{
"idElement": "svg_1679969785136",
"levelShow": "1",
"officeCode": "A07",
"stroke": null,
"transform": null,
"stcd": "42000005",
"width": "36",
"x": "4928",
"y": "666",
"isWindowShow": 1,
"style": null,
"id": "1640538304657096705",
"height": "36"
},
{
"idElement": "svg_1680684083023",
"levelShow": "1",
"officeCode": "A07",
"stroke": null,
"transform": null,
"stcd": "42000011",
"width": "36",
"x": "4933",
"y": "749",
"isWindowShow": 1,
"style": null,
"id": "1640538536836988930",
"height": "36"
},
{
"idElement": "svg_1679970042352",
"levelShow": "1",
"officeCode": "A06A22",
"stroke": null,
"transform": null,
"stcd": "42000010",
"width": "36",
"x": "5720",
"y": "373",
"isWindowShow": 1,
"style": null,
"id": "1640539322979581953",
"height": "36"
},
{
"idElement": "svg_1679970559896",
"levelShow": "1",
"officeCode": "A06A22",
"stroke": null,
"transform": null,
"stcd": "42080208",
"width": "36",
"x": "5501",
"y": "373",
"isWindowShow": 1,
"style": null,
"id": "1640541554378670082",
"height": "36"
},
{
"idElement": "svg_1679970689837",
"levelShow": "1",
"officeCode": "A06A20",
"stroke": null,
"transform": null,
"stcd": "42080401",
"width": "36",
"x": "4760",
"y": "383",
"isWindowShow": 1,
"style": null,
"id": "1640542099277479937",
"height": "36"
},
{
"idElement": "svg_1681544908255",
"levelShow": "1",
"officeCode": "A06A22",
"stroke": null,
"transform": null,
"stcd": "4211223303",
"width": "36",
"x": "5389",
"y": "373",
"isWindowShow": null,
"style": null,
"id": "1647144698692894722",
"height": "36"
},
{
"idElement": "svg_1681545640285",
"levelShow": "1",
"officeCode": "A07",
"stroke": null,
"transform": null,
"stcd": "0007246017",
"width": "36",
"x": "4933",
"y": "2206",
"isWindowShow": null,
"style": null,
"id": "1647147909474549761",
"height": "36"
},
{
"idElement": "svg_1686119263004",
"levelShow": "2",
"officeCode": "A06A20",
"stroke": null,
"transform": null,
"stcd": "0000000185",
"width": "36",
"x": "1094",
"y": "88",
"isWindowShow": null,
"style": null,
"id": "1665924881558142977",
"height": "36"
},
{
"idElement": "svg_1686383014825",
"levelShow": "2",
"officeCode": "A06A20",
"stroke": null,
"transform": null,
"stcd": "0000000186",
"width": "36",
"x": "1042",
"y": "136",
"isWindowShow": null,
"style": null,
"id": "1665924978488508417",
"height": "36"
},
{
"idElement": "svg_1686382550328",
"levelShow": "2",
"officeCode": "A06A20",
"stroke": null,
"transform": null,
"stcd": "42080202",
"width": "36",
"x": "1260",
"y": "239",
"isWindowShow": null,
"style": null,
"id": "1665925899842879489",
"height": "36"
},
{
"idElement": "svg_1686119226075",
"levelShow": "2",
"officeCode": "A06A20",
"stroke": null,
"transform": null,
"stcd": "42080201",
"width": "36",
"x": "1310",
"y": "303",
"isWindowShow": null,
"style": null,
"id": "1665925958101762049",
"height": "36"
},
{
"idElement": "svg_1686382532474",
"levelShow": "2",
"officeCode": "A06A20",
"stroke": null,
"transform": null,
"stcd": "42080204",
"width": "36",
"x": "1241",
"y": "155",
"isWindowShow": null,
"style": null,
"id": "1665926121801252866",
"height": "36"
},
{
"idElement": "svg_1686382974869",
"levelShow": "2",
"officeCode": "A05",
"stroke": null,
"transform": null,
"stcd": "42999999",
"width": "36",
"x": "1120",
"y": "422",
"isWindowShow": null,
"style": null,
"id": "1667437123747315714",
"height": "36"
},
{
"idElement": "svg_1687073890520",
"levelShow": "2",
"officeCode": "A07",
"stroke": null,
"transform": null,
"stcd": "0007246011",
"width": "36",
"x": "4927",
"y": "1003",
"isWindowShow": null,
"style": null,
"id": "1670335080452718593",
"height": "36"
},
{
"idElement": "svg_1687074005094",
"levelShow": "2",
"officeCode": "A07",
"stroke": null,
"transform": null,
"stcd": "0007246022",
"width": "36",
"x": "4927",
"y": "1553",
"isWindowShow": null,
"style": null,
"id": "1670335560826355714",
"height": "36"
}
],
"total": 17,
"size": 1000,
"current": 1,
"orders": [],
"optimizeCountSql": true,
"hitCount": false,
"countId": null,
"maxLimit": null,
"searchCount": true,
"pages": 1
},
"timestamp": 1689145633556
}

View File

@ -0,0 +1,96 @@
{
"success": true,
"message": "操作成功!",
"extMessage": "",
"code": 200,
"result": {
"records": [
{
"idElement": "svg_1682924517666",
"levelShow": "2",
"officeCode": "A06A21",
"stroke": null,
"transform": null,
"stcd": "ZH201626",
"width": "36",
"x": "1714",
"y": "703",
"isWindowShow": null,
"style": null,
"id": "1652931348219953154",
"height": "36"
},
{
"idElement": "svg_1682926143271",
"levelShow": "2",
"officeCode": "A06A21",
"stroke": null,
"transform": null,
"stcd": "ZH201552",
"width": "36",
"x": "1713",
"y": "1067",
"isWindowShow": null,
"style": null,
"id": "1652938166631530498",
"height": "36"
},
{
"idElement": "svg_1682991158657",
"levelShow": "2",
"officeCode": "A06A21",
"stroke": null,
"transform": null,
"stcd": "ZH201551",
"width": "36",
"x": "1710",
"y": "1673",
"isWindowShow": null,
"style": null,
"id": "1653210864574136322",
"height": "36"
},
{
"idElement": "svg_1687074247023",
"levelShow": "2",
"officeCode": "A07",
"stroke": null,
"transform": null,
"stcd": "ZH201508",
"width": "36",
"x": "4929",
"y": "904",
"isWindowShow": null,
"style": null,
"id": "1670336575562711041",
"height": "36"
},
{
"idElement": "svg_1687074351943",
"levelShow": "2",
"officeCode": "A07",
"stroke": null,
"transform": null,
"stcd": "ZH201512",
"width": "36",
"x": "4779",
"y": "2719",
"isWindowShow": null,
"style": null,
"id": "1670337015599726593",
"height": "36"
}
],
"total": 5,
"size": 1000,
"current": 1,
"orders": [],
"optimizeCountSql": true,
"hitCount": false,
"countId": null,
"maxLimit": null,
"searchCount": true,
"pages": 1
},
"timestamp": 1689145633569
}

View File

@ -0,0 +1,976 @@
{
"success": true,
"message": "操作成功!",
"extMessage": "",
"code": 200,
"result": {
"records": [
{
"strokeWidth": "20",
"strokeLinejoin": null,
"idElement": "svg_041",
"levelShow": "1",
"officeCode": "",
"chanName": "清江渠",
"fill": "none",
"stroke": "#b1fd7b",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "2850",
"y1": "3788",
"x2": "2850",
"y2": "4300",
"style": null,
"id": "20251118100741"
},
{
"strokeWidth": "20",
"strokeLinejoin": null,
"idElement": "svg_042",
"levelShow": "1",
"officeCode": "",
"chanName": "清江渠2",
"fill": "none",
"stroke": "#b1fd7b",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "3950",
"y1": "2900",
"x2": "3950",
"y2": "3400",
"style": null,
"id": "20251118100742"
},
{
"strokeWidth": "20",
"strokeLinejoin": null,
"idElement": "svg_043",
"levelShow": "1",
"officeCode": "",
"chanName": "丰收渠",
"fill": "none",
"stroke": "#b1fd7b",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "4200",
"y1": "2900",
"x2": "4200",
"y2": "3400",
"style": null,
"id": "20251118100743"
},
{
"strokeWidth": "20",
"strokeLinejoin": null,
"idElement": "svg_044",
"levelShow": "1",
"officeCode": "",
"chanName": "双收渠",
"fill": "none",
"stroke": "#b1fd7b",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "4450",
"y1": "2900",
"x2": "4450",
"y2": "3400",
"style": null,
"id": "20251118100744"
},
{
"strokeWidth": "20",
"strokeLinejoin": null,
"idElement": "svg_045",
"levelShow": "1",
"officeCode": "",
"chanName": "司马渠",
"fill": "none",
"stroke": "#b1fd7b",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "5000",
"y1": "1450",
"x2": "5000",
"y2": "2500",
"style": null,
"id": "20251118100745"
},
{
"strokeWidth": "20",
"strokeLinejoin": null,
"idElement": "svg_046",
"levelShow": "1",
"officeCode": "",
"chanName": "南阳渠",
"fill": "none",
"stroke": "#b1fd7b",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "5200",
"y1": "1650",
"x2": "5200",
"y2": "2450",
"style": null,
"id": "20251118100746"
},
{
"strokeWidth": "20",
"strokeLinejoin": null,
"idElement": "svg_047",
"levelShow": "1",
"officeCode": "",
"chanName": "萌树渠",
"fill": "none",
"stroke": "#b1fd7b",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "5400",
"y1": "1500",
"x2": "5400",
"y2": "2400",
"style": null,
"id": "20251118100747"
},
{
"strokeWidth": "20",
"strokeLinejoin": null,
"idElement": "svg_048",
"levelShow": "1",
"officeCode": "",
"chanName": "竺家大沟",
"fill": "none",
"stroke": "#b1fd7b",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "5600",
"y1": "1600",
"x2": "5600",
"y2": "2350",
"style": null,
"id": "20251118100748"
},
{
"strokeWidth": "23",
"strokeLinejoin": null,
"idElement": "svg_008",
"levelShow": "1",
"officeCode": "",
"chanName": "七零二渠",
"fill": "none",
"stroke": "rgba(237, 125, 49, 1)",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "1200",
"y1": "1280",
"x2": "1200",
"y2": "1788",
"style": null,
"id": "20251118100708"
},
{
"strokeWidth": "23",
"strokeLinejoin": null,
"idElement": "svg_001",
"levelShow": "1",
"officeCode": "",
"chanName": "联灌渠",
"fill": "none",
"stroke": "rgba(237, 125, 49, 1)",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "500",
"y1": "1800",
"x2": "1100",
"y2": "1800",
"style": null,
"id": "20251118100701"
},
{
"strokeWidth": "23",
"strokeLinejoin": null,
"idElement": "svg_049",
"levelShow": "1",
"officeCode": "",
"chanName": "七零二渠",
"fill": "none",
"stroke": "rgba(237, 125, 49, 1)",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "1200",
"y1": "1280",
"x2": "1200",
"y2": "1789",
"style": null,
"id": "20251118100749"
},
{
"strokeWidth": "23",
"strokeLinejoin": null,
"idElement": "svg_009",
"levelShow": "1",
"officeCode": "",
"chanName": "边江灌渠",
"fill": "none",
"stroke": "rgba(237, 125, 49, 1)",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "2300",
"y1": "1400",
"x2": "2700",
"y2": "1400",
"style": null,
"id": "20251118100709"
},
{
"strokeWidth": "23",
"strokeLinejoin": null,
"idElement": "svg_010",
"levelShow": "1",
"officeCode": "",
"chanName": "边江灌渠",
"fill": "none",
"stroke": "rgba(237, 125, 49, 1)",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "2700",
"y1": "1400",
"x2": "3100",
"y2": "1400",
"style": null,
"id": "20251118100710"
},
{
"strokeWidth": "23",
"strokeLinejoin": null,
"idElement": "svg_011",
"levelShow": "1",
"officeCode": "",
"chanName": "大熊渠",
"fill": "none",
"stroke": "rgba(237, 125, 49, 1)",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "2700",
"y1": "1150",
"x2": "3100",
"y2": "1150",
"style": null,
"id": "20251118100711"
},
{
"strokeWidth": "23",
"strokeLinejoin": null,
"idElement": "svg_012",
"levelShow": "1",
"officeCode": "",
"chanName": "幸福渠",
"fill": "none",
"stroke": "rgba(237, 125, 49, 1)",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "4700",
"y1": "1850",
"x2": "5700",
"y2": "1850",
"style": null,
"id": "20251118100712"
},
{
"strokeWidth": "23",
"strokeLinejoin": null,
"idElement": "svg_013",
"levelShow": "1",
"officeCode": "",
"chanName": "联剅渠",
"fill": "none",
"stroke": "rgba(237, 125, 49, 1)",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "1100",
"y1": "3000",
"x2": "1650",
"y2": "3000",
"style": null,
"id": "20251118100713"
},
{
"strokeWidth": "23",
"strokeLinejoin": null,
"idElement": "svg_014",
"levelShow": "1",
"officeCode": "",
"chanName": "河谭渠",
"fill": "none",
"stroke": "rgba(237, 125, 49, 1)",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "1100",
"y1": "3150",
"x2": "1650",
"y2": "3150",
"style": null,
"id": "20251118100714"
},
{
"strokeWidth": "23",
"strokeLinejoin": null,
"idElement": "svg_015",
"levelShow": "1",
"officeCode": "",
"chanName": "聂谭渠",
"fill": "none",
"stroke": "rgba(237, 125, 49, 1)",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "1100",
"y1": "3300",
"x2": "1650",
"y2": "3300",
"style": null,
"id": "20251118100715"
},
{
"strokeWidth": "23",
"strokeLinejoin": null,
"idElement": "svg_016",
"levelShow": "1",
"officeCode": "",
"chanName": "十子纵渠",
"fill": "none",
"stroke": "rgba(237, 125, 49, 1)",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "1100",
"y1": "3450",
"x2": "1650",
"y2": "3450",
"style": null,
"id": "20251118100716"
},
{
"strokeWidth": "23",
"strokeLinejoin": null,
"idElement": "svg_017",
"levelShow": "1",
"officeCode": "",
"chanName": "南北公路渠",
"fill": "none",
"stroke": "rgba(237, 125, 49, 1)",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "1600",
"y1": "2300",
"x2": "4700",
"y2": "2300",
"style": null,
"id": "20251118100717"
},
{
"strokeWidth": "23",
"strokeLinejoin": null,
"idElement": "svg_019",
"levelShow": "1",
"officeCode": "",
"chanName": "泰张管渠",
"fill": "none",
"stroke": "rgba(237, 125, 49, 1)",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "2400",
"y1": "2800",
"x2": "2400",
"y2": "3500",
"style": null,
"id": "20251118100719"
},
{
"strokeWidth": "23",
"strokeLinejoin": null,
"idElement": "svg_020",
"levelShow": "1",
"officeCode": "",
"chanName": "东陈岭灌渠",
"fill": "none",
"stroke": "rgba(237, 125, 49, 1)",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "2150",
"y1": "2800",
"x2": "2150",
"y2": "3500",
"style": null,
"id": "20251118100720"
},
{
"strokeWidth": "23",
"strokeLinejoin": null,
"idElement": "svg_021",
"levelShow": "1",
"officeCode": "",
"chanName": "阳湖十三渠",
"fill": "none",
"stroke": "rgba(237, 125, 49, 1)",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "1900",
"y1": "2800",
"x2": "1900",
"y2": "3500",
"style": null,
"id": "20251118100721"
},
{
"strokeWidth": "23",
"strokeLinejoin": null,
"idElement": "svg_022",
"levelShow": "1",
"officeCode": "",
"chanName": "四清渠",
"fill": "none",
"stroke": "rgba(237, 125, 49, 1)",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "2200",
"y1": "3788",
"x2": "2700",
"y2": "3788",
"style": null,
"id": "20251118100722"
},
{
"strokeWidth": "23",
"strokeLinejoin": null,
"idElement": "svg_023",
"levelShow": "1",
"officeCode": "",
"chanName": "列沙渠",
"fill": "none",
"stroke": "rgba(237, 125, 49, 1)",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "2700",
"y1": "3788",
"x2": "3200",
"y2": "3788",
"style": null,
"id": "20251118100723"
},
{
"strokeWidth": "23",
"strokeLinejoin": null,
"idElement": "svg_024",
"levelShow": "1",
"officeCode": "",
"chanName": "立双灌渠",
"fill": "none",
"stroke": "rgba(237, 125, 49, 1)",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "2700",
"y1": "2600",
"x2": "3600",
"y2": "2600",
"style": null,
"id": "20251118100724"
},
{
"strokeWidth": "23",
"strokeLinejoin": null,
"idElement": "svg_025",
"levelShow": "1",
"officeCode": "",
"chanName": "新贵林渠道",
"fill": "none",
"stroke": "rgba(237, 125, 49, 1)",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "2700",
"y1": "2450",
"x2": "3600",
"y2": "2450",
"style": null,
"id": "20251118100725"
},
{
"strokeWidth": "23",
"strokeLinejoin": null,
"idElement": "svg_026",
"levelShow": "1",
"officeCode": "",
"chanName": "龙台渠",
"fill": "none",
"stroke": "rgba(237, 125, 49, 1)",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "3100",
"y1": "1800",
"x2": "3100",
"y2": "2461.5",
"style": null,
"id": "20251118100726"
},
{
"strokeWidth": "23",
"strokeLinejoin": null,
"idElement": "svg_027",
"levelShow": "1",
"officeCode": "",
"chanName": "费湖渠",
"fill": "none",
"stroke": "rgba(237, 125, 49, 1)",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "3320",
"y1": "1800",
"x2": "3320",
"y2": "2461.5",
"style": null,
"id": "20251118100727"
},
{
"strokeWidth": "23",
"strokeLinejoin": null,
"idElement": "svg_028",
"levelShow": "1",
"officeCode": "",
"chanName": "黄林灌渠",
"fill": "none",
"stroke": "rgba(237, 125, 49, 1)",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "3540",
"y1": "1800",
"x2": "3540",
"y2": "2461.5",
"style": null,
"id": "20251118100728"
},
{
"strokeWidth": "23",
"strokeLinejoin": null,
"idElement": "svg_029",
"levelShow": "1",
"officeCode": "",
"chanName": "魏阳渠",
"fill": "none",
"stroke": "rgba(237, 125, 49, 1)",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "3760",
"y1": "1800",
"x2": "3760",
"y2": "2461.5",
"style": null,
"id": "20251118100729"
},
{
"strokeWidth": "23",
"strokeLinejoin": null,
"idElement": "svg_030",
"levelShow": "1",
"officeCode": "",
"chanName": "大兴灌渠",
"fill": "none",
"stroke": "rgba(237, 125, 49, 1)",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "3980",
"y1": "1800",
"x2": "3980",
"y2": "2461.5",
"style": null,
"id": "20251118100730"
},
{
"strokeWidth": "23",
"strokeLinejoin": null,
"idElement": "svg_031",
"levelShow": "1",
"officeCode": "",
"chanName": "兰花灌渠",
"fill": "none",
"stroke": "rgba(237, 125, 49, 1)",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "4200",
"y1": "1800",
"x2": "4200",
"y2": "2610",
"style": null,
"id": "20251118100731"
},
{
"strokeWidth": "23",
"strokeLinejoin": null,
"idElement": "svg_032",
"levelShow": "1",
"officeCode": "",
"chanName": "低灌渠",
"fill": "none",
"stroke": "rgba(237, 125, 49, 1)",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "3750",
"y1": "2600",
"x2": "4700",
"y2": "2600",
"style": null,
"id": "20251118100732"
},
{
"strokeWidth": "23",
"strokeLinejoin": null,
"idElement": "svg_033",
"levelShow": "1",
"officeCode": "",
"chanName": "八一渠",
"fill": "none",
"stroke": "rgba(237, 125, 49, 1)",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "3750",
"y1": "2750",
"x2": "4700",
"y2": "2750",
"style": null,
"id": "20251118100733"
},
{
"strokeWidth": "23",
"strokeLinejoin": null,
"idElement": "svg_034",
"levelShow": "1",
"officeCode": "",
"chanName": "首渠",
"fill": "none",
"stroke": "rgba(237, 125, 49, 1)",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "3750",
"y1": "2900",
"x2": "4700",
"y2": "2900",
"style": null,
"id": "20251118100734"
},
{
"strokeWidth": "23",
"strokeLinejoin": null,
"idElement": "svg_035",
"levelShow": "1",
"officeCode": "",
"chanName": "金龟渠",
"fill": "none",
"stroke": "rgba(237, 125, 49, 1)",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "3750",
"y1": "3500",
"x2": "4700",
"y2": "3500",
"style": null,
"id": "20251118100735"
},
{
"strokeWidth": "23",
"strokeLinejoin": null,
"idElement": "svg_036",
"levelShow": "1",
"officeCode": "",
"chanName": "长湖渠",
"fill": "none",
"stroke": "rgba(237, 125, 49, 1)",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "3750",
"y1": "3650",
"x2": "4700",
"y2": "3650",
"style": null,
"id": "20251118100736"
},
{
"strokeWidth": "23",
"strokeLinejoin": null,
"idElement": "svg_037",
"levelShow": "1",
"officeCode": "",
"chanName": "立新渠",
"fill": "none",
"stroke": "rgba(237, 125, 49, 1)",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "3750",
"y1": "3800",
"x2": "4700",
"y2": "3800",
"style": null,
"id": "20251118100737"
},
{
"strokeWidth": "23",
"strokeLinejoin": null,
"idElement": "svg_038",
"levelShow": "1",
"officeCode": "",
"chanName": "新丰渠",
"fill": "none",
"stroke": "rgba(237, 125, 49, 1)",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "3750",
"y1": "3950",
"x2": "4700",
"y2": "3950",
"style": null,
"id": "20251118100738"
},
{
"strokeWidth": "23",
"strokeLinejoin": null,
"idElement": "svg_039",
"levelShow": "1",
"officeCode": "",
"chanName": "",
"fill": "none",
"stroke": "rgba(237, 125, 49, 1)",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "4700",
"y1": "3950",
"x2": "5300",
"y2": "3950",
"style": null,
"id": "20251118100739"
},
{
"strokeWidth": "23",
"strokeLinejoin": null,
"idElement": "svg_040",
"levelShow": "1",
"officeCode": "",
"chanName": "樊湖渠",
"fill": "none",
"stroke": "rgba(237, 125, 49, 1)",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "4700",
"y1": "4100",
"x2": "5300",
"y2": "4100",
"style": null,
"id": "20251118100740"
},
{
"strokeWidth": "25",
"strokeLinejoin": null,
"idElement": "svg_018",
"levelShow": "1",
"officeCode": "",
"chanName": "新南渠",
"fill": "none",
"stroke": "rgba(0, 176, 240, 1)",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "1600",
"y1": "2800",
"x2": "2700",
"y2": "2800",
"style": null,
"id": "20251118100718"
},
{
"strokeWidth": "25",
"strokeLinejoin": null,
"idElement": "svg_002",
"levelShow": "1",
"officeCode": "",
"chanName": "颜南渠",
"fill": "none",
"stroke": "rgba(0, 176, 240, 1)",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "1087.5",
"y1": "1800",
"x2": "2700",
"y2": "1800",
"style": null,
"id": "20251118100702"
},
{
"strokeWidth": "25",
"strokeLinejoin": null,
"idElement": "svg_003",
"levelShow": "1",
"officeCode": "",
"chanName": "颜北渠",
"fill": "none",
"stroke": "rgba(0, 176, 240, 1)",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "2700",
"y1": "1800",
"x2": "4712.5",
"y2": "1800",
"style": null,
"id": "20251118100703"
},
{
"strokeWidth": "25",
"strokeLinejoin": null,
"idElement": "svg_004",
"levelShow": "1",
"officeCode": "",
"chanName": "",
"fill": "none",
"stroke": "rgba(0, 176, 240, 1)",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "1100",
"y1": "1800",
"x2": "1100",
"y2": "3696",
"style": null,
"id": "20251118100704"
},
{
"strokeWidth": "25",
"strokeLinejoin": null,
"idElement": "svg_005",
"levelShow": "1",
"officeCode": "",
"chanName": "新列渠",
"fill": "none",
"stroke": "rgba(0, 176, 240, 1)",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "2700",
"y1": "1800",
"x2": "2700",
"y2": "3800",
"style": null,
"id": "20251118100705"
},
{
"strokeWidth": "25",
"strokeLinejoin": null,
"idElement": "svg_006",
"levelShow": "1",
"officeCode": "",
"chanName": "",
"fill": "none",
"stroke": "rgba(0, 176, 240, 1)",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "4700",
"y1": "1800",
"x2": "4700",
"y2": "4328",
"style": null,
"id": "20251118100706"
},
{
"strokeWidth": "27",
"strokeLinejoin": null,
"idElement": "svg_007",
"levelShow": "1",
"officeCode": "",
"chanName": "颜总渠",
"fill": "none",
"stroke": "#5071be",
"transform": null,
"baseinfo": "",
"strokeLinecap": null,
"x1": "2700",
"y1": "800",
"x2": "2700",
"y2": "1812.5",
"style": null,
"id": "20251118100707"
}
],
"total": 161,
"size": 10,
"current": 1,
"orders": [],
"optimizeCountSql": true,
"hitCount": false,
"countId": null,
"maxLimit": null,
"searchCount": true,
"pages": 17
},
"timestamp": 1689145633381
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,43 @@
{
"success": true,
"message": "操作成功!",
"extMessage": "",
"code": 200,
"result": {
"records": [
{
"strokeWidth": "12",
"idElement": "svg_82",
"d": "m1149.09069,963.272 20.54543,1.81818",
"levelShow": "1",
"officeCode": "A05",
"id": "20221201102301",
"opacity": "undefined",
"fill": "none",
"stroke": "#72ca73"
},
{
"strokeWidth": "20",
"idElement": "svg_159",
"d": "m1730.90874,400.72711l3.63636,98.18184",
"levelShow": "1",
"officeCode": "A06A21",
"id": "20221201102302",
"opacity": "undefined",
"fill": "none",
"stroke": "#00b0f0"
}
],
"total": 2,
"size": 1000,
"current": 1,
"orders": [],
"optimizeCountSql": true,
"hitCount": false,
"countId": null,
"maxLimit": null,
"searchCount": true,
"pages": 1
},
"timestamp": 1689145633425
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,249 @@
{
"success": true,
"message": "操作成功!",
"extMessage": "",
"code": 200,
"result": {
"records": [
{
"stcd":"1",
"chanName": "联灌渠",
"ghtX":1000,
"ghtY":1750
},
{
"stcd":"2",
"chanName": "七零二渠",
"ghtX":1150,
"ghtY":1700
},
{
"stcd":"3",
"chanName": "联剅渠",
"ghtX":1100,
"ghtY":2950
},
{
"stcd":"4",
"chanName": "河谭渠",
"ghtX":1100,
"ghtY":3100
},
{
"stcd":"5",
"chanName": "聂谭渠",
"ghtX":1100,
"ghtY":3250
},
{
"stcd":"6",
"chanName": "十子纵渠",
"ghtX":1100,
"ghtY":3400
},
{
"stcd":"7",
"chanName": "阳湖十三渠",
"ghtX":1850,
"ghtY":2800
},
{
"stcd":"8",
"chanName": "东陈岭灌渠",
"ghtX":2100,
"ghtY":2800
},
{
"stcd":"9",
"chanName": "泰张管渠",
"ghtX":2350,
"ghtY":2800
},
{
"stcd":"10",
"chanName": "新南渠",
"ghtX":2590,
"ghtY":2750
},
{
"stcd":"11",
"chanName": "四清渠",
"ghtX":2590,
"ghtY":3738
},
{
"stcd":"12",
"chanName": "颜南渠",
"ghtX":2570,
"ghtY":1750
},
{
"stcd":"13",
"chanName": "边江灌渠",
"ghtX":2590,
"ghtY":1350
},
{
"stcd":"14",
"chanName": "长江",
"ghtX":2650,
"ghtY":800
},
{
"stcd":"15",
"chanName": "颜中渠",
"ghtX":2650,
"ghtY":1830
},
{
"stcd":"16",
"chanName": "大熊渠",
"ghtX":2710,
"ghtY":1100
},
{
"stcd":"17",
"chanName": "东兴渠",
"ghtX":2710,
"ghtY":1350
},
{
"stcd":"19",
"chanName": "颜北渠",
"ghtX":2725,
"ghtY":1750
},
{
"stcd":"20",
"chanName": "南北公路渠",
"ghtX":2710,
"ghtY":2250
},
{
"stcd":"21",
"chanName": "新贵林渠",
"ghtX":2710,
"ghtY":2400
},
{
"stcd":"22",
"chanName": "立双灌渠",
"ghtX":2710,
"ghtY":2550
},
{
"stcd":"23",
"chanName": "列沙渠",
"ghtX":2710,
"ghtY":3738
},
{
"stcd":"24",
"chanName": "龙台渠",
"ghtX":3050,
"ghtY":1800
},
{
"stcd":"25",
"chanName": "费湖渠",
"ghtX":3270,
"ghtY":1800
},
{
"stcd":"26",
"chanName": "黄林灌渠",
"ghtX":3490,
"ghtY":1800
},
{
"stcd":"27",
"chanName": "魏阳渠",
"ghtX":3710,
"ghtY":1800
},
{
"stcd":"28",
"chanName": "大兴灌渠",
"ghtX":3930,
"ghtY":1800
},
{
"stcd":"29",
"chanName": "兰花灌渠",
"ghtX":4150,
"ghtY":1800
},
{
"stcd":"30",
"chanName": "低灌渠",
"ghtX":4590,
"ghtY":2550
},
{
"stcd":"31",
"chanName": "八一渠",
"ghtX":4590,
"ghtY":2700
},
{
"stcd":"32",
"chanName": "首渠",
"ghtX":4590,
"ghtY":2850
},
{
"stcd":"33",
"chanName": "金龟渠",
"ghtX":4590,
"ghtY":3450
},
{
"stcd":"34",
"chanName": "长湖渠",
"ghtX":4590,
"ghtY":3600
},
{
"stcd":"35",
"chanName": "立新渠",
"ghtX":4590,
"ghtY":3750
},
{
"stcd":"36",
"chanName": "新丰渠",
"ghtX":4590,
"ghtY":3900
},
{
"stcd":"37",
"chanName": "幸福渠",
"ghtX":4710,
"ghtY":1800
},
{
"stcd":"38",
"chanName": "",
"ghtX":4710,
"ghtY":3900
},
{
"stcd":"39",
"chanName": "樊湖渠",
"ghtX":4710,
"ghtY":4050
}
],
"total": 161,
"size": 10,
"current": 1,
"orders": [],
"optimizeCountSql": true,
"hitCount": false,
"countId": null,
"maxLimit": null,
"searchCount": true,
"pages": 17
},
"timestamp": 1689145633381
}

View File

@ -0,0 +1,987 @@
{
"success": true,
"message": "操作成功!",
"extMessage": "",
"code": 200,
"result": {
"records": [
{
"strokeWidth": "1",
"idElement": "svg_01",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#ffffff",
"stroke": "#ffffff",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "730",
"name": "联灌渠",
"y": "1770",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "50",
"id": "20251118100701",
"isDel": "0",
"fontWeight": "bold",
"isVertical": false
},
{
"strokeWidth": "2",
"idElement": "svg_02",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#EFF109",
"stroke": "#EFF109",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "1800",
"name": "颜南渠",
"y": "1770",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "55",
"id": "20251118100702",
"isDel": "0",
"fontWeight": "bold",
"isVertical": false
},
{
"strokeWidth": "2",
"idElement": "svg_03",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#EFF109",
"stroke": "#EFF109",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "3600",
"name": "颜北渠",
"y": "1770",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "55",
"id": "20251118100703",
"isDel": "0",
"fontWeight": "bold",
"isVertical": false
},
{
"strokeWidth": "2",
"idElement": "svg_04",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#EFF109",
"stroke": "#EFF109",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "2760",
"name": "新列渠",
"y": "3200",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "55",
"id": "20251118100704",
"isDel": "0",
"fontWeight": "bold",
"isVertical": true
},
{
"strokeWidth": "2",
"idElement": "svg_05",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#EFF109",
"stroke": "#EFF109",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "2640",
"name": "颜总渠",
"y": "1000",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "55",
"id": "20251118100705",
"isDel": "0",
"fontWeight": "bold",
"isVertical": true
},
{
"strokeWidth": "2",
"idElement": "svg_06",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#EFF109",
"stroke": "#EFF109",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "2640",
"name": "颜中渠",
"y": "2000",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "55",
"id": "20251118100706",
"isDel": "0",
"fontWeight": "bold",
"isVertical": true
},
{
"strokeWidth": "1",
"idElement": "svg_07",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#ffffff",
"stroke": "#ffffff",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "1255",
"name": "七零二渠",
"y": "1400",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "50",
"id": "20251118100707",
"isDel": "0",
"fontWeight": "bold",
"isVertical": true
},
{
"strokeWidth": "1",
"idElement": "svg_08",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#ffffff",
"stroke": "#ffffff",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "2400",
"name": "边江灌渠",
"y": "1370",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "50",
"id": "20251118100708",
"isDel": "0",
"fontWeight": "bold",
"isVertical": false
},
{
"strokeWidth": "1",
"idElement": "svg_09",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#ffffff",
"stroke": "#ffffff",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "2830",
"name": "东兴渠",
"y": "1370",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "50",
"id": "20251118100709",
"isDel": "0",
"fontWeight": "bold",
"isVertical": false
},
{
"strokeWidth": "1",
"idElement": "svg_10",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#ffffff",
"stroke": "#ffffff",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "2830",
"name": "大熊渠",
"y": "1115",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "50",
"id": "20251118100710",
"isDel": "0",
"fontWeight": "bold",
"isVertical": false
},
{
"strokeWidth": "1",
"idElement": "svg_11",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#ffffff",
"stroke": "#ffffff",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "4800",
"name": "幸福渠",
"y": "1815",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "50",
"id": "20251118100711",
"isDel": "0",
"fontWeight": "bold",
"isVertical": false
},
{
"strokeWidth": "1",
"idElement": "svg_12",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#ffffff",
"stroke": "#ffffff",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "1300",
"name": "联剅渠",
"y": "2970",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "50",
"id": "20251118100712",
"isDel": "0",
"fontWeight": "bold",
"isVertical": false
},
{
"strokeWidth": "1",
"idElement": "svg_13",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#ffffff",
"stroke": "#ffffff",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "1300",
"name": "河谭渠",
"y": "3125",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "50",
"id": "20251118100713",
"isDel": "0",
"fontWeight": "bold",
"isVertical": false
},
{
"strokeWidth": "1",
"idElement": "svg_14",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#ffffff",
"stroke": "#ffffff",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "1300",
"name": "聂谭渠",
"y": "3275",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "50",
"id": "20251118100714",
"isDel": "0",
"fontWeight": "bold",
"isVertical": false
},
{
"strokeWidth": "1",
"idElement": "svg_15",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#ffffff",
"stroke": "#ffffff",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "1300",
"name": "十子纵渠",
"y": "3425",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "50",
"id": "20251118100715",
"isDel": "0",
"fontWeight": "bold",
"isVertical": false
},
{
"strokeWidth": "1",
"idElement": "svg_39",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#ffffff",
"stroke": "#ffffff",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "2000",
"name": "南北公路渠",
"y": "2270",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "50",
"id": "20251118100739",
"isDel": "0",
"fontWeight": "bold",
"isVertical": false
},
{
"strokeWidth": "2",
"idElement": "svg_16",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#EFF109",
"stroke": "#EFF109",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "2000",
"name": "新南渠",
"y": "2770",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "55",
"id": "20251118100716",
"isDel": "0",
"fontWeight": "bold",
"isVertical": false
},
{
"strokeWidth": "1",
"idElement": "svg_40",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#ffffff",
"stroke": "#ffffff",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "2450",
"name": "泰张管渠",
"y": "3050",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "50",
"id": "20251118100740",
"isDel": "0",
"fontWeight": "bold",
"isVertical": true
},
{
"strokeWidth": "1",
"idElement": "svg_46",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#ffffff",
"stroke": "#ffffff",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "2200",
"name": "东陈岭灌渠",
"y": "3050",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "50",
"id": "20251118100746",
"isDel": "0",
"fontWeight": "bold",
"isVertical": true
},
{
"strokeWidth": "1",
"idElement": "svg_17",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#ffffff",
"stroke": "#ffffff",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "1950",
"name": "阳湖十三渠",
"y": "3050",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "50",
"id": "20251118100717",
"isDel": "0",
"fontWeight": "bold",
"isVertical": true
},
{
"strokeWidth": "1",
"idElement": "svg_18",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#ffffff",
"stroke": "#ffffff",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "2350",
"name": "四清渠",
"y": "3760",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "50",
"id": "20251118100718",
"isDel": "0",
"fontWeight": "bold",
"isVertical": false
},
{
"strokeWidth": "1",
"idElement": "svg_41",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#ffffff",
"stroke": "#ffffff",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "2900",
"name": "列沙渠",
"y": "3760",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "50",
"id": "20251118100741",
"isDel": "0",
"fontWeight": "bold",
"isVertical": false
},
{
"strokeWidth": "1",
"idElement": "svg_19",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#ffffff",
"stroke": "#ffffff",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "3000",
"name": "立双灌渠",
"y": "2665",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "50",
"id": "20251118100719",
"isDel": "0",
"fontWeight": "bold",
"isVertical": false
},
{
"strokeWidth": "1",
"idElement": "svg_20",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#ffffff",
"stroke": "#ffffff",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "3000",
"name": "新贵林渠道",
"y": "2515",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "50",
"id": "20251118100720",
"isDel": "0",
"fontWeight": "bold",
"isVertical": false
},
{
"strokeWidth": "1",
"idElement": "svg_21",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#ffffff",
"stroke": "#ffffff",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "3145",
"name": "龙台渠",
"y": "1900",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "50",
"id": "20251118100721",
"isDel": "0",
"fontWeight": "bold",
"isVertical": true
},
{
"strokeWidth": "1",
"idElement": "svg_22",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#ffffff",
"stroke": "#ffffff",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "3365",
"name": "费湖渠",
"y": "1900",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "50",
"id": "20251118100722",
"isDel": "0",
"fontWeight": "bold",
"isVertical": true
},
{
"strokeWidth": "1",
"idElement": "svg_23",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#ffffff",
"stroke": "#ffffff",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "3585",
"name": "黄林灌渠",
"y": "1900",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "50",
"id": "20251118100723",
"isDel": "0",
"fontWeight": "bold",
"isVertical": true
},
{
"strokeWidth": "1",
"idElement": "svg_24",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#ffffff",
"stroke": "#ffffff",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "3805",
"name": "魏阳渠",
"y": "1900",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "50",
"id": "20251118100724",
"isDel": "0",
"fontWeight": "bold",
"isVertical": true
},
{
"strokeWidth": "1",
"idElement": "svg_25",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#ffffff",
"stroke": "#ffffff",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "4025",
"name": "大兴灌渠",
"y": "1900",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "50",
"id": "20251118100725",
"isDel": "0",
"fontWeight": "bold",
"isVertical": true
},
{
"strokeWidth": "1",
"idElement": "svg_26",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#ffffff",
"stroke": "#ffffff",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "4245",
"name": "兰花灌渠",
"y": "1900",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "50",
"id": "20251118100726",
"isDel": "0",
"fontWeight": "bold",
"isVertical": true
},
{
"strokeWidth": "1",
"idElement": "svg_27",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#ffffff",
"stroke": "#ffffff",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "4145",
"name": "低灌渠",
"y": "2665",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "50",
"id": "20251118100727",
"isDel": "0",
"fontWeight": "bold",
"isVertical": false
},
{
"strokeWidth": "1",
"idElement": "svg_28",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#ffffff",
"stroke": "#ffffff",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "4145",
"name": "八一渠",
"y": "2815",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "50",
"id": "20251118100728",
"isDel": "0",
"fontWeight": "bold",
"isVertical": false
},
{
"strokeWidth": "1",
"idElement": "svg_29",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#ffffff",
"stroke": "#ffffff",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "3800",
"name": "首渠",
"y": "2965",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "50",
"id": "20251118100729",
"isDel": "0",
"fontWeight": "bold",
"isVertical": false
},
{
"strokeWidth": "1",
"idElement": "svg_30",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#ffffff",
"stroke": "#ffffff",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "4145",
"name": "金龟渠",
"y": "3565",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "50",
"id": "20251118100730",
"isDel": "0",
"fontWeight": "bold",
"isVertical": false
},
{
"strokeWidth": "1",
"idElement": "svg_31",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#ffffff",
"stroke": "#ffffff",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "4145",
"name": "长湖渠",
"y": "3715",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "50",
"id": "20251118100731",
"isDel": "0",
"fontWeight": "bold",
"isVertical": false
},
{
"strokeWidth": "1",
"idElement": "svg_32",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#ffffff",
"stroke": "#ffffff",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "4145",
"name": "立新渠",
"y": "3865",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "50",
"id": "20251118100732",
"isDel": "0",
"fontWeight": "bold",
"isVertical": false
},
{
"strokeWidth": "1",
"idElement": "svg_33",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#ffffff",
"stroke": "#ffffff",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "4145",
"name": "新丰渠",
"y": "4015",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "50",
"id": "20251118100733",
"isDel": "0",
"fontWeight": "bold",
"isVertical": false
},
{
"strokeWidth": "1",
"idElement": "svg_42",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#ffffff",
"stroke": "#ffffff",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "4940",
"name": "樊湖渠",
"y": "4165",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "50",
"id": "20251118100742",
"isDel": "0",
"fontWeight": "bold",
"isVertical": false
},
{
"strokeWidth": "1",
"idElement": "svg_43",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#ffffff",
"stroke": "#ffffff",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "2890",
"name": "清江渠",
"y": "4000",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "45",
"id": "20251118100743",
"isDel": "0",
"fontWeight": "bold",
"isVertical": true
},
{
"strokeWidth": "1",
"idElement": "svg_44",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#ffffff",
"stroke": "#ffffff",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "4000",
"name": "清江渠",
"y": "3050",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "45",
"id": "20251118100744",
"isDel": "0",
"fontWeight": "bold",
"isVertical": true
},
{
"strokeWidth": "1",
"idElement": "svg_45",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#ffffff",
"stroke": "#ffffff",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "4250",
"name": "丰收渠",
"y": "3050",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "45",
"id": "20251118100745",
"isDel": "0",
"fontWeight": "bold",
"isVertical": true
},
{
"strokeWidth": "1",
"idElement": "svg_34",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#ffffff",
"stroke": "#ffffff",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "4500",
"name": "双收渠",
"y": "3050",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "45",
"id": "20251118100734",
"isDel": "0",
"fontWeight": "bold",
"isVertical": true
},
{
"strokeWidth": "1",
"idElement": "svg_35",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#ffffff",
"stroke": "#ffffff",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "5050",
"name": "司马渠",
"y": "2000",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "45",
"id": "20251118100735",
"isDel": "0",
"fontWeight": "bold",
"isVertical": true
},
{
"strokeWidth": "1",
"idElement": "svg_36",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#ffffff",
"stroke": "#ffffff",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "5250",
"name": "南阳渠",
"y": "2000",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "45",
"id": "20251118100736",
"isDel": "0",
"fontWeight": "bold",
"isVertical": true
},
{
"strokeWidth": "1",
"idElement": "svg_37",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#ffffff",
"stroke": "#ffffff",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "5450",
"name": "萌树渠",
"y": "2000",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "45",
"id": "20251118100737",
"isDel": "0",
"fontWeight": "bold",
"isVertical": true
},
{
"strokeWidth": "1",
"idElement": "svg_38",
"levelShow": "1",
"officeCode": "",
"xmlSpace": "preserve",
"textAnchor": "start",
"fill": "#ffffff",
"stroke": "#ffffff",
"transform": null,
"fontFamily": "Noto Sans JP",
"x": "5650",
"name": "竺家大沟",
"y": "2000",
"style": "vector-effect: non-scaling-stroke",
"fontSize": "45",
"id": "20251118100738",
"isDel": "0",
"fontWeight": "bold",
"isVertical": true
}
],
"total": 209,
"size": 1000,
"current": 1,
"orders": [],
"optimizeCountSql": true,
"hitCount": false,
"countId": null,
"maxLimit": null,
"searchCount": true,
"pages": 1
},
"timestamp": 1689145633439
}

File diff suppressed because it is too large Load Diff

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

32
public/iframe/bim.html Normal file
View File

@ -0,0 +1,32 @@
<html>
<body>
<script>
let i = 1;
window.addEventListener('message', e => {
document.getElementById('msg').innerHTML = `接收到父页面的post消息(${i++}): ${JSON.stringify(e.data)}`
})
function msg(gateNumber) {
parent.postMessage({
type: 'gateClicked',
data: gateNumber,
}, '*')
}
</script>
<h1>超图BIM控件-iframe</h1>
<button onclick="msg(1);">test1</button>
<button onclick="msg(2);">test2</button>
<button onclick="msg(3);">test3</button>
<button onclick="msg(4);">test4</button>
<div id="msg" style="word-break: break-all;">
</div>
</body>
</html>

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,59 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>socket io frame</title>
<script src="socket.io.js"></script>
<script>
</script>
</head>
<body>
<script>
const qs = window.location.search.substr(1).split('&')
.map(o => o.split('='))
.reduce((total, cur) => {
total[cur[0]] = cur[1];
return total;
}, {});
const gaorNum = parseInt(qs.gaorNum);
const stcd = qs.stcd;
function msg(data) {
return window.parent[qs.func](data);
}
const socket = io.connect(window.location.origin, { path: '/zhzmkzv2/service/socket.io' });
socket.on('connect', (c) => {
console.log('connect', c);
});
socket.on('heartbeat', (data) => {
console.log('heartbeat', data);
});
for (let i = 1; i <= gaorNum; i += 1) {
socket.on(`${stcd}:${i}`, (data) => {
console.log('接收 socketdata', data);
if (typeof data === "string") {
data = JSON.parse(data);
}
msg(data)
});
}
socket.on('disconnect', () => {
console.log('disconnect');
});
socket.on('connect_error', (error) => {
console.log('connect_error socket io', error);
});
</script>
</body>
</html>

BIN
public/images/ent1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
public/images/ent2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
public/images/ent3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
public/images/entSel.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
public/images/offline.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
public/images/online.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

44
public/index.html Normal file
View File

@ -0,0 +1,44 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta name="description" content="Web site created using create-react-app" />
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>颜家台灌区</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>

BIN
public/logo192.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

BIN
public/logo512.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

25
public/manifest.json Normal file
View File

@ -0,0 +1,25 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}

3
public/robots.txt Normal file
View File

@ -0,0 +1,3 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:

Binary file not shown.

BIN
src/assets/icons/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

BIN
src/assets/icons/logo64.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
src/assets/icons/switch.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
src/assets/icons/user.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -0,0 +1,2 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1660979818572" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1211" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><defs><style type="text/css">@font-face { font-family: feedback-iconfont; src: url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.woff2?t=1630033759944") format("woff2"), url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.woff?t=1630033759944") format("woff"), url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.ttf?t=1630033759944") format("truetype"); }
</style></defs><path d="M0 0m81.92 0l860.16 0q81.92 0 81.92 81.92l0 860.16q0 81.92-81.92 81.92l-860.16 0q-81.92 0-81.92-81.92l0-860.16q0-81.92 81.92-81.92Z" fill="#29BEFC" p-id="1212"></path><path d="M282.95168 623.616l10.48576 3.52256V324.89472h434.176v307.93728l11.30496-5.36576c14.90944-7.04512 27.40224-6.02112 43.8272-4.79232l8.51968 0.65536V261.16096h-98.54976V184.32h-364.544v76.84096H229.62176v364.87168l9.37984-1.76128c16.01536-2.94912 28.50816-5.77536 43.95008-0.65536z m109.1584-375.52128h236.83072v13.1072H392.11008z" fill="#FFFFFF" p-id="1213"></path><path d="M602.112 623.0016a93.96224 93.96224 0 0 1 52.18304 15.9744l12.288 8.192v-191.6928h-72.21248v167.5264zM363.84768 648.92928l9.13408-6.88128a93.88032 93.88032 0 0 1 46.4896-19.08736l7.00416-0.8192v-166.7072h-72.4992v189.27616zM477.02016 635.65824a92.44672 92.44672 0 0 1 9.87136 6.47168l29.4912 22.36416 29.12256-22.03648v-209.67424h-72.54016v200.704zM853.44256 768.73728l-26.05056-19.49696a84.86912 84.86912 0 0 0-101.62176 0l-25.96864 19.53792a16.384 16.384 0 0 1-19.74272 0l-26.0096-19.53792a84.95104 84.95104 0 0 0-101.70368 0l-25.88672 19.53792a16.67072 16.67072 0 0 1-19.82464 0l-25.96864-19.53792a84.95104 84.95104 0 0 0-101.66272 0l-25.96864 19.53792a16.5888 16.5888 0 0 1-19.78368 0L307.2 749.24032a84.91008 84.91008 0 0 0-101.66272 0l-33.9968 25.76384A33.95584 33.95584 0 0 0 212.992 828.86656l33.66912-25.43616a16.5888 16.5888 0 0 1 19.78368 0l25.92768 19.49696a84.74624 84.74624 0 0 0 101.62176 0l26.0096-19.49696a16.384 16.384 0 0 1 19.70176 0l25.35424 19.2512a86.50752 86.50752 0 0 0 76.47232 13.35296 83.92704 83.92704 0 0 0 25.88672-13.1072l26.0096-19.53792a16.384 16.384 0 0 1 19.74272 0l25.96864 19.49696a84.91008 84.91008 0 0 0 101.66272 0l25.96864-19.53792a16.384 16.384 0 0 1 19.74272 0l25.68192 19.29216q1.06496 0.90112 2.21184 1.67936a33.95584 33.95584 0 0 0 52.8384-33.792 33.54624 33.54624 0 0 0-13.80352-21.79072z" fill="#FFFFFF" p-id="1214"></path><path d="M863.88736 674.4064l-26.8288-20.15232a87.61344 87.61344 0 0 0-105.02144 0l-26.78784 20.15232a17.16224 17.16224 0 0 1-20.48 0l-26.78784-20.15232a87.6544 87.6544 0 0 0-105.02144 0l-26.8288 20.15232a17.08032 17.08032 0 0 1-20.48 0l-26.86976-20.15232a87.53152 87.53152 0 0 0-104.98048 0l-26.8288 20.15232a17.08032 17.08032 0 0 1-20.48 0l-26.78784-20.15232a87.57248 87.57248 0 0 0-104.98048 0l-34.77504 26.33728a35.06176 35.06176 0 0 0 42.3936 55.82848l34.65216-26.29632a17.08032 17.08032 0 0 1 20.48 0l26.86976 20.15232a87.69536 87.69536 0 0 0 104.98048 0l26.8288-20.15232a17.08032 17.08032 0 0 1 20.48 0l26.8288 20.11136a86.95808 86.95808 0 0 0 52.26496 17.57184h0.36864v-8.192 8.192a87.40864 87.40864 0 0 0 52.38784-17.57184l26.74688-20.15232a17.08032 17.08032 0 0 1 20.48 0l26.8288 20.15232a87.73632 87.73632 0 0 0 104.98048 0l26.8288-20.15232a17.08032 17.08032 0 0 1 20.48 0l26.8288 20.11136a35.06176 35.06176 0 1 0 42.35264-55.82848z" fill="#FFFFFF" p-id="1215"></path></svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

View File

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="1361px" height="609px" viewBox="0 0 1361 609" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 46.2 (44496) - http://www.bohemiancoding.com/sketch -->
<title>Group 21</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Ant-Design-Pro-3.0" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="账户密码登录-校验" transform="translate(-79.000000, -82.000000)">
<g id="Group-21" transform="translate(77.000000, 73.000000)">
<g id="Group-18" opacity="0.8" transform="translate(74.901416, 569.699158) rotate(-7.000000) translate(-74.901416, -569.699158) translate(4.901416, 525.199158)">
<ellipse id="Oval-11" fill="#CFDAE6" opacity="0.25" cx="63.5748792" cy="32.468367" rx="21.7830479" ry="21.766008"></ellipse>
<ellipse id="Oval-3" fill="#CFDAE6" opacity="0.599999964" cx="5.98746479" cy="13.8668601" rx="5.2173913" ry="5.21330997"></ellipse>
<path d="M38.1354514,88.3520215 C43.8984227,88.3520215 48.570234,83.6838647 48.570234,77.9254015 C48.570234,72.1669383 43.8984227,67.4987816 38.1354514,67.4987816 C32.3724801,67.4987816 27.7006688,72.1669383 27.7006688,77.9254015 C27.7006688,83.6838647 32.3724801,88.3520215 38.1354514,88.3520215 Z" id="Oval-3-Copy" fill="#CFDAE6" opacity="0.45"></path>
<path d="M64.2775582,33.1704963 L119.185836,16.5654915" id="Path-12" stroke="#CFDAE6" stroke-width="1.73913043" stroke-linecap="round" stroke-linejoin="round"></path>
<path d="M42.1431708,26.5002681 L7.71190162,14.5640702" id="Path-16" stroke="#E0B4B7" stroke-width="0.702678964" opacity="0.7" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="1.405357899873153,2.108036953469981"></path>
<path d="M63.9262187,33.521561 L43.6721326,69.3250951" id="Path-15" stroke="#BACAD9" stroke-width="0.702678964" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="1.405357899873153,2.108036953469981"></path>
<g id="Group-17" transform="translate(126.850922, 13.543654) rotate(30.000000) translate(-126.850922, -13.543654) translate(117.285705, 4.381889)" fill="#CFDAE6">
<ellipse id="Oval-4" opacity="0.45" cx="9.13482653" cy="9.12768076" rx="9.13482653" ry="9.12768076"></ellipse>
<path d="M18.2696531,18.2553615 C18.2696531,13.2142826 14.1798519,9.12768076 9.13482653,9.12768076 C4.08980114,9.12768076 0,13.2142826 0,18.2553615 L18.2696531,18.2553615 Z" id="Oval-4" transform="translate(9.134827, 13.691521) scale(-1, -1) translate(-9.134827, -13.691521) "></path>
</g>
</g>
<g id="Group-14" transform="translate(216.294700, 123.725600) rotate(-5.000000) translate(-216.294700, -123.725600) translate(106.294700, 35.225600)">
<ellipse id="Oval-2" fill="#CFDAE6" opacity="0.25" cx="29.1176471" cy="29.1402439" rx="29.1176471" ry="29.1402439"></ellipse>
<ellipse id="Oval-2" fill="#CFDAE6" opacity="0.3" cx="29.1176471" cy="29.1402439" rx="21.5686275" ry="21.5853659"></ellipse>
<ellipse id="Oval-2-Copy" stroke="#CFDAE6" opacity="0.4" cx="179.019608" cy="138.146341" rx="23.7254902" ry="23.7439024"></ellipse>
<ellipse id="Oval-2" fill="#BACAD9" opacity="0.5" cx="29.1176471" cy="29.1402439" rx="10.7843137" ry="10.7926829"></ellipse>
<path d="M29.1176471,39.9329268 L29.1176471,18.347561 C23.1616351,18.347561 18.3333333,23.1796097 18.3333333,29.1402439 C18.3333333,35.1008781 23.1616351,39.9329268 29.1176471,39.9329268 Z" id="Oval-2" fill="#BACAD9"></path>
<g id="Group-9" opacity="0.45" transform="translate(172.000000, 131.000000)" fill="#E6A1A6">
<ellipse id="Oval-2-Copy-2" cx="7.01960784" cy="7.14634146" rx="6.47058824" ry="6.47560976"></ellipse>
<path d="M0.549019608,13.6219512 C4.12262681,13.6219512 7.01960784,10.722722 7.01960784,7.14634146 C7.01960784,3.56996095 4.12262681,0.670731707 0.549019608,0.670731707 L0.549019608,13.6219512 Z" id="Oval-2-Copy-2" transform="translate(3.784314, 7.146341) scale(-1, 1) translate(-3.784314, -7.146341) "></path>
</g>
<ellipse id="Oval-10" fill="#CFDAE6" cx="218.382353" cy="138.685976" rx="1.61764706" ry="1.61890244"></ellipse>
<ellipse id="Oval-10-Copy-2" fill="#E0B4B7" opacity="0.35" cx="179.558824" cy="175.381098" rx="1.61764706" ry="1.61890244"></ellipse>
<ellipse id="Oval-10-Copy" fill="#E0B4B7" opacity="0.35" cx="180.098039" cy="102.530488" rx="2.15686275" ry="2.15853659"></ellipse>
<path d="M28.9985381,29.9671598 L171.151018,132.876024" id="Path-11" stroke="#CFDAE6" opacity="0.8"></path>
</g>
<g id="Group-10" opacity="0.799999952" transform="translate(1054.100635, 36.659317) rotate(-11.000000) translate(-1054.100635, -36.659317) translate(1026.600635, 4.659317)">
<ellipse id="Oval-7" stroke="#CFDAE6" stroke-width="0.941176471" cx="43.8135593" cy="32" rx="11.1864407" ry="11.2941176"></ellipse>
<g id="Group-12" transform="translate(34.596774, 23.111111)" fill="#BACAD9">
<ellipse id="Oval-7" opacity="0.45" cx="9.18534718" cy="8.88888889" rx="8.47457627" ry="8.55614973"></ellipse>
<path d="M9.18534718,17.4450386 C13.8657264,17.4450386 17.6599235,13.6143199 17.6599235,8.88888889 C17.6599235,4.16345787 13.8657264,0.332739156 9.18534718,0.332739156 L9.18534718,17.4450386 Z" id="Oval-7"></path>
</g>
<path d="M34.6597385,24.809694 L5.71666084,4.76878945" id="Path-2" stroke="#CFDAE6" stroke-width="0.941176471"></path>
<ellipse id="Oval" stroke="#CFDAE6" stroke-width="0.941176471" cx="3.26271186" cy="3.29411765" rx="3.26271186" ry="3.29411765"></ellipse>
<ellipse id="Oval-Copy" fill="#F7E1AD" cx="2.79661017" cy="61.1764706" rx="2.79661017" ry="2.82352941"></ellipse>
<path d="M34.6312443,39.2922712 L5.06366663,59.785082" id="Path-10" stroke="#CFDAE6" stroke-width="0.941176471"></path>
</g>
<g id="Group-19" opacity="0.33" transform="translate(1282.537219, 446.502867) rotate(-10.000000) translate(-1282.537219, -446.502867) translate(1142.537219, 327.502867)">
<g id="Group-17" transform="translate(141.333539, 104.502742) rotate(275.000000) translate(-141.333539, -104.502742) translate(129.333539, 92.502742)" fill="#BACAD9">
<circle id="Oval-4" opacity="0.45" cx="11.6666667" cy="11.6666667" r="11.6666667"></circle>
<path d="M23.3333333,23.3333333 C23.3333333,16.8900113 18.1099887,11.6666667 11.6666667,11.6666667 C5.22334459,11.6666667 0,16.8900113 0,23.3333333 L23.3333333,23.3333333 Z" id="Oval-4" transform="translate(11.666667, 17.500000) scale(-1, -1) translate(-11.666667, -17.500000) "></path>
</g>
<circle id="Oval-5-Copy-6" fill="#CFDAE6" cx="201.833333" cy="87.5" r="5.83333333"></circle>
<path d="M143.5,88.8126685 L155.070501,17.6038544" id="Path-17" stroke="#BACAD9" stroke-width="1.16666667"></path>
<path d="M17.5,37.3333333 L127.466252,97.6449735" id="Path-18" stroke="#BACAD9" stroke-width="1.16666667"></path>
<polyline id="Path-19" stroke="#CFDAE6" stroke-width="1.16666667" points="143.902597 120.302281 174.935455 231.571342 38.5 147.510847 126.366941 110.833333"></polyline>
<path d="M159.833333,99.7453842 L195.416667,89.25" id="Path-20" stroke="#E0B4B7" stroke-width="1.16666667" opacity="0.6"></path>
<path d="M205.333333,82.1372105 L238.719406,36.1666667" id="Path-24" stroke="#BACAD9" stroke-width="1.16666667"></path>
<path d="M266.723424,132.231988 L207.083333,90.4166667" id="Path-25" stroke="#CFDAE6" stroke-width="1.16666667"></path>
<circle id="Oval-5" fill="#C1D1E0" cx="156.916667" cy="8.75" r="8.75"></circle>
<circle id="Oval-5-Copy-3" fill="#C1D1E0" cx="39.0833333" cy="148.75" r="5.25"></circle>
<circle id="Oval-5-Copy-2" fill-opacity="0.6" fill="#D1DEED" cx="8.75" cy="33.25" r="8.75"></circle>
<circle id="Oval-5-Copy-4" fill-opacity="0.6" fill="#D1DEED" cx="243.833333" cy="30.3333333" r="5.83333333"></circle>
<circle id="Oval-5-Copy-5" fill="#E0B4B7" cx="175.583333" cy="232.75" r="5.25"></circle>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 466 KiB

BIN
src/assets/images/menu.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

BIN
src/assets/images/menu1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 325 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 319 B

View File

@ -0,0 +1,63 @@
import { Menu } from 'antd';
import React, { useMemo } from 'react';
import { useLocation, useNavigate } from 'react-router';
import { MenuItem } from '../../models/_/defs';
const { SubMenu } = Menu;
export function selectedMenu(menu: MenuItem[], menuIndexes: string[]) {
if (!menuIndexes || !menuIndexes[0]) {
return [];
}
const menuItem = menu.find((o) => o.id === menuIndexes[0]);
return (menuItem && menuItem.children) || [];
}
const SiderMenu: React.FC<{
menu: MenuItem[],
menuIndexes: string[],
}> = ({ menu, menuIndexes }) => {
const subMenu = useMemo(() => selectedMenu(menu, menuIndexes), [menu, menuIndexes]);
const location = useLocation();
const pathname = location.pathname;
const navigate = useNavigate();
function goto(url: string) {
if (pathname !== url) {
navigate(url);
}
}
return (
<Menu
key={menuIndexes[0] || '0'}
mode="inline"
selectedKeys={[`${menuIndexes[2] || menuIndexes[1]}`]}
defaultOpenKeys={[`${menuIndexes[1]}`]}
>
{
subMenu.map((o: any) => (
o.children && o.children.length > 0 ? (
<SubMenu key={o.id} icon={o.icon ? <img style={{ width: 16, height: 16 }} src={`/assets/icons/${o.icon}.png`} /> : undefined} title={o.title}>
{
o.children.map((oo: any) => (
<Menu.Item
onClick={() => goto(oo.path)} key={oo.id}>{oo.title}</Menu.Item>
))
}
</SubMenu>
) : (
<Menu.Item
icon={o.icon ? <img style={{ width: 16, height: 16 }} src={`/assets/icons/${o.icon}.png`} /> : undefined}
onClick={() => goto(o.path)} key={o.id}>{o.title}</Menu.Item>
)
))
}
</Menu>
);
}
export default React.memo(SiderMenu);

View File

@ -0,0 +1,63 @@
import React from 'react';
import { useNavigate } from 'react-router';
import { MenuItem } from '../../models/_/defs';
function getMenuUrl(menuItem: MenuItem | undefined): string | null {
if (!menuItem) {
return null;
}
const url = menuItem.path || menuItem.redirect;
if (url) {
return url;
}
if (menuItem.children && menuItem.children.length) {
for (const m of menuItem.children) {
const url = getMenuUrl(m);
if (url) {
return url;
}
}
}
return null;
}
const TopMenu: React.FC<{
menu: MenuItem[];
menuIndexes: string[];
}> = ({ menu, menuIndexes }) => {
const navigate = useNavigate();
const menuClicked = (id: string) => {
const menuItem = menu.find(m => m.id == id);
const url = getMenuUrl(menuItem);
if (url) {
navigate(url);
}
}
return (
<div className='app-top-menu'>
{
menu?.map(o => (
<div
key={o.id}
className={`app-top-menu-item${menuIndexes[0] == o.id ? ' active' : ''}`}
onClick={() => menuClicked(o.id)}
>
<img src={`${process.env.PUBLIC_URL}/assets/icons2/${o.icon}`} />
{o.title}
</div>
))
}
</div>
)
}
export default React.memo(TopMenu);

View File

@ -0,0 +1,75 @@
import { BellOutlined } from '@ant-design/icons';
import { Layout } from 'antd';
import React, { Suspense, useEffect, useMemo } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Outlet, useNavigate } from 'react-router';
import { useLocation } from 'react-router-dom';
import Icon1 from '../../assets/icons/icon.png';
import { SUBTITLE, TITLE, config } from '../../config';
import { findLeafMenu, findMenu } from '../../models/auth/menu';
import { Dispatch, RootState } from '../../models/store';
import { getParameter } from '../../utils/utils';
import SiderMenu from './SiderMenu';
import TopMenu from './TopMenu';
import './style.less';
const { Header, Content, Sider } = Layout;
const DashboardLayout: React.FC = () => {
const location = useLocation();
const pathname = location.pathname;
const dispatch = useDispatch();
const menu = useSelector((state: RootState) => state.auth.menu);
const [menuIndexes, leafMenu] = useMemo(() => [
findMenu(menu, pathname),
findLeafMenu(menu, pathname),
], [menu, pathname]);
useEffect(() => {
if (leafMenu) {
document.title = '颜家台灌区 · ' + leafMenu.title
}
}, [leafMenu]);
useEffect(()=>{
dispatch.auth.loadMenu(undefined);
console.log(menu);
},[])
return (
<Layout className="app-root">
<Header className="app-header">
<a className='app-icon-a' href='https://219.138.108.99:30046/guide/'>
<img alt="..." className="app-icon" src={Icon1} />
<span className="app-title">{TITLE}-{SUBTITLE}</span>
</a>
<TopMenu menu={menu} menuIndexes={menuIndexes} />
<div className='flex-grow-1'></div>
</Header>
<Layout>
{
menuIndexes.length > 1 ? (
<Sider className="app-sider" width={208}>
<SiderMenu menu={menu} menuIndexes={menuIndexes} />
</Sider>
) : null
}
<Content className="app-content">
<div className={menuIndexes.length > 1 ? 'content-root' : 'content-root-fs'}>
<Suspense fallback={null}>
<Outlet />
</Suspense>
</div>
</Content>
</Layout>
</Layout>
)
};
export default DashboardLayout

View File

@ -0,0 +1,134 @@
.app-root {
height: 100vh;
.app-header {
display: flex;
align-items: center;
padding: 0 12px 0 0;
overflow: hidden;
z-index: 20;
color: #fff !important;
background-image: url(../../assets/images/menu.png);
background-size: 100% 100%;
.app-icon-a {
display: flex;
align-items: center;
justify-content: center;
padding: 0 10px;
.app-icon {
width: 32px;
height: 32px;
}
.app-title {
font-size: 18px;
font-weight: 500;
color: #fff;
text-align: left;
padding-left: 10px;
}
margin-right: 8px;
}
/*
.ant-menu {
background: transparent;
}
.ant-menu-item-active {
background-color: #fff;
}
.ant-menu-item-selected {
//background-color: rgba(70, 128, 221, .75);
}
.ant-menu-item-selected::after {
border-bottom: 3px solid #86b9ff;
}
.ant-menu-horizonal>.ant-menu-item::after {
right: 0;
left: 0;
}
*/
.app-top-menu {
display: flex;
align-items: center;
.app-top-menu-item {
height: 64px;
padding: 0 20px;
font-size: 16px;
cursor: pointer;
display: flex;
align-items: center;
img {
width: 18px;
margin-right: 8px;
}
&.active {
background-color: rgba(70, 128, 221, .75);
border-bottom: 3px solid #86b9ff;
}
}
}
.user-menu {
display: flex;
height: 59px;
align-items: center;
padding: 0 14px;
.user-menu-icon {
width: 28px;
margin: 20px 10px 20px 0;
}
&:hover {
background-color: hsla(0, 0%, 100%, .3);
}
}
}
.app-sider {
overflow-y: auto;
overflow-x: hidden;
background-color: #fff !important;
z-index: 10;
}
.app-content {
z-index: 0;
display: flex;
flex-direction: column;
}
.content-root {
padding: 10px 0 10px 10px;
flex-grow: 1;
overflow-y: auto;
overflow-x: hidden;
}
.content-root-fs {
padding: 0;
flex-grow: 1;
overflow: hidden;
}
}
.content-body {
background-color: #fff;
padding: 20px;
}

View File

@ -0,0 +1,329 @@
.ant-btn-primary,
.ant-btn-default {
padding: 0 15px;
border-radius: 4px;
}
.ant-form-item-label>label {
font-weight: bold;
padding-right: 8px;
}
.ant-input,
.ant-select-selector {
border-radius: 4px !important;
// box-shadow: 0 0 2px 2px #f5f5f5 !important;
}
.ant-input-search {
.ant-input {
border-radius: 4px 0 0 4px !important;
}
.ant-btn {
border-radius: 0 4px 4px 0 !important;
min-width: 80px;
}
}
.ant-radio-group {
.ant-radio-button-wrapper:first-child {
border-radius: 8px 0 0 8px !important
}
.ant-radio-button-wrapper:last-child {
border-radius: 0 8px 8px 0 !important
}
.ant-radio-button-wrapper {
border: 1px solid @primary-color !important;
&:hover {
background-color: #D9EBFF;
}
}
.ant-radio-button-wrapper {
color: #3B7CFF;
}
}
.common-style {
.ant-table-container {
border: 1px solid #e8e8e8 !important;
}
.ant-table-thead>tr>th,
.ant-table-tbody>tr>td,
.ant-table tfoot>tr>th,
.ant-table tfoot>tr>td {
padding: 12px 8px;
border-right: 1px solid transparent !important;
}
.ant-table-thead>tr>th {
background-color: #e0edff !important;
border-bottom: 1px solid #e8e8e8;
}
.ant-table-tbody>tr:not(.ant-table-placeholder)>td {
border-top: 1px solid #e0edff;
border-bottom: 1px solid #e0edff;
&.ant-table-cell-row-hover {
background: #f4f8ff;
color: #3773c5;
}
}
.ant-table-tbody tr:not(.ant-table-placeholder):nth-child(2n) {
background: #f4f8ff;
}
.ant-pagination {
.ant-pagination-item:not(.ant-pagination-item-active) {
border: none !important;
}
.ant-pagination-item-link {
border: none !important;
}
.ant-pagination-item-active {
background-color: #3773c5 !important;
border-radius: 99px;
a {
color: #fff !important;
}
}
}
}
.ant-modal-content {
border-radius: 4px;
.ant-modal-header {
background: #2a66c2;
border-radius: 4px 4px 0 0;
.ant-modal-title {
color: #fff !important;
}
.ant-modal-close {
color: #fff !important;
}
}
}
.ant-btn-link.ant-btn-sm {
color: #3773c5;
height: 18px;
}
.anticon-close.ant-modal-close-icon {
color: #fff;
}
td.ant-table-column-sort {
background-color: unset;
}
.ant-modal.fullscreen {
width: 100vw !important;
max-width: 100vw !important;
top: 0;
padding-bottom: 0;
.ant-modal-body {
height: calc(100vh - 55px);
overflow-y: auto;
}
}
/*
.ant-table-thead>tr>th {
border-bottom: none !important;
background: @primary-color !important;
color: #fff !important;
font-weight: 600 !important;
&::before {
width: 0 !important;
}
&:first-child {
border-top-left-radius: 16px !important;
}
&:last-child {
border-top-right-radius: 16px !important;
}
}
.ant-table {
background: transparent !important;
}
.ant-table-tbody>tr>td {
border-bottom: none !important;
background: #fff;
box-shadow: 3px 2px 3px 2px #E8ECF1;
padding: 12px 16px !important;
&:first-child {
border-top-left-radius: 8px;
border-bottom-left-radius: 8px;
}
&:last-child {
border-top-right-radius: 8px;
border-bottom-right-radius: 8px;
}
}
.ant-table table {
border-spacing: 0 8px !important;
}
.ant-pagination {
.ant-select-selector {
border: none !important;
}
.ant-pagination-item:not(.ant-pagination-item-active) {
border: none !important;
}
.ant-pagination-item-link {
border: none !important;
}
.ant-pagination-item-active {
background-color: @primary-color;
border-radius: 99px;
a {
color: #fff !important;
}
}
.ant-pagination-options-quick-jumper input {
border: none !important;
}
}
.ant-btn-primary,
.ant-btn-default {
min-width: 110px;
border-radius: 99px;
}
.ant-input,
.ant-select-selector {
border-radius: 4px !important;
box-shadow: 0 0 2px 2px #f5f5f5 !important;
}
.ant-input-search {
.ant-input-lg {
border-top-left-radius: 99px !important;
border-bottom-left-radius: 99px !important;
}
.ant-btn-lg {
border-top-right-radius: 99px !important;
border-bottom-right-radius: 99px !important;
min-width: 80px;
}
}
.kai-comp .ant-picker-range {
border-top-right-radius: 4px !important;
border-bottom-right-radius: 4px !important;
border-top-left-radius: 0px !important;
border-bottom-left-radius: 0px !important;
box-shadow: 0 0 2px 2px #f5f5f5 !important;
}
.kai-comp .ant-picker-status-error.ant-picker {
border-left: none;
}
.tree-select {
.ant-tree {
border: 1px solid #f3f5f8;
background: #f9fafc;
border-radius: 4px !important;
padding: 8px !important;
}
.ant-tree-switcher {
background-color: transparent !important;
}
.ant-tree-switcher {
display: flex;
align-items: center;
justify-content: center;
color: #C7CBD3;
font-size: 12px;
}
}
.ant-radio-group {
.ant-radio-button-wrapper:first-child {
border-radius: 8px 0 0 8px !important
}
.ant-radio-button-wrapper:last-child {
border-radius: 0 8px 8px 0 !important
}
.ant-radio-button-wrapper {
border: 1px solid @primary-color !important;
&:hover {
background-color: #D9EBFF;
}
}
.ant-radio-button-wrapper {
color: #3B7CFF;
}
}
.ant-checkbox-checked {
.ant-checkbox-inner {
background-color: #3b7cff !important;
border-color: #3b7cff !important;
}
&::after {
border: none !important;
}
}
.ant-checkbox-inner {
border-radius: 4px !important;
border-width: 1.4px !important;
border-color: #C7CBD3 !important;
}
*/

View File

@ -0,0 +1,30 @@
import { Button, Popconfirm } from 'antd';
import React from 'react';
import { CrudContext } from './useCrud';
const CancelCrud: React.FC<{
crudCtx: CrudContext<any>,
confirm?: boolean,
text?: string
}> = ({ crudCtx, confirm, text }) => {
text = text || '返回';
if (confirm) {
return (
<Popconfirm title="是否要放弃表单返回列表"
onConfirm={() => {
crudCtx.goto(null, null);
}}
>
<Button size="small" type="link">{text}</Button>
</Popconfirm>
)
} else {
return (
<Button onClick={() => crudCtx.goto(null, null)} size="small" type="link">{text}</Button>
)
}
};
export default CancelCrud

View File

@ -0,0 +1,11 @@
export const DEF_INPUT_LEN = 464;
export const DEF_INPUT_LEN_QUARTS = 92;
export const DEF_LAYOUT = {
labelCol: { span: 8 },
wrapperCol: { span: 16 },
};
export const DEF_TAIL_LAYOUT = {
wrapperCol: { offset: 8, span: 16 },
};

View File

@ -0,0 +1,48 @@
import { DeleteOutlined, EditOutlined, QuestionCircleOutlined, UndoOutlined, FileSearchOutlined } from '@ant-design/icons';
import { Button, Popconfirm, Tooltip } from 'antd'
import React from 'react'
type IProps = {
icon?: React.ReactNode;
danger?: boolean;
text?: string;
tooltip?: string;
onClick?: () => any;
};
const OpButton: React.FC<IProps> = ({ tooltip, icon, danger, text, onClick }) => {
if (tooltip) {
return (
<Tooltip title={tooltip}>
<Button icon={icon} danger={danger} onClick={onClick} type="link" size='small'>{text}</Button>
</Tooltip>
)
}
return (
<Button icon={icon} danger={danger} onClick={onClick} type="link" size='small'>{text}</Button>
)
}
export default OpButton;
type ITypedProps = {
onClick?: () => void;
}
export const DelOpButton: React.FC<ITypedProps> = ({ onClick }) => (
<Popconfirm title="确定删除?" icon={<QuestionCircleOutlined style={{ color: 'red' }} />} onConfirm={onClick}>
<OpButton text='删除' icon={<DeleteOutlined />} danger />
</Popconfirm>
)
export const EditOpButton: React.FC<ITypedProps> = ({ onClick }) =>
<OpButton text='编辑' icon={<EditOutlined />} onClick={onClick} />
export const ViewOpButton: React.FC<ITypedProps> = ({ onClick }) =>
<OpButton text='查看' icon={<FileSearchOutlined />} onClick={onClick} />
export const RestoreOpButton: React.FC<ITypedProps> = ({ onClick }) =>
<OpButton text='恢复' icon={<UndoOutlined />} onClick={onClick} />

View File

@ -0,0 +1,44 @@
import { useState } from "react";
export type BasicCrudType = 'add' | 'edit' | 'view';
export const CRUD_NAMES = {
add: '新增',
edit: '编辑'
}
export type CrudContext<modes = any> = {
mode: modes | null;
record: any;
goto: (mode: modes | null, r: any) => void;
loading: boolean;
setLoading: (val: boolean) => void;
}
export default function useCrud<modes = any>(params?: {
mode?: modes;
record?: any;
}): CrudContext<modes> {
const [loading, setLoading] = useState(false);
const [state, setState] = useState<{
mode: modes | null;
record: any;
}>({
mode: params?.mode || null,
record: params?.record,
})
const goto = (mode: modes | null, record: any) => {
setState({ mode, record })
};
return {
...state,
goto,
loading,
setLoading,
}
}

View File

@ -0,0 +1,144 @@
import { TablePaginationConfig, TableProps } from 'antd';
import { useEffect, useReducer, useRef } from 'react';
export type PageResult<T> = {
list: T[];
totalRow: number;
records?:T[];
total?:number
}
export type SearchOption = {
pageSize?: number;
pageNumber?: number;
search?: { [key: string]: any };
sortField?: string;
sortOrder?: 'asc' | 'desc';
}
type TableState<T> = {
abort: boolean;
data: T[];
total: number;
loading: boolean;
pageSize: number;
pageNumber: number;
search: { [key: string]: string };
sortField?: string;
sortOrder?: 'asc' | 'desc';
}
export type PageTableContext<T> = {
tableProps: TableProps<T>,
search: (params?: SearchOption) => void,
refresh: () => void,
initialSearch?: { [key: string]: string },
noRender: (index: number) => number;
searchParams: { [key: string]: string; }
}
function usePageTable<T>(
service: (params?: SearchOption) => Promise<PageResult<T>>,
options: SearchOption = {}
): PageTableContext<T> {
const [, forceRender] = useReducer(s => s + 1, 1);
const state = useRef<TableState<T>>({
abort: false,
data: [],
total: 0,
loading: false,
pageSize: options.pageSize ?? 10,
pageNumber: options.pageNumber ?? 1,
sortField: options.sortField,
sortOrder: options.sortOrder,
search: options.search || {},
});
useEffect(() => {
const stateRef = state.current;
stateRef.abort = false;
search();
return () => { stateRef.abort = true; }
}, []);
const search = (opt: SearchOption = {}) => {
const s = state.current;
if (s.loading || s.abort) {
return;
}
s.loading = true;
forceRender();
const pageParams = {
pageNumber: opt?.pageNumber ?? s.pageNumber,
pageSize: opt?.pageSize ?? s.pageSize,
sortField: opt?.sortField ?? s.sortField,
sortOrder: opt?.sortOrder ?? s.sortOrder,
search: opt?.search ?? s.search,
...opt,
};
service(pageParams).then((data) => {
if (!s.abort) {
s.search = pageParams.search;
s.sortField = pageParams.sortField;
s.sortOrder = pageParams.sortOrder;
s.pageNumber = pageParams.pageNumber;
s.pageSize = pageParams.pageSize;
s.data = data.list??data.records;
s.total = data.totalRow??data.total;
s.loading = false;
forceRender();
}
});
}
const handleTableChange = (pagination: any, filters: any, sort: any) => {
const { field, order } = sort;
if (field && order) {
const sortOrder: any = order === 'ascend' ? 'asc' : 'desc';
search({ pageNumber: pagination.current, pageSize: pagination.pageSize, sortOrder, sortField: field });
return;
}
search({ pageNumber: pagination.current, pageSize: pagination.pageSize });
}
return {
tableProps: {
bordered: true,
dataSource: state.current.data,
pagination: {
pageSize: state.current.pageSize,
current: state.current.pageNumber,
total: state.current.total,
...DefaultPaginationParam,
},
loading: state.current.loading,
onChange: handleTableChange,
},
search: (params?: SearchOption) => search({ ...params, pageNumber: 1 }),
refresh: search,
initialSearch: options?.search,
noRender: (index) => (state.current.pageNumber - 1) * state.current.pageSize + (index + 1),
searchParams: state.current.search,
}
}
export default usePageTable;
export const DefaultPaginationParam: TablePaginationConfig = {
showTotal: (total: number, range: [number, number]) => `${range[0]}-${range[1]}${total}`,
showSizeChanger: true,
showQuickJumper: true,
pageSizeOptions: ['10', '20', '50', '100'],
size: 'small'
}

171
src/config/chart.ts Normal file
View File

@ -0,0 +1,171 @@
export const timeAxisX = {
type: 'time',
axisTick: {
show: false
},
axisLine: {
lineStyle: {
color: '#1187cd',
},
},
axisLabel: {
interval: 0,
fontSize: 14,
},
splitLine: {
show: true,
lineStyle: {
color: '#1187cd44',
type: [5, 5]
},
},
}
export const enumAxisX = (values: string[], formatter?: boolean) => {
return {
data: values,
axisTick: {
show: false
},
axisLine: {
lineStyle: {
color: '#1187cd',
},
},
splitLine: {
show: true,
lineStyle: {
color: '#1187cd44',
type: [5, 5]
},
},
axisLabel: {
fontSize: 18,
formatter: formatter === false ? undefined : charLongNameFormatter
},
}
}
export const unitAsNameY = (unit: string, right?: boolean) => {
return {
name: unit,
nameGap: -6,
nameTextStyle: {
padding: right ? [0, 24, 0, 0] : [0, 0, 0, 16],
},
}
}
export const charLongNameFormatter = (value: string) => {
var strs = value.split('');
let ret = '';
for (let i = 0; strs[i]; i += 1) {
if (i > 0) {
ret += '\n';
}
ret += strs[i];
}
return ret;
}
export const valueAxisY = {
type: 'value',
splitLine: {
show: true,
lineStyle: {
color: '#1187cd44',
type: [5, 5]
},
},
axisLabel: {
margin: 20,
fontSize: 12,
},
axisTick: {
show: false
},
nameTextStyle: {
fontSize: 12,
},
}
export const valueAxisYNoLabel = {
type: 'value',
splitLine: {
show: true,
lineStyle: {
color: '#1187cd44',
type: [5, 5]
},
},
axisLabel: {
show: false,
},
axisTick: {
show: false
},
}
export const minmaxMarkPoint = {
label: {
color: '#fff',
},
data: [
{ type: 'max', name: 'Max', label: { fontSize: 18, textBorderColor: '#000', textBorderWidth: 1 } },
{ type: 'min', name: 'Min', label: { fontSize: 18, textBorderColor: '#000', textBorderWidth: 1 } }
]
}
export const labelLegend = {
textStyle: {
fontSize: 16,
},
itemWidth: 24,
itemHeight: 14,
}
export const containLabelGrid = (top?: number) => {
return {
left: 10,
right: 10,
bottom: 10,
top: top || 30,
containLabel: true,
}
}
export const smoothAreaLine = (colorSharpFormat: string) => {
return {
type: 'line',
color: colorSharpFormat,
smooth: true,
symbol: 'none'
}
}
export const smoothAreaLineEx = (colorSharpFormat: string) => {
return {
type: 'line',
color: colorSharpFormat,
smooth: true,
}
}
export const gradientBarWithLabel = {
type: 'bar',
label: {
show: true,
position: 'top',
textBorderWidth: 0,
fontSize: 12,
}
}

37
src/config/consts.tsx Normal file
View File

@ -0,0 +1,37 @@
export const StationConsts: any = {
ctrlType: [
{ label: 'PLC', value: 'PLC' },
{ label: 'RTU', value: 'RTU' },
{ label: 'ROCKET', value: 'ROCKET' }
],
ctrlProtocol: [
{ label: '楚禹', value: '楚禹' },
{ label: '徐州伟思', value: '徐州伟思' },
{ label: 'PLC', value: 'PLC' },
{ label: '722', value: '722' },
{ label: '潞碧垦', value: '潞碧垦' }
],
ctrlProtocol2: [
{ label: '楚禹', value: '楚禹' },
{ label: '徐州伟思', value: '徐州伟思' },
{ label: '722', value: '722' },
],
wagaType: [
{ label: '分水闸', value: '分水闸' },
{ label: '泄洪闸', value: '泄洪闸' },
{ label: '节制闸', value: '节制闸' },
{ label: '排水闸', value: '排水闸' },
{ label: '退水闸', value: '退水闸' },
{ label: '引(进)水闸', value: '引(进)水闸' },
{ label: '挡潮闸', value: '挡潮闸' },
{ label: '船闸', value: '船闸' },
{ label: '涵闸', value: '涵闸' },
{ label: '其它', value: '其它' },
],
gaType: {
"waga": "水闸",
"slcga": "涵闸"
}
}

8
src/config/index.ts Normal file
View File

@ -0,0 +1,8 @@
export const TITLE = '颜家台灌区'
export const SUBTITLE = '管理平台';
export const config = {
title: '管理平台',
transitionDuaration: 500,
};

57
src/index.less Normal file
View File

@ -0,0 +1,57 @@
@import '~antd/dist/antd.less';
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
overflow-y: hidden;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}
#root {
min-width: 1280px;
}
.flex-grow-1 {
flex-grow: 1;
}
@font-face {
font-family: "Password Dots Regular";
src: url('./assets/fonts/password.ttf');
}
*,
:after,
:before {
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
::-webkit-scrollbar {
height: 8px;
width: 8px;
}
::-webkit-scrollbar-thumb {
background: #d6dde9;
border-radius: 4px;
border: 1px solid #c4cfe1;
}
::-webkit-scrollbar-track {
background-color: #f6f6f6;
}
::selection {
color: #fff;
background: #3b7cff;
}

25
src/index.tsx Normal file
View File

@ -0,0 +1,25 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import { ConfigProvider } from 'antd';
import zhCN from 'antd/lib/locale/zh_CN';
import 'moment/locale/zh-cn';
import { Provider } from 'react-redux';
import { HashRouter } from 'react-router-dom';
import { store } from './models/store';
import AppRouters from './views/AppRouters';
import './index.less';
import './components/ant_override.less'
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
root.render(
<Provider store={store}>
<HashRouter>
<ConfigProvider locale={zhCN}>
<AppRouters />
</ConfigProvider>
</HashRouter>
</Provider>
);

7
src/models/_/apipath.ts Normal file
View File

@ -0,0 +1,7 @@
export const apiPaths = {
auth: {
login: '/zhzmkzv2/service/sysuser/doLogin',
registerByToken: '/zhzmkzv2/service/sysuser/registerByToken',
page: `/zhzmkzv2/service/sysuser/page`,
},
};

178
src/models/_/defs.ts Normal file
View File

@ -0,0 +1,178 @@
export type MenuItem = {
id: string;
title: string;
path?: string;
redirect?: string;
icon?: string;
children?: MenuItem[];
}
export type GateKeyRecord = {
stcd: string;
}
export type CCTVObject = {
indexCode: string;
name: string;
sname: string;
stcd: string;
gateNumber: number[];
region: string;
}
export type StationItem = {
stcd: string;
hpCode: string;
name: string;
irrName?: string; // 所属灌区
irrCode: string;
gaorNum: number; // 闸孔数量
engName?: string; // 管理单位
engCode: string;
minHgt: number;
maxHgt: number;
wagaType: string;
ctrlType: 'RTU' | 'PLC' | 'ROCKET';
ctrlProtocol: string; // '722' | 'PLC' | '楚禹' ...
ghtX: number;
ghtY: number;
gaType: 'waga' | 'slcga'; // 水闸, 涵闸
uprzStcd: string;
dwrzStcd: string;
flowStcd: string;
lgtd?: number;
lttd?: number;
vip?: boolean;
bim?: boolean;
real?: SzReal;
cctvs?: CCTVObject[]; // 视频点列表
_idx?: number;
_sort?: number;
_fav?: boolean;
}
// rtu的设备状态
export type GateRuntime = {
stcd: string;
tm: string;
gateNumber: number;
closedSignal?: number; // 下限位
closeingSignal?: number; // 下降中
errorSignal?: number; // 故障
openedSignal?: number; //
openingSignal?: number; //
powerSignal?: number; // 电源
realAperture?: number; // 当前开度
remoteSignal?: number; // 远程
setAperture?: number; // 设定开度
_idx?: number;
_stationName?: string;
_irrName?: string;
_irrCode?: string;
_engCode?: string;
_online?: boolean;
}
// 接口分页操作人员stcd/闸站名称所属灌区管理单位起始结束时间最近操作列表stcd闸孔编号(可选)
export type OpLogListItem = {
id: number,
stcd: string;
stationName: string;
gateNumber: string;
userName: string,
userId: number;
tm: string;
cmd: string; // 操作指令
ip: string;
// todo 新加的
curAperture?: number; // 当前开度
setAperture?: number; // 设定开度
result: 0 | 1;
msg?: string; // 操作错误的详细信息
source: 'web' | 'app';
uprz?: number;
upss?: number;
dwrz?: number;
dwss?: number;
flow?: number;
};
// 接口列表带权限查询条件有按照stcd查找)
export type SzReal = {
stcd: string;
stationName?: string;
z1?: number;
zz1?: number;
z1tm?: number;
z2?: number;
zz2?: number;
z2tm?: number;
hq?: number;
hqtm?: number;
}
export type StationRealComp = StationItem & {
runtime?: (GateRuntime | undefined)[];
oplogs?: OpLogListItem[];
real?: SzReal;
_idx?: number;
_sort?: number;
_fav?: boolean;
}
export type GateDocItem = {
stcd: string;
gateName: string;
irrName: string;
filename: string;
displayName: string;
uploadTM: string;
}
export type SelectItem = { value: string; label: string };
export type SortConfigItem = {
id?: number;
name: string;
sort: string[];
irr?:SelectItem[];
};
export type whiteListItem = {
acl: string;
tm: string;
userId: number;
username: string;
}
export type AlertRuleItem = {
id: number;
stcd: string;
name: string;
gate: number;
type: 1 | 2 | 3 | 0;
max: number;
min: number;
irr: string;
irrName: string;
eng: string;
engName: string;
}
export type AlertLog = any;
export type ResType =
'工程外景照片' |
'工程多媒体资料' |
'工程设计图纸' |
'工程结构示意图' |
'工程技术参数示意图' |
'工程分布图';

126
src/models/auth/_.ts Normal file
View File

@ -0,0 +1,126 @@
import { message } from "antd";
import { XINDA_TOKEN, httpPost } from "../../utils/request";
import { MenuItem } from "../_/defs";
import { apiPaths } from "../_/apipath";
export type LoginUser = {
id: number;
loginName: string;
name: string;
roleList: string[];
tokenInfo: {
tokenValue: string;
};
op: 0 | 1;
ad: 0 | 1;
roleCodes: string[];
}
export type AuthState = {
user: LoginUser | null | -1;
menu: MenuItem[];
}
export const USER_SESSION_KEY = '__usereinfo__';
export function removeLoginInfo() {
sessionStorage.removeItem(USER_SESSION_KEY);
sessionStorage.removeItem('TOKEN');
sessionStorage.removeItem(XINDA_TOKEN);
}
export function setLoginInfo(userInfo: string, token: string) {
sessionStorage.setItem(USER_SESSION_KEY, userInfo);
sessionStorage.setItem('TOKEN', token);
}
export function getUserFromSession(): LoginUser | null {
const strUser = sessionStorage.getItem(USER_SESSION_KEY);
if (!strUser) {
return null;
}
try {
const obj: LoginUser = JSON.parse(strUser);
if (obj.id && obj.tokenInfo.tokenValue) {
return obj;
}
} catch (e) { }
return null
}
function adjustRoleCodes(result: LoginUser) {
const roleCodes: string[] = [];
if (typeof result.roleCodes === 'string') {
const codes = (result.roleCodes as string).split(',');
for (const o of codes) {
if (o === 'ALL') {
roleCodes.push(o)
}
}
for (const o of codes) {
if (o !== 'ALL') {
roleCodes.push(o)
}
}
}
result.roleCodes = roleCodes;
}
export async function regByToken(token: string): Promise<LoginUser | undefined> {
const result: LoginUser | null = await httpPost(apiPaths.auth.registerByToken, { token });
if (!result) {
message.error('登陆失败');
return;
}
adjustRoleCodes(result);
sessionStorage.setItem(XINDA_TOKEN, token);
setLoginInfo(JSON.stringify(result), result.tokenInfo?.tokenValue);
return result;
}
export async function login(form: { username: string, password: string }): Promise<LoginUser | undefined> {
const result: LoginUser | null = await httpPost(apiPaths.auth.login, {
loginName: form.username,
password: form.password
});
if (!result) {
message.error('登陆失败');
return;
}
adjustRoleCodes(result);
if (!result.roleCodes.length) {
result.roleCodes = ['ALL'];
}
setLoginInfo(JSON.stringify(result), result.tokenInfo?.tokenValue);
return result;
}
function idgen() {
let id = 1;
return () => `${id++}`
}
export function loadMenu(): MenuItem[] {
const id = idgen();
return [
{ id: id(), title: '闸门总览', path: '/mgr/home', icon: 'zxjk.png' },
// { id: id(), title: '闸门监控', path: '/mgr/real', icon: 'zxjk.png' },
].filter(Boolean);
}
export function defaultHomePage() {
return '/mgr/home';
}

59
src/models/auth/index.ts Normal file
View File

@ -0,0 +1,59 @@
import { createModel } from "@rematch/core";
import { RootModel } from "..";
import { MenuItem } from "../_/defs";
import { AuthState, getUserFromSession, loadMenu, login, LoginUser, regByToken, removeLoginInfo } from "./_";
export const auth = createModel<RootModel>()({
state: {
user: getUserFromSession(),
menu: [],
} as AuthState,
reducers: {
setUser(state, user: LoginUser): AuthState {
return { ...state, user };
},
setMenu(state, menu: MenuItem[]): AuthState {
return { ...state, menu };
},
},
effects: {
async regByToken(token: string): Promise<boolean> {
const result = await regByToken(token);
if (result) {
this.setUser(result);
sessionStorage.setItem('__useToken', '1');
return true;
}
this.setUser(-1);
return false;
},
async login(form: { username: string, password: string }): Promise<boolean> {
const result = await login(form);
if (result) {
this.setUser(result);
sessionStorage.setItem('__useToken', '0');
return true;
}
return false;
},
logout() {
removeLoginInfo();
this.setUser(null);
},
async loadMenu(payload, s) {
this.setMenu(loadMenu());
}
}
});

61
src/models/auth/menu.ts Normal file
View File

@ -0,0 +1,61 @@
import { MenuItem } from "../_/defs";
export function findMenu(menus: MenuItem[], pathname: string) {
if (!menus) {
return [];
}
for (const m1 of menus) {
if (m1.path === pathname) {
return [m1.id];
}
if (m1.children && m1.children.length) {
for (const m2 of m1.children) {
if (m2.path === pathname) {
return [m1.id, m2.id];
}
if (m2.children && m2.children.length) {
for (const m3 of m2.children) {
if (m3.path === pathname) {
return [m1.id, m2.id, m3.id];
}
}
}
}
}
}
return [];
}
export function findLeafMenu(menus: MenuItem[], pathname: string) {
if (!menus) {
return null;
}
for (const m1 of menus) {
if (m1.path === pathname) {
return m1;
}
if (m1.children && m1.children.length) {
for (const m2 of m1.children) {
if (m2.path === pathname) {
return m2;
}
if (m2.children && m2.children.length) {
for (const m3 of m2.children) {
if (m3.path === pathname) {
return m3;
}
}
}
}
}
}
return null;
}

10
src/models/index.ts Normal file
View File

@ -0,0 +1,10 @@
import { Models } from "@rematch/core"
import { auth } from "./auth";
export interface RootModel extends Models<RootModel> {
auth: typeof auth;
}
export const models: RootModel = {
auth,
};

10
src/models/store.ts Normal file
View File

@ -0,0 +1,10 @@
import { init, RematchDispatch, RematchRootState } from '@rematch/core'
import { models, RootModel } from './index'
export const store = init({
models,
})
export type Store = typeof store
export type Dispatch = RematchDispatch<RootModel>
export type RootState = RematchRootState<RootModel>

1
src/react-app-env.d.ts vendored Normal file
View File

@ -0,0 +1 @@
/// <reference types="react-scripts" />

21
src/setupProxy.js Normal file
View File

@ -0,0 +1,21 @@
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function (app) {
app.use(
'/zhzmkzv2/service',
createProxyMiddleware({
target: 'https://219.138.108.99:19000',
changeOrigin: true,
})
);
app.use(
'/yjt',
createProxyMiddleware({
target: 'http://ywxj.cloudowr.cn',
changeOrigin: true,
})
);
};

218
src/utils/request.ts Normal file
View File

@ -0,0 +1,218 @@
import { message } from "antd";
import axios, { AxiosRequestConfig } from "axios";
import { SearchOption } from "../components/crud/usePageTable";
import { apiPaths } from "../models/_/apipath";
// 此文件根据后端接口的实际规则进行调整
export const XINDA_TOKEN = 'XINDA_TOKEN';
let lastLoginErrorMsg = 0;
function loginError(data: any) {
const now = Date.now();
if (now - lastLoginErrorMsg < 3000) {
return;
}
lastLoginErrorMsg = now;
if (
data.msg.startsWith('Token已被顶下线') ||
data.msg.startsWith('Token已被踢下线')
) {
message.error('该账号已在别处登录');
} else if (
data.msg.startsWith('Token已过期')
) {
message.error('登陆已过期,请重新登陆');
} else {
message.error('登陆信息异常,请重新登陆');
}
}
export async function xindaRequest(url: string, method: 'GET' | 'POST', params: Object) {
const resp = await axios.post(apiPaths.auth.page, {
token: sessionStorage.getItem(XINDA_TOKEN),
url,
method,
...params
});
const data = resp.data;
if (data.code === 200) {
return data.result || true;
}
return null
}
export async function paginate(url: string, params: SearchOption = {}) {
const { search, ...pagerParams } = params;
const reqParams: any = {
...search,
...pagerParams
};
try {
const data = await httpPost(url, reqParams);
if (!data) {
message.error('请求失败')
return { list: [], totalRow: 0 }
}
return { list: data.records || [], totalRow: data.total ?? 0 }
} catch (e) {
return { list: [], totalRow: 0 }
}
}
export async function paginateDemo(url: string, params: SearchOption = {}) {
const parts = url.replace('/zhzmkzv2/service/', '').split('/').join('_') + '.json';
const data = await httpGet(`${process.env.PUBLIC_URL}/demodata/${parts}`);
if (!data) {
message.error('请求失败')
return { list: [], totalRow: 0 }
}
return { list: data.records || [], totalRow: data.total ?? 0 }
}
export async function httpPost(url: string, params: Object | string, config?: AxiosRequestConfig<Object>) {
try {
// const token = sessionStorage.getItem('TOKEN');
const resp = await axios.post(url, params, config);
const data = resp.data;
if (data.code === 200) {
return data.data || true;
}
/*
if (data.code === 401) {
const dispatch: Dispatch | undefined = (window as any).__dispatch__;
if (dispatch) {
dispatch.auth.logout();
}
}
*/
if (data.code === 401 && data.msg) {
loginError(data);
} else if (typeof data.msg === 'string') {
message.error(data.msg);
}
return null;
} catch (e) {
console.log(e);
return null;
}
}
export async function httpGet(url: string, params?: any) {
try {
// const token = sessionStorage.getItem('TOKEN');
const resp = await axios.get(url, {
params,
// headers: { Authorization: `Bearer ${token}` }
});
const data = resp.data;
if (data.code === 200) {
return data.data;
}
if (data.code === 401 && data.msg) {
loginError(data);
} else if (typeof data.msg === 'string') {
message.error(data.msg);
}
/*
if (data.code === 401) {
const dispatch: Dispatch | undefined = (window as any).__dispatch__;
if (dispatch) {
dispatch.auth.logout();
}
}
*/
return null;
} catch (e) {
console.log(e);
return null;
}
}
export async function httpGet2(url: string, params?: any) {
try {
// const token = sessionStorage.getItem('TOKEN');
const resp = await axios.get(url, {
params,
// headers: { Authorization: `Bearer ${token}` }
});
const data = resp.data;
if (data.code === 200) {
return data;
}
if (data.code === 401 && data.msg) {
loginError(data);
} else if (typeof data.msg === 'string') {
message.error(data.msg);
}
/*
if (data.code === 401) {
const dispatch: Dispatch | undefined = (window as any).__dispatch__;
if (dispatch) {
dispatch.auth.logout();
}
}
*/
return null;
} catch (e) {
console.log(e);
return null;
}
}
export async function httpGet3(url: string, params?: any) {
try {
const resp = await axios.get(url, {
params,
});
const data = resp.data;
if (data && typeof data === 'object' && 'code' in data) {
if (data.code === 200) {
return data.data;
}
if (data.code === 401 && data.msg) {
loginError(data);
} else if (typeof data.msg === 'string') {
message.error(data.msg);
}
return null;
}
return data;
} catch (e) {
console.log(e);
return null;
}
}
export const downLoad = async (url: string, params: any) => {
let parts = [];
if (typeof params !== 'string') {
for (const key in params) {
const value = params[key];
parts.push(`${key}=${encodeURIComponent(`${value}`)}`);
}
} else {
parts.push(params);
}
console.log(`${url}?${parts.join('&')}`);
window.open(`${url}?${parts.join('&')}`);
}

52
src/utils/useRequest.ts Normal file
View File

@ -0,0 +1,52 @@
import { useState, useEffect, useRef, useReducer } from "react";
export type RequestContext<DataType> = {
data?: DataType;
error?: any;
loading: boolean;
refresh: () => void;
}
/**
* @param p
* @returns
* @todo deal refresh when loading
*/
const useRequest = <DataType = any>(p: () => Promise<DataType>, dependences?: any[]): RequestContext<DataType> => {
const [data, setData] = useState<DataType | undefined>()
const [error, setError] = useState<any>();
const [loading, setLoading] = useState(false);
const abort = useRef(false);
const [_, refresh] = useReducer(s => s + 1, 0);
useEffect(() => {
const doFetch = async () => {
setLoading(true);
abort.current = false;
try {
const data = await p();
if (!abort.current) {
setData(data);
}
} catch (e) {
if (!abort.current) {
setError(e);
}
} finally {
if (!abort.current) {
setLoading(false);
}
}
};
doFetch();
return () => {
abort.current = true;
};
}, dependences ? [...dependences, _] : [_]);
console.log({ data, error, loading, refresh });
return { data, error, loading, refresh};
};
export default useRequest;

13
src/utils/useSize.ts Normal file
View File

@ -0,0 +1,13 @@
import useResizeObserver from '@react-hook/resize-observer';
import React, { useEffect, useReducer } from 'react';
export default function useSize(target: React.RefObject<HTMLElement>) {
const [size, setSize] = React.useState<DOMRect>();
React.useLayoutEffect(() => {
setSize(target.current?.getBoundingClientRect())
}, [target]);
useResizeObserver(target, (entry) => setSize(entry.contentRect))
return size
}

162
src/utils/utils.ts Normal file
View File

@ -0,0 +1,162 @@
import moment from "moment";
import { StationItem, StationRealComp } from "../models/_/defs";
export function changeObjectStringToMoment(obj: { [key: string]: any }, fields: string[]): any {
const ret = { ...obj };
for (const f of fields) {
if (f in ret && typeof ret[f] === 'string') {
ret[f] = moment(ret[f]);
}
}
return ret;
}
export async function base64FromFile(file: File): Promise<string | undefined> {
return new Promise((resolve) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
const str = reader.result;
if (typeof str === 'string') {
resolve(str);
}
resolve(undefined);
}
reader.onerror = () => {
resolve(undefined);
}
})
}
export const normFile = (e: any) => {
if (Array.isArray(e)) {
return e;
}
return e?.fileList;
};
export function randNum(a: number, b: number) {
const ret = a * Math.random() + b;
return parseFloat(ret.toFixed(2));
}
export function getParameter(param: string) {
var query = window.location.hash;
var iLen = param.length;
var iStart = query.indexOf(param);
if (iStart == -1)
return "";
iStart += iLen + 1;
var iEnd = query.indexOf("&", iStart);
if (iEnd == -1)
return query.substring(iStart);
return query.substring(iStart, iEnd);
}
export function toFixed3(val: any) {
if (typeof val !== 'number') {
return '-';
}
return val.toFixed(3);
}
export function renTm(val: any) {
if (!val) {
return '-'
}
return moment(val).format('MM-DD HH:mm:ss')
}
export function dpContainerTransform(containerWidth: number, containerHeight: number, size?: DOMRect): undefined | string {
if (!size) {
return;
}
const sx = size.width / containerWidth;
const sy = size.height / containerHeight;
const scale = sx < sy ? sx : sy;
if (!scale) {
return
}
const offx = containerWidth * (sx - scale) * 0.5;
const offy = containerHeight * (sy - scale) * 0.5;
return `scale(${scale.toFixed(3)}) translate(${offx.toFixed(3)}px, ${offy.toFixed(3)}px)`;
}
export function notEmpty<TValue>(value: TValue | null | undefined): value is TValue {
if (value === null || value === undefined) return false;
return true;
}
export function renAperture(val?: any) {
if (typeof val !== 'number') {
return '-'
}
return (val / 1000).toFixed(3);
}
export function apertureMeter(val?: any): number | undefined {
if (typeof val !== 'number') {
return undefined
}
return val / 1000;
}
export function renOpenNum(rec?: StationRealComp) {
if (rec?.ctrlType === 'PLC') {
return rec.runtime?.filter(o => typeof o?.closedSignal === 'number' && !o.closedSignal).length ?? 0;
} else {
return rec?.runtime?.filter(o => o && o.realAperture && o.realAperture > 0).length ?? 0;
}
}
export function renMaxKd(rec?: StationRealComp) {
const rt: number[] = rec?.runtime?.map(o => o?.realAperture).filter(o => typeof o === 'number') as number[];
if (!rt) {
return '-';
}
const mx = Math.max(...rt);
return renAperture(mx)
}
export function tmpreset(val: string): [moment.Moment, moment.Moment] | undefined {
if (val === 'd1') {
return [moment(), moment()];
} else if (val === 'd7') {
return [moment().add(-7, 'day'), moment()];
} else if (val === 'm1') {
return [moment().add(-1, 'month'), moment()];
} else if (val === 'm3') {
return [moment().add(-3, 'month'), moment()];
} else if (val === 'y1') {
return [moment().add(-1, 'year'), moment()];
} else if (val === '本月') {
return [moment().startOf('month'), moment()];
} else if (val === 'm6') {
return [moment().add(-6, 'month'), moment()];
}
return undefined;
}
export function getBasePath(): string {
if (process.env.PUBLIC_URL.startsWith('http')) {
return process.env.PUBLIC_URL;
} else {
return window.location.origin + process.env.PUBLIC_URL;
}
}

37
src/views/AppRouters.tsx Normal file
View File

@ -0,0 +1,37 @@
import React, { useEffect } from 'react';
import { useDispatch } from 'react-redux';
import { Navigate, useRoutes } from 'react-router';
import DashboardLayout from '../components/DashboardLayout';
import { Dispatch } from '../models/store';
import NotFound from './NotFound';
import HomePage from './Home'
const AppRouters: React.FC = () => {
const dispatch = useDispatch<Dispatch>();
useEffect(() => {
(window as any).__dispatch__ = dispatch;
return () => {
delete (window as any).__dispatch__;
}
}, [dispatch]);
let element = useRoutes([
{ path: '/', element: <Navigate to="/mgr/home" /> },
{
path: '/mgr', element: <DashboardLayout />, children: [
{ path: 'home', element: <HomePage /> },
{ path: 'real', element: <HomePage /> },
{ path: '*', element: <NotFound /> },
]
},
{ path: '*', element: <NotFound /> },
]);
return element;
}
export default AppRouters

23
src/views/Home/IrrTabs.js Normal file
View File

@ -0,0 +1,23 @@
const IrrTabs = ({ ctx }) => {
const { tabRole, selArea, setSelArea } = ctx;
// 处理点击事件
const handleClick = (areaCode) => {
// 设置选中的区域
setSelArea(areaCode);
};
return (
<div className='irr-tabs'>
{
tabRole.map(o => (
<div onClick={() => handleClick(o)} key={o} className={`item ${selArea.label === o.label ? 'active' : 'deactive'}`}>{o.label}</div>
))
}
</div>
)
}
export default IrrTabs

View File

@ -0,0 +1,28 @@
import React, { useState } from 'react'
import Panel from './gqgs';
// import Panel作物种植 from './作物种植';
import StList from './StList';
import IrrTabs from './IrrTabs';
import { ArrowLeftOutlined, ArrowRightOutlined } from '@ant-design/icons';
const PanelGroup = ({ ctx }) => {
const { selArea, setSelArea } = ctx;
const [fold, setFold] = useState(false);
return (
<div className='home-panel-root' style={{ transform: fold ? 'translateX(100%)' : undefined }}>
<IrrTabs ctx={ctx} />
<Panel ctx={ctx} />
<div style={{ height: 8 }}></div>
<StList ctx={ctx} />
<div className='arrowBox' onClick={() => setFold(val => !val)}>
{fold ? <ArrowLeftOutlined /> : <ArrowRightOutlined />}
</div>
</div>
)
}
export default PanelGroup

141
src/views/Home/RealTable.js Normal file
View File

@ -0,0 +1,141 @@
import React, { useRef, useState,useMemo } from 'react'
import { Button, Table, Tooltip, Modal, DatePicker, Tabs } from 'antd';
import ReactECharts from 'echarts-for-react';
import useSize from '../../utils/useSize';
import { renMaxKd, renOpenNum } from '../../utils/utils';
import { httpPost } from '../../utils/request';
import moment from 'moment';
const RealTable = ({ ctx }) => {
const divref = useRef(null);
const size = useSize(divref);
const [visible, setVisible] = useState(false);
const [detailRow, setDetailRow] = useState();
const [range, setRange] = useState([moment().add(-7, 'day'), moment()]);
const [tabKey, setTabKey] = useState('PH');
const [list, setList] = useState([]);
const getUnit = (key) => key === 'PH' ? '' : 'mg/L';
const loadDetail = async (rowArg) => {
const target = rowArg;
if (!target) return;
const params = {
mn: target.stcd || target.mn,
startTime: range?.[0]?.format('YYYY-MM-DD HH:mm:ss'),
endTime: range?.[1]?.format('YYYY-MM-DD HH:mm:ss'),
};
const data = await httpPost('/yjt/wq/list', params);
setList(Array.isArray(data) ? data : []);
};
const columns = [
{ title: '站点名称', key: 'mn',dataIndex:"mn",ellipsis: true, width: 90},
{
title: '数据时间', key: 'tm', dataIndex: "tm", align: 'center', width: 80,
render: (v, r) => <span style={{color:r.status === 'false'? 'red':'#000'}}>{v ? moment(v).format('MM-DD HH:mm:ss'):""}</span>
},
{ title: 'PH值', key: 'ph', dataIndex:"ph",align: 'center', width: 70},
{ title: '总磷(mg/L)', key: 'p', dataIndex:"p",align: 'center', width: 70},
{ title: 'COD(mg/L)', key: 'cod', dataIndex:"cod",align: 'center', width: 90},
{ title: '氨氮(mg/L)', key: 'ad', dataIndex: "ad", align: 'center', width: 70 },
{
title: '操作', key: 'operation', width: 70, align: 'center',
render: (value, row) => (
<Button type='link' onClick={() => { setDetailRow(row); setVisible(true); loadDetail(row); }}>{'详情'}</Button>
)
},
];
const flowColumns = [
{ title: '测流点', key: 'mn',dataIndex:"mn",ellipsis: true, width: 90},
{ title: '水深(m)', key: 'ph', dataIndex:"ph",align: 'center', width: 70},
{ title: '瞬时流量(m³/s)', key: 'p', dataIndex:"p",align: 'center', width: 70},
{ title: '累计水量(m³)', key: 'cod', dataIndex:"cod",align: 'center', width: 90},
{
title: '操作', key: 'operation', width: 70, align: 'center',
render: (value, row) => (
<Button type='link' onClick={() => { setDetailRow(row); setVisible(true); loadDetail(row); }}>{'详情'}</Button>
)
},
];
const newCols = useMemo(() => {
return ctx?.selArea?.label == '水质'? columns : flowColumns
},[ctx])
const height = (ctx.dataWithFav.length + 1) * 40;
return (
<div ref={divref} style={{ flexGrow: 1, height: 100 }}>
<Table
size='small'
pagination={false}
dataSource={ctx?.selArea?.label == '水质'? ctx.dataWithFav:[]}
rowKey={row => row.mn}
columns={newCols}
scroll={size?.height && size.height < height ? { y: size.height - 48 } : undefined}
/>
<Modal title='水质详情' open={visible} destroyOnClose onCancel={() => { setVisible(false);setTabKey('PH') }} footer={null} width={900}>
<div style={{ display: 'flex', alignItems: 'center', marginBottom: 8 }}>
<DatePicker.RangePicker value={range} onChange={setRange} allowClear={false} showTime={{ format: 'HH:mm' }} format='YYYY-MM-DD HH:mm' />
<Button style={{ marginLeft: 8 }} type='primary' onClick={()=>loadDetail(detailRow)}>查询</Button>
</div>
<div style={{ display: 'flex', gap: 12 }}>
<div style={{ width: 420 }}>
<Table
size='small'
pagination={false}
dataSource={list}
rowKey={row => row.mn}
columns={[
{ title: '时间', dataIndex: 'tm', key: 'tm', width: 140, render: (v, r) => <span>{v ? moment(v).format('YYYY-MM-DD HH:mm:ss'):""} </span>},
{ title: 'PH值', dataIndex: 'ph', key: 'ph', width: 80 },
{ title: '总磷(mg/L)', dataIndex: 'p', key: 'p', width: 120 },
{ title: 'COD(mg/L)', dataIndex: 'cod', key: 'cod', width: 140 },
{ title: '氨氮(mg/L)', dataIndex: 'ad', key: 'ad', width: 120 },
]}
scroll={{y:400,x:"auto"}}
/>
</div>
<div style={{ flex: 1 ,marginLeft:10}}>
<Tabs activeKey={tabKey} onChange={setTabKey} items={['PH','总磷','COD','氨氮'].map(k => ({ key: k, label: k }))} />
<ReactECharts style={{ height: 360,width:420}}
notMerge
option={{
grid:{top:"8%",bottom:"8%"},
tooltip: { trigger: 'axis', formatter: (params) => { const p = Array.isArray(params) ? params[0] : params; const unit = getUnit(tabKey); return `${p.axisValue}<br/>${p.seriesName}: ${p.data === null ? '' : p.data}${unit ? ' ' + unit : ''}`; } },
xAxis: { type: 'category', data: list.map(o => moment(o.time || o.tm).format('MM-DD HH:mm'))},
yAxis: (() => {
const vals = list.map(o => {
if (tabKey === 'PH') return o.ph;
if (tabKey === '总磷') return o.p;
if (tabKey === 'COD') return o.cod;
return o.ad;
}).filter(v => typeof v === 'number');
const unit = getUnit(tabKey);
console.log("unit",unit);
return {
type: 'value',
min: vals.length ? Math.floor(Math.min(...vals)) : undefined,
max: vals.length ? Math.ceil(Math.max(...vals)) : undefined,
name: unit || '',
nameLocation: 'end'
};
})(),
series: [{ name: tabKey, type: 'line', smooth: true, data: list.map(o => {
if (tabKey === 'PH') return o.ph;
if (tabKey === '总磷') return o.p;
if (tabKey === 'COD') return o.cod;
return o.ad;
}) }]
}} />
</div>
</div>
</Modal>
</div>
)
}
export default RealTable

36
src/views/Home/StList.js Normal file
View File

@ -0,0 +1,36 @@
import { SearchOutlined,BarChartOutlined } from '@ant-design/icons';
import { Button, Input } from 'antd';
import React, { useRef } from 'react';
import RealTable from './RealTable';
const StList = ({ ctx }) => {
const inputRef = useRef(null);
return (
<div className='stlist-root panel-card ltborder'>
<div className='title' style={{borderBottom: "1px solid #ffffff88"}}>
<BarChartOutlined className='icon' />
<div className='text'>{ctx?.selArea?.label == '水质'?"站点列表":"侧站点列表" }</div>
</div>
<div style={{ display: 'flex', alignItems: 'center', padding: 8 }}>
<Input
key={ctx.selArea}
ref={inputRef}
placeholder='请输入站点名称'
style={{ width: 200, marginRight: 8, backgroundColor: '#fff1', borderColor: '#fff4', color: '#fff' }}
/>
<Button
icon={<SearchOutlined />}
style={{ backgroundColor: '#fff1', color: '#fff', borderColor: '#fff4' }}
onClick={() => ctx.setFilterName(inputRef.current?.input.value)}
>
搜索
</Button>
<div style={{ flexGrow: 1 }}></div>
</div>
<RealTable ctx={ctx} />
</div>
)
}
export default StList

View File

@ -0,0 +1,55 @@
import React, { useMemo } from 'react';
const StLayer = ({ onHover, data, level, href, onClick, style, onContextMenu,flowData }) => {
if (!data) {
return null;
}
console.log('flowData:', data);
if (flowData && flowData.length > 0) {
console.log('flowData sample:', flowData[0]);
}
return (
<g>
{
data.map((o) => {
// 检查该闸门是否有流量
const hasFlow = (o.real?.hq && o.real?.hq > 0) ? true : false
// 计算图像中心点
const centerX = o.ghtX + 50; // 图像宽度的一半(100/2)
const centerY = o.ghtY + 50; // 图像高度的一半(100/2)
const imageStyle = {
...style,
animation: hasFlow ? 'rotate 2s linear infinite' : 'none',
// 使用transform属性直接设置旋转和旋转中心
transform: hasFlow ? `rotate(360deg)` : 'none',
transformOrigin: `${centerX}px ${centerY}px`
};
return (<image
key={o.stcd}
onClick={(e) => {
e.stopPropagation();
onClick && onClick(o);
}}
onContextMenu={(e) => {
if (onContextMenu) {
e.preventDefault();
onContextMenu(o);
}
}}
onMouseEnter={() => onHover(o.stcd)}
onMouseLeave={() => onHover()}
x={o.ghtX}
y={o.ghtY}
width={100}
height={100}
href={href ? href(o) : undefined}
style={imageStyle}
/>)
})
}
</g>
)
}
export default StLayer;

View File

@ -0,0 +1,36 @@
import React from 'react'
const SvgLineLayer = ({ data, level, className, onClick }) => {
if (!data) {
return null;
}
return (
<g>
{
data.map((o) => (
level >= o.levelShow ? (
<line
key={o.id}
x1={o.x1}
y1={o.y1}
x2={o.x2}
y2={o.y2}
transform={o.transform}
fill={o.fill}
stroke={o.stroke}
strokeLinecap={o.strokeLinecap}
strokeLinejoin={o.strokeLinejoin}
strokeWidth={o.strokeWidth}
className={typeof className === 'function' ? className(o) : className}
onDoubleClick={() => onClick && onClick(o)}
/>
) : null
))
}
</g>
)
}
export default SvgLineLayer;

View File

@ -0,0 +1,35 @@
import React from 'react'
const SvgTextLayer = ({ data, level, href, onClick, style }) => {
if (!data) {
return null;
}
return (
<g>
{
data.map((o) => (
level >= o.levelShow ? (
<text
key={o.id}
onClick={() => onClick && onClick(o)}
x={o.x}
y={o.y}
fontSize={o.fontSize}
stroke={o.stroke}
fill={o.fill}
transform={o.transform}
fontFamily={o.fontFamily}
strokeWidth={o.strokeWidth}
writing-mode={o?.isVertical?'tb':null}
>
{o.name}
</text>
) : null
))
}
</g>
)
}
export default SvgTextLayer;

View File

@ -0,0 +1,189 @@
import Panzoom, { PanzoomObject } from '@panzoom/panzoom';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import useRequest from '../../../utils/useRequest';
import SvgLineLayer from './SvgLineLayer';
import SvgTextLayer from './SvgTextLayer';
import StLayer from './StLayer';
import './index.less';
const IMG_W = 7000;
const IMG_H = 4500;
function _panToExtent(extent, clientX, clientY) {
const sx = clientX / (extent[2] - extent[0]);
const sy = clientY / (extent[3] - extent[1]);
return {
startX: (clientX - (extent[0] + extent[2])) * 0.5,
startY: (clientY - (extent[1] + extent[3])) * 0.5,
startScale: sx < sy ? sx : sy,
}
}
//获取数据
async function fetchDemoData(name, officeCodes) {
let ret = await fetch(`${process.env.PUBLIC_URL}/data/${name}.json`).then(resp => resp.json());
const records = Array.isArray(ret.result) ? ret.result : ret.result.records;
return records
// if (Array.isArray(records)) {
// records.forEach(o => {
// for (const f of transField) {
// if (typeof o[f] === 'string') {
// o[f] = parseFloat(o[f])
// }
// }
// })
// }
// if (!officeCodes || officeCodes[0] === 'ALL') {
// return records;
// }
// return records.filter((o) => {
// if (!o.officeCode) {
// return true;
// }
// return officeCodes.find(cc => {
// if (cc === 'A06A19') {
// return o.officeCode.startsWith('A05') || o.officeCode.startsWith('A08')
// } else {
// if (o.officeCode.startsWith(cc)) {
// return true;
// }
// }
// })
// });
}
const SvgMap = ({ctx}) => {
const panzoomRef = useRef();
const containerRef = useRef(null);
const outerRef = useRef(null);
const svgRef = useRef(null);
const [level, setLevel] = useState(1);
const [uiScale, setUiScale] = useState('1');
const [selId, setSelId] = useState();
const lineReq = useRequest(() => fetchDemoData('overviewLineEntity', ctx.officeCode));
const textReq = useRequest(() => fetchDemoData('overviewTextEntity', ctx.officeCode));
const stReq = useRequest(() => fetchDemoData('overviewStEntity', ctx.officeCode));
//不知道是干什么的函数1
const panToEntent = (extent) => {
const w = outerRef.current?.clientWidth ?? 0;
const h = outerRef.current?.clientHeight ?? 0;
const param = _panToExtent(extent, w, h);
panzoomRef.current?.zoom(param.startScale)
setTimeout(() => panzoomRef.current?.pan(param.startX, param.startY))
}
//不知道是干什么的函数2
const panToPOI = (x, y, width = 100, height = 100) => {
panToEntent([x - width, y - height, x + width, y + height]);
}
useEffect(()=>{
const w = outerRef.current?.clientWidth ?? 0;
const h = outerRef.current?.clientHeight ?? 0;
const param = _panToExtent([0, 0, IMG_W, IMG_H], w, h);
//移动
panzoomRef.current = Panzoom(containerRef.current, {
maxScale: 2,
minScale: 0.2,
...param
});
//缩放
outerRef.current.addEventListener('wheel', panzoomRef.current.zoomWithWheel);
// svgRef.current.addEventListener('click', clickEvent);
// containerRef.current.addEventListener('panzoomzoom', (e) => {
// const scale = e.detail.scale;
// if (scale > 0.6) {
// setLevel(3);
// } else if (scale > 0.4) {
// setLevel(2);
// } else {
// setLevel(1);
// }
// setUiScale((1 / (panzoomRef.current?.getScale() || 1)).toFixed(2));
// })
return () => {
if (panzoomRef.current) {
outerRef.current?.removeEventListener('wheel', panzoomRef.current.zoomWithWheel);
// svgRef.current?.removeEventListener('click', clickEvent);
panzoomRef.current.destroy();
panzoomRef.current = undefined;
}
}
},[])
useEffect(() => {
// 修改三干渠视图位置
// if (ctx.selArea === 'D00000020') {
// panToPOI(4971, 377, 923, 486);
// } else {
// const extent = AREA_OPTIONS.find(o => o.value === ctx.selArea)?.extent;
// if (extent) {
// panToEntent(extent);
// }
// }
// const AREA_OPTIONS = [
// { label: '全部', value: '', roleCode: 'ALL', extent: [611, 69, 6074, 3017] },
// { label: '总干渠', value: 'D00000290', roleCode: 'A06A20', chanCode: '420802001350', extent: [1701, 147, 5120, 666] },
// { label: '二干渠', value: 'D00000300', roleCode: 'A06A21', chanCode: '420802000280', extent: [238, 292, 2945, 2260] },
// { label: '四干渠', value: 'D00000310', roleCode: 'A06A22', chanCode: '420802001147', extent: [4108, 37, 6908, 1979] },
// { label: '三干渠', value: 'D00000020', roleCode: 'A07', chanCode: '420804001388', extent: [3629, 25, 6336, 1992] },
// { label: '水库枢纽', value: 'D00001300', roleCode: 'A06A19', chanCode: '', extent: [1701, 147, 5120, 666] },
// ];
// const extent = AREA_OPTIONS.find(o => o.value === ctx.selArea)?.extent;
// if (extent) {
// panToEntent(extent);
// }
panToEntent([500, 500, 7000, 4500])
}, [ctx.selArea]);
return (
<div ref={outerRef} style={{ height: '100%', backgroundColor: '#0d2d52', position: 'relative' }}>
<div ref={containerRef} style={{ height: '100%' }}>
<svg ref={svgRef} width={IMG_W} height={IMG_H}>
<SvgLineLayer data={lineReq.data} level={level} onClick={(o) => { if (o.chanName) { ctx.setPopChan() } }} />
<SvgTextLayer data={textReq.data} level={level} />
<StLayer
style={{ cursor: 'pointer' }}
onClick={(o) => {
setSelId(o.stcd);
// ctx?.setPopSt(o);
}}
onHover={()=>{
// setHover
}}
data={stReq.data}
level={level}
href={o => `${process.env.PUBLIC_URL}/images/${o.stcd === selId ? 'entSel' : 'ent1'}.png`}
// flowData={gateFlowReq.data} // 传递流量数据
/>
</svg>
</div>
</div>
)
}
export default SvgMap

View File

@ -0,0 +1,105 @@
.flotation {
position: absolute;
top: 0;
left: 0;
width: 0;
height: 0;
.flotation-list {
opacity: .9;
position: absolute;
cursor: pointer;
.rectangle {
border-radius: 10px;
border: 1px solid #0082df;
background-image: linear-gradient(#0e2c74, #9198e5);
color: #fff;
display: flex;
flex-direction: column;
width: 160px;
font-size: 12px;
.title {
display: flex;
padding: 4px 8px;
img {
width: 14px;
height: 16px;
margin-right: 4px;
}
}
.row {
display: flex;
flex-direction: row;
align-items: center;
padding: 0 8px;
line-height: 1;
margin-bottom: 4px;
.key {
width: 40%;
opacity: 0.8;
}
.val {
font-weight: bold;
}
}
}
.triangle {
width: 0;
height: 0;
margin: 0 auto;
border: 5px solid transparent;
border-top: 10px solid #0082df;
border-bottom: none;
}
}
}
.svg_ani_flow {
stroke-dasharray: 10000;
stroke-dashoffset: 50000;
animation: ani_flow-668f1f5c 50s linear infinite;
animation-fill-mode: forwards;
}
.svg_ani_flow_back {
stroke-dasharray: 10000;
stroke-dashoffset: 50000;
animation: ani_flow_back-668f1f5c 50s linear infinite;
animation-fill-mode: forwards;
}
@keyframes ani_flow-668f1f5c {
0% {
stroke-dasharray: 20, 30
}
to {
stroke-dasharray: 23, 30
}
}
@keyframes ani_flow_back-668f1f5c {
0% {
stroke-dasharray: 23, 30
}
to {
stroke-dasharray: 20, 30
}
}
@keyframes rotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}

69
src/views/Home/_.js Normal file
View File

@ -0,0 +1,69 @@
import { useEffect, useMemo, useState } from "react";
import { httpGet3 } from "../../utils/request";
const tabRole = [
{ label: '水质', value: 'D00000290', roleCode: 'A06A20', chanCode: '420802001350', extent: [1701, 147, 5120, 666] },
{ label: '流量', value: 'D00000290', roleCode: 'A06A20', chanCode: '420802001350', extent: [1701, 147, 5120, 666] },
]
export function usePageContext() {
const [filterName, setFilterName] = useState();
const [selArea, setSelArea] = useState(tabRole[0]);
const [stData, setStData] = useState([])
// const [specialStationData, setSpecialStationData] = useState([]);
const dataWithSpecialStation = useMemo(() => {
const kw = (filterName || '').trim().toLowerCase();
if (!kw) return stData;
return stData.filter(o => ((o.mn).toLowerCase()).includes(kw));
}, [stData, filterName])
const fetchSpecialStationData = async () => {
try {
// 获取所有水质数据
const allList = await httpGet3(`/yjt/wq/real/online`);
let data = [];
if (Array.isArray(allList)) {
data = allList;
} else if (allList && typeof allList === 'object') {
data = Object.keys(allList).reduce((acc, statusKey) => {
const arr = Array.isArray(allList[statusKey]) ? allList[statusKey] : [];
return acc.concat(arr.map(item => ({ ...item, status: statusKey })));
}, []);
}
setStData(data.map(o => ({ ...o, name: o.name || o.stationName || o.stnm })));
} catch (error) {
console.log(error);
}
}
useEffect(()=>{
fetchSpecialStationData()
},[])
return {
// reqTm,
// fav,
// dataReq,
// officeCode: user.roleCodes,
tabRole,
selArea,
setSelArea,
dataWithFav: dataWithSpecialStation,
// popSt,
// setPopSt,
// popChan,
// setPopChan,
filterName,
setFilterName,
// filterIrrCode,
// setFilterIrrCode,
// waterTm,
// setWaterTm,
// cntStat,
}
}

56
src/views/Home/gqgs.js Normal file
View File

@ -0,0 +1,56 @@
import { useMemo } from 'react';
import { BarChartOutlined, DownOutlined, UpOutlined } from '@ant-design/icons';
import { DatePicker } from 'antd';
const Panel = ({ ctx }) => {
const countObj = useMemo(() => {
const online = ctx?.dataWithFav.filter(item => {
if (item.status === 'true') {
return item
}
});
const offline = ctx?.dataWithFav.filter(item => {
if (item.status === 'false') {
return item
}
});
return {
online,
offline
}
},[ctx])
return (
<div className='panel-card'>
<div className='title'>
<BarChartOutlined className='icon' />
<div className='text'>{ctx?.selArea?.label == '水质'?"站点状态":"侧站点状态" }</div>
</div>
<div className='body sepline' style={{ height: 161 }}>
<div style={{ display: 'flex', alignItems: 'center', height: '100%', padding: 8,justifyContent:'center' }}>
<div style={{ display: 'flex', alignItems: 'center', marginRight: 24 }}>
<div style={{ width: 80, height: 80, borderRadius: '50%', display: 'flex', alignItems: 'center', justifyContent: 'center', marginRight: 12 }}>
<img src={`${process.env.PUBLIC_URL}/images/online.png`} style={{width:'100%',height:"100%"}}/>
</div>
<div>
<div style={{ fontSize: 13, color: '#cfe6ff' }}>在线站点数量</div>
<div style={{ fontSize: 22, fontWeight: 700, color: '#2ed158',textAlign:'center' }}>{ctx?.selArea?.label == '水质'?countObj.online?.length ?? '-':0}</div>
</div>
</div>
<div style={{ display: 'flex', alignItems: 'center' }}>
<div style={{ width: 80, height: 80, borderRadius: '50%', display: 'flex', alignItems: 'center', justifyContent: 'center', marginRight: 12 }}>
<img src={`${process.env.PUBLIC_URL}/images/offline.png`} style={{width:'100%',height:"100%"}}/>
</div>
<div>
<div style={{ fontSize: 13, color: '#cfe6ff' }}>离线站点数量</div>
<div style={{ fontSize: 22, fontWeight: 700, color: '#ff4d4f',textAlign:'center' }}>{ctx?.selArea?.label == '水质'?countObj.offline?.length ?? '-':0}</div>
</div>
</div>
</div>
</div>
</div>
)
}
export default Panel;

20
src/views/Home/index.js Normal file
View File

@ -0,0 +1,20 @@
import React from 'react'
import SvgMap from './SvgMap'
import { usePageContext } from './_'
import PanelGroup from './PanelGroup'
import './index.less'
const Home = () => {
const ctx = usePageContext();
return (
<div className='home-root'>
<SvgMap ctx={ctx} />
<PanelGroup ctx={ctx} />
</div>
)
}
export default Home

Some files were not shown because too many files have changed in this diff Show More