Commit 59875678 authored by wuhao's avatar wuhao 🎯

aders

parents
Pipeline #1158 failed with stages
# http://editorconfig.org
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
[Makefile]
indent_style = tab
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/npm-debug.log*
/yarn-error.log
/yarn.lock
/package-lock.json
# production
/dist
.history
# misc
.DS_Store
# umi
/src/.umi
/src/.umi-production
/src/.umi-test
/.env.local
registry=https://registry.npmmirror.com
**/*.md
**/*.svg
**/*.ejs
**/*.html
package.json
.umi
.umi-production
.umi-test
{
"singleQuote": true,
"trailingComma": "all",
"printWidth": 80,
"overrides": [
{
"files": ".prettierrc",
"options": { "parser": "json" }
}
]
}
import { defineConfig } from 'umi';
import routes from './routes';
export default defineConfig({
antd: {
dark: false,
},
nodeModulesTransform: {
type: 'none',
},
routes: [
{
path: '/',
component: '@/layouts/index',
routes,
},
],
fastRefresh: {},
theme: {
'primary-color': '#1890ff',
},
ssr: {},
proxy: {
'/website/': {
target: 'http://192.168.40.117:12345/',
changeOrigin: true,
pathRewrite: { '^': '' },
},
'/staticfile/': {
target: 'http://192.168.40.2/',
changeOrigin: true,
pathRewrite: { '^/staticfile': '' },
},
},
});
# umi project
## Getting Started
Install dependencies,
```bash
$ yarn
```
Start the dev server,
```bash
$ yarn start
```
const express = require('express');
const app = express();
const render = require('./dist/umi.server');
const proxy = require('express-http-proxy');
const fs = require('fs');
// 这里简单的用fs读取一下文件,后面直接 扔给前端
const umijs = fs.readFileSync('./dist/umi.js');
const umicss = fs.readFileSync('./dist/umi.css');
const port = 3000;
const domain = 'http://localhost';
app.use(express.static('dist'));
app.use(
'/website',
proxy('http://192.168.40.117:12345', {
proxyReqPathResolver: function (req) {
return '/website' + req.url;
},
}),
);
app.use('/staticfile', proxy('http://192.168.40.2', {}));
// Express
app.use(async (req, res) => {
// 或者从 CDN 上下载到 server 端
// const serverPath = await downloadServerBundle('http://cdn.com/bar/umi.server.js');
/*
这里做了路由判断,更好的方案是用nginx配置静态目录(指向build好的目录,如dist)
或者通过express设置静态目录,umi加入publicPath配置
*/
if (req && req.url === '/umi.css') {
res.setHeader('Content-Type', 'text/css');
res.send(umicss);
} else if (req && req.url === '/umi.js') {
res.setHeader('Content-Type', 'text/js');
res.send(umijs);
} else {
res.setHeader('Content-Type', 'text/html');
const context = {};
const { html, error, rootContainer } = await render({
// 有需要可带上 query
path: req.url,
context,
});
res.send(html);
}
});
app.listen(port, (err) => {
if (err) {
throw err;
}
console.log(`> Ready on port ${port}, ${domain}:${port}`);
});
{
"private": true,
"scripts": {
"start": "umi dev",
"build": "umi build",
"postinstall": "umi generate tmp",
"prettier": "prettier --write '**/*.{js,jsx,tsx,ts,less,md,json}'",
"test": "umi-test",
"test:coverage": "umi-test --coverage"
},
"gitHooks": {
"pre-commit": "lint-staged"
},
"lint-staged": {
"*.{js,jsx,less,md,json}": [
"prettier --write"
],
"*.ts?(x)": [
"prettier --parser=typescript --write"
]
},
"dependencies": {
"@ant-design/pro-layout": "^6.5.0",
"ahooks": "^3.7.2",
"express": "^4.18.2",
"express-http-proxy": "^1.6.3",
"react": "17.x",
"react-dom": "17.x",
"umi": "^3.5.35",
"umi-request": "^1.4.0"
},
"devDependencies": {
"@types/react": "^17.0.0",
"@types/react-dom": "^17.0.0",
"@umijs/preset-react": "1.x",
"@umijs/test": "^3.5.35",
"lint-staged": "^10.0.7",
"prettier": "^2.2.0",
"typescript": "^4.1.2",
"yorkie": "^2.0.0"
}
}
export default [
{
path: '/',
redirect: '/home',
},
{
path: '/home',
name: '首页',
component: '@/pages/index',
},
{
path: '/about',
name: '关于南高',
routes: [
{
path: '/about/insert',
name: '走进南高',
component: '@/pages/index',
},
{
path: '/about/honer',
name: '南高荣誉',
component: '@/pages/index',
},
{
path: '/about/join',
name: '加入南高',
component: '@/pages/index',
},
{
path: '/about/news',
name: '南高资讯',
component: '@/pages/index',
},
{
path: '/about/contact',
name: '联系我们',
component: '@/pages/index',
},
],
},
{
path: '/together',
name: '战略合作',
component: '@/pages/index',
},
{
path: '/factory',
name: '智能工厂解决方案',
routes: [
{
path: '/factory/typea',
name: '工业软件',
type: 'group',
routes: [
{
path: '/factory/typea/mes',
name: 'MES智能制造管理系统',
component: '@/pages/index',
},
{
path: '/factory/typea/wms',
name: 'WMS智能仓储管理系统',
component: '@/pages/index',
},
{
path: '/factory/typea/ems',
name: 'EMS设备运维管理系统',
component: '@/pages/index',
},
{
path: '/factory/typea/iot',
name: 'IOT数据采集系统',
component: '@/pages/index',
},
{
path: '/factory/typea/plm',
name: 'PLM产品生命周期管理系统',
component: '@/pages/index',
},
{
path: '/factory/typea/pdm',
name: 'PDM产品数据管理系统',
component: '@/pages/index',
},
],
},
{
path: '/factory/typeb',
name: '智能硬件',
type: 'group',
routes: [
{
path: '/factory/typeb/datagate',
name: '智能网关',
component: '@/pages/index',
},
],
},
],
},
{
path: '/internet',
name: '工业互联网平台',
component: '@/pages/index',
},
{
path: '/cgx',
name: '产供需平台',
component: '@/pages/index',
routes: [
{
path: '/cgx/cgxpt',
name: '南京智能制造装备产业促进会产供需平台',
component: '@/pages/index',
},
{
path: '/cgx/lim',
name: '江苏省智能装备产业联盟数控机床产供需平台',
component: '@/pages/index',
},
],
},
];
export async function getInitialState() {
return {
a: 1,
};
}
This source diff could not be displayed because it is too large. You can view the blob instead.
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="54" height="54" viewBox="0 0 54 54" fill="none"><defs><rect id="path_0" x="0" y="0" width="8.480446931075607" height="13.999999999999984" /></defs><g opacity="1" transform="translate(0.7084777586314885 0.7080078125) rotate(0 26.16652224136879 26.16652224136879)"><g opacity="1" transform="translate(21.92629877583102 19.166522241368632) rotate(0 4.240223465537803 6.999999999999992)"><mask id="bg-mask-0" fill="white"><use xlink:href="#path_0"></use></mask><g mask="url(#bg-mask-0)" ><path id="路径 1" fill-rule="evenodd" style="fill:#0C64C9" transform="translate(0 0) rotate(0 4.240223465537803 6.999999999999992)" opacity="1" d="M0.98,0.89L0.98,0.89C0.5,1.39 0.49,2.18 0.97,2.69L3.73,5.65C3.78,5.7 3.83,5.76 3.88,5.81L4.35,6.36C4.67,6.73 4.67,7.27 4.35,7.64L3.91,8.16C3.84,8.24 3.77,8.31 3.7,8.38L0.86,11.33C0.38,11.83 0.38,12.61 0.86,13.11L0.86,13.11C1.09,13.34 1.4,13.47 1.72,13.47C2.04,13.47 2.35,13.34 2.58,13.11L6.49,9.06C7.6,7.91 7.61,6.08 6.51,4.92L2.7,0.9C2.48,0.66 2.17,0.53 1.84,0.53C1.52,0.52 1.21,0.66 0.98,0.89Z " /></g></g><path id="矩形 6" style="stroke:#0C64C9; stroke-width:1; stroke-opacity:1; stroke-dasharray:0 0" transform="translate(7.6639969244283 7.6639969244283) rotate(45 18.50252531694049 18.50252531694049)" d="M10,37.01L27.01,37.01C32.53,37.01 37.01,32.53 37.01,27.01L37.01,10C37.01,4.48 32.53,0 27.01,0L10,0C4.48,0 0,4.48 0,10L0,27.01C0,32.53 4.48,37.01 10,37.01Z " /></g></svg>
\ No newline at end of file
html,
body,
#root {
width: 100%;
height: 100%;
}
.ant-menu-item-group-title {
color: rgba(0, 0, 0, 1) !important;
position: relative;
font-weight: bold !important;
&::before {
content: '';
background-color: rgba(31, 108, 232, 0.8);
position: absolute;
left: 8px;
top: 12px;
width: 2px;
height: 14px;
border-radius: 4px;
}
}
.ant-menu-item-group-title + ul {
border-bottom: 1px solid #f0f0f0;
}
.ant-drawer-body {
padding: 0 !important;
}
.center {
display: flex;
justify-content: center;
align-items: center;
}
.bglight {
background-image: linear-gradient(
145deg,
#3d67ff 0%,
#3d67ff 25%,
#f74249 50%,
#3d67ff 75%,
#3d67ff 100%
);
background-size: 400% 400%;
background-position: 0% 64%;
}
@keyframes bgmove {
0% {
background-position: 0% 50%;
}
50% {
background-position: 200% 100%;
}
100% {
background-position: 0% 50%;
}
}
import React, { useState, useEffect, useMemo } from 'react';
import styles from './index.less';
import { Menu, Grid, Drawer, Tooltip } from 'antd';
import { history } from 'umi';
import routes from '../../routes';
import { MenuOutlined, PlayCircleFilled } from '@ant-design/icons';
const { useBreakpoint } = Grid;
const mapTree = (org) => {
const haveChildren = Array.isArray(org.routes) && org.routes.length > 0;
if (!org.name) return;
const children = haveChildren
? {
children: org.routes.map((i) => mapTree(i)),
}
: {};
return {
key: org.path,
label: org.name,
type: org.type,
...children,
};
};
const MenuRender = ({ arrs, mode, activeKey }) => {
return (
<Menu
mode={mode ?? 'horizontal'}
activeKey={activeKey}
items={arrs}
onClick={({ item, key, keyPath, domEvent }) => {
history.push(key);
}}
/>
);
};
function Layout({ children, location }) {
const [collspan, setcollspan] = useState(false);
const screens = useBreakpoint();
const arrs = useMemo(() => {
let arr = [];
routes.map((org) => {
if (org.name) {
arr.push(mapTree(org));
}
});
return arr;
}, []);
return (
<div className={styles.container}>
<Drawer
open={collspan}
title={false}
maskClosable={true}
onClose={() => {
setcollspan(false);
}}
closable={false}
width={260}
>
<MenuRender mode="inline" activeKey={location?.pathname} arrs={arrs} />
</Drawer>
<header>
<div style={{ flex: 1 }}>
{!screens.sm ? (
<img
src={require('@/assets/logo.svg')}
alt=""
style={{ width: '100%' }}
/>
) : (
<img
src={require('@/assets/logo.svg')}
style={{ height: 52 }}
alt=""
/>
)}
</div>
<div className={styles.menu} style={{ flexShrink: 0 }}>
{!screens.xl ? (
<div className={styles.dll}>
<MenuOutlined
onClick={() => {
setcollspan(!collspan);
}}
/>
<Tooltip title="产品演示" placement="bottom">
<PlayCircleFilled style={{ fontSize: 20, color: '#000000' }} />
</Tooltip>
</div>
) : (
<>
<MenuRender
activeKey={location?.pathname}
arrs={arrs}
></MenuRender>
<div
className="center bglight"
style={{
width: 130,
height: 80,
marginRight: -24,
color: '#fff',
cursor: 'pointer',
}}
>
<PlayCircleFilled
style={{ fontSize: 20, color: '#ffffff', marginRight: 6 }}
/>
产品演示
</div>
</>
)}
</div>
</header>
<div className="content">{children}</div>
<footer></footer>
</div>
);
}
export default Layout;
.container {
height: 100%;
li {
span {
text-align: center !important;
}
}
header {
height: 80px;
width: 100%;
padding: 0 24px;
display: flex;
justify-content: space-between;
align-items: center;
img {
height: 65%;
}
.menu {
height: 80px;
display: flex;
justify-content: flex-end;
align-items: flex-end;
> ul {
height: 100% !important;
line-height: 80px !important;
}
}
.dll {
width: 98px;
height: 80px;
padding: 0 16px;
display: flex;
justify-content: space-around;
align-items: center;
margin-right: -24px;
> * {
font-size: 20px;
color: @primary-color;
}
}
}
}
import styles from './index.less';
import { useModel } from 'umi';
import React, { useState, useEffect } from 'react';
import { Carousel } from 'antd';
import { useWindowSize } from '@/utils/windowsize';
import { doFetch } from '@/utils/doFetch';
import { useRequest } from 'ahooks';
// match: 与客户端页面 props 中的 match 保持一致,有当前路由的相关数据。
// isServer:是否为服务端在执行该方法。
// route:当前路由对象
// history:history 对象
function IndexPage({ route }) {
// const { initialState, loading, error, refresh, setInitialState } =
// useModel('@@initialState');
const { width, height } = useWindowSize(); //设备宽高
const { data } = useRequest(async () => {
let res = await doFetch({ url: '/indexPic/list' });
return res?.data?.dataList ?? [];
});
console.log(data);
useEffect(() => {}, []);
return (
<div>
<Carousel autoplay>
{data?.map((it, i) => {
return (
<div key={it.id}>
<div
className={styles.banner}
style={{
width,
height: (980 / 1920) * width,
backgroundImage: `url(${it.picUrl})`,
}}
>
1
</div>
</div>
);
})}
</Carousel>
</div>
);
}
// IndexPage.getInitialProps = async (ctx) => {
// return await doFetch({url:"/indexPic/list"})
// };
export default IndexPage;
.banner {
background: #364d79;
background-size: cover;
background-position: center;
}
import request from './request';
export async function doFetch({ url, params }) {
if (!url) {
return;
}
return request('' + url, {
method: 'post',
data: params,
});
}
export async function postFetch({ url, params }) {
return request(url, {
method: 'post',
data: params,
});
}
export async function getFetch({ url, params }) {
return request(url, {
method: 'get',
params,
});
}
export async function formFetch({ url, params }) {
return request(url, {
method: 'post',
data: params,
type: 'form',
});
}
/**
* request 网络请求工具
* 更详细的 api 文档: https://github.com/umijs/umi-request
*/
import { extend } from 'umi-request';
import { message, notification, Modal } from 'antd';
import { history } from 'umi';
import qs from 'query-string';
const codeMessage = {
200: '服务器成功返回请求的数据。',
201: '新建或修改数据成功。',
202: '一个请求已经进入后台排队(异步任务)。',
204: '删除数据成功。',
400: '发出的请求有错误,服务器没有进行新建或修改数据的操作。',
401: '用户没有权限(令牌、用户名、密码错误)。',
403: '用户得到授权,但是访问是被禁止的。',
404: '发出的请求针对的是不存在的记录,服务器没有进行操作。',
406: '请求的格式不可得。',
410: '请求的资源被永久删除,且不会再得到的。',
422: '当创建一个对象时,发生一个验证错误。',
500: '服务器发生错误,请检查服务器。',
502: '网关错误。',
503: '服务不可用,服务器暂时过载或维护。',
504: '网关超时。',
};
/**
* 异常处理程序
*/
const errorHandler = (error) => {
const { response } = error;
if (response && response.status) {
const errorText = codeMessage[response.status] || response.statusText;
const { status, url } = response;
if (response?.url.indexOf('api/user_token') == -1) {
notification.error({
message: `请求错误 ${status}: ${url}`,
description: errorText,
});
}
} else if (!response) {
if (response?.url.indexOf('api/user_token') == -1) {
notification.error({
description: '您的网络发生异常,无法连接服务器',
message: '网络异常',
});
}
}
return response ? response : {};
};
/**
* 配置request请求时的默认参数
*/
const request = extend({
prefix: '/website', //前缀代理
errorHandler,
// 默认错误处理
credentials: 'include', // 默认请求是否带上cookie
});
// request拦截器, 改变url 或 options.
request.interceptors.request.use(async (url, options) => {
let token = localStorage.getItem('TOKENES');
if (token) {
const headers =
options.type == 'form'
? {
token: token,
}
: {
'Content-Type': 'application/json',
Accept: 'application/json',
token: token,
};
return {
url: url,
options: { ...options, headers: headers, useCache: true, ttl: 2000 },
};
}
});
// response拦截器, 处理response
request.interceptors.response.use(async (response, options) => {
if (options.responseType == 'blob') {
const data = await response.clone().blob();
let blobUrl = window.URL.createObjectURL(data);
const a = document.createElement('a');
a.style.display = 'none';
let temp =
response.headers.get('Content-Disposition').split(';')[1].split('=')[1] ||
'';
let fileDefaultName = decodeURI(temp);
let pathname = '表格';
a.download = fileDefaultName || pathname + '.xls';
a.href = blobUrl;
a.click();
a.remove();
} else {
const data = await response.clone().json();
// 详情返回的response处理
if (data?.code != '0000') {
message.destroy();
message.warn(data?.msg);
if (data?.code == '0001' && window.location.href.indexOf('login') == -1) {
localStorage.clear();
history.replace('/user/login');
}
}
}
return response;
});
export default request;
import { useState, useEffect } from 'react';
export const useWindowSize = () => {
// 第一步:声明能够体现视口大小变化的状态
const [windowSize, setWindowSize] = useState({
width: window.innerWidth,
height: window.innerHeight,
});
// 第二步:通过生命周期 Hook 声明回调的绑定和解绑逻辑
useEffect(() => {
const updateSize = () =>
setWindowSize({
width: window.innerWidth,
height: window.innerHeight,
});
window?.addEventListener('resize', updateSize);
return () => window.removeEventListener('resize', updateSize);
}, []);
return windowSize;
};
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"importHelpers": true,
"jsx": "react-jsx",
"esModuleInterop": true,
"sourceMap": true,
"baseUrl": "./",
"strict": true,
"paths": {
"@/*": ["src/*"],
"@@/*": ["src/.umi/*"]
},
"allowSyntheticDefaultImports": true
},
"include": [
"mock/**/*",
"src/**/*",
"config/**/*",
".umirc.ts",
"typings.d.ts"
],
"exclude": [
"node_modules",
"lib",
"es",
"dist",
"typings",
"**/__test__",
"test",
"docs",
"tests"
]
}
declare module '*.css';
declare module '*.less';
declare module '*.png';
declare module '*.svg' {
export function ReactComponent(
props: React.SVGProps<SVGSVGElement>,
): React.ReactElement;
const url: string;
export default url;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment