Commit cd69671b authored by wuyongsheng's avatar wuyongsheng

Merge branch 'ci' into 'staging'

Ci

See merge request !3
parents ef2c151e eadc095d
FROM nginx:latest
COPY ./build /var/www/v3
COPY ./cert /cert
COPY ./nginx/nginx_test_10005.conf /etc/nginx/nginx.conf
RUN \
mkdir -p /var/log/nginx && \
chmod 777 /var/log/nginx && \
touch /var/log/nginx/error.log && \
chmod 777 /var/log/nginx/error.log && \
touch /var/log/nginx/nginx.pid && \
chmod 777 /var/log/nginx/nginx.pid
EXPOSE 10005
ENTRYPOINT ["nginx","-g","daemon off;"]
\ No newline at end of file
......@@ -9,7 +9,7 @@ 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.
Open [http://localhost:8088](http://localhost:8088) to view it in the browser.
The page will reload if you make edits.\
You will also see any lint errors in the console.
......
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA3s2Tnn2xs2F9GcrS7p6YY/c44qg+n7pv38/zwSAsTZ+KoFnC
uTyuK6U2O/oEy8imkScWUMbhmN0AJreY+szqsGuimrXuFpABUMvr+OF4ZThf8dnj
OBwA3s3hWoO0I83rP+S/5nHfYnm+dJ68DFLDnQB3LcZsb/GiazxKMHzR8mJhovYE
STq4g6te8vzk3++SHJKX4bOXGqA2PdzeEisg/u/Cm5tZh0KgZbRg/JD4vIiRPVnr
aVXcytmYC49uT95sN5mzL2LBiIFJ77zIAaa6WyYn/2Iw8s5uP374NbqsqR/wVAJs
XNMEujWATdwO5eGQSlSESDh7NQkTq9r6amyFlwIDAQABAoIBADTYHYMh3Nvm630K
lizygMJ1CJD5xqCr34z+DZpovxlKFd8iawT0V3sSnGJtUmXjGV6kHq7Z/Pf8suR7
91TE9YUSgmafb/D6BtXbCATntV6MmHUMcNAGFE7EFgcZ5cf4NyvYXYuSxqDcr0eJ
vqBNoQfD7IB255FFhnhYvF/zuvf53E4qi9/m/eQ0AGKogaTtyKsTS5F82JAjappq
4S3UijrY7Waf5F1dGL9z4PwDC1sONsww54BtjUz//eGHkwMTCxO2ZAKKhGoXI3D6
XxeQUDrZzIgKV5/t5n4zV6QW8Y6sWBBrgMQfmzO1Squ9Tzy38itE37MWXY9yK87v
8EW0p4ECgYEA87nUW4AzxEVEnctB0KgHheOBkncCnFlKnerosEOLC/eujeM3kTa0
p6fNRImHjN49nuqg5z/U3iTm+jcJiQQddJPCvBHF630bM2L8to2vVI5xcDrUG4wo
GF2806wDzsOcyDo1z0kGbd+QxYnX5j8Qp+BcNar1ld8s2b9HMSN1748CgYEA6gYB
NsbfM01CLswld1ckTKMQYn0hVTBWmpl79Yk6XcRnJbUj9rzVSD81wv1QLykaj9zO
kDId0hKwsQqVoal2sB4VjbJBrciKXIKCZ9o31Eo8LBPCIeFau+yp73M1IHjZWGBc
eHSiCyOgq/39IHMMvjMLOx19pd2ShYiDdi23hXkCgYB2ADiyfGWT1z2bcDdTQKcz
yayILxqSfCDGSF+UR39gsfBPPf0/T080BOg7EKMSLt+Cu3Jfw+XaD9/MsSzqq5Vf
RdL4n1pF43Jx9LEJ6ZtDwxtlDPZ4x+j5sxijGxtU1hxoTNaUn3R/ach7+3sOPOZh
gRzj1vvELiNW4WckgViuPQKBgQCeleEeuJeqUTGHOuosvA2qLVo+E6OR8gbODzJ0
SkEWJ7DqWZz8aCx0H/mToEtFGiqY0L3d80hIAkhgQNbzTT5TzJ84fVKKrHouhHZQ
YA0zO/cYu27zvJ3a+V6TGFQpJBvNCse/DPJ+b+9CfgSZh71b6oUy0yJBUywmd0L2
w7Y4qQKBgQC6WRgZ6E2I5PJMflLI2YKsz7KrMwvtJMY2mfZhNHup4vDJmc8jhrRF
GkJyZj+8StwCRErl2Z09d5nGzOi/+DHrSQdayfObHAo6NAfTMExaZOaUdhxxrzVi
jT3AWri3AW2+Ei18acGXfVP5fF1nAmPVmVNxRtxFUzBszzaKVpcDSQ==
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIF6jCCBNKgAwIBAgIQBHtGXn1JBnAxkirfAJ6QIjANBgkqhkiG9w0BAQsFADBZ
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMTMwMQYDVQQDEypS
YXBpZFNTTCBUTFMgRFYgUlNBIE1peGVkIFNIQTI1NiAyMDIwIENBLTEwHhcNMjEw
NjA4MDAwMDAwWhcNMjIwNjA4MjM1OTU5WjAXMRUwEwYDVQQDDAwqLmNsb3VkYW0u
Y24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDezZOefbGzYX0ZytLu
nphj9zjiqD6fum/fz/PBICxNn4qgWcK5PK4rpTY7+gTLyKaRJxZQxuGY3QAmt5j6
zOqwa6Kate4WkAFQy+v44XhlOF/x2eM4HADezeFag7Qjzes/5L/mcd9ieb50nrwM
UsOdAHctxmxv8aJrPEowfNHyYmGi9gRJOriDq17y/OTf75Ickpfhs5caoDY93N4S
KyD+78Kbm1mHQqBltGD8kPi8iJE9WetpVdzK2ZgLj25P3mw3mbMvYsGIgUnvvMgB
prpbJif/YjDyzm4/fvg1uqypH/BUAmxc0wS6NYBN3A7l4ZBKVIRIOHs1CROr2vpq
bIWXAgMBAAGjggLuMIIC6jAfBgNVHSMEGDAWgBSkjeW+fHnkcCNtLik0rSNY3PUx
fzAdBgNVHQ4EFgQUC5fZPEyzRt0LXku8OFLtjBUxaUkwIwYDVR0RBBwwGoIMKi5j
bG91ZGFtLmNuggpjbG91ZGFtLmNuMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAU
BggrBgEFBQcDAQYIKwYBBQUHAwIwPgYDVR0gBDcwNTAzBgZngQwBAgEwKTAnBggr
BgEFBQcCARYbaHR0cDovL3d3dy5kaWdpY2VydC5jb20vQ1BTMIGFBggrBgEFBQcB
AQR5MHcwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBPBggr
BgEFBQcwAoZDaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL1JhcGlkU1NMVExT
RFZSU0FNaXhlZFNIQTI1NjIwMjBDQS0xLmNydDAJBgNVHRMEAjAAMIIBfwYKKwYB
BAHWeQIEAgSCAW8EggFrAWkAdgApeb7wnjk5IfBWc59jpXflvld9nGAK+PlNXSZc
JV3HhAAAAXnpYz/4AAAEAwBHMEUCIQDgrYEEPoRY0oRzcpDCu3gW4OJtXzeyQlmo
e25p5o+JSQIgLSgIZWkdHZNVUBsdmi5NY9BbM8D0DCinlrDOLUTaBi0AdwAiRUUH
WVUkVpY/oS/x922G4CMmY63AS39dxoNcbuIPAgAAAXnpY0BOAAAEAwBIMEYCIQDb
UcpTWE+UGxnrWqA1/h28DvhakqEzQqNr1Pf5P31AxwIhAPdmmjrRAvGiqW3RBJVw
RvxmpLGvc12445pw+Xj81T7dAHYAQcjKsd8iRkoQxqE6CUKHXk4xixsD6+tLx2jw
kGKWBvYAAAF56WNAFQAABAMARzBFAiEA+AH8S2VvEdIjgrodGEDiKlTidyKigM4a
WbkEwEWNfLUCICv0w3apBeY8PU5s6SgJEX7WIU/ZPl9QxIjEcUuktORcMA0GCSqG
SIb3DQEBCwUAA4IBAQDNBnMLKBijkBxwbsByUNgVeAzZFsX30ew5fe9ngLngnSa3
LgwRl7tdrG8yBA3rATAu6+WxriQ8/vvWmjqIKAOnvy7/wSEoh+1vk4KAgg8EVghg
xgT0gjeRRw40oDv4wDsWvsOsCMsCZ4r0gS4VvVfywWsnuGWv65qEuHYmrp1ozbvE
Q/8PAJOkJbTnh89ix60khA6GCI66nC4KEgKvR9BGUvzVwiERDlDho8N7jyEOrJOn
LdOdnhiNajDMFkwhjJUY6dYixTM+BwJbR1n2/NoI9Ksv6hWT5chNVnHkPWfr8A+m
bwEc3WpLF3ZO5zx2kuSqVmJ/IHCTvdMhVr3XAHp3
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFUTCCBDmgAwIBAgIQB5g2A63jmQghnKAMJ7yKbDANBgkqhkiG9w0BAQsFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
QTAeFw0yMDA3MTYxMjI1MjdaFw0yMzA1MzEyMzU5NTlaMFkxCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxMzAxBgNVBAMTKlJhcGlkU1NMIFRMUyBE
ViBSU0EgTWl4ZWQgU0hBMjU2IDIwMjAgQ0EtMTCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBANpuQ1VVmXvZlaJmxGVYotAMFzoApohbJAeNpzN+49LbgkrM
Lv2tblII8H43vN7UFumxV7lJdPwLP22qa0sV9cwCr6QZoGEobda+4pufG0aSfHQC
QhulaqKpPcYYOPjTwgqJA84AFYj8l/IeQ8n01VyCurMIHA478ts2G6GGtEx0ucnE
fV2QHUL64EC2yh7ybboo5v8nFWV4lx/xcfxoxkFTVnAIRgHrH2vUdOiV9slOix3z
5KPs2rK2bbach8Sh5GSkgp2HRoS/my0tCq1vjyLJeP0aNwPd3rk5O8LiffLev9j+
UKZo0tt0VvTLkdGmSN4h1mVY6DnGfOwp1C5SK0MCAwEAAaOCAgswggIHMB0GA1Ud
DgQWBBSkjeW+fHnkcCNtLik0rSNY3PUxfzAfBgNVHSMEGDAWgBQD3lA1VtFMu2bw
o+IbG8OXsj3RVTAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwEG
CCsGAQUFBwMCMBIGA1UdEwEB/wQIMAYBAf8CAQAwNAYIKwYBBQUHAQEEKDAmMCQG
CCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wewYDVR0fBHQwcjA3
oDWgM4YxaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0R2xvYmFsUm9v
dENBLmNybDA3oDWgM4YxaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0
R2xvYmFsUm9vdENBLmNybDCBzgYDVR0gBIHGMIHDMIHABgRVHSAAMIG3MCgGCCsG
AQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BTMIGKBggrBgEFBQcC
AjB+DHxBbnkgdXNlIG9mIHRoaXMgQ2VydGlmaWNhdGUgY29uc3RpdHV0ZXMgYWNj
ZXB0YW5jZSBvZiB0aGUgUmVseWluZyBQYXJ0eSBBZ3JlZW1lbnQgbG9jYXRlZCBh
dCBodHRwczovL3d3dy5kaWdpY2VydC5jb20vcnBhLXVhMA0GCSqGSIb3DQEBCwUA
A4IBAQAi49xtSOuOygBycy50quCThG45xIdUAsQCaXFVRa9asPaB/jLINXJL3qV9
J0Gh2bZM0k4yOMeAMZ57smP6JkcJihhOFlfQa18aljd+xNc6b+GX6oFcCHGr+gsE
yPM8qvlKGxc5T5eHVzV6jpjpyzl6VEKpaxH6gdGVpQVgjkOR9yY9XAUlFnzlOCpq
sm7r2ZUKpDfrhUnVzX2nSM15XSj48rVBBAnGJWkLPijlACd3sWFMVUiKRz1C5PZy
el2l7J/W4d99KFLSYgoy5GDmARpwLc//fXfkr40nMY8ibCmxCsjXQTe0fJbtrrLL
yWQlk9VDV296EI/kQOJNLVEkJ54P
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA2h+f/zQBlO2s+HQbpXS1rTjvKuyFAUKwTO8DxshjOpNNQ0gd
ivRxEaraM37BaKkmq+JhtX+a6dt5+sxxXGTexKVP0X8X8hDn+tqHAiwuUr24ktwU
vg3tjAdbAPi4wbjdYIAJib34MqQ8tq+XxZn9m5iqb0+HfxOfs+hSWval4tmHNESQ
HtbHo6ciRRPMIS7gDj05PLaq4uQsFPp29jeP51l3LlvKBbQrtbH98xIGZFL6qv31
DKrD1uiJE97izLpvqN2RFqkfiv0cTH3YiJca7lJheNzC/T516zcK2MBoSbeYe7no
igG/1eYk1OH2Q6tboc9+KxIK1Giou+7SiNaOtwIDAQABAoIBAFIwgXLBr2jlJ/yU
j4hIUl67qc8kQTfI37KVi3g/MLi1IXNdPJiL5AESvlaSCCG+Pw6cZlHkC8TbyPo6
R+rXLWOuoMVhXO3+9dJ9vkqQyEGwMFjSKdS1XdGaQe27Sq7gUDZY+H8ZAGlgnmn9
/zPbgwa6v1ni/zzgcZhyTXnuH3K672Eok6rU0H//6zQWIhx/dUTsZrXAMt2FRKLH
SQGkHERHHsQEs5pS0qnfuUnFRyuAcXevPSgf6c0CYOeHcVYhIqBIf15cB6fg1g6A
7W4gvtrMTDnGw1MXaiUbscxO3nTyawVadH+tUBT/ctVJtudRZGhKQz/WdVa2CHmB
BnAyUtECgYEA98yiTz5IEvkO+pLTnxhnfjheVJFxX5mP530v+bKcFnfkENwvC65q
AcUnqhQqrttPc9pMJam98+O/xyxKiY0/lxZtqxLqJzAPPxb/itDVcOrj6QewgSOm
QUCpAnMO3afHnSg7LG66eU+/uCSxbS7qm9Pc1K+77080jwWayc7YrucCgYEA4VeT
hjCT+ptsbnWOMt07naWwlCZBugwGQHoUtOR4mLvKJZheL6daM4LeAXtIzLpGav6x
z87E1tLhdNBReCkhLT4jn8LYrz1s+HxAVmI+v6iY2rpR/v8r2clXIGwH8JyMTR8j
bTWl5QmoA9elChgVLvrlZGxQGSJdHUHaeZi+N7ECgYEAxbkVxc83aVQrvIrNqwOp
CNDni+klopeAeMCuODppS5BMfZuDOnnoAhOTq6U9zZoW0qVb3y2K8QFINB/GNe1r
0R3HUhrclXpGoBu0ucoalWgHhRhqoRCWBzkV4mt2cC0BHQhN9w0/Y67blo5IuIsY
DlDFwzuZ5MC5emmJcf/Ha/8CgYBO+tzv+XLEMVlt1bIDTdspQ/uB0W7UAIbobmF3
jWRfU+JkDuVkGmnZCBM7vbQkXV10/tPfm/8NtFflE2aakP/Z1Z+yzR4ZPZRF+3ap
UEHh9vusHgXDNDhwWss4x+R4hsX9+d321wjQH/RNdHWZ9hrmnnVsHzJrvMmaCYzD
da+l4QKBgF7iQghdh1pSbQ8J+nqoAlfnl0y6caEJhU8uUrTpGPGdvfkLq6+k1xto
ORTCsIuksaCkj9XoLU3jZ6jt/GzFAnnQvSPTQaclndWOP+EHTdapkJlt6r87Q6Ep
c4rQPtF8IPcAU1lPQ7qXWPr/s5Sch+TdNpccguQIh8rxpO7kNoNI
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIF6TCCBNGgAwIBAgIQAVabY7t0gl1XHkjo1TrjuDANBgkqhkiG9w0BAQsFADBZ
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMTMwMQYDVQQDEypS
YXBpZFNTTCBUTFMgRFYgUlNBIE1peGVkIFNIQTI1NiAyMDIwIENBLTEwHhcNMjEw
NzEzMDAwMDAwWhcNMjIwNzEzMjM1OTU5WjAXMRUwEwYDVQQDDAwqLmNsb3VkYW0u
aW8wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaH5//NAGU7az4dBul
dLWtOO8q7IUBQrBM7wPGyGM6k01DSB2K9HERqtozfsFoqSar4mG1f5rp23n6zHFc
ZN7EpU/RfxfyEOf62ocCLC5SvbiS3BS+De2MB1sA+LjBuN1ggAmJvfgypDy2r5fF
mf2bmKpvT4d/E5+z6FJa9qXi2Yc0RJAe1sejpyJFE8whLuAOPTk8tqri5CwU+nb2
N4/nWXcuW8oFtCu1sf3zEgZkUvqq/fUMqsPW6IkT3uLMum+o3ZEWqR+K/RxMfdiI
lxruUmF43ML9PnXrNwrYwGhJt5h7ueiKAb/V5iTU4fZDq1uhz34rEgrUaKi77tKI
1o63AgMBAAGjggLtMIIC6TAfBgNVHSMEGDAWgBSkjeW+fHnkcCNtLik0rSNY3PUx
fzAdBgNVHQ4EFgQUKNmwoyvcYxknIeWrGgB17wXD1xswIwYDVR0RBBwwGoIMKi5j
bG91ZGFtLmlvggpjbG91ZGFtLmlvMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAU
BggrBgEFBQcDAQYIKwYBBQUHAwIwPgYDVR0gBDcwNTAzBgZngQwBAgEwKTAnBggr
BgEFBQcCARYbaHR0cDovL3d3dy5kaWdpY2VydC5jb20vQ1BTMIGFBggrBgEFBQcB
AQR5MHcwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBPBggr
BgEFBQcwAoZDaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL1JhcGlkU1NMVExT
RFZSU0FNaXhlZFNIQTI1NjIwMjBDQS0xLmNydDAJBgNVHRMEAjAAMIIBfgYKKwYB
BAHWeQIEAgSCAW4EggFqAWgAdwApeb7wnjk5IfBWc59jpXflvld9nGAK+PlNXSZc
JV3HhAAAAXqdvbcqAAAEAwBIMEYCIQDbgUtt0UX/SwKc/RVzBoQWUksj4dXdnMfE
WMUbaqYdVgIhAKy+vcX+xm8IZ/YpJfP1+R7xiKaBkLtzgTwxhfUR5615AHYAUaOw
9f0BeZxWbbg3eI8MpHrMGyfL956IQpoN/tSLBeUAAAF6nb23YQAABAMARzBFAiEA
nGcPuCMkeH32PEkVEb2qTnWA87gTMrIEJr8X4iRfqRYCIHrUzK4lTm4x4fFturkm
NaeblQ4RZEQxLmd6Xa/FTllaAHUAQcjKsd8iRkoQxqE6CUKHXk4xixsD6+tLx2jw
kGKWBvYAAAF6nb23BAAABAMARjBEAiAybogxPq7CD6FJQA8sx/9IhSif7YH+fPqO
r5khx0tB/wIgSj6wuEjJdJU5OXnIXQ7xO0OfGQL5tjhXtCTKgJsWos0wDQYJKoZI
hvcNAQELBQADggEBAIzs+SXR6E97fcOcayJjEVHS6WnWsw3fOE985WP5wIWytkFO
MnvTgKbJ1A6z9yKHzqaDDtBMsaNLZlQpgQZ2mcQnWq/+Vr0W39Jh/afmDNnofngU
rrA6Oo32Pu1CYs+geqJMOW6iz3rIZGHjDVHPKN8fy7HlsuWaUc9Pfq6yuzLS4x87
idOlYR0NDRiOo+6xchCGpgtYFcOjLBSxzkLIcxAs2ifIxj7GUz44WVnXzB+PWaFd
642likJEWvt+SObOuVI7O3X/qjjVyCJSB5q5FLCHCUA0IFF8qh9AtB4vYPzvF/eZ
OEvSpC8V9T5jfPzOU6tDf+iOE6azMB4kVNdh7d0=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFUTCCBDmgAwIBAgIQB5g2A63jmQghnKAMJ7yKbDANBgkqhkiG9w0BAQsFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
QTAeFw0yMDA3MTYxMjI1MjdaFw0yMzA1MzEyMzU5NTlaMFkxCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxMzAxBgNVBAMTKlJhcGlkU1NMIFRMUyBE
ViBSU0EgTWl4ZWQgU0hBMjU2IDIwMjAgQ0EtMTCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBANpuQ1VVmXvZlaJmxGVYotAMFzoApohbJAeNpzN+49LbgkrM
Lv2tblII8H43vN7UFumxV7lJdPwLP22qa0sV9cwCr6QZoGEobda+4pufG0aSfHQC
QhulaqKpPcYYOPjTwgqJA84AFYj8l/IeQ8n01VyCurMIHA478ts2G6GGtEx0ucnE
fV2QHUL64EC2yh7ybboo5v8nFWV4lx/xcfxoxkFTVnAIRgHrH2vUdOiV9slOix3z
5KPs2rK2bbach8Sh5GSkgp2HRoS/my0tCq1vjyLJeP0aNwPd3rk5O8LiffLev9j+
UKZo0tt0VvTLkdGmSN4h1mVY6DnGfOwp1C5SK0MCAwEAAaOCAgswggIHMB0GA1Ud
DgQWBBSkjeW+fHnkcCNtLik0rSNY3PUxfzAfBgNVHSMEGDAWgBQD3lA1VtFMu2bw
o+IbG8OXsj3RVTAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwEG
CCsGAQUFBwMCMBIGA1UdEwEB/wQIMAYBAf8CAQAwNAYIKwYBBQUHAQEEKDAmMCQG
CCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wewYDVR0fBHQwcjA3
oDWgM4YxaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0R2xvYmFsUm9v
dENBLmNybDA3oDWgM4YxaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0
R2xvYmFsUm9vdENBLmNybDCBzgYDVR0gBIHGMIHDMIHABgRVHSAAMIG3MCgGCCsG
AQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BTMIGKBggrBgEFBQcC
AjB+DHxBbnkgdXNlIG9mIHRoaXMgQ2VydGlmaWNhdGUgY29uc3RpdHV0ZXMgYWNj
ZXB0YW5jZSBvZiB0aGUgUmVseWluZyBQYXJ0eSBBZ3JlZW1lbnQgbG9jYXRlZCBh
dCBodHRwczovL3d3dy5kaWdpY2VydC5jb20vcnBhLXVhMA0GCSqGSIb3DQEBCwUA
A4IBAQAi49xtSOuOygBycy50quCThG45xIdUAsQCaXFVRa9asPaB/jLINXJL3qV9
J0Gh2bZM0k4yOMeAMZ57smP6JkcJihhOFlfQa18aljd+xNc6b+GX6oFcCHGr+gsE
yPM8qvlKGxc5T5eHVzV6jpjpyzl6VEKpaxH6gdGVpQVgjkOR9yY9XAUlFnzlOCpq
sm7r2ZUKpDfrhUnVzX2nSM15XSj48rVBBAnGJWkLPijlACd3sWFMVUiKRz1C5PZy
el2l7J/W4d99KFLSYgoy5GDmARpwLc//fXfkr40nMY8ibCmxCsjXQTe0fJbtrrLL
yWQlk9VDV296EI/kQOJNLVEkJ54P
-----END CERTIFICATE-----
error_log /var/log/nginx/error.log warn;
pid /var/log/nginx/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for" "$upstream_addr"';
access_log /var/log/nginx/access.log main;
sendfile on;
client_max_body_size 100M;
#tcp_nopush on;
server {
listen 10005;
root /var/www;
index index.html index.htm;
resolver 127.0.0.11 valid=10s;
location / {
try_files $uri /v3/index.html;
index /v3/index.html;
#add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
}
location ^~ /accounts/ {
set $accountservice "http://account-service:6000";
proxy_pass $accountservice;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location ^~ /uaa/ {
set $authservice "http://auth-service:5000";
proxy_pass $authservice;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location ^~ /intelligroup/ {
set $intelliservice "http://intelligroup-service:8000";
proxy_pass $intelliservice;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location ^~ /vps/ {
set $intellivps "http://intelligroup-vps:10000";
proxy_pass $intellivps;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location /zhihu-xg/ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_pass https://xg.zhihu.com/;
}
location ^~ /c3app/ {
set $c3app "http://c3-app:6600";
proxy_pass $c3app;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location ^~ /ecc/ {
set $ecc "http://c3-ecc-app:6700";
proxy_pass $ecc;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location ^~ /ip/ {
set $c3ip "http://c3-ip-app:6800";
proxy_pass $c3ip;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location ^~ /angelia/ {
set $angelia "http://angelia:10002";
proxy_pass $angelia;
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location ^~ /message/ {
set $message "http://message-service:10005";
proxy_pass $message;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location ^~ /intellicost/ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
set $intellicost "http://intellicost-app:10001";
proxy_pass $intellicost;
}
location ^~ /c3oc/ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
set $c3oc "http://c3-oc-app:6602";
proxy_pass $c3oc;
}
location ^~ /c3ce/ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
set $c3ce "http://c3-ce-app:6601";
proxy_pass $c3ce;
}
location ^~ /ceadmin/ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
set $ceadmin "http://c3-ceadmin-app:7701";
proxy_pass $ceadmin;
}
location ^~ /imapp/ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_connect_timeout 4s; #配置点1
proxy_read_timeout 180s; #配置点2,如果没效,可以考虑这个时间配置长一点
proxy_send_timeout 12s; #配置点3
set $imapp "http://im-app:8081";
proxy_pass $imapp;
}
location ^~ /cpp/ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
set $cpp "http://cp-project-app:8801";
proxy_pass $cpp;
}
location ^~ /dataset/ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
set $dataset "http://dataset-app:7081";
proxy_pass $dataset;
}
location ~ /grafana/(.*) {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
set $grafana "http://grafana:3000";
proxy_pass $grafana;
}
location ^~ /config/ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
set $config "http://config:6666";
proxy_pass $config;
}
location ~ /grafana/(.*) {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
set $grafana "http://grafana:3000";
proxy_pass $grafana;
}
location ^~ /wordpress/ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
set $wordpress "http://cloudam-wordpress";
#rewrite ^/wordpress/(.*)$ /$1 break;
proxy_pass $wordpress;
}
location ^~ /wp-content/ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
set $wordpress "http://cloudam-wordpress";
#rewrite ^/wordpress/(.*)$ /$1 break;
proxy_pass $wordpress;
}
location ^~ /wp-admin/ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
set $wordpress "http://cloudam-wordpress";
#rewrite ^/wordpress/(.*)$ /$1 break;
proxy_pass $wordpress;
}
location ^~ /wp-includes/ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
set $wordpress "http://cloudam-wordpress";
#rewrite ^/wordpress/(.*)$ /$1 break;
proxy_pass $wordpress;
}
location ^~ /wp-json/ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
set $wordpress "http://cloudam-wordpress";
#rewrite ^/wordpress/(.*)$ /$1 break;
proxy_pass $wordpress;
}
location ~ .*\.php$ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
set $wordpress "http://cloudam-wordpress";
#rewrite ^/wordpress/(.*)$ /$1 break;
proxy_pass $wordpress;
}
# Any route containing a file extension (e.g. /devicesfile.js)
location ~ ^.+\..+$ {
try_files $uri =404;
}
}
}
This diff is collapsed.
......@@ -8,7 +8,9 @@
"@emotion/react": "^11.9.0",
"@emotion/styled": "^11.8.1",
"@mui/icons-material": "^5.6.2",
"@mui/lab": "^5.0.0-alpha.84",
"@mui/material": "^5.6.4",
"@mui/styles": "^5.8.0",
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.3",
"@svgr/webpack": "^5.5.0",
"@testing-library/jest-dom": "^5.16.4",
......@@ -28,6 +30,7 @@
"browserslist": "^4.18.1",
"camelcase": "^6.2.1",
"case-sensitive-paths-webpack-plugin": "^2.4.0",
"classnames": "^2.3.1",
"css-loader": "^6.5.1",
"css-minimizer-webpack-plugin": "^3.2.0",
"dotenv": "^10.0.0",
......@@ -43,11 +46,13 @@
"jest": "^27.4.3",
"jest-resolve": "^27.4.2",
"jest-watch-typeahead": "^1.0.0",
"lodash": "^4.17.21",
"mini-css-extract-plugin": "^2.4.5",
"mobx": "^6.5.0",
"mobx-react": "^7.4.0",
"mobx-react-lite": "^3.4.0",
"mockjs": "^1.1.0",
"moment": "^2.29.3",
"postcss": "^8.4.4",
"postcss-flexbugs-fixes": "^5.0.2",
"postcss-loader": "^6.2.1",
......@@ -78,9 +83,11 @@
"workbox-webpack-plugin": "^6.4.1"
},
"scripts": {
"dev": "set \"REACT_APP_PROXY=http://47.57.4.97\" && npm start",
"relrese-cn": "set \"REACT_APP_PROXY=http://47.75.104.171\" && npm start",
"relrese-en": "set \"REACT_APP_PROXY=http://47.57.235.86\" && npm start",
"start:master": "set \"REACT_APP_ENV=master\" && npm start",
"start:dev-cn": "set \"REACT_APP_ENV=dev-cn\" && npm start",
"start:dev-en": "set \"REACT_APP_ENV=dev-en\" && npm start",
"start:release-cn": "set \"REACT_APP_ENV=release-cn\" && npm start",
"start:release-en": "set \"REACT_APP_ENV=release-en\" && npm start",
"start": "node scripts/start.js",
"build": "node scripts/build.js",
"test": "node scripts/test.js"
......
......@@ -42,7 +42,7 @@ if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
}
// Tools like Cloud9 rely on this.
const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3000;
const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 8088;
const HOST = process.env.HOST || "0.0.0.0";
if (process.env.HOST) {
......
import { BACKEND_API_URI_PREFIX } from "./api_prefix";
const RESTAPI = {
API_USER_FETCH: `${BACKEND_API_URI_PREFIX}/accounts/current`, //获取账户信息
// API_PRIVILEGE_LIST: `${BACKEND_API_URI_PREFIX}/routes/privilege/list`, //
API_PROJECT_LIST: `${BACKEND_API_URI_PREFIX}/cpp/project/list`, //获取产品下的项目列表
API_PROJECT_ADD: `${BACKEND_API_URI_PREFIX}/cpp/project/add`, //新增项目
API_PROJECT_UPDATE: `${BACKEND_API_URI_PREFIX}/cpp/project/update`, //新增项目
API_PROJECT_DELETE: `${BACKEND_API_URI_PREFIX}/cpp/project/delete`, //删除项目
API_PROJECT_GET: `${BACKEND_API_URI_PREFIX}/cpp/project/get`, //获取项目信息
API_CPCE_HPCZONE: `${BACKEND_API_URI_PREFIX}/cpp/cpce/hpczone`, //获取计算区列表
};
export default RESTAPI;
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-05-31 10:17:48
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-01 16:57:23
* @FilePath: /bkunyun/src/api/api_prefix.ts
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
// const AWSPREFIX = "/0xaws";
// const PRIVATIZATIONPREFIX = "/fileserver"
// const PRIVATIZATION_API_URI_PREFIX = process.env.NODE_ENV === 'development' ? "http://123.57.131.31" : "";
let BACKEND_API_URI_PREFIX = "";
console.log('process.env.REACT_APP_ENV: ', process.env.REACT_APP_ENV)
switch (process.env.REACT_APP_ENV) {
case "dev-cn":
BACKEND_API_URI_PREFIX = "http://47.57.4.97";
break;
case "dev-en":
BACKEND_API_URI_PREFIX = "http://47.75.109.159";
break;
case "release-cn":
BACKEND_API_URI_PREFIX = "http://47.75.104.171";
break;
case "release-en":
BACKEND_API_URI_PREFIX = "http://47.57.235.86";
break;
case "global":
BACKEND_API_URI_PREFIX = "https://www.cloudam.io";
break;
default:
if (['www.bkunyun.com'].includes(window.location.host)) {
BACKEND_API_URI_PREFIX = "https://www.bkunyun.com";
} else {
BACKEND_API_URI_PREFIX = "http://47.57.4.97";
}
break;
}
export { BACKEND_API_URI_PREFIX } // 导出放在11行后面,避免发布时被替换
import request from "@/utils/axios/service";
import Api from "./api_manager";
function current() {
return request({
url: "/accounts/current",
url: Api.API_USER_FETCH,
method: "get",
});
}
......@@ -14,4 +15,17 @@ function menu() {
});
}
export { current, menu };
type projectListParams = {
product: string;
name?: string;
};
function product(params: projectListParams) {
return request({
url: Api.API_PROJECT_LIST,
method: "get",
params,
});
}
export { current, menu, product };
import axios, { AxiosInstance, AxiosResponse, AxiosRequestConfig } from 'axios';
import React, { useContext } from 'react';
import _ from 'lodash';
import localStorageKey from '@/utils/localStorageKey';
import { BACKEND_API_URI_PREFIX } from './api_prefix';
import qs from 'qs';
export interface IAxiosRequestConfig extends AxiosRequestConfig {
/** 取消全局错误提示 */
noToastWarn?: boolean;
/** 允许截流 */
allowIntercept?: boolean;
}
export type HttpConfig = IAxiosRequestConfig;
export interface IRequest {
method: <T>(config: AxiosRequestConfig) => Promise<T>;
config: IAxiosRequestConfig;
}
export class Http {
instance: AxiosInstance;
/** 请求方法集合
* key-唯一标识
*/
requestList: {
[key: string]: IRequest[];
} = {};
/** 请求锁 */
isRequesting: { [key: string]: boolean } = {};
constructor(defaultConfig: IAxiosRequestConfig = {}) {
this.instance = axios.create(defaultConfig);
}
/** 更新回调函数数组 */
setRequestList = (key: string, params: IRequest) => {
this.requestList = {
[key]: this.requestList[key] ? [...this.requestList[key], params] : [params],
};
};
/** 处理成功请求
* first-首次请求 last-最后一次请求 key-请求路径
*/
handleSuccess = ({ key, resolve, res: firstRes }: { key: string; resolve: any; res: any }) => {
this.isRequesting[key] = false;
const requestLen = this.requestList[key]?.length || 0;
if (requestLen >= 2) {
const first = this.requestList[key][0];
const last = this.requestList[key][requestLen - 1];
if (!_.isEqual(first.config, last.config)) {
// @ts-ignore
last.method<T>(last.config).then((lastRes: AxiosResponse<any>) => {
resolve(lastRes?.data);
});
} else {
resolve(firstRes.data);
}
} else {
resolve(firstRes.data);
}
this.requestList[key] = [];
};
/** 请求截流
* 当多次发起请求并且第一次请求未结束时,若参数完全一致只允许首次请求,不一致在首次结束后,进行最后一次
*/
requestInterception<T>(config: IAxiosRequestConfig): Promise<T> {
const requestMethod = this.instance.request;
const key: string = config.url || '';
return new Promise((resolve, reject) => {
if (this.isRequesting[key]) {
this.setRequestList(key, { method: requestMethod, config });
} else {
this.isRequesting[key] = true;
this.setRequestList(key, { method: requestMethod, config });
requestMethod<T>(config)
.then((res: AxiosResponse<any>) => {
/** 可以接入日志监控 */
// const { code, msg = '' } = res.data;
// if (code !== 200 && code !== 0) {
// this.handleSentry({
// ...sentryParams,
// msg,
// code,
// });
// }
this.handleSuccess({
res,
key,
resolve,
});
})
.catch((e) => {
/** 可以接入日志监控 */
// this.handleSentry({
// ...sentryParams,
// msg: e.error || '',
// code: e.code || '',
// });
reject(e);
});
}
});
}
request<T>(config: IAxiosRequestConfig) {
const requestMethod = this.instance.request<T>(config);
return requestMethod.then((res) => res.data);
}
getConfig(config?: IAxiosRequestConfig, data?: any ) {
let Authorization: string =
`Bearer ` +
JSON.parse(localStorage.getItem(localStorageKey.TOKEN) || "{}")
?.access_token || "";
const newConfig = {
headers:{Authorization, ...config?.headers, },...config
}
if (
newConfig?.headers['Content-Type'] === "application/x-www-form-urlencoded"
) {
console.log(222)
newConfig.data = qs.stringify(data);
}
return newConfig
}
get<T>(url: string, config?: IAxiosRequestConfig) {
if (config?.allowIntercept) {
return this.requestInterception<T>({ url: `${BACKEND_API_URI_PREFIX}${url}`, method: 'GET', ...this.getConfig(config) });
}
return this.request<T>({ url: `${BACKEND_API_URI_PREFIX}${url}`, method: 'GET', ...this.getConfig(config) });
}
patch<T>(url: string, data?: any, config?: IAxiosRequestConfig) {
return this.request<T>({ method: 'PATCH', url: `${BACKEND_API_URI_PREFIX}${url}`, data, ...this.getConfig(config, data) });
}
put<T>(url: string, data?: any, config?: IAxiosRequestConfig) {
return this.request<T>({ method: 'PUT', url: `${BACKEND_API_URI_PREFIX}${url}`, data, ...this.getConfig(config, data) });
}
post<T>(url: string, data?: any, config?: IAxiosRequestConfig) {
if (config?.allowIntercept) {
return this.requestInterception<T>({ method: 'POST', url: `${BACKEND_API_URI_PREFIX}${url}`, data, ...this.getConfig(config, data) });
}
return this.request<T>({ method: 'POST', url: `${BACKEND_API_URI_PREFIX}${url}`, data, ...this.getConfig(config, data) });
}
del<T>(url: string, config?: IAxiosRequestConfig) {
return this.request<T>({ method: 'DELETE', url: `${BACKEND_API_URI_PREFIX}${url}`, ...this.getConfig(config) });
}
}
const rawHttp = new Http();
const HttpContext = React.createContext<Http>(rawHttp);
export const HttpProvider = HttpContext.Provider;
export function useHttp(raw?: boolean) {
const httpClient = useContext(HttpContext);
return raw ? rawHttp : httpClient;
}
export default rawHttp;
export interface IResponse<T> {
errorCode: number;
massage: string;
data: T;
}
import request from "@/utils/axios/service";
import Api from "./api_manager";
function current() {
return request({
url: Api.API_USER_FETCH,
method: "get",
});
}
function menu() {
return request({
url: "/accounts/menu-mock",
method: "get",
});
}
type projectListParams = {
product: string;
name?: string;
};
// 查询当前用户可以看到的项目列表
const product = (params: projectListParams) => {
return request({
url: Api.API_PROJECT_LIST,
method: "get",
params,
});
};
type addProjectParams = {
product: string;
name: string;
zoneId: string;
desc?: string;
};
// 新增项目
const addProject = (params: addProjectParams) => {
console.log("params", params);
return request({
url: Api.API_PROJECT_ADD,
method: "post",
data: params,
});
};
// 获取计算区列表
const hpczone = () => {
return request({
url: Api.API_CPCE_HPCZONE,
method: "get",
});
};
type getProjectParams = {
id: string;
};
// 获取项目信息
const getProject = (params: getProjectParams) => {
return request({
url: Api.API_PROJECT_GET,
method: "get",
params,
});
};
// 修改项目信息
const updateProject = (params: addProjectParams) => {
return request({
url: Api.API_PROJECT_UPDATE,
method: "put",
data: params,
});
};
type deleteProjectParams = {
id: string;
};
// 删除项目
const deleteProject = (params: deleteProjectParams) => {
return request({
url: Api.API_PROJECT_DELETE,
method: "delete",
params,
});
};
export {
current,
menu,
product,
hpczone,
addProject,
getProject,
updateProject,
deleteProject,
};
<?xml version="1.0" encoding="UTF-8"?>
<svg width="119px" height="27px" viewBox="0 0 119 27" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>北鲲云logo_</title>
<defs>
<polygon id="path-1" points="0 0 48.1108878 0 48.1108878 15.686238 0 15.686238"></polygon>
</defs>
<g id="上线UI" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="项目数据" transform="translate(-22.000000, -126.000000)">
<g id="北鲲云logo_" transform="translate(22.000000, 126.000000)">
<path d="M39.4160116,16.129697 C39.4160116,16.129697 35.8617144,13.8283505 33.4579761,12.2907723 C28.9557704,9.40936365 23.6308733,7.1439019 18.3225279,8.06213677 C26.4412077,9.70205286 31.7163057,16.3593295 33.7815258,18.3160056 L39.4160116,16.129697 Z" id="Fill-1" fill="#00CCCC"></path>
<g id="编组" transform="translate(14.396480, 11.313762)">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<g id="Clip-4"></g>
<path d="M48.0952038,2.94059755 C47.9699866,1.52219197 42.7661328,-0.875142368 34.133199,0.326625947 C22.1729422,1.99090819 16.0112489,8.31030749 0,6.18735083 C1.95554711,7.54284743 4.32848486,8.9664216 7.15004559,10.3960504 C19.48984,16.6470768 31.0858156,17.1005826 39.1217368,13.1107354 C47.1700358,9.11409527 48.2650386,4.87054473 48.0952038,2.94059755" id="Fill-3" fill="#0066FF" mask="url(#mask-2)"></path>
</g>
<path d="M62.4671581,14.1301955 C61.7737139,18.9901359 51.2048072,18.696856 40.3666116,9.85976834 C32.7395892,3.64093481 23.2271126,-1.58789445 14.4590306,0.446310336 C25.6419334,2.01593376 32.3365914,9.37082082 38.7199335,14.9810912 C46.2154059,21.5668938 53.9951356,24.1833758 59.460938,20.439553 C60.4101419,19.6080025 62.9146296,16.8747106 62.4671581,14.1301955" id="Fill-5" fill="#00CCCC"></path>
<path d="M7.09564087,13.7262489 C4.47658657,12.8839183 3.05976124,13.7402779 0.197468951,13.2445374 C4.61835546,15.7899884 9.81846712,16.953657 14.3965228,17.5010832 C15.7251204,17.6613092 17.2485962,18.0390584 19.2958253,17.911173 C17.9112398,17.7583308 16.4329573,17.0332531 14.4588435,15.2970537 C11.4244136,12.6275568 6.81541343,8.7833159 0,8.16869809 C3.95369685,9.94698441 4.97615999,12.1334407 7.09564087,13.7262489" id="Fill-7" fill="#0066FF"></path>
<polygon id="Fill-9" fill="#383838" points="71.061145 15.6809167 66.4009066 15.6809167 66.4009066 17.4498996 71.061145 17.4498996 71.061145 21.6295074 66.4022019 23.8370811 66.4022019 25.9291739 71.061145 23.7202712 71.061145 26.5542766 72.9264494 26.5542766 72.9264494 10.7614638 71.061145 10.7614638"></polygon>
<path d="M77.0271253,18.7894179 C78.638541,18.152206 80.3829461,17.3311404 81.6354058,16.5226271 L81.6354058,14.4321586 C80.2424725,15.2641521 78.6894915,16.0248191 77.0271253,16.6874309 L77.0271253,10.7612865 L75.1593742,10.7612865 L75.1593742,24.7223552 C75.1593742,26.0394566 75.6313134,26.5543947 77.0271253,26.5543947 L81.312,26.5543947 L81.9457142,24.7864455 L77.0271253,24.7864455 L77.0271253,18.7894179 Z" id="Fill-11" fill="#383838"></path>
<path d="M119,18.2076574 L119,16.4386746 L103.455797,16.4386746 L103.455797,18.2076574 L107.60394,18.2076574 L104.584623,24.7863717 C104.158308,25.712581 104.774463,26.5233094 105.825568,26.5233094 L110.452271,26.5233094 L112.186458,26.5233094 L116.818198,26.5233094 C117.866137,26.5233094 118.480996,25.712581 118.055978,24.7863717 L116.119141,20.5657106 L114.011606,20.5657106 L115.947723,24.7863717 L112.186458,24.7863717 L110.452271,24.7863717 L106.693453,24.7863717 L109.712051,18.2076574 L119,18.2076574 Z" id="Fill-13" fill="#383838"></path>
<polygon id="Fill-15" fill="#383838" points="105.226296 13.0111687 117.227284 13.0111687 117.227284 11.2430719 105.226296 11.2430719"></polygon>
<polygon id="Fill-17" fill="#383838" points="84.9240411 26.5543947 91.756438 25.2734733 91.756438 23.6560036 84.9240411 24.9375157"></polygon>
<path d="M85.4223047,21.8090786 L85.4223047,23.1721065 L86.8565453,23.1721065 L87.7559502,23.1721065 L89.1582388,23.1721065 L91.5228288,23.1721065 L91.5228288,22.2983214 L91.5228288,21.8090786 L91.5228288,16.9229999 C91.5228288,15.9544083 91.1781217,15.5771021 90.1524921,15.5771021 L90.0053979,15.5771021 C90.5071302,14.5320155 91.0382238,13.1189262 91.0382238,12.6321938 C91.0382238,12.1339428 90.9124309,12.011669 90.3514003,12.011669 L88.0882795,12.011669 C88.1976646,11.597149 88.2833017,11.1795279 88.3218743,10.7611684 L86.7638558,10.7611684 C86.472402,12.2972699 86.0371643,13.4113201 84.8300418,14.7759724 L84.8300418,16.7469729 C85.039025,16.5895528 85.2320322,16.4222385 85.4223047,16.2546289 L85.4223047,21.8090786 Z M86.8565453,18.7082269 L87.7556623,18.7082269 L87.7556623,16.94013 L86.8565453,16.94013 L86.8565453,18.7082269 Z M86.8565453,21.8090786 L87.7556623,21.8090786 L87.7556623,20.0408341 L86.8565453,20.0408341 L86.8565453,21.8090786 Z M89.1582388,21.8090786 L90.0898835,21.8090786 L90.0898835,20.0408341 L89.1582388,20.0408341 L89.1582388,21.8090786 Z M89.1582388,18.7082269 L90.0898835,18.7082269 L90.0898835,16.94013 L89.1582388,16.94013 L89.1582388,18.7082269 Z M87.5797826,13.4073329 L89.4175967,13.4073329 C89.1968115,14.0652191 88.9093876,14.7452563 88.4394634,15.5771021 L87.7559502,15.5771021 L86.8565453,15.5771021 L86.3920903,15.5771021 L86.1148854,15.5771021 C86.7294571,14.9084357 87.2169406,14.1749406 87.5797826,13.4073329 L87.5797826,13.4073329 Z" id="Fill-18" fill="#383838"></path>
<path d="M100.016915,17.9521229 L100.016915,17.0775995 L100.016915,16.5896857 L100.016915,12.4161324 C100.016915,11.4485746 99.672784,11.07053 98.6462909,11.07053 L93.7327395,11.07053 L93.2675648,11.07053 L92.2987867,11.07053 L92.2987867,16.5896857 L92.2987867,17.9521229 L93.7327395,17.9521229 L100.016915,17.9521229 Z M93.7327395,13.8296648 L98.5844019,13.8296648 L98.5844019,12.4332626 L93.7327395,12.4332626 L93.7327395,13.8296648 Z M93.7327395,16.5896857 L98.5844019,16.5896857 L98.5844019,15.1929881 L93.7327395,15.1929881 L93.7327395,16.5896857 Z" id="Fill-19" fill="#383838"></path>
<polygon id="Fill-20" fill="#383838" points="93.7327971 22.1619743 96.2745621 22.1619743 96.2745621 20.7989464 93.7327971 20.7989464 93.7327971 18.7250174 92.2988443 18.7250174 92.2988443 20.7989464 92.2988443 22.1619743 92.2988443 25.191352 92.2988443 26.5543799 93.7327971 26.5543799 96.0143407 26.5543799 96.5008166 25.191352 93.7327971 25.191352"></polygon>
<path d="M98.2526771,22.4462166 C99.1657551,22.1132125 99.9252622,21.7852293 100.735432,21.3871011 L100.735432,19.9441817 C99.9100058,20.3545668 99.1425827,20.6785628 98.2526771,21.0013774 L98.2526771,18.7251355 L96.8180047,18.7251355 L96.8180047,25.2083049 C96.8180047,26.1780779 97.1634315,26.5542027 98.1902124,26.5542027 L100.546023,26.5542027 L101.020553,25.1914701 L98.2526771,25.1914701 L98.2526771,22.4462166 Z" id="Fill-21" fill="#383838"></path>
</g>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="220px" height="143px" viewBox="0 0 220 143" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>编组 6</title>
<defs>
<rect id="path-1" x="0" y="0" width="72.6" height="77" rx="2.2"></rect>
<filter x="-17.2%" y="-16.2%" width="139.9%" height="137.7%" filterUnits="objectBoundingBox" id="filter-2">
<feOffset dx="2" dy="2" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
<feGaussianBlur stdDeviation="4.5" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0.0553718645 0 0 0 0 0.196954257 0 0 0 0.1 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix>
</filter>
</defs>
<g id="上线UI" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="未创建项目" transform="translate(-720.000000, -376.000000)">
<g id="编组-6" transform="translate(720.000000, 376.000000)">
<rect id="矩形" x="0" y="0" width="220" height="143"></rect>
<g id="img_启动ssh" transform="translate(13.200000, 17.600000)">
<g id="编组-7">
<ellipse id="椭圆形" fill="#F3F9FF" fill-rule="nonzero" opacity="0.55971" cx="90.11849" cy="61.6" rx="90.11849" ry="61.6"></ellipse>
<g id="矩形" transform="translate(16.418490, 12.100000)" fill="#F2F2F5" fill-rule="nonzero">
<rect id="矩形" x="1.95399252e-15" y="0" width="149.6" height="100.1" rx="2.2"></rect>
</g>
<path d="M16.41849,14.3 C16.41849,13.08494 17.40343,12.1 18.61849,12.1 L163.8186,12.1 C165.033,12.1 166.0186,13.08494 166.0186,14.3 L166.0186,24.2 L16.41849,24.2 L16.41849,14.3 Z" id="矩形备份-9" fill="#D9DDE3" fill-rule="nonzero"></path>
<rect id="矩形备份-15" fill="#FFFFFF" fill-rule="nonzero" x="30.71849" y="40.7" width="123.2" height="64.9" rx="1.1"></rect>
<rect id="矩形_2" fill-opacity="0.159801" fill="#136EFA" fill-rule="nonzero" x="36.21849" y="44" width="11" height="11"></rect>
<rect id="矩形备份-2" fill-opacity="0.159801" fill="#86A8DD" fill-rule="nonzero" x="76.91849" y="68.2" width="42.9" height="4.4" rx="1.1"></rect>
<rect id="矩形备份-4" fill-opacity="0.159801" fill="#86A8DD" fill-rule="nonzero" x="76.91849" y="90.2" width="42.9" height="4.4" rx="1.1"></rect>
<rect id="矩形备份-3" fill-opacity="0.159801" fill="#86A8DD" fill-rule="nonzero" x="60.41849" y="68.2" width="11" height="4.4" rx="1.1"></rect>
<rect id="矩形备份-5" fill-opacity="0.159801" fill="#86A8DD" fill-rule="nonzero" x="60.41849" y="90.2" width="11" height="4.4" rx="1.1"></rect>
<rect id="矩形备份" fill-opacity="0.235003" fill="#02CDD1" fill-rule="nonzero" x="50.51849" y="44" width="11" height="11"></rect>
<rect id="矩形备份-34" fill="#FFFFFF" fill-rule="nonzero" x="30.71849" y="28.6" width="123.2" height="8.8" rx="1.1"></rect>
<circle id="椭圆形备份-11" fill="#FFFFFF" fill-rule="nonzero" cx="37.31849" cy="18.7" r="2.2"></circle>
<circle id="椭圆形备份-13" fill="#FFFFFF" fill-rule="nonzero" cx="48.31849" cy="18.7" r="2.2"></circle>
<circle id="椭圆形备份-12" fill="#FFFFFF" fill-rule="nonzero" cx="26.31849" cy="18.7" r="2.2"></circle>
<rect id="矩形备份-21" fill="#4C93FF" fill-rule="nonzero" x="34.01849" y="31.9" width="17.6" height="2.2"></rect>
<rect id="矩形备份-35" fill="#4C93FF" fill-rule="nonzero" x="129.7186" y="33" width="17.6" height="1.65"></rect>
<g id="编组-6" transform="translate(116.518600, 35.200000)" fill-rule="nonzero">
<g id="矩形">
<use fill="black" fill-opacity="1" filter="url(#filter-2)" xlink:href="#path-1"></use>
<use fill="#FFFFFF" xlink:href="#path-1"></use>
</g>
</g>
<circle id="椭圆形_2" stroke-opacity="0.346236" stroke="#136EFA" stroke-width="2.2" cx="43.91849" cy="71.5" r="7.7"></circle>
<circle id="椭圆形备份" fill-opacity="0.753196" fill="#18B267" fill-rule="nonzero" cx="43.91849" cy="92.4" r="7.7"></circle>
<path d="M51.61849,70.4 C51.61849,66.75493 48.66356,63.8 45.01849,63.8" id="形状" stroke="#136EFA" stroke-width="3.3"></path>
<polyline id="路径-7" stroke="#FFFFFF" stroke-width="1.1" points="39.8134 92.9005 42.69518 95.94827 48.19518 90.44827"></polyline>
</g>
<g id="编组备份" transform="translate(131.918600, 59.400000)">
<path d="M16.9103,27.88181 L15.3142,33.44319 L10.5765,33.44319 C10.3422,33.44319 10.1519,33.59356 10.1519,33.77902 L10.1519,34.77463 C10.1519,34.96009 10.3422,35.11079 10.5765,35.11079 L31.5436,35.11079 C31.7768,35.11079 31.9671,34.96009 31.9671,34.77463 L31.9671,33.75636 C31.9671,33.57112 31.7768,33.42075 31.5436,33.42075 L26.1778,33.42075 L24.3529,27.83671 L16.9103,27.88181 Z" id="Fill-1" fill="#136EFA"></path>
<path d="M39.9179,28.787 L1.8447,28.787 C0.825,28.787 0,27.96112 0,26.94219 L0,1.84481 C0,0.82588 0.825,0 1.8447,0 L39.9179,0 C40.9365,0 41.7626,0.82588 41.7626,1.84481 L41.7626,26.94219 C41.7626,27.96112 40.9365,28.787 39.9179,28.787 Z" id="Fill-3" fill="#136EFA"></path>
<polygon id="Fill-5" fill="#FFFFFF" opacity="0.881487" points="1.6357 24.90576 40.0433 24.90576 40.0433 1.41724 1.6357 1.41724"></polygon>
<path d="M21.5248,26.78984 C21.5248,27.12897 21.2509,27.40364 20.911,27.40364 C20.5722,27.40364 20.2972,27.12897 20.2972,26.78984 C20.2972,26.45071 20.5722,26.17604 20.911,26.17604 C21.2509,26.17604 21.5248,26.45071 21.5248,26.78984 Z" id="Fill-7" fill="#EFEFEF"></path>
</g>
</g>
</g>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="32px" height="32px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>编组 18备份 3</title>
<g id="上线UI" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="编组-18备份-3">
<rect id="矩形" fill="#FFFFFF" x="0" y="0" width="32" height="32" rx="4"></rect>
<g id="编组-18备份" transform="translate(6.000000, 6.000000)">
<rect id="矩形" x="0" y="0" width="20" height="20"></rect>
<g id="编组-17" transform="translate(1.666667, 1.800000)">
<path d="M0,12.3158333 L0,6.76916667 C0,6.11833333 0.7125,5.71916667 1.2675,6.05833333 L7.10083333,9.62333333 C7.34916667,9.77416667 7.5,10.0433333 7.5,10.3341667 L7.5,15.8808333 C7.5,16.5316667 6.7875,16.9308333 6.2325,16.5916667 L0.399166667,13.0266667 C0.150833333,12.8758333 0,12.6066667 0,12.3158333 Z" id="路径" fill="#A8CAFF" fill-rule="nonzero"></path>
<path d="M16.6666667,11.9933333 L16.6666667,7.79416667 C16.6666667,6.89833333 16.6666667,6.45 16.4533333,6.2125 C16.3308333,6.07583333 16.1658333,5.98333333 15.985,5.95 C15.6708333,5.89166667 15.2883333,6.12583333 14.5241667,6.5925 L9.84083333,9.455 L9.84083333,9.455 C9.5725,9.61833333 9.43916667,9.7 9.34666667,9.81666667 C9.29166667,9.88583333 9.24833333,9.96333333 9.21833333,10.0458333 C9.16666667,10.1858333 9.16666667,10.3425 9.16666667,10.6566667 L9.16666667,14.8558333 C9.16666667,15.7516667 9.16666667,16.2 9.38,16.4375 C9.5025,16.5741667 9.6675,16.6666667 9.84833333,16.7 C10.1625,16.7583333 10.545,16.5241667 11.3091667,16.0575 L15.9925,13.195 C16.2608333,13.0316667 16.3941667,12.95 16.4866667,12.8333333 C16.5416667,12.7641667 16.585,12.6866667 16.615,12.6041667 C16.6666667,12.4641667 16.6666667,12.3075 16.6666667,11.9933333 Z" id="路径" fill="#A8CAFF" fill-rule="nonzero"></path>
<path d="M2.47083333,3.315 L7.91083333,0.115 C8.17166667,-0.0383333333 8.495,-0.0383333333 8.75583333,0.115 L14.1958333,3.315 C14.7433333,3.6375 14.7433333,4.42916667 14.1958333,4.75166667 L8.75583333,7.95166667 C8.495,8.105 8.17166667,8.105 7.91083333,7.95166667 L2.47083333,4.75166667 C1.92333333,4.42916667 1.92333333,3.6375 2.47083333,3.315 Z" id="路径" fill="#A8CAFF" fill-rule="nonzero"></path>
<circle id="椭圆形" fill="#1370FF" fill-rule="nonzero" cx="14.1666667" cy="13.2" r="3.33333333"></circle>
<line x1="14.1666667" y1="13.2" x2="14.1666667" y2="11.5333333" id="路径" stroke="#FFFFFF" stroke-width="0.8125" stroke-linecap="round"></line>
<line x1="14.1666667" y1="13.2" x2="15.4166667" y2="13.2" id="路径" stroke="#FFFFFF" stroke-width="0.8125" stroke-linecap="round"></line>
</g>
</g>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>编组 18</title>
<g id="上线UI" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="编组-18">
<rect id="矩形" x="0" y="0" width="24" height="24"></rect>
<g id="编组-17" transform="translate(2.000000, 2.160000)">
<path d="M0,14.779 L0,8.123 C0,7.342 0.855,6.863 1.521,7.27 L8.521,11.548 C8.819,11.729 9,12.052 9,12.401 L9,19.057 C9,19.838 8.145,20.317 7.479,19.91 L0.479,15.632 C0.181,15.451 0,15.128 0,14.779 Z" id="路径" fill="#AFCEFF" fill-rule="nonzero"></path>
<path d="M20,14.392 L20,9.353 C20,8.278 20,7.74 19.744,7.455 C19.597,7.291 19.399,7.18 19.182,7.14 C18.805,7.07 18.346,7.351 17.429,7.911 L11.809,11.346 L11.809,11.346 C11.487,11.542 11.327,11.64 11.216,11.78 C11.15,11.863 11.098,11.956 11.062,12.055 C11,12.223 11,12.411 11,12.788 L11,17.827 C11,18.902 11,19.44 11.256,19.725 C11.403,19.889 11.601,20 11.818,20.04 C12.195,20.11 12.654,19.829 13.571,19.269 L19.191,15.834 C19.513,15.638 19.673,15.54 19.784,15.4 C19.85,15.317 19.902,15.224 19.938,15.125 C20,14.957 20,14.769 20,14.392 Z" id="路径" fill="#AFCEFF" fill-rule="nonzero"></path>
<path d="M2.965,3.978 L9.493,0.138 C9.806,-0.046 10.194,-0.046 10.507,0.138 L17.035,3.978 C17.692,4.365 17.692,5.315 17.035,5.702 L10.507,9.542 C10.194,9.726 9.806,9.726 9.493,9.542 L2.965,5.702 C2.308,5.315 2.308,4.365 2.965,3.978 Z" id="路径" fill="#AFCEFF" fill-rule="nonzero"></path>
<circle id="椭圆形" fill="#1370FF" fill-rule="nonzero" cx="17" cy="15.84" r="4"></circle>
<line x1="17" y1="15.84" x2="17" y2="13.84" id="路径" stroke="#FFFFFF" stroke-linecap="round"></line>
<line x1="17" y1="15.84" x2="18.5" y2="15.84" id="路径" stroke="#FFFFFF" stroke-linecap="round"></line>
</g>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>1.Base基础/Icon图标/项目设置</title>
<defs>
<filter color-interpolation-filters="auto" id="filter-1">
<feColorMatrix in="SourceGraphic" type="matrix" values="0 0 0 0 0.540000 0 0 0 0 0.564000 0 0 0 0 0.600000 0 0 0 1.000000 0"></feColorMatrix>
</filter>
</defs>
<g id="1.Base基础/Icon图标/项目设置" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<rect id="背景" x="0" y="0" width="16" height="16"></rect>
<g filter="url(#filter-1)" id="项目设置">
<g>
<path d="M10.3115139,0.785133195 C10.3755597,0.771624135 10.4453689,0.766989913 10.5042749,0.794023758 L10.496,0.792 L12.4222041,1.92660078 C12.4559203,1.95719461 12.4812649,1.99554138 12.4995296,2.03712459 L12.521778,2.10136218 C12.5433438,2.18324054 12.5426377,2.27315196 12.5086525,2.35408221 L12.5086525,2.35408221 L12.5048006,2.36325497 L12.500855,2.37339637 C12.4840295,2.41651602 12.2821914,2.9537808 12.2821914,3.4239819 C12.2821914,4.19023092 12.5792307,4.88335657 13.0540612,5.3859324 C13.5439168,5.90441126 14.2215221,6.22104975 14.9662484,6.22104975 L14.9662484,6.22104975 L14.9972506,6.22104975 C15.0498002,6.28382486 15.076073,6.37642377 15.0946517,6.48033289 C15.1008851,6.51473263 15.25,7.34188133 15.25,8.00533082 C15.25,8.66737979 15.1010676,9.49361375 15.0943199,9.53058939 C15.07605,9.63286911 15.0492782,9.72511901 14.9979973,9.78866221 L14.9979973,9.78866221 L14.9662682,9.78866221 C14.2215791,9.78866221 13.5440039,10.1052781 13.0541588,10.6236657 C12.5792668,11.1262288 12.2822113,11.819322 12.2822113,12.5854135 C12.2822113,13.0633674 12.4859773,13.5981268 12.5029718,13.6411469 L12.5029718,13.6411469 L12.5074956,13.6526223 C12.5434026,13.7339976 12.5443228,13.8251291 12.5223924,13.9079504 C12.5028075,13.9819135 12.4646577,14.0530337 12.4018898,14.099455 L12.405,14.095 L10.4481974,15.2366664 C10.4348404,15.2411364 10.4210591,15.2444698 10.4069281,15.2466857 L10.3635604,15.25 C10.263522,15.25 10.1638019,15.2086135 10.1012748,15.1361523 C9.8023742,14.7872629 8.74070743,13.8890234 7.95899092,13.8890234 C7.23777174,13.8890234 6.20467319,14.6831976 5.82852375,15.113358 C5.78299038,15.1660371 5.71513977,15.1953819 5.64752747,15.2103769 C5.5856678,15.2240961 5.51805495,15.2283952 5.4681655,15.2052094 L5.4681655,15.2052094 L5.464,15.203 L3.57644234,14.0819598 C3.54295021,14.0517742 3.51787907,14.0137663 3.49982514,13.9725262 L3.47783167,13.9088156 C3.45618706,13.8264678 3.45718182,13.735983 3.49128245,13.654389 L3.49128245,13.654389 L3.49560429,13.6438226 L3.50193727,13.6273674 C3.53876372,13.5297751 3.71780868,13.0304496 3.71780868,12.5853924 C3.71780868,11.8193033 3.42075488,11.1262121 2.94586849,10.6236497 C2.45602443,10.1052579 1.77845122,9.7886411 1.03377167,9.7886411 L1.03377167,9.7886411 L1.00292788,9.7886411 C0.950315899,9.72573378 0.923953458,9.6326991 0.904129254,9.52195387 C0.897650311,9.48798028 0.75,8.66482749 0.75,8.0053097 C0.75,7.34441337 0.897848614,6.52032512 0.905715983,6.47853298 C0.923936126,6.37654964 0.950558339,6.28454366 1.00153983,6.22107084 L1.00153983,6.22107084 L1.03377167,6.22107084 C1.7784884,6.22107084 2.45609161,5.9044315 2.94594621,5.38594835 C3.4207711,4.88337328 3.71780868,4.19024958 3.71780868,3.42400299 C3.71780868,3.02238874 3.57391765,2.58082274 3.51757676,2.42371732 L3.49612978,2.36618463 L3.49315408,2.35869169 C3.45683118,2.27204258 3.45656197,2.18287001 3.47809083,2.10170557 C4.57078234,1.37491171 5.22597891,1.07614779 5.67360535,0.949157118 C5.79924532,0.913513324 5.89595722,0.889926603 5.97304559,0.890276597 C6.30133364,1.23618208 7.30122443,2.03357391 8.0410091,2.03357391 C8.79391996,2.03357391 9.82900874,1.20312298 10.1257116,0.879260616 C10.1726744,0.827482687 10.2425344,0.7996829 10.3115139,0.785133195 Z" id="路径" stroke="#8A9099" stroke-width="1.5" fill-rule="nonzero"></path>
<circle id="椭圆形备份" stroke="#8A9099" stroke-width="1.5" cx="8" cy="8" r="2.45"></circle>
</g>
</g>
</g>
</svg>
\ No newline at end of file
/* 修改滚动条样式 */
div::-webkit-scrollbar,
main::-webkit-scrollbar {
width: 8px;
height: 5px !important;
}
div::-webkit-scrollbar-track,
main::-webkit-scrollbar-track {
background-color: #fff;
-webkit-border-radius: 2em;
-moz-border-radius: 2em;
border-radius: 2em;
}
div::-webkit-scrollbar-thumb,
main::-webkit-scrollbar-thumb {
background-color: #d8d8d8;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
height: 5px !important;
}
body,
h1,
h2,
h3,
h4,
h5,
h6,
hr,
p,
blockquote,
dl,
dt,
dd,
ul,
ol,
li,
pre,
form,
fieldset,
legend,
button,
input,
textarea,
th,
td {
margin: 0;
padding: 0;
}
body,
button,
input,
select,
textarea {
font: 12px/1.5tahoma, arial, \5b8b\4f53;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-size: 100%;
}
address,
cite,
dfn,
em,
var {
font-style: normal;
}
code,
kbd,
pre,
samp {
font-family: couriernew, courier, monospace;
}
small {
font-size: 12px;
}
ul,
ol {
list-style: none;
}
a {
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
sup {
vertical-align: text-top;
}
sub {
vertical-align: text-bottom;
}
legend {
color: #000;
}
fieldset,
img {
border: 0;
}
button,
input,
select,
textarea {
font-size: 100%;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
input::-webkit-input-placeholder {
color: #c2c6cc;
}
input::-moz-placeholder {
/* Mozilla Firefox 19+ */
color: #c2c6cc;
}
input:-moz-placeholder {
/* Mozilla Firefox 4 to 18 */
color: #c2c6cc;
}
input:-ms-input-placeholder {
/* Internet Explorer 10-11 */
color: #c2c6cc;
}
.infoList {
background-color: #fff;
}
.infoListLi {
display: flex;
justify-content: flex-start;
align-items: flex-start;
font-size: 14px;
line-height: 22px;
margin-bottom: 24px;
}
.infoListLiLabel {
width: 80px;
color: #8a9099;
margin-right: 24px;
}
.infoListLiValue {
color: #1e2633;
width: 460px;
}
import style from "./InformationDisplay.module.css";
import React from "react";
type InfoLi = {
label: string | number;
value: string | number;
};
type InfoList = Array<InfoLi>;
type InformationDisplayProps = {
infoList: InfoList;
};
const InformationDisplay = (props: InformationDisplayProps) => {
const { infoList } = props;
return (
<div className={style.infoList}>
{infoList.map((item) => {
return (
<div className={style.infoListLi} key={item.label}>
<div className={style.infoListLiLabel}>{item.label}</div>
<div className={style.infoListLiValue}>{item.value}</div>
</div>
);
})}
</div>
);
};
export default InformationDisplay;
import InformationDisplay from "./InformationDisplay";
export default InformationDisplay;
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-01 16:53:15
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-04 15:00:09
* @FilePath: /bkunyun/src/components/Material.Ui/Button.jsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import React from "react";
import PropTypes from "prop-types";
import { makeStyles } from "@mui/styles";
import { Typography, Button, Menu, MenuItem } from "@mui/material";
const useStyles = makeStyles({
root: { backgroundColor: "#136EFA", boxShadow: "none !important", color: "#ffffff", "&:hover": { backgroundColor: "#0055D9" } },
containedSecondary: { backgroundColor: "#D62C1F", boxShadow: "none !important", "&:hover": { backgroundColor: "#D82C1F" } },
outlined: { backgroundColor: '#FFFFFF', border: "1px solid #136EFA", boxShadow: "none !important", color: "#136EFA", "&:hover": { backgroundColor: "rgba(19, 110, 250, 0.1)" } },
outlinedSecondary: { border: "1px solid #D62C1F", color: "#D62C1F", "&:hover": { border: "1px solid #D62C1F", backgroundColor: "rgba(214, 44, 31, 0.1)" } },
label: { "& p": { fontSize: "13px" } },
text: { backgroundColor: 'transparent', boxShadow: "none !important" },
textPrimary: { color: "#136EFA", "&:hover": { backgroundColor: "#E8F1FF" } },
textSecondary: { color: "#F44335", "&:hover": { backgroundColor: "rgba(244, 67, 53, 0.1)" } },
sizeSmall: { "& p": { fontSize: "12px" } },
sizeLarge: { "& p": { fontSize: "14px" } },
menuItemRoot: {}
})
const ButtonComponent = (props) => {
const classes = useStyles();
const { img, select, selectCallBack, text, size, click, variant, color, disabled, disableElevation, disableFocusRipple, btnStyle = {}, fontSize = '' } = props;
const [anchorEl, setAnchorEl] = React.useState(null);
const defultClick = (event) => event && event.stoppropagation && event.stoppropagation()
// 更多按钮 点击 弹出菜单
const handleClick = (event) => setAnchorEl(event.currentTarget);
// 关闭更多 menu 弹框
const handleClose = () => setAnchorEl(null);
// 选择更多按钮回调
const handleCloseOption = (item, key) => {
setAnchorEl(null);
selectCallBack && selectCallBack(item, key)
};
return (
<>
<Button
size={size || "medium"}
variant={variant || "contained"}
color={color || "primary"}
disabled={disabled || false}
disableElevation={disableElevation || false}
disableFocusRipple={disableFocusRipple || false}
classes={{
root: btnStyle.root || classes.root,
label: btnStyle.label || classes.label,
disabled: btnStyle.disabled || classes.disabled,
containedSecondary: btnStyle.containedSecondary || classes.containedSecondary,
outlined: btnStyle.outlined || classes.outlined,
outlinedSecondary: btnStyle.outlinedSecondary || classes.outlinedSecondary,
text: btnStyle.text || classes.text,
textPrimary: btnStyle.textPrimary || classes.textPrimary,
textSecondary: btnStyle.textSecondary || classes.textSecondary,
sizeSmall: btnStyle.sizeSmall || classes.sizeSmall,
sizeLarge: btnStyle.sizeLarge || classes.sizeLarge,
}}
style={{...props.style}}
onClick={select ? handleClick : (click || defultClick)}
>
{img || ''}
<Typography style={{ fontSize: fontSize }}>{text || ""}</Typography>
</Button>
<Menu
id="simple-menu"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleClose}
>
{
select && select.length > 0 && select.map((item, key) => {
return (
<MenuItem
key={key}
classes={{ root: classes.menuItemRoot }}
onClick={() => handleCloseOption(item, key)}>
{item.text || ""}
</MenuItem>
)
})
}
</Menu>
</>
)
}
ButtonComponent.propTypes = {
size: PropTypes.oneOf(["large", "medium", "small"]),
variant: PropTypes.oneOf(["contained", "outlined", "text"]),
color: PropTypes.oneOf(["default", "inherit", "primary", "secondary"]),
disabled: PropTypes.bool,
disableElevation: PropTypes.bool,
disableFocusRipple: PropTypes.bool,
text: PropTypes.string,
onClick: propTypes.func.isRequired,
};
export default ButtonComponent;
\ No newline at end of file
import 'date-fns';
import React, { useState } from 'react';
import { Grid, Typography } from '@material-ui/core';
import DateFnsUtils from '@date-io/date-fns';
import {
MuiPickersUtilsProvider,
KeyboardDatePicker,
} from '@material-ui/pickers';
import makeStyles from "@material-ui/styles/makeStyles";
import frLocale_cn from "date-fns/locale/zh-CN";
import frLocale_en from "date-fns/locale/en-US";
import { isEn } from "../../../commons/utils/helper.js";
const frLocale = isEn() ? frLocale_en : frLocale_cn
const useStyles = makeStyles({
dateInputBox: {
width: "8.125rem",
boxSizing: "border-box",
},
dateInputBody: {
height: "36px !important",
},
root: {
margin: "0",
background: "#FFFFFF",
borderRadius: "4px",
border: "1px solid #D8D8D8",
},
input: {
fontSize: "0.8125rem",
padding: "8px 0 8px 8px",
marginRight: "-10px"
},
label: {
opacity: "0.3",
},
rootButton: {
background: "none",
backgroundColor: "none",
'&:hover': {
background: "none",
backgroundColor: "none"
},
'&:before': {
background: "none",
backgroundColor: "none"
},
'&:hover:before': {
background: "none",
backgroundColor: "none"
},
'&:after': {
background: "none",
backgroundColor: "none"
}
},
underline: {
border: "none",
content: "",
borderBottom: "none",
'&:before': {
border: "none",
content: "",
borderBottomStyle: "none !important",
borderBottom: "none",
},
'&:hover:before': {
border: "none",
content: "",
borderBottom: "none",
},
'&:after': {
border: "none",
content: "",
borderBottom: "none",
}
},
calendar_body: {
display: 'flex',
marginLeft: "-0.5rem",
alignItems: "center",
justifyContent: "center",
marginRight: "10px",
height: "36px",
marginLeft: "10px"
},
lineFiltrate: {
width: '1rem',
height: "1px",
backgroundColor: "#D8D8D8",
margin: "0 0.3125rem"
},
})
export default function MaterialUIPickers(props) {
const { startTime, endTime, DateChange, lastDate } = props;
const [openDatePicker, setOpenDatePicker] = useState({
one: false,
two: false,
})
const classes = useStyles()
const openCalendar = (type, date) => {
setOpenDatePicker({
one: type === 'start' ? date : openDatePicker[`${type === 'start' ? 'one' : 'two'}`],
two: type === 'end' ? date : openDatePicker[`${type === 'start' ? 'one' : 'two'}`],
})
};
const closeCalendar = () => {
setOpenDatePicker({
one: false,
two: false,
})
};
const handleDateChange = (type, date) => {
let d = new Date(date);
DateChange(type, d)
setOpenDatePicker({
one: false,
two: false,
})
}
const Calendar = (type) => {
return (
<Grid container item className={classes.dateInputBox}>
<MuiPickersUtilsProvider utils={DateFnsUtils} locale={frLocale} >
<Grid container justifycontent="space-around" className={classes.dateInputBody}>
<KeyboardDatePicker
disableToolbar
variant="inline"
open={openDatePicker[`${type === 'start' ? 'one' : 'two'}`]}
format={isEn() ? "MM/dd/yyyy" : "yyyy-MM-dd"}
disableFuture
minDate={lastDate ? new Date(lastDate) : new Date("1900-01-01")}
margin="normal"
id="date-picker-inline"
onClick={() => openCalendar(type, true)}
onOpen={() => openCalendar(type, true)}
onClose={() => closeCalendar()}
value={type === 'start' ? startTime : endTime}
onChange={(date) => handleDateChange(type, date)}
InputProps={{
classes: {
input: classes.input,
underline: classes.underline
},
}}
classes={{
root: classes.root
}}
KeyboardButtonProps={{
'aria-label': 'change date',
classes: {
root: classes.rootButton,
label: classes.label
},
}}
/>
</Grid>
</MuiPickersUtilsProvider>
</Grid>
)
}
return (
<Grid className={classes.calendar_body}>
{Calendar('start')}
<Typography className={classes.lineFiltrate}></Typography>
{Calendar('end')}
</Grid>
);
}
\ No newline at end of file
import React from 'react';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import { Radio } from "@material-ui/core";
import Checkbox from '@material-ui/core/Checkbox';
import PropTypes from "prop-types";
import makeStyles from "@material-ui/styles/makeStyles";
const useStyles = makeStyles({
label: { color: "#383838", fontSize: "14px" },
root: { marginRight: 0 },
radioRoot: { color: "#c9c9c9" },
radioChecked: { color: "#136EFA !important" },
})
const CheckBoxComponent = props => {
const { defaultChecked = false, checkChange, label, color, id, checkBoxStyle = {}, size, disabled, labelPlacement, controllChecked, controllCheckChange, controll, radio, show = true } = props;
const [checked, setChecked] = React.useState(defaultChecked);
const classes = useStyles()
const handleChange = (event) => {
setChecked(event.target.checked);
checkChange && checkChange(event.target.checked)
};
const controllHandleChange = (event) => {
controllCheckChange(event.target.checked)
};
if (!show) return ""
if (controll) {
return (
<FormControlLabel
control={
radio ?
<Radio size={'small'}
classes={{ root: classes.radioRoot, checked: classes.radioChecked }}
checked={controllChecked} onChange={controllHandleChange} /> :
<Checkbox
checked={controllChecked}
onChange={controllHandleChange}
name={id || "name"}
color={color || "primary"}
disabled={disabled || false}
size={size || "medium"}
/>
}
label={label || ""}
labelPlacement={labelPlacement || "end"}
classes={{
label: checkBoxStyle.label || classes.label,
root: checkBoxStyle.root || classes.root,
}}
/>
)
}
return (
<FormControlLabel
control={
<Checkbox
checked={checked}
onChange={handleChange}
name={id || "name"}
color={color || "primary"}
disabled={disabled || false}
size={size || "medium"}
/>
}
label={label || ""}
labelPlacement={labelPlacement || "end"}
classes={{
label: checkBoxStyle.label || classes.label,
root: checkBoxStyle.root || classes.root,
}}
/>
)
}
CheckBoxComponent.propTypes = {
size: PropTypes.oneOf(["medium", "small"]),
disabled: PropTypes.oneOf([true, false]),
};
export default CheckBoxComponent
\ No newline at end of file
import React from "react";
import PropTypes from "prop-types";
import makeStyles from "@material-ui/styles/makeStyles";
import { Typography, Button, Menu, MenuItem } from "@material-ui/core";
import ArrowDropDownIcon from '@material-ui/icons/ArrowDropDown';
import CheckboxComponent from "@/commons/components/Material.Ui/Checkbox"
import Text from "@/commons/components/Material.Ui/Text"
import { isEn } from "@/commons/utils/helper";
const useStyles = makeStyles({
root: { backgroundColor: "#136EFA", boxShadow: "none !important", color: "#ffffff", "&:hover": { backgroundColor: "#0055D9" } },
containedSecondary: { backgroundColor: "#D62C1F", boxShadow: "none !important", "&:hover": { backgroundColor: "#D82C1F" } },
outlined: { backgroundColor: '#FFFFFF', border: "1px solid #136EFA", boxShadow: "none !important", color: "#136EFA", "&:hover": { backgroundColor: "rgba(19, 110, 250, 0.1)" } },
outlinedSecondary: { border: "1px solid #D62C1F", color: "#D62C1F", "&:hover": { border: "1px solid #D62C1F", backgroundColor: "rgba(214, 44, 31, 0.1)" } },
label: { "& p": { fontSize: "13px" } },
text: { backgroundColor: 'transparent', boxShadow: "none !important" },
textPrimary: { color: "#136EFA", "&:hover": { backgroundColor: "#E8F1FF" } },
textSecondary: { color: "#F44335", "&:hover": { backgroundColor: "rgba(244, 67, 53, 0.1)" } },
sizeSmall: { "& p": { fontSize: "12px" } },
sizeLarge: { "& p": { fontSize: "14px" } },
menuItemRoot: { width: "110px" },
textStyle: { padding: "8px 22px", borderRight: "1px solid rgb(0,44,112,0.2)" },
textStyle_en: { padding: "8px 16px", borderRight: "1px solid rgb(0,44,112,0.2)" },
checkBoxBody: { width: "100%", marginLeft: "0px" }
})
const ButtonComponent = (props) => {
const classes = useStyles();
const { subText, Checked, selectCallBack, text, size, click, variant, color, disabled, disableElevation, disableFocusRipple, btnStyle = {}, fontSize, subClick } = props;
const [anchorEl, setAnchorEl] = React.useState(null);
const defultClick = (event) => event && event.stoppropagation && event.stoppropagation()
// 更多按钮 点击 弹出菜单
const handleClick = (event) => {
setAnchorEl(event.currentTarget)
}
// 关闭更多 menu 弹框
const handleClose = () => setAnchorEl(null);
// 选择更多按钮回调
const handleCloseOption = (item, key) => {
setAnchorEl(null);
selectCallBack && selectCallBack(item, key)
};
return (
<>
<Button
size={size || "medium"}
variant={variant || "contained"}
color={color || "primary"}
disabled={disabled || false}
disableElevation={disableElevation || false}
disableFocusRipple={disableFocusRipple || false}
classes={{
root: btnStyle.root || classes.root,
label: btnStyle.label || classes.label,
disabled: btnStyle.disabled || classes.disabled,
containedSecondary: btnStyle.containedSecondary || classes.containedSecondary,
outlined: btnStyle.outlined || classes.outlined,
outlinedSecondary: btnStyle.outlinedSecondary || classes.outlinedSecondary,
text: btnStyle.text || classes.text,
textPrimary: btnStyle.textPrimary || classes.textPrimary,
textSecondary: btnStyle.textSecondary || classes.textSecondary,
sizeSmall: btnStyle.sizeSmall || classes.sizeSmall,
sizeLarge: btnStyle.sizeLarge || classes.sizeLarge,
}}
style={{ ...props.style, boxShadow: "none !important", backgroundColor: "#136EFA", padding: "0px 0px", width: "110px" }}
>
<Typography
className={isEn() ? classes.textStyle_en : classes.textStyle}
style={fontSize ? { fontSize: fontSize } : {}}
onClick={click}
>
{text || ""}</Typography>
<div
style={{ display: "flex", padding: "0px 5px" }}
onClick={handleClick}
>
<ArrowDropDownIcon fontSize={"small"} style={{ color: "#fff" }} />
</div>
</Button>
<Menu
id="simple-menu"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleClose}
style={{ marginTop: "47px", marginLeft: isEn() ? "-77px" : "-76px" }}
>
<div style={{ width: "110px" }}>
<CheckboxComponent
defaultChecked={Checked}
label={<Text text={subText} op={"lg"} variant={"body1"} />}
labelPlacement={"end"}
size={"small"}
checkChange={(event) => subClick(event)}
checkBoxStyle={{
root: classes.checkBoxBody
}}
/>
</div>
</Menu>
</>
)
}
ButtonComponent.propTypes = {
size: PropTypes.oneOf(["large", "medium", "small"]),
variant: PropTypes.oneOf(["contained", "outlined", "text"]),
color: PropTypes.oneOf(["default", "inherit", "primary", "secondary"]),
disabled: PropTypes.bool,
disableElevation: PropTypes.bool,
disableFocusRipple: PropTypes.bool,
};
export default ButtonComponent;
\ No newline at end of file
import React, { useMemo } from 'react';
import { withStyles } from '@material-ui/core/styles';
import Dialog from '@material-ui/core/Dialog';
import MuiDialogTitle from '@material-ui/core/DialogTitle';
import MuiDialogContent from '@material-ui/core/DialogContent';
import MuiDialogActions from '@material-ui/core/DialogActions';
import IconButton from '@material-ui/core/IconButton';
import CloseIcon from '@material-ui/icons/Close';
import Typography from '@material-ui/core/Typography';
import Slide from '@material-ui/core/Slide';
import ButtonComponent from "@/commons/components/Material.Ui/Button";
import useMediaQuery from '@material-ui/core/useMediaQuery';
import { useTheme } from '@material-ui/core/styles';
import PropTypes from "prop-types";
import { CLOUDE } from "@/commons/utils/constants"
import { useEffect } from 'react';
const styles = (theme) => ({
root: {
margin: 0,
padding: "16px 24px",
},
closeButton: {
position: 'absolute',
right: theme.spacing(1),
top: theme.spacing(1) - 4,
color: theme.palette.grey[500],
},
});
const DialogTitle = withStyles(styles)((props) => {
const { children, classes, onClose, ...other } = props;
return (
<MuiDialogTitle disableTypography className={classes.root} {...other}>
<Typography variant="body1">{children}</Typography>
{onClose ? (
<IconButton aria-label="close" className={classes.closeButton} onClick={() => onClose(false)}>
<CloseIcon />
</IconButton>
) : null}
</MuiDialogTitle>
);
});
const DialogActions = withStyles(() => ({
root: {
margin: 0,
padding: "16px 24px",
"& > :not(:first-child)": {
marginLeft: "15px"
}
},
}))(MuiDialogActions);
const Transition = React.forwardRef(function Transition(props, ref) {
return <Slide direction={props.direction || "up"} ref={ref} {...props} />;
});
const AlertDialogSlide = props => {
const { open, handleClose, dividers, content, padding = true,confirmDisabled=false, header, canncel = CLOUDE.canncel, confirm = CLOUDE.confirm, fullScreen, scroll, maxWidth, bottom, backAndKey, direction, classes, contentStyle } = props;
const theme = useTheme();
const mediaFull = useMediaQuery(theme.breakpoints.down('sm'));
const [fullWidth, setFullWidth] = React.useState(true);
const DialogContent = withStyles(() => ({
root: {
padding: padding ? "20px 24px 40px" : "0", fontWeight: "400", ...contentStyle
},
dividers: { borderColor: "rgba(34, 34, 34, 0.08)" },
}))(MuiDialogContent);
const otherName = useMemo(() => { return (content) }, [content])
return (
<Dialog
open={open}
classes={classes}
TransitionComponent={Transition}
keepMounted
onClose={() => handleClose(false)}
fullScreen={fullScreen || mediaFull}
scroll={scroll || "paper"}
aria-describedby="dialog"
aria-labelledby="confirmation-dialog-title"
fullWidth={fullWidth}
// disableBackdropClick={backAndKey || true}//点击屏幕外关闭
// disableEscapeKeyDown={backAndKey || true}//按下键盘ESC关闭
maxWidth={maxWidth || "sm"}
>
<DialogTitle id="customized-dialog-title" onClose={handleClose}>
{header || ""}
</DialogTitle>
<DialogContent dividers={dividers || true}>
{/* {content || ""} */}
{otherName}
</DialogContent>
{
!bottom && (canncel || confirm) && <DialogActions>
{canncel && <ButtonComponent click={() => handleClose(false)} variant={"outlined"} text={canncel} />}
{confirm && <ButtonComponent click={() => handleClose(1)} text={confirm} disabled={ confirmDisabled || false} />}
</DialogActions>
}
{
bottom && bottom
}
</Dialog>
)
}
AlertDialogSlide.propTypes = {
maxWidth: PropTypes.oneOf([false, "xs", "sm", "md", "lg", "xl"]),
scroll: PropTypes.oneOf(['paper', 'body'])
};
export default AlertDialogSlide
\ No newline at end of file
import React from 'react'
import { Grid , Typography } from '@material-ui/core'
import icondelete from '../../assets/img/iconDelete.svg'
import iconDashboard from '../../assets/img/iconDashboard.svg'
import { makeStyles } from '@material-ui/core'
const Style = makeStyles({
paddingbox:{
borderRadius: '4px',
border:' 1px solid rgba(19, 110, 250, 1)',
cursor:'pointer',
minHeight:'33px',
display:'flex',
alignItems:'center',
// justifyContent:'center'
},
content:{
color:'rgba(19, 110, 250, 1)',
fontSize:'13px',
lineHeight:'17px',
fontWeight:'400',
fontFamily:'PingFangSC-Regular, PingFang SC'
},
img:{
// width:'17px',
marginRight:'4px'
}
})
export default props =>{
const { startIcon = '' , color , onClick , text = '' , marginright = '16px' ,style={} , paddingleft='' } = props
const classes = Style()
const icon = (str)=>{
switch(str){
case 'delete' :
return icondelete;
case 'dashboard':
return iconDashboard;
default:
break;
}
}
return <Grid onClick = {()=>{onClick&&onClick()}} className = {classes.paddingbox}
style={{padding:Boolean(startIcon)?'3px 14px 3px 7px':' 6px 8px ',marginRight:marginright,paddingLeft:paddingleft, ...style}}>
{startIcon&& <img src ={icon(startIcon)} alt ='' className= {classes.img}/>}
<Typography className={classes.content}>{ text }</Typography>
</Grid>
}
\ No newline at end of file
import React from "react";
import TextField from '@mui/material/TextField';
import MenuItem from '@mui/material/MenuItem';
import { makeStyles } from "@mui/styles";
import cx from "classnames"
const useStyles = makeStyles({
MuiOutlinedInputInputLarge: { padding: "13.5px 15px", MozAppearance: 'textfield' },
MuiOutlinedInputInput: { padding: "12px 15px", "&::placeholder": { fontSize: "14px" }, MozAppearance: 'textfield' },
MuiOutlinedInputInputSmall: { padding: "10px 15px", "&::placeholder": { fontSize: "13px" }, MozAppearance: 'textfield' },
MuiOutlinedInputInputXsmall: { padding: "8px 15px", "&::placeholder": { fontSize: "12px" }, MozAppearance: 'textfield' },
outlinedLarge: { transform: "translate(14px, 15.5px) scale(1)", fontSize: '14px', fontWeight: '400', color: '#707070' },
outlined: { transform: "translate(14px, 14px) scale(1)", fontSize: '14px', fontWeight: '400', color: '#707070' },
outlinedSmall: { transform: "translate(14px, 11px) scale(1)", fontSize: '14px', fontWeight: '400', color: '#707070' },
outlinedXsmall: { transform: "translate(12px, 11px) scale(1)", fontSize: '13px', fontWeight: '400', color: '#707070' },
notchedOutline: { borderColor: "rgba(216, 216, 216, 1)" },
root: {
"&:hover": {
"& .MuiOutlinedInput-notchedOutline": { borderColor: "rgba(19, 110, 250, 0.9)" }
},
},
error: {
"& .MuiOutlinedInput-notchedOutline": {
borderColor: "#D62C1F !important"
},
},
disabled: {
color: "#E3E3E3 !important",
"& .MuiOutlinedInput-notchedOutline": { borderColor: "#E3E3E3 !important" },
"&:hover": {
"& .MuiOutlinedInput-notchedOutline": { borderColor: "#E3E3E3 !important" }
},
},
errorLabel: { color: "#D62C1F !important" },
errorFormHelperTextProps: { color: "#D62C1F !important", fontSize: "12px", lineHeight: '14px' },
SelectPropsright: { textAlign: "right" },
SelectPropscenter: { textAlign: "center" },
SelectPropsleft: { textAlign: "left" },
selectProp: { fontSize: "14px" },
selectPropsLarge: { fontSize: "14px" },
selectPropsSmall: { fontSize: "13px" },
selectPropsXsmall: { fontSize: "12px" },
adornedEnd: { paddingRight: "8px" },
defaultSelectStyle: { fontSize: "14px" }
})
export default props => {
const classes = useStyles();
const { label, type, variant, disabled, onChange, placeholder, value, textAlign, customClass,
autoFocus, defaultValue, error, fullWidth, margin, select, disabledClass, onBlur, selectStyle,
multiline, required, rows, startAdornment, endAdornment, helperText, size, onkeydown, selectSize, onFocus
} = props;
const onChangeDefault = () => { }
const resizeBys = (sty) => {
switch (size) {
case "large":
return sty + "Large";
case "small":
return sty + "Small";
case "xsmall":
return sty + "Xsmall";
default:
return sty;
}
}
const reSelectSizeBys = (sty) => {
switch (selectSize) {
case "large":
return sty + "Large";
case "small":
return sty + "Small";
case "xsmall":
return sty + "Xsmall";
default:
return sty;
}
}
const onBlurDefault = () => {
}
const onFocusDefault = () => { }
if (![undefined, null].includes(value)) {
return (
<TextField
label={label || ""}
autoFocus={autoFocus || false}
type={type || "text"}
value={value || ""}
placeholder={placeholder || ""}
variant={variant || "outlined"}
select={select ? true : false}
disabled={disabled || false}
onChange={onChange || onChangeDefault}
onBlur={onBlur || onBlurDefault}
error={error || false}
helperText={helperText || ""}
fullWidth={fullWidth || false}
onFocus={onFocus || onFocusDefault}
rows={rows || 1}
multiline={multiline || false}
required={required || false}
InputProps={{
margin: margin || "none",
classes: {
root: classes.root,
input: cx({
width: '320px',
height: '32px',
[classes[resizeBys("MuiOutlinedInputInput")]]: true,
[classes[`SelectProps${textAlign}`]]: textAlign,
[customClass]: customClass,
}),
notchedOutline: classes.notchedOutline,
error: classes.error,
disabled: disabledClass || classes.disabled,
adornedEnd: classes.adornedEnd
},
startAdornment: startAdornment || "",
endAdornment: endAdornment || ""
}}
InputLabelProps={{
classes: {
outlined: classes[resizeBys("outlined")],
error: classes.errorLabel
}
}}
FormHelperTextProps={{
classes: {
root: classes.rootFormHelperTextProps,
error: classes.errorFormHelperTextProps
}
}}
SelectProps={{
native: (select && select.native) || false,
classes: {
outlined: textAlign ? classes[`SelectProps${textAlign}`] : classes['SelectPropsleft'],
selectMenu: classes[reSelectSizeBys("selectProps")]
}
}}
>
{
select && select.json && select.json.length > 0 && select.json.map((option, key) => {
return (
<MenuItem key={key} disabled={option.disabled || false} value={option.value} className={selectStyle || classes.defaultSelectStyle}>
{option.label}
</MenuItem>
)
})
}
</TextField>
)
}
return (
<TextField
label={label || ""}
autoFocus={autoFocus || false}
type={type || "text"}
defaultValue={defaultValue || ""}
placeholder={placeholder || ""}
variant={variant || "outlined"}
select={select ? true : false}
disabled={disabled || false}
onChange={onChange || onChangeDefault}
onBlur={onBlur || onBlurDefault}
error={error || false}
helperText={helperText || ""}
fullWidth={fullWidth || false}
rows={rows || 1}
multiline={multiline || false}
required={required || false}
onKeyDown={onkeydown || (() => { })}
InputProps={{
margin: margin || "none",
classes: {
root: classes.root,
input: cx({
[classes[resizeBys("MuiOutlinedInputInput")]]: true,
[classes[`SelectProps${textAlign}`]]: textAlign,
[customClass]: customClass
}),
notchedOutline: classes.notchedOutline,
error: classes.error,
disabled: disabledClass || classes.disabled,
adornedEnd: classes.adornedEnd
},
startAdornment: startAdornment || "",
endAdornment: endAdornment || ""
}}
InputLabelProps={{
classes: {
outlined: classes[resizeBys("outlined")],
error: classes.errorLabel
}
}}
FormHelperTextProps={{
classes: {
root: classes.rootFormHelperTextProps,
error: classes.errorFormHelperTextProps
}
}}
SelectProps={{
native: (select && select.native) || false,
classes: {
outlined: textAlign ? classes[`SelectProps${textAlign}`] : classes['SelectPropsleft'],
}
}}
>
{
select && select.json && select.json.length > 0 && select.json.map((option, key) => {
return (
<MenuItem key={key} disabled={option.disabled || false} value={option.value} className={selectStyle || classes.defaultSelectStyle}>
{option.label}
</MenuItem>
)
})
}
</TextField>
)
}
\ No newline at end of file
import React from "react";
import Table from "@material-ui/core/Table";
import TableBody from "@material-ui/core/TableBody";
import TableCell from "@material-ui/core/TableCell";
import TableContainer from "@material-ui/core/TableContainer";
import TablePagination from "@material-ui/core/TablePagination";
import TableRow from "@material-ui/core/TableRow";
import Paper from "@material-ui/core/Paper";
import Checkbox from "@material-ui/core/Checkbox";
import Spin from "@/commons/components/Material.Ui/Spin";
import { CLOUDE } from '@/commons/utils/constants';
import EnhancedTableToolbarComponent from "./Table/EnhancedTableToolbar"
import EnhancedTableHeadComponent from "./Table/EnhancedTableHead"
import { getComparator, stableSort, useStyles } from "./Table/function";
import ActionsComponent from "./Table/ActionsComponent"
import { useEffect } from "react";
import Tooltip from '@material-ui/core/Tooltip';
export default function EnhancedTable(props) {
const classes = useStyles();
const [order, setOrder] = React.useState("asc");
const [orderBy, setOrderBy] = React.useState("");
const { headCells, rows, footer = true, elevation1, tableStyle, tableContainerStyle, stickyheader, TableHeadClasses, onRowClick, defaultRow, minHeight = '', borderBottom = '', onDoubleClick, bodyTableCellStyle, headTableCellStyle, cancelHover,
load, size, checkboxData, rowsPerPage = 10, initSelected, page = 0, changePage = function () { }, toolbar, count, param, disabledparam = "id", headTableCellCheckbox, RowHeight = '', CellWidth = '', rowHover, TableNodataPadding = '', TableNodataLineHeight = '' } = props;
const [selected, setSelected] = React.useState(initSelected || []);
const [rowsPerPageOptions, setRowsPerPageOptions] = React.useState(initSelected || [5, 10, 20, 50, { value: -1, label: 'All' }]);
const [spin, setSpin] = React.useState(false)
const [onRow, setOnRow] = React.useState('')
useEffect(() => {
setOnRow(defaultRow)
}, [defaultRow])
const onRowClickDefault = (value) => {
setOnRow(value)
onRowClick(value)
}
const handleRequestSort = (event, property) => {
const isAsc = orderBy === property && order === "asc";
setOrder(isAsc ? "desc" : "asc");
setOrderBy(property);
};
const handleSelectAllClick = (event) => {
if (event.target.checked) {
const newSelecteds = rows.map((n) => n[param || 'id']);
setSelected(newSelecteds);
checkboxData(newSelecteds);
return;
}
setSelected([]);
checkboxData([]);
};
React.useEffect(() => {
setSpin(load)
}, [load]);
const handleClick = (event, name) => {
const selectedIndex = selected.indexOf(name);
let newSelected = [];
if (selectedIndex === -1) {
newSelected = newSelected.concat(selected, name);
} else if (selectedIndex === 0) {
newSelected = newSelected.concat(selected.slice(1));
} else if (selectedIndex === selected.length - 1) {
newSelected = newSelected.concat(selected.slice(0, -1));
} else if (selectedIndex > 0) {
newSelected = newSelected.concat(
selected.slice(0, selectedIndex),
selected.slice(selectedIndex + 1)
);
}
checkboxData(newSelected)
setSelected(newSelected);
};
const handleOnPageChange = (event, newPage) => {
changePage(newPage, rowsPerPage);
};
const handleChangeRowsPerPage = (event) => {
changePage(0, parseInt(event.target.value, 10));
};
const isSelected = (name) => selected.indexOf(name) !== -1;
const emptyRows = rowsPerPage - Math.min(rowsPerPage, rows.length - page * rowsPerPage);
return (
<div className={classes.root}>
<Paper className={classes.paper} classes={{ elevation1: elevation1 || classes.elevation1 }} >
<Spin spin={spin} />
{toolbar && toolbar}
<TableContainer style={{ ...tableContainerStyle }}>
<Table stickyHeader={stickyheader || false} className={classes.table} style={{ ...tableStyle }} aria-labelledby="tableTitle" size={size || "medium"} aria-label="cloudam table header" >
<EnhancedTableHeadComponent
classes={classes}
{...props}
numSelected={selected.length}
headTableCellCheckbox={headTableCellCheckbox}
headTableCell={headTableCellStyle}
order={order}
orderBy={orderBy}
onSelectAllClick={handleSelectAllClick}
onRequestSort={handleRequestSort}
rowCount={rows.length}
headCells={headCells || []}
/>
<TableBody>
{
(rows.length === 0 && !load) && <TableRow>
<TableCell
colSpan={headCells.filter(k => k.id === "checkbox").length === 0 ? headCells.length : headCells.length + 1}
className={classes.TypographyStyle}
style={{ minHeight: minHeight, height: minHeight, borderBottom: borderBottom, padding: TableNodataPadding, lineHeight: TableNodataLineHeight }}
>
No Data
</TableCell>
</TableRow>
}
{stableSort(rows, getComparator(order, orderBy)).slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage).map((row, index) => {
const isItemSelected = isSelected(row[param || "id"]);
const labelId = `enhanced-table-checkbox-${index}`;
return (
<TableRow
hover={rowHover ? false : (row[disabledparam || "enabled"] ? true : false)}
onClick={(event) => {
if (!row[disabledparam]) return;
onRowClick && onRowClickDefault(row[param || "id"])
headCells.filter(k => k.id === "checkbox").length > 0 && handleClick(event, row[param || "id"])
}}
onDoubleClick={() => {
onDoubleClick && onDoubleClick(row)
}}
style={{
height: RowHeight,
border: onRow === row[param || "id"] ? !row[disabledparam] ? "" : '1px solid #136EFA' : "",
backgroundColor: onRow === row[param || "id"] ? !row[disabledparam] ? "rgba(255, 255, 255, 0.4)" : "rgba(19, 110, 250, 0.1)" : "",
cursor: props.cursor ? (row[props.cursor] ? "pointer" : "auto") : (onRowClick ? !row[disabledparam] ? "no-drop" : "pointer" : "auto"),
opacity: !row[disabledparam] ? 0.3 : 1
}}
classes={{
root: cancelHover && classes.cancelHoverStyle
}}
role="checkbox"
aria-checked={isItemSelected}
tabIndex={-1}
key={row[param || "id"]}
selected={isItemSelected}
>
{
headCells.filter(k => k.id === "checkbox").length > 0 && <TableCell padding="checkbox">
<Checkbox color={"primary"} checked={isItemSelected} inputProps={{ "aria-labelledby": labelId }} />
</TableCell>
}
{
headCells.map((item, k) => {
let subscript = rows.findIndex((e) => e[item.id] === 'merge')
if (index !== subscript && row[item.id] === 'merge') return null
return (
<TableCell key={k} component="th" id={labelId + k}
style={{ width: CellWidth, textAlign: item.numeric ? "right" : "left", paddingRight: item.sort && item.numeric ? "40px" : "", boxSizing: "border-box" }}
scope="row"
rowSpan={(row[item.id] === 'merge') ? (rows.length - (index)) : 1}
padding={item.disablePadding ? "none" : "normal"}
classes={{
body: bodyTableCellStyle || classes.bodyTableCell,
}}
> {row[item.id] === 'merge' ? ((item.id === 'parallelFileSystem' && rows[0].parallelFileSystem === "merge") ? CLOUDE.chargesText16 : "") : row[item.id]}</TableCell>
)
})
}
</TableRow>
);
})}
{/* {emptyRows > 0 && (
<TableRow style={{ height: (dense ? 33 : 53) * emptyRows }}>
<TableCell colSpan={6} />
</TableRow>
)} */}
</TableBody>
</Table>
</TableContainer>
{
footer && <TablePagination
rowsPerPageOptions={rowsPerPageOptions}
component="div"
count={count || rows.length}
rowsPerPage={rowsPerPage}
page={page}
ActionsComponent={ActionsComponent}
onChangePage={handleOnPageChange}
onChangeRowsPerPage={handleChangeRowsPerPage}
/>
}
</Paper>
</div>
);
}
import React, { useState, useEffect, useRef } from "react";
import TextField from '@material-ui/core/TextField';
import cx from "classnames"
import { makeStyles } from '@material-ui/core/styles';
import { Grid, List, ListItem, ListItemText, Chip } from "@material-ui/core";
import Checkbox from '@material-ui/core/Checkbox';
import ArrowDropDownIcon from '@material-ui/icons/ArrowDropDown';
const useStyles = makeStyles({
MuiOutlinedInputInputLarge: { padding: "13.5px 15px" },
MuiOutlinedInputInput: { padding: "12px 15px" },
MuiOutlinedInputInputSmall: { padding: "10px 15px" },
outlinedLarge: { transform: "translate(14px, 15.5px) scale(1)", fontSize: '14px', fontWeight: '400', color: '#707070' },
outlined: { transform: "translate(14px, 14px) scale(1)", fontSize: '14px', fontWeight: '400', color: '#707070' },
outlinedSmall: { transform: "translate(14px, 11px) scale(1)", fontSize: '14px', fontWeight: '400', color: '#707070' },
notchedOutline: { borderColor: "rgba(216, 216, 216, 1)" },
root: {
width: "100%",
"&:hover": {
"& .MuiOutlinedInput-notchedOutline": { borderColor: "rgba(19, 110, 250, 0.9)" }
},
},
error: {
"& .MuiOutlinedInput-notchedOutline": {
borderColor: "#D62C1F !important"
},
},
disabled: {
color: "#E3E3E3 !important",
"& .MuiOutlinedInput-notchedOutline": { borderColor: "#E3E3E3 !important" },
"&:hover": {
"& .MuiOutlinedInput-notchedOutline": { borderColor: "#E3E3E3 !important" }
},
},
errorLabel: { color: "#D62C1F !important" },
errorFormHelperTextProps: { color: "#D62C1F !important", fontSize: "12px" },
wrap: { width: "100%", position: "relative" },
contentWrap: {
padding: "8px 0", height: 0, transition: "all 1s", position: "absolute", zIndex: 9, width: "100%",
backgroundColor: "#FFFFFF", boxShadow: "0px 2px 3px 0px rgba(0, 0, 0, 0.16)", borderRadius: "4px",
overflowY: "scroll",
maxHeight: "398px"
},
contentWrapOpenPosition:{top:"-400px"},
contentWrapOpen: { height: "auto" },
ArrowDropDownIconRoot: { transition: "all 0.2s", transform: "rotate(0)", position: "absolute", right: "15px", top: "6px" },
ArrowDropDownIconRootOpen: { transform: "rotate(180deg)" },
inputWrap: { position: "relative" },
checked: { color: "#136EFA !important" }
})
let time = null;
export default props => {
const classes = useStyles();
const { label, type, variant, disabled, onChange, placeholder, autoFocus, defaultValue, error, fullWidth, margin, multiline, required, rows, startAdornment, endAdornment, helperText, size, option, callback, values = [], inputValue } = props;
const [open, setOpen] = useState(false)
const [curDomBottom, setCurDomBottom] = useState('')
const onChangeDefault = (e) => {
onChange && throttle(e.target.value)
}
const handleMouseUp = (event) => {
setOpen(false)
event && event.stopPropagation()
}
//节流
const throttle = (e) => {
if (!time) {
time = setTimeout(() => {
onChange(e)
time = null
}, 400);
}
}
const inputEl = useRef(null);
useEffect(() => {
window.addEventListener('click', handleMouseUp, false)
return () => window.removeEventListener('click', handleMouseUp, false)
}, [])
const resizeBys = (sty) => {
switch (size) {
case "large":
return sty + "Large";
case "small":
return sty + "Small";
default:
return sty;
}
}
// 获取当前 元素距离底部位置
const scrollFun = (sty) => {
let dom = inputEl.current;
const height = window.innerHeight //可视区窗口高度
const curDomHeight = dom.offsetHeight
// const curDomHeight = dom.getBoundingClientRect().height
const curDomY = dom.getBoundingClientRect().y
const curDomBottom = height - curDomHeight - curDomY
if( curDomBottom<400 ){
setCurDomBottom("top")
}else setCurDomBottom("")
}
const selectClick = (e, item) => {
callback && callback(item)
}
return (
<Grid ref={inputEl} className={cx({ [classes.wrap]: true, })} onClick={(e) => e.stopPropagation()}>
<Grid className={cx({ [classes.inputWrap]: true, })}>
<TextField
onFocus={() => {
scrollFun()
setOpen(true);
}}
label={label || ""}
style={{ width: "100%" }}
autoFocus={autoFocus || false}
defaultValue={defaultValue || ""}
type={type || "text"}
placeholder={placeholder || ""}
variant={variant || "outlined"}
disabled={disabled || false}
onChange={onChangeDefault}
error={error || false}
helperText={helperText || ""}
fullWidth={fullWidth || false}
rows={rows || 1}
multiline={multiline || false}
required={required || false}
InputProps={{
margin: margin || "none",
classes: {
root: classes.root,
input: classes[resizeBys("MuiOutlinedInputInput")],
notchedOutline: classes.notchedOutline,
error: classes.error,
disabled: classes.disabled
},
startAdornment: startAdornment || "",
endAdornment: endAdornment || "",
}}
InputLabelProps={{
classes: {
outlined: classes[resizeBys("outlined")],
error: classes.errorLabel
}
}}
FormHelperTextProps={{
classes: {
root: classes.rootFormHelperTextProps,
error: classes.errorFormHelperTextProps
}
}}
/>
<ArrowDropDownIcon classes={{
root: cx({
[classes.ArrowDropDownIconRoot]: true,
[classes.ArrowDropDownIconRootOpen]: open
})
}} />
</Grid>
{
open && inputValue !== "" && (
<Grid onClick={(e) => e.stopPropagation()} className={cx({
[classes.contentWrap]: true,
[classes.contentWrapOpen]: open,
[classes.contentWrapOpenPosition]: curDomBottom==="top",
})
} id="select-wrap-content">
<Grid className={classes.gridScroll}>
<List component="nav" className={classes.root} aria-label="contacts">
{
option && option.map((item, key) => {
return (
<ListItem
selected={values.filter(k => k.value === item.value).length > 0}
classes={{ root: classes.rootListItem }} key={key} button
onClick={(event) => selectClick(event, item)}
>
<ListItemText primary={item.label} />
<Checkbox
checked={values.filter(k => k.value === item.value).length > 0}
onChange={(event) => selectClick(event, item)}
classes={{
checked: classes.checked
}}
/>
</ListItem>
)
})
}
</List>
</Grid>
</Grid>
)
}
</Grid >
)
}
\ No newline at end of file
import React, { useState, useEffect } from "react";
import Selectzone from './Selectzone.jsx'
import { Grid, Typography, List, ListItem, ListItemText } from '@mui/material';
import { makeStyles } from "@mui/styles";
import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown';
import cx from "classnames"
const useStyles = makeStyles({
wrapHeightLarge: { height: "44px" },
wrapHeight: { height: "40px" },
wrapHeightSmall: { height: "36px" },
wrapHeightXsmall: { height: "32px" },
wrap: { width: "100%", position: "relative" },
noBorderwrap: { width: "125px", position: "relative" },
noBorderEnwrap: { width: "165px", position: "relative" },
inputWrap: {
display: "flex", justifyContent: "space-between", alignItems: "center", background: "#FFFFFF", borderRadius: '4px', border: "1px solid #D8D8D8",
cursor: "pointer", padding: "0 15px",
"&:hover": { borderColor: "#136EFA" }
},
noBorderinputWrap: {
display: "flex", justifyContent: "space-between", alignItems: "center", background: "#FFFFFF",
cursor: "pointer", padding: "0",
},
inputHeightLarge: { height: "44px" },
inputHeight: { height: "40px" },
inputHeightSmall: { height: "36px" },
inputHeightXsmall: { height: "32px" },
inputWrapOpen: { border: "1px solid #136EFA" },
text: { color: "#1B1B1B", fontSize: '14px', fontWeight: 400 },
ArrowDropDownIconRoot: { transition: "all 0.2s", transform: "rotate(0)" },
ArrowDropDownIconRootOpen: { transform: "rotate(180deg)" },
contentWrap: {
padding: "8px 0", height: 0, transition: "all 1s", position: "absolute", zIndex: 9, width: "100%",
backgroundColor: "#FFFFFF", boxShadow: "0px 2px 3px 0px rgba(0, 0, 0, 0.16)", borderRadius: "4px",
overflowY: "auto",
maxHeight: "400px"
},
contentWrapOpen: { height: "auto" },
rootListItem: { width: "100%", paddingRight: "0px" },
root: { flex: '1 1 auto', minWidth: 0, color: '#222', marginTop: '4px', marginBottom: '4px' },
primary: { fontSize: "14px" },
lg: { fontSize: "16px" },
sm: { fontSize: "13px" },
md: { fontSize: "12px" },
selected: {
// background:'red',
// color:'red'
}
})
export default props => {
const classes = useStyles();
const { value, size, option, callback, noBorder, rootStyle, customSvg, textStyle, sz, startIcon, DropdownboxStyle, DropdownboxitemStyle } = props;
const [open, setOpen] = useState(false)
const [values, setValue] = useState(value || '请选择')
const handleClick = (event) => {
event.stopPropagation()
setOpen((open) => !open)
}
const handleMouseUp = (event) => {
setOpen(false)
event && event.stopPropagation()
}
useEffect(() => {
window.addEventListener('click', handleMouseUp, false)
return () => window.removeEventListener('click', handleMouseUp, false)
}, [])
useEffect(() => {
setValue(value)
}, [value])
const selectClick = (event, item) => {
setValue(item.label)
callback && callback(item)
handleMouseUp()
event.stopPropagation()
}
const resizeBys = (sty) => {
switch (size) {
case "large":
return sty + "Large";
case "small":
return sty + "Small";
case "xsmall":
return sty + "Xsmall";
default:
return sty;
}
}
const reBorder = (sty) => {
switch (noBorder) {
case "true_cn":
return "noBorder" + sty;
case "true_en":
return "noBorderEn" + sty;
default:
return sty;
}
}
const fontsizeFun = () => {
switch (sz) {
case 'lg':
case 'sm':
case 'md':
return sz;
default:
return "primary"
}
}
return (
<Grid className={
cx({
[classes[reBorder('wrap')]]: true,
[classes[resizeBys("wrapHeight")]]: true,
})
} onClick={(e) => e.stopPropagation()}>
<Grid onClick={handleClick} className={
cx({
[classes[resizeBys('inputHeight')]]: true,
[classes[reBorder('inputWrap')]]: true,
[classes.inputWrapOpen]: open && !noBorder
})
}
style={{ ...rootStyle }}
>
{startIcon && startIcon}
<Typography className={classes.text} style={{ ...textStyle }}>{values || '请选择'}</Typography>
{
customSvg ? (
(
<div style={{ ...customSvg }}>
<ArrowDropDownIcon classes={{
root: cx({
[classes.ArrowDropDownIconRoot]: true,
[classes.ArrowDropDownIconRootOpen]: open
})
}} />
</div>
)
) : (<ArrowDropDownIcon classes={{
root: cx({
[classes.ArrowDropDownIconRoot]: true,
[classes.ArrowDropDownIconRootOpen]: open
})
}} />)
}
</Grid>
{
open && (
<Grid onClick={(e) => e.stopPropagation()} className={
cx({
[classes.contentWrap]: true,
[classes.contentWrapOpen]: open
})
} style={{ ...DropdownboxStyle, DropdownboxitemStyle }} id="select-wrap-content">
<Grid className={classes.gridScroll}>
<List component="nav" className={classes.root} aria-label="contacts">
{
option && option.map((item, key) => {
return (
<ListItem
selected={values === item.label}
classes={{ root: classes.rootListItem, selected: classes.selected }} key={key} button
style={{ ...DropdownboxitemStyle }}
onClick={(event) => selectClick(event, item)}
>
{item.icon ? <Selectzone Icon={item.icon} selected={values === item.label} key={key} classes={{ root: classes.rootListItem, popper: classes.popper, primary: classes[fontsizeFun()] }} selectClick={selectClick} item={item} /> : <ListItemText primary={item.label}
classes={{ primary: classes[fontsizeFun()] }}
/>}
</ListItem>
)
})
}
</List>
</Grid>
</Grid>
)
}
</Grid >
)
}
\ No newline at end of file
This diff is collapsed.
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-01 16:53:15
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-05 16:39:01
* @FilePath: /bkunyun/src/components/Material.Ui/Selectzone.jsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import React, { useState, useEffect } from "react";
import { makeStyles } from '@mui/styles';
import {
Grid,
ListItemText,
Tooltip,
} from "@mui/material";
import icon from "@/assets/img/icon_about_grey.png";
const useStyles = makeStyles({
popper:{fontSize:'12px'}
})
export default props => {
const classesstyle=useStyles()
const { item, classes , Icon , selected } = props;
const [hover, sethover] = useState(false);
const [select,setselect] = useState(false)
useEffect(() => {
setselect(selected?true:false)
}, [selected]);
const move = () => {
!hover&&sethover(true)
};
const leave = () => {
hover&&sethover(false)
};
return (
<Grid
onMouseEnter={move}
onMouseLeave ={leave}
style={{display:'flex',alignItems:"center",justifyContent:'space-between',width:"100%",background:Icon === 'dashBoard' &&selected?'rgba(25, 28, 31, 1)':''}}
>
{
Icon === 'dashBoard' && <Grid style={{
width:'2px',
height:'34px',
marginRight:'13px',
background:selected?'linear-gradient(180deg, #F05A28 0%, #FBC40D 100%)':'transparent',
}}></Grid>
}
<ListItemText
primary={item.label}
classes={{ primary: classes.primary }}
/>
{Icon !=='dashBoard' &&item.description&&hover&&<Tooltip
arrow
placement={'top'}
classes={{
tooltip: classesstyle.popper,
}}
title={item.description?item.description:""}><img src={item.src?item.src:icon} alt='' style={{ width: "16px",height:'16px', marginRight: "10px" ,marginLeft:'auto'}}/></Tooltip>}
</Grid>
);
};
import React from "react";
import "./css/Spin.css";
export default (props) => {
const { spin, relative } = props;
if (!spin) return ""
return (
<div className="ant-spin ant-spin-spinning ant-spin-show-text" style={{ position: relative ? "relative" : "" }}>
<span className="ant-spin-dot ant-spin-dot-spin">
<i className="ant-spin-dot-item"></i>
<i className="ant-spin-dot-item"></i>
<i className="ant-spin-dot-item"></i>
<i className="ant-spin-dot-item"></i>
</span>
<div className="ant-spin-text">Loading...</div>
<div className="ant-spin-background">
</div>
</div>
)
}
\ No newline at end of file
import React from "react";
import Table from "@mui/material/Table";
import TableBody from "@mui/material/TableBody";
import TableCell from "@mui/material/TableCell";
import TableContainer from "@mui/material/TableContainer";
import TablePagination from "@mui/material/TablePagination";
import TableRow from "@mui/material/TableRow";
import Paper from "@mui/material/Paper";
import Checkbox from "@mui/material/Checkbox";
// import Spin from "./Spin";
import EnhancedTableToolbarComponent from "./Table/EnhancedTableToolbar"
import EnhancedTableHeadComponent from "./Table/EnhancedTableHead"
import { getComparator, stableSort, useStyles } from "./Table/function";
import ActionsComponent from "./Table/ActionsComponent"
import { useEffect } from "react";
export default function EnhancedTable(props) {
const classes = useStyles;
const [order, setOrder] = React.useState("asc");
const [orderBy, setOrderBy] = React.useState("");
const { headCells, rows, footer = true, elevation1, tableStyle,tablecellstyle, tableContainerStyle, stickyheader, TableHeadClasses, onRowClick, defaultRow, minHeight='', borderBottom='', onDoubleClick,
load, size, checkboxData, rowsPerPage = 10, initSelected, page = 0, changePage = function () { }, toolbar, count, param, disabledparam = "id", headTableCellCheckbox ,RowHeight='',CellWidth='',rowHover, TableNodataPadding = '',TableNodataLineHeight=''} = props;
const [selected, setSelected] = React.useState(initSelected || []);
const [rowsPerPageOptions, setRowsPerPageOptions] = React.useState(initSelected || [5, 10, 20, 50, { value: -1, label: 'All' }]);
// const [spin, setSpin] = React.useState(false)
const [onRow, setOnRow] = React.useState('')
useEffect(() => {
setOnRow(defaultRow)
}, [defaultRow])
const onRowClickDefault = (value) => {
setOnRow(value)
onRowClick(value)
}
const handleRequestSort = (event, property) => {
const isAsc = orderBy === property && order === "asc";
setOrder(isAsc ? "desc" : "asc");
setOrderBy(property);
};
const handleSelectAllClick = (event) => {
if (event.target.checked) {
const newSelecteds = rows.map((n) => n[param || 'id']);
setSelected(newSelecteds);
checkboxData(newSelecteds);
return;
}
setSelected([]);
checkboxData([]);
};
// React.useEffect(() => {
// setSpin(load)
// }, [load]);
const handleClick = (event, name) => {
const selectedIndex = selected.indexOf(name);
let newSelected = [];
if (selectedIndex === -1) {
newSelected = newSelected.concat(selected, name);
} else if (selectedIndex === 0) {
newSelected = newSelected.concat(selected.slice(1));
} else if (selectedIndex === selected.length - 1) {
newSelected = newSelected.concat(selected.slice(0, -1));
} else if (selectedIndex > 0) {
newSelected = newSelected.concat(
selected.slice(0, selectedIndex),
selected.slice(selectedIndex + 1)
);
}
checkboxData(newSelected)
setSelected(newSelected);
};
const handleOnPageChange = (event, newPage) => {
changePage(newPage, rowsPerPage);
};
const handleChangeRowsPerPage = (event) => {
changePage(0, parseInt(event.target.value, 10));
};
const isSelected = (name) => selected.indexOf(name) !== -1;
const emptyRows = rowsPerPage - Math.min(rowsPerPage, rows.length - page * rowsPerPage);
return (
<div className={classes.root}>
<Paper className={classes.paper} classes={{ elevation1: elevation1 || classes.elevation1 }} >
{/* <Spin spin={spin} /> */}
{toolbar && toolbar}
<TableContainer style={{ ...tableContainerStyle }}>
<Table stickyHeader={stickyheader || false} className={classes.table} style={{ ...tableStyle }} aria-labelledby="tableTitle" size={size || "medium"} aria-label="cloudam table header" >
<EnhancedTableHeadComponent
classes={classes()}
{...props}
numSelected={selected.length}
headTableCellCheckbox={headTableCellCheckbox}
order={order}
orderBy={orderBy}
onSelectAllClick={handleSelectAllClick}
onRequestSort={handleRequestSort}
rowCount={rows.length}
headCells={headCells || []}
/>
<TableBody>
{
(rows.length === 0 && !load) && <TableRow>
<TableCell
colSpan={headCells?.filter(k => k.id === "checkbox")?.length === 0 ? headCells?.length : headCells?.length + 1}
className={classes.TypographyStyle}
style={{ minHeight: minHeight, height: minHeight, borderBottom: borderBottom ,padding:TableNodataPadding,lineHeight:TableNodataLineHeight}}
>
No Data
</TableCell>
</TableRow>
}
{stableSort(rows, getComparator(order, orderBy)).slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage).map((row, index) => {
const isItemSelected = isSelected(row[param || "id"]);
const labelId = `enhanced-table-checkbox-${index}`;
return (
<TableRow
hover={ rowHover ? false : (row[disabledparam || "enabled"] ? true : false)}
onDoubleClick={() => {
onDoubleClick && onDoubleClick(row)
}}
style={{
height:RowHeight,
border: onRow === row[param || "id"] ? !row[disabledparam] ? "" : '1px solid #136EFA' : "",
backgroundColor: onRow === row[param || "id"] ? !row[disabledparam] ? "rgba(255, 255, 255, 0.4)" : "rgba(19, 110, 250, 0.1)" : "",
cursor: props.cursor ? (row[props.cursor] ? "pointer" : "auto") : (onRowClick ? !row[disabledparam] ? "no-drop" : "pointer" : "auto"),
}}
role="checkbox"
aria-checked={isItemSelected}
tabIndex={-1}
key={row[param || "id"] || index}
selected={isItemSelected}
>
{
headCells.filter(k => k.id === "checkbox").length > 0 && <TableCell
onClick={(event) => {
// if (!row[disabledparam]) return;
onRowClick && onRowClickDefault(row[param || "id"])
headCells.filter(k => k.id === "checkbox").length > 0 && handleClick(event, row[param || "id"])
}}
padding="checkbox">
<Checkbox color={"primary"} checked={isItemSelected} inputProps={{ "aria-labelledby": labelId }} />
</TableCell>
}
{
headCells.filter(item=>item.id !== 'checkbox').map((item, k) => {
return (
<TableCell key={k} component="th" id={labelId + k}
// align={}
style={{ width:CellWidth, textAlign: item.numeric ? "right" : "left", paddingRight: item.sort && item.numeric ? "40px" : "",border:tablecellstyle }}
scope="row"
padding={item.disablePadding ? "none" : "normal"}
classes={{
body: props.bodyTableCell || classes.bodyTableCell
}}
> {
item.render ? <>{item.render(row[item.id],row,index)}</> :
row[item.id]
}
</TableCell>
)
})
}
</TableRow>
);
})}
{/* {emptyRows > 0 && (
<TableRow style={{ height: (dense ? 33 : 53) * emptyRows }}>
<TableCell colSpan={6} />
</TableRow>
)} */}
</TableBody>
</Table>
</TableContainer>
{
footer && <TablePagination
rowsPerPageOptions={rowsPerPageOptions}
component="div"
count={count || rows.length}
rowsPerPage={rowsPerPage}
page={page}
ActionsComponent={ActionsComponent}
onChangePage={handleOnPageChange}
onChangeRowsPerPage={handleChangeRowsPerPage}
/>
}
</Paper>
</div>
);
}
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-01 16:53:15
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-02 10:16:28
* @FilePath: /bkunyun/src/components/Material.Ui/Table/ActionsComponent.jsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import React from 'react';
import PropTypes from 'prop-types';
import Button from "@mui/material/Button";
import IconButton from '@mui/material/IconButton';
import FirstPageIcon from '@mui/icons-material/FirstPage';
import KeyboardArrowLeft from '@mui/icons-material/KeyboardArrowLeft';
import KeyboardArrowRight from '@mui/icons-material/KeyboardArrowRight';
import LastPageIcon from '@mui/icons-material/LastPage';
import { makeStyles } from "@mui/styles";
const useStyles = makeStyles({
firstPageIconStyle: { width: '28px', height: '28px', padding: 0, backgroundColor: '#FFFFFF', borderRadius: '2px', border: '1px solid #D8D8D8', margin: "0 6px" },
KeyboardArrowLeftStyle:{ width: '28px', height: '28px', padding: 0, backgroundColor: '#FFFFFF', borderRadius: '2px', border: '1px solid #D8D8D8', marginRight: "3px" },
keyboardArrowRightStyle:{ width: '28px', height: '28px', padding: 0, backgroundColor: '#FFFFFF', borderRadius: '2px', border: '1px solid #D8D8D8', marginLeft: "3px" },
lastPageIconStyle:{ width: '28px', height: '28px', padding: 0, backgroundColor: '#FFFFFF', borderRadius: '2px', border: '1px solid #D8D8D8', margin: "0 6px" }
})
const TablePaginationActionsConsole = props => {
const classes = useStyles();
const { count, page, rowsPerPage, onChangePage } = props;
const handleFirstPageButtonClick = (event) => {
onChangePage(event, 0);
}
const handleBackButtonClick = (event) => {
onChangePage(event, page - 1);
}
const handleNextButtonClick = (event) => {
onChangePage(event, page + 1);
}
const btnClick = (event, item) => {
onChangePage(event, item);
}
const handleLastPageButtonClick = (event) => {
onChangePage(event, Math.max(0, Math.ceil(count / rowsPerPage) - 1));
}
const buttons = (count, page, rowsPerPage) => {
let max = 1;
if( rowsPerPage !== -1 ){
max = count % rowsPerPage === 0 ? count / rowsPerPage : parseInt(count / rowsPerPage) + 1;
}
let arr = [...Array(max).keys()];
return arr.map((item) => {
if (item - 4 <= page && item + 4 >= page && count > 4)
return <Button
key={item}
onClick={() => btnClick('', item)}
style={{ minWidth: '28px', marginRight: "3px", marginLeft: "3px", minHeight: '28px', lineHeight: '28px', fontSize: "12px", border: page === item ? "1px solid #136EFA" : "1px solid #D8D8D8", color: page === item ? "#fff" : "#111111", background: page === item ? '#136EFA' : "#fff", borderRadius: "2px", padding: '0' }}>
{item + 1}
</Button>
return ""
})
}
return (
<div style={{ flexShrink: 0, }}>
<IconButton
onClick={handleFirstPageButtonClick}
disabled={page === 0}
className={classes.firstPageIconStyle}
aria-label="first page"
>
<FirstPageIcon />
</IconButton>
<IconButton
className = { classes.KeyboardArrowLeftStyle }
onClick={handleBackButtonClick} disabled={page === 0} aria-label="previous page">
<KeyboardArrowLeft />
</IconButton>
{
buttons(count, page, rowsPerPage)
}
<IconButton
onClick={handleNextButtonClick}
className={classes.keyboardArrowRightStyle}
disabled={page >= Math.ceil(count / rowsPerPage) - 1}
aria-label="next page"
>
<KeyboardArrowRight />
</IconButton>
<IconButton
className={classes.lastPageIconStyle}
onClick={handleLastPageButtonClick}
disabled={page >= Math.ceil(count / rowsPerPage) - 1}
aria-label="last page"
>
<LastPageIcon />
</IconButton>
</div>
);
}
TablePaginationActionsConsole.propTypes = {
count: PropTypes.number.isRequired,
onChangePage: PropTypes.func.isRequired,
page: PropTypes.number.isRequired,
rowsPerPage: PropTypes.number.isRequired,
};
export default TablePaginationActionsConsole
\ No newline at end of file
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-01 16:53:15
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-07 18:21:51
* @FilePath: /bkunyun/src/components/Material.Ui/Table/EnhancedTableHead.jsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import React from "react";
import TableHead from "@mui/material/TableHead";
import TableSortLabel from "@mui/material/TableSortLabel";
import PropTypes from "prop-types";
import TableRow from "@mui/material/TableRow";
import TableCell from "@mui/material/TableCell";
import Checkbox from "@mui/material/Checkbox";
import Typography from "@mui/material/Typography";
import Tooltip from '@mui/material/Tooltip';
import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline';
const EnhancedTableHead = (props) => {
const { classes, onSelectAllClick, order, orderBy, TableHeadClasses, numSelected, rowCount, onRequestSort, headCells, headTableCell, headTableCellCheckbox,RowStyle } = props;
const createSortHandler = (property) => (event) => {
onRequestSort(event, property);
};
return (
<TableHead classes={{ root: TableHeadClasses || classes.TableHeadClasses }} sx={{
th:{
backgroundColor: '#F7F8FA',
}
}}>
<TableRow style={{...RowStyle}}>
{
headCells.filter(k => k.id === "checkbox").length > 0 && <TableCell padding="checkbox">
<Checkbox
color={'primary'}
indeterminate={numSelected > 0 && numSelected < rowCount}
checked={rowCount > 0 && numSelected === rowCount}
onChange={onSelectAllClick}
inputProps={{ "aria-label": "select all desserts" }}
/>
</TableCell>
}
{headCells.map((headCell,k) => (
<TableCell
key={headCell.id}
style={{ width: headCell.width ? headCell.width : "", textAlign: headCell.numeric ? "right" : "left", display: headCell.id !== "checkbox" ? "" : "none" }}
padding={headCell.disablePadding ? "none" : "normal"}
sortDirection={orderBy === headCell.id ? order : false}
classes={{ head:( k && headTableCell) || classes.headTableCell }}
>
{
headCell.sort && <TableSortLabel active={orderBy === headCell.id} direction={order} onClick={createSortHandler(headCell.id)} >
{headCell.label}
</TableSortLabel>
}
{
!headCell.sort && <Typography className={headTableCellCheckbox || ''} style={headCell.tooltip ? { display: "flex", alignItems: "center" } : {}} >
{headCell.label}
{headCell.tooltip ? <Tooltip title={headCell.tooltip} placement="top" arrow>
<ErrorOutlineIcon style={{ fontSize: "16px",marginLeft:"5px" }} fontSize="small" />
</Tooltip> : ""}
</Typography>
}
</TableCell>
))}
</TableRow>
</TableHead>
);
}
EnhancedTableHead.propTypes = {
classes: PropTypes.object.isRequired,
numSelected: PropTypes.number.isRequired,
onRequestSort: PropTypes.func.isRequired,
onSelectAllClick: PropTypes.func.isRequired,
order: PropTypes.oneOf(["asc", "desc"]).isRequired,
orderBy: PropTypes.string.isRequired,
rowCount: PropTypes.number.isRequired,
};
export default EnhancedTableHead
\ No newline at end of file
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-01 16:53:15
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-02 10:18:54
* @FilePath: /bkunyun/src/components/Material.Ui/Table/EnhancedTableToolbar.jsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import React from "react";
import { useToolbarStyles } from "./function";
import Toolbar from "@mui/material/Toolbar";
import Typography from "@mui/material/Typography";
import PropTypes from "prop-types";
import clsx from "clsx";
import IconButton from "@mui/material/IconButton";
import Tooltip from "@mui/material/Tooltip";
import DeleteIcon from "@mui/icons-material/Delete";
import FilterListIcon from "@mui/icons-material/FilterList";
const EnhancedTableToolbar = (props) => {
const classes = useToolbarStyles();
const { numSelected } = props;
return (
<Toolbar
className={clsx(classes.root, { [classes.highlight]: numSelected > 0 })}
>
{numSelected > 0 ? (
<Typography
className={classes.title}
color="inherit"
variant="subtitle1"
component="div"
>
{numSelected} selected
</Typography>
) : (
<Typography
className={classes.title}
variant="h6"
id="tableTitle"
component="div"
>
Nutrition
</Typography>
)}
{numSelected > 0 ? (
<Tooltip title="Delete">
<IconButton aria-label="delete">
<DeleteIcon />
</IconButton>
</Tooltip>
) : (
<Tooltip title="Filter list">
<IconButton aria-label="filter list">
<FilterListIcon />
</IconButton>
</Tooltip>
)}
</Toolbar>
);
};
EnhancedTableToolbar.propTypes = {
numSelected: PropTypes.number.isRequired,
};
export default EnhancedTableToolbar;
\ No newline at end of file
import { makeStyles } from "@mui/styles";
/*
*@分割线=======================================================================================================================================
*@Description: 排序算法
*@File:
*@param: {} []
*@MethodAuthor: dawei.liu
*@Date: 2021-07-22 14:42:51
*/
export function descendingComparator(a, b, orderBy) {
if (b[orderBy] < a[orderBy]) return -1;
if (b[orderBy] > a[orderBy]) return 1;
return 0;
}
/*
*@分割线=======================================================================================================================================
*@Description: 表格排序
*@File: /commons/components/Material.Ui/Table.jsx
*@param: {} []
*@MethodAuthor: dawei.liu
*@Date: 2021-07-22 14:42:36
*/
export function getComparator(order, orderBy) {
return order === "desc"
? (a, b) => descendingComparator(a, b, orderBy)
: (a, b) => -descendingComparator(a, b, orderBy);
}
/*
*@分割线=======================================================================================================================================
*@Description: 排序算法
*@File:
*@param: {} []
*@MethodAuthor: dawei.liu
*@Date: 2021-07-22 14:42:24
*/
export function stableSort(array, comparator) {
const stabilizedThis = array.map((el, index) => [el, index]);
stabilizedThis.sort((a, b) => {
const order = comparator(a[0], b[0]);
if (order !== 0) return order;
return a[1] - b[1];
});
return stabilizedThis.map((el) => el[0]);
}
/*
*@分割线=======================================================================================================================================
*@Description: table toolbar styles
*@File: EnhancedTableToolbar
*@param: {} []
*@MethodAuthor: dawei.liu
*@Date: 2021-07-22 14:41:53
*/
export const useToolbarStyles = makeStyles((theme) => ({
root: {
paddingLeft: theme.spacing(2),
paddingRight: theme.spacing(1),
},
highlight:
theme.palette.type === "light"
? {
color: theme.palette.primary.main,
backgroundColor: "red",
}
: {
color: theme.palette.text.primary,
backgroundColor: theme.palette.primary.dark,
},
title: { flex: "1 1 100%" },
}));
/*
*@分割线=======================================================================================================================================
*@Description: 样式
*@File:
*@param: {theme} [theme]
*@MethodAuthor: dawei.liu
*@Date: 2021-07-22 14:40:37
*/
export const useStyles = makeStyles((theme) => ({
root: { width: "100%", position: "relative" },
paper: { width: "100%", marginBottom: 8 },
elevation1: { boxShadow: "none", padding: "20px" },
elevationNoPadding: { boxShadow: "none", padding: "0" },
table: { minWidth: 500 },
visuallyHidden: {
border: 0,
clip: "rect(0 0 0 0)",
height: 1,
margin: -1,
overflow: "hidden",
padding: 0,
position: "absolute",
top: 20,
width: 1,
},
LinearProgressStyle: {
position: "absolute",
left: 0,
top: "0",
width: "100%",
},
TypographyStyle: {
height: "300px",
width: "100%",
justifyContent: "center",
alignItems: "center",
color: "#666",
fontSize: "16px",
textAlign: "center",
},
bodyTableCell: {
color: "#222222",
fontSize: "12px",
borderBottom: "1px solid rgba(34, 34, 34, 0.08)",
padding: "10px",
paddingLeft: "16px",
},
headTableCell: {
color: "rgba(34, 34, 34, 0.65)",
fontSize: "12px",
padding: "16px",
},
rootTableContainer: {
position: "relative",
overflowX: "auto",
maxHeight: "700px",
},
TableHeadClasses: { backgroundColor: "rgba(34, 34, 34, 0.03)" },
bodyTableCellRoot: { borderBottom: "1px solid rgba(34, 34, 34, 0.08)" },
TypographyboderStyle: {
height: "300px",
width: "100%",
justifyContent: "center",
alignItems: "center",
color: "#666",
fontSize: "16px",
textAlign: "center",
borderBottom: "none",
},
rootTableboderContainer: {
position: "relative",
overflowX: "auto",
maxHeight: "700px",
border: "1px solid rgb(216, 216, 216)",
},
cancelHoverStyle: { "&:hover": { background: "none !important" } },
}));
This diff is collapsed.
import React from "react";
import { Typography } from "@material-ui/core";
import PropTypes from "prop-types";
import makeStyles from "@material-ui/styles/makeStyles";
const useStyles = makeStyles({
h3: { fontSize: "24px" },
h4: { fontSize: "20px" },
h5: { fontSize: "16px" },
body1: { fontSize: "14px" },
subtitle1: { fontSize: "13px" },
subtitle2: { fontSize: "12px" },
colorInherit: { color: "#222222" },
colorInherit_hover: { color: "#222222", "&:hover": { color: "#136EFA" } },
colorSecondary: { color: "#00CCCC" },
colorError: { color: "#FF4E4E" },
colorTextPrimary: { color: "#0DD09B" },
HiddenRoot: {
overflow: 'hidden',
textOverflow: 'ellipsis',
display: '-webkit-box',
WebkitBoxOrient: 'vertical',
},
line: {
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
}
});
const TextComponent = props => {
const classes = useStyles();
const fontWT = (fontWeight) => {
switch (fontWeight) {
case "small":
return 300;
case "large":
return 500;
case "big":
return 600;
case "bigger":
return 800;
default:
return 400;
}
}
const opacityFun = (value) => {
switch (value) {
case 'l':
return 0.05
case 'm':
return 0.08
case 'mh':
return 0.1
case 'h':
return 0.15
case 'xs':
return 0.25
case 'ss':
return 0.3
case 'sm':
return 0.45
case 'mm':
return 0.5
case 'md':
return 0.65
case 'gx':
return 0.8
case 'lg':
return 0.85
default:
return 1
}
}
const { text, align, color, display, gutterBottom, variant, fw, op, style, wordBreak, line, click, hover, hoverClass = false } = props;
const defaultClick = () => { }
const stylesFun = () => {
return {
wordBreak: wordBreak ? "break-all" : "keep-all",
textTransform: "none",
...style,
fontWeight: fontWT(fw),
opacity: opacityFun(op),
WebkitLineClamp: line && line.num ? line.num : 1,
width: line && line.width ? line.width : "auto",
maxWidth: line && line.maxWidth ? line.maxWidth : "100%",
}
}
return (
<Typography
align={align || "inherit"}
color={color || "inherit"}
display={display || "initial"}
gutterBottom={gutterBottom || false}
variant={variant || "body1"}
onClick={click || defaultClick}
classes={{
h3: classes.h3,
h4: classes.h4,
h5: classes.h5,
body1: classes.body1,
subtitle1: classes.subtitle1,
subtitle2: classes.subtitle2,
colorInherit: hover ? (hoverClass || classes.colorInherit_hover) : classes.colorInherit,
colorSecondary: classes.colorSecondary,
colorTextPrimary: classes.colorTextPrimary,
colorError: classes.colorError,
root: line ? (line.num && line.num === 1 ? classes.line : classes.HiddenRoot) : classes.root
}}
style={stylesFun()}
>
{text || ''}
</Typography>
)
}
TextComponent.propTypes = {
fw: PropTypes.oneOf(["bigger","big", "large", "medium", "small"]),
variant: PropTypes.oneOf(['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'subtitle1', 'subtitle2', 'body1', 'body2', 'caption', 'button', 'overline', 'srOnly', 'inherit']),
color: PropTypes.oneOf(["initial", "inherit", "primary", "secondary", "textPrimary", "textSecondary", "error"]),
op: PropTypes.oneOf(['', 'l', 'm', 'mh', 'h', 'xs', 'ss', 'sm', 'mm', 'md', 'lg', 'gx', 'xl']),
};
export default TextComponent
\ No newline at end of file
import React from 'react';
import ErrorOutlineIcon from '@material-ui/icons/ErrorOutline';
import Text from "@/commons/components/Material.Ui/Text"
import makeStyles from "@material-ui/styles/makeStyles";
import { Grid } from '@material-ui/core';
const useStyles = makeStyles({
tipBody: { width: "100%", height: "40px", background: "#FFEDED", boxShadow: "0px 2px 6px 0px rgba(189, 14, 0, 0.03)", borderRadius: "4px", display: "flex", alignItems: "center" },
root: { marginRight: 0 }
})
export default props => {
const { text } = props;
const classes = useStyles()
return (
<Grid className={classes.tipBody}>
<ErrorOutlineIcon style={{ color: "#FF4E4E", margin: "0px 10px 0px 20px" }} fontSize="small" />
<Text color={"error"} variant={"subtitle2"} text={text} />
</Grid>
)
}
\ No newline at end of file
import React from 'react';
import ErrorOutlineIcon from '@material-ui/icons/ErrorOutline';
import makeStyles from "@material-ui/styles/makeStyles";
import { Grid } from '@material-ui/core';
import { Typography } from "@material-ui/core";
import { BACKEND_API_URI_PREFIX } from "@/commons/utils/api_prefix";
const useStyles = makeStyles({
tipBody: { border: "1px solid rgba(19, 110, 250, 0.09)", borderRadius: "4px", display: "flex", alignItems: "center" },
root: { marginRight: 0 },
goText: {
color: "rgb(19, 110, 250)",
cursor: "pointer",
'&:hover': {
textDecoration: "underline"
}
}
})
export default props => {
const { style, text, iconColor, backgroundColor, margin, manual } = props;
const classes = useStyles()
return (
<Grid className={style ? style : classes.tipBody} style={{ backgroundColor: backgroundColor ? backgroundColor : "#FFEDED", margin: margin ? margin : "0" }} >
<ErrorOutlineIcon style={{ color: iconColor ? iconColor : "#FF4E4E", margin: "0px 10px 0px 20px" }} fontSize="small" />
<Typography style={{ fontSize: "12px", marginRight: "20px" ,padding:'12px 0'}}>
{text || ''}
{
manual ? (
<span className={classes.goText} onClick={()=>{
window.open(BACKEND_API_URI_PREFIX + '/helpce/docs/2027/about3', '_blank')
}}>
安装手册
</span>
) : ""
}
</Typography>
</Grid>
)
}
\ No newline at end of file
import React from 'react';
import makeStyles from '@material-ui/styles/makeStyles';
import Tooltip from "@/commons/components/Material.Ui/Tooltip";
const COIN_IAMGE_TIPS = require("@/console/cloudelastic/assets/img/templates/icon_about_grey.png");
const useStyles = makeStyles({
tooltipStyle: { lineHeight: "22px" ,backgroundColor: "#4D4D4D", borderRadius: "4px",padding:"8px 10px"}
});
export default props => {
const classes = useStyles();
const { title, marginLeft,iconWidth } = props;
return (
<Tooltip title={title} tooltip={classes.tooltipStyle}>
<img src={COIN_IAMGE_TIPS} style={{ width:iconWidth || "16px", marginLeft: marginLeft || "8px" }} alt="" />
</Tooltip>
)
}
\ No newline at end of file
import React, { useState } from 'react';
import Button from '@material-ui/core/Button';
import Tooltip from '@material-ui/core/Tooltip';
import makeStyles from "@material-ui/styles/makeStyles";
const useStyles = makeStyles({
tooltip: { backgroundColor: "#4D4D4D", borderRadius: "4px",padding:"8px 10px" ,fontSize:'12px'},
})
export default props => {
const classes = useStyles()
const { title, placement, children,tooltip } = props
return (
<Tooltip
interactive={true}
title={title}
classes={{
popper: classes.popper,
tooltip:tooltip || classes.tooltip
}}
placement={placement || "top"}>
{children}
</Tooltip>
)
}
// placement 'bottom-end'
// | 'bottom-start'
// | 'bottom'
// | 'left-end'
// | 'left-start'
// | 'left'
// | 'right-end'
// | 'right-start'
// | 'right'
// | 'top-end'
// | 'top-start'
// | 'top'
import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import Dialogs from "@/commons/components/Dialog/Dialogs";
import { Typography } from "@material-ui/core";
import { CopyToClipboard } from 'react-copy-to-clipboard';
import FileCopyOutlinedIcon from '@material-ui/icons/FileCopyOutlined';
import Public from "@/commons/components/Public";
import { CLOUDE } from "@/commons/utils/constants";
import { Grid } from "@material-ui/core";
import Text from "@/commons/components/Material.Ui/Text"
const useStyles = makeStyles({
classNameType:{ maxWidth:'inherit' }
})
export default props => {
const { open, password, closeDialogCallBack, system } = props;
const classes = useStyles()
const { setMessages, render } = Public()
return render(
<Dialogs
dialogs={open}
type="2"
classes={classes}
isBotton={false}
btnMarginTop="20px"
mixWidth="28rem"
height="11.125rem"
classNameType = {'classNameType'}
isBottom={true}
style={{ flex: 1 }}
closeAccountDialog={() => closeDialogCallBack()}
>
<Grid style={{ margin: "0 auto", padding: "46px 0 60px", boxSizing: "border-box", alignItems: 'center' }}>
<Grid style={{ display: "flex", }} >
<Text variant={"body1"} text={CLOUDE['userName'] + ":" + (system === "LINUX" ? "cloudam" : "Administrator")} />
<CopyToClipboard text={system === "LINUX" ? "cloudam" : "Administrator"}
onCopy={() => {
setMessages({
message: CLOUDE['copySuccess'],
messagetype: 'success',
})
}}>
<FileCopyOutlinedIcon fontSize={'small'} style={{ color: "#136EFA", marginLeft: "10px", cursor: "pointer" }} />
</CopyToClipboard>
</Grid>
<Grid style={{ display: "flex", }} >
<Grid style={{ textAlign: 'center', display: "flex", alignItems: "center" }}>
<Text variant={"body1"} text={CLOUDE['password'] + ":"} />
<Text variant={"body1"} text={password} />
</Grid>
<CopyToClipboard text={`${password}`}
onCopy={() => {
setMessages({
message: CLOUDE['copySuccess'],
messagetype: 'success',
})
}}>
<FileCopyOutlinedIcon fontSize={'small'} style={{ color: "#136EFA", marginLeft: "10px", cursor: "pointer" }} />
</CopyToClipboard>
</Grid>
</Grid>
</Dialogs>
)
}
\ No newline at end of file
import React from 'react'
import { makeStyles,Grid, } from '@material-ui/core'
import Text from "@/commons/components/Material.Ui/Text"
import ArrowDropUpIcon from '@material-ui/icons/ArrowDropUp';
import SelectComponent from "@/commons/components/Material.Ui/Input"
import ArrowDropDownIcon from '@material-ui/icons/ArrowDropDown';
const style= makeStyles({
flex:{
minWidth:'74px',
height:'32px',
display:'flex',
alignItems:'center',
justifyContent:'space-evenly',
border:'1px solid rgba(216, 216, 216, 0.6)'
},
icon:{
height:'32px',
display:'flex',
flexDirection:'column',
justifyContent:'space-around'
// overflow:'hidden',
},
up:{
height:'0',
width:'0',
cursor:'pointer',
border:'5px solid transparent',
borderBottomColor:'rgba(117, 117, 117, 1)'
},
down:{
height:'0',
width:'0',
cursor:'pointer',
border:'5px solid transparent',
borderTopColor:'rgba(117, 117, 117, 1)'
},
handwareRightContentGrid2:{
width:'74px',
height:'32px',
},
customizationRoot:{
height:'16px',
}
})
let time = 0
let timer = null
let timer2 = null
let numCache = 0
let upCache = false
export default props => {
const classes = style()
const [num,setNum] = React.useState(72)
const { change, current } = props
const operation ={
down:(up)=>{
numCache = num
time = 0
upCache = up ? true : false
window.addEventListener('mouseup',operation.up)
timer = setTimeout( ()=>{
time = 1
operation.ldown(up)
} ,500 )
},
up:()=>{
window.removeEventListener('mouseup',operation.up)
clearTimeout(timer)
timer = null
timer2 && clearTimeout(timer2)
timer2 = null
if(time === 0 && !(!upCache && numCache <= 0)) {
setNum(upCache?numCache+1:numCache-1)
}
timer = 0
},
ldown:(up)=>{
timer2 && clearTimeout(timer2)
if( !up && numCache <= 0 ) return
numCache = up?(numCache+1):(numCache-1)
setNum(numCache)
timer2 = setTimeout(()=>{
time = time+1
operation.ldown(up)
},time>10?100:200)
},
change:(e)=>{
if( e.target.value.indexOf('-') > -1 ) return
setNum(Number(e.target.value))
}
}
React.useEffect(()=>{
time = 0
timer = null
timer2 = null
numCache = 0
upCache = false
},[])
React.useEffect(()=>{
![undefined,''].includes(current) && setNum(current)
},[current])
React.useEffect(()=>{
change && change( num )
},[num])
const typeInput = {
icon: (type) => {
return (
<Grid className={classes.icon}>
<Grid className={classes.up} onMouseDown={()=>operation.down(1)}></Grid>
<Grid className={classes.down} onMouseDown={()=>operation.down()}></Grid>
</Grid>
)
},
}
return (
<Grid className={classes.handwareRightContentGrid2}>
<SelectComponent
size='xsmall'
customClass = {classes.customizationRoot}
fullWidth={true}
textAlign={"right"}
value={String(num)}
endAdornment={typeInput.icon("cpu")}
type={'number'}
onChange={operation.change}
/>
</Grid>)
}
\ No newline at end of file
.ant-spin-spinning{
opacity:1
}
.ant-spin{
position: absolute;
top: 0;
left: 0;
z-index: 4;
display: block;
width: 100%;
z-index: 999;
height: 100%;
min-height: 100px;
box-sizing: border-box;
margin: 0;
padding: 0;
font-size: 14px;
font-variant: tabular-nums;
line-height: 1.5715;
list-style: none;
font-feature-settings: "tnum";
color: #1890ff;
text-align: center;
transition: transform .3s cubic-bezier(.78,.14,.15,.86);
}
.ant-spin.ant-spin-show-text .ant-spin-dot{
margin-top: -20px;
}
.ant-spin .ant-spin-dot{
position: absolute;
top: 50%;
left: 50%;
margin: -10px;
z-index: 11111;
}
.ant-spin-dot-spin{
transform: rotate( 45deg );
-webkit-animation: antRotate 1.2s infinite linear;
animation: antRotate 1.2s infinite linear;
}
.ant-spin-dot{
display: inline-block;
font-size: 20px;
width: 1em;
height: 1em;
}
.ant-spin-dot-item{
position: absolute;
display: block;
width: 9px;
height: 9px;
background-color: #1890ff;
border-radius: 100%;
transform: scale(.75);
transform-origin: 50% 50%;
opacity: .3;
-webkit-animation: antSpinMove 1s infinite linear alternate;
animation: antSpinMove 1s infinite linear alternate;
}
.ant-spin-dot-item:nth-child(1){
top: 0;
left: 0;
}
.ant-spin-dot-item:nth-child(2){
top: 0;
right: 0;
-webkit-animation-delay: .4s;
animation-delay: .4s;
}
.ant-spin-dot-item:nth-child(3) {
right: 0;
bottom: 0;
-webkit-animation-delay: .8s;
animation-delay: .8s;
}
.ant-spin-dot-item:nth-child(4) {
bottom: 0;
left: 0;
-webkit-animation-delay: 1.2s;
animation-delay: 1.2s;
}
.ant-spin .ant-spin-text {
position: absolute;
top: 50%;
width: 100%;
padding-top: 5px;
text-shadow: 0 1px 2px #fff;
font-weight: 500;
}
.ant-spin.ant-spin-show-text .ant-spin-text {
display: block;
}
@-webkit-keyframes antRotate {
to {
transform: rotate(405deg)
}
}
@keyframes antRotate {
to {
transform: rotate(405deg)
}
}
@-webkit-keyframes antSpinMove {
to {
opacity: 1
}
}
@keyframes antSpinMove {
to {
opacity: 1
}
}
.ant-spin-background{
width: 100%;
height: 100%;
background-color: rgba(255,255,255,0.6);
z-index: 9999;
transition: all 0.3s;
}
\ No newline at end of file
import { useStores } from "@/store/index";
import { elements } from "@/router";
import { current, menu } from "@/api/demo_api";
import { product } from "@/api/project_api";
import localStorageKey from "@/utils/localStorageKey";
import NotFound from "@/views/404";
import useMyRequest from "@/hooks/useMyRequest";
import { useEffect } from "react";
const useMyRouter = () => {
const { permissionStore, menuStore } = useStores();
const { permissionStore, menuStore, currentProjectStore } = useStores();
const userInfo = useMyRequest(current);
const menuInfo = useMyRequest(menu);
const productInfo = useMyRequest(product);
useEffect(() => {
userInfo.run();
menuInfo.run();
productInfo.run({
product: "CADD",
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
if (userInfo.res && menuInfo.res) {
localStorage.setItem(localStorageKey.TOKEN, JSON.stringify(userInfo.res));
localStorage.setItem(
localStorageKey.USER_INFO,
JSON.stringify(userInfo.res)
);
permissionStore.restAddRoutes();
for (let item of menuInfo.res.data) {
......@@ -32,8 +41,20 @@ const useMyRouter = () => {
menuStore.initMenu(menuInfo.res.data);
permissionStore.initAllRoutes();
}
if (productInfo.res) {
let list = productInfo.data?.data;
if (list.length === 0) {
currentProjectStore.setProjectList([]);
currentProjectStore.changeProject({});
} else {
currentProjectStore.setProjectList(list);
currentProjectStore.changeProject(list[0]);
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [userInfo.data, menuInfo.data]);
}, [userInfo.data, menuInfo.data, productInfo.data]);
return permissionStore.allRoutes;
};
......
.noProject {
width: 100%;
height: calc(100vh - 57px);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.noDataImg {
width: 220px;
margin-bottom: 4px;
}
.text1 {
line-height: 24px;
font-size: 16px;
color: #1e2633;
margin-bottom: 4px;
}
.text2 {
line-height: 22px;
font-size: 14px;
color: #8a9099;
margin-bottom: 24px;
}
.button {
background-color: #1370ff;
color: #fff;
}
import style from "./NoProject.module.css";
import noData from "@/assets/project/noData.svg";
import { Button } from "@mui/material";
import AddIcon from "@mui/icons-material/Add";
import AddProject from "@/views/Project/components/AddProject";
import React from "react";
const NoProject = () => {
let addProjectRef: any = React.createRef();
const handleClickOpen = () => {
addProjectRef.current.handleClickOpen();
};
return (
<div className={style.noProject}>
<img src={noData} alt="" className={style.noDataImg} />
<div className={style.text1}>当前产品暂无项目</div>
<div className={style.text2}>请先创建项目</div>
<Button
variant="contained"
size="large"
className={style.button}
startIcon={<AddIcon />}
onClick={handleClickOpen}
style={{ backgroundColor: "#1370ff", color: "#fff" }}
>
创建项目
</Button>
<AddProject onRef={addProjectRef} />
</div>
);
};
export default NoProject;
import NoProject from "./NoProject";
export default NoProject;
import React, { FC } from "react";
import { Typography, Menu, MenuItem, IconButton, Button } from "@mui/material";
import { makeStyles } from "@mui/styles";
import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown';
import cx from "classnames"
type ButtonTagProps = {
text: string;
variant?: "text" | 'contained' | 'outlined';
click: any;
select?: any[];
fontSize?: string;
dropValue?: boolean;
drop?: boolean;
}
const useStyles = makeStyles({
root: { backgroundColor: "#136EFA", boxShadow: "none !important", color: "#ffffff", "&:hover": { backgroundColor: "#ffffff !important" } },
ArrowDropDownIconRoot: { color: "#8A9099", transition: "all 0.2s !important", transform: "rotate(0)" },
ArrowDropDownIconRootOpen: { color: "#8A9099", transform: "rotate(180deg)" },
})
const ButtonComponent = (props: ButtonTagProps) => {
const classes = useStyles();
const [anchorEl, setAnchorEl] = React.useState(null);
const handleClick = (event: { currentTarget: React.SetStateAction<null>; }) => setAnchorEl(event.currentTarget);
const defultClick = (event: { stoppropagation: () => any; }) => event && event.stoppropagation && event.stoppropagation()
const handleClose = () => setAnchorEl(null);
return (
<>
<Button
variant={props.variant || 'contained'}
disableRipple={true}
disableFocusRipple={true}
classes={{
root: classes.root,
}}
sx={{ color: "#565C66" }}//暂定
onClick={props.select ? handleClick : (props.click || defultClick)}
>
<Typography style={{ fontSize: props.fontSize || "14px" }}>{props.text}</Typography>
{
(props.select && props.select.length > 0 || props.drop) && <ArrowDropDownIcon classes={{
root: cx({
[classes.ArrowDropDownIconRoot]: true,
[classes.ArrowDropDownIconRootOpen]: Boolean(props.dropValue || anchorEl)
})
}} />
}
</Button>
<Menu
id="product-menu"
keepMounted
anchorEl={anchorEl}
open={Boolean(anchorEl)}
onClose={handleClose}
MenuListProps={{
"aria-labelledby": "product-button",
}}
>
{
props.select && props.select.length > 0 && props.select.map((item, key) => {
return (
<MenuItem
key={item.path}
onClick={() => {
// navigate(item.path);
handleClose();
}}
>
{item.name}
</MenuItem>
);
})}
</Menu>
</>
)
}
export default ButtonComponent;
\ No newline at end of file
import React from "react";
import {
Button,
Dialog,
DialogActions,
DialogContent,
DialogTitle,
} from "@mui/material";
import CloseIcon from "@mui/icons-material/Close";
export interface IDialogProps {
/** 自定义类名 */
className?: string;
/** 自定义样式 */
style?: React.CSSProperties;
/** 弹窗的标题 */
title?: string;
/** 是否显示弹窗 */
open: boolean;
isHideHeader?: boolean;
/** 是否隐藏弹窗底部按钮部分 */
isHideFooter?: boolean;
/** 自定义底部按钮 */
footerRender?: () => React.ReactNode;
/** 是否显示取消按钮 */
showCancel?: boolean;
/** 是否显示确定按钮 */
showConfirm?: boolean;
/** 关闭弹窗时的回调函数 */
onClose?: () => void;
/** 点击确定按钮时的回调函数 */
onConfirm?: () => void;
/** 取消按钮文案 */
cancelText?: string;
/** 确认按钮文案 */
okText?: string;
/** 是否禁用确认按钮 */
disabledConfirm?: boolean;
children: React.ReactNode;
}
export interface IFooter {
isHideFooter?: boolean;
footerRender?: () => React.ReactNode;
showCancel?: boolean;
/** 是否显示确定按钮 */
showConfirm?: boolean;
/** 关闭弹窗时的回调函数 */
onClose?: () => void;
/** 点击确定按钮时的回调函数 */
onConfirm?: () => void;
/** 取消按钮文案 */
cancelText?: string;
/** 确认按钮文案 */
okText?: string;
/** 是否禁用确认按钮 */
disabledConfirm?: boolean;
}
const MyDialog: React.FunctionComponent<IDialogProps> = (props) => {
const {
title,
open,
style,
onClose,
onConfirm,
isHideFooter,
isHideHeader,
children,
footerRender,
className,
showCancel = true,
/** 是否显示确定按钮 */
showConfirm = true,
cancelText,
okText,
disabledConfirm,
} = props;
const Footer = () => {
if (isHideFooter) return null;
return footerRender ? (
footerRender()
) : (
<DialogActions style={{ padding: "0 24px 24px 24px" }}>
{showCancel ? (
<Button onClick={onClose} variant="outlined" size="small">
{cancelText || "取消"}
</Button>
) : null}
{showConfirm ? (
<Button
onClick={onConfirm}
variant="contained"
size="small"
disabled={disabledConfirm}
>
{okText || "确定"}
</Button>
) : null}
</DialogActions>
);
};
return (
<Dialog
open={open}
onClose={onClose}
style={style}
className={className}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
{isHideHeader ? null : (
<DialogTitle id="alert-dialog-title">
<div
style={{
display: "flex",
justifyContent: "space-between",
alignItems: "center",
}}
>
<span>{title}</span>
<CloseIcon
onClick={onClose}
style={{ color: "#C2C6CC", cursor: "pointer" }}
/>
</div>
</DialogTitle>
)}
<DialogContent style={{ minWidth: 400 }}>{children}</DialogContent>
{Footer()}
</Dialog>
);
};
export default MyDialog;
import {
Button,
Dialog,
DialogActions,
DialogContent,
IconButton,
DialogTitle,
} from "@mui/material";
import LoadingButton from "@mui/lab/LoadingButton";
import CloseIcon from "@mui/icons-material/Close";
import { useState } from "react";
import { useImperativeHandle } from "react";
const MyDialog = (props: any) => {
const [open, setOpen] = useState(false);
const {
title,
handleSubmit,
submitloading,
submitStyle = { backgroundColor: "#1370FF" },
} = props;
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
useImperativeHandle(props.onRef, () => {
return {
handleClickOpen: handleClickOpen,
handleClose: handleClose,
};
});
return (
<Dialog
open={open}
onClose={handleClose}
aria-labelledby="form-dialog-title"
>
{title && <DialogTitle id="form-dialog-title">{title}</DialogTitle>}
<DialogContent>
{props.children}
<IconButton
aria-label="delete"
style={{ position: "absolute", top: "10px", right: "12px" }}
onClick={handleClose}
>
<CloseIcon style={{ color: "#C2C6CC" }} />
</IconButton>
</DialogContent>
<DialogActions style={{ padding: "24px" }}>
<Button
onClick={handleClose}
color="inherit"
variant="contained"
style={{ color: "#1E2633", backgroundColor: "#fff" }}
>
取消
</Button>
<LoadingButton
loading={submitloading}
onClick={handleSubmit}
color="primary"
variant="contained"
style={submitStyle}
>
确认
</LoadingButton>
</DialogActions>
</Dialog>
);
};
export default MyDialog;
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2021-12-04 15:46:25
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-07 21:13:38
* @FilePath: /lionet-slb-pc/src/components/SearchView/components/Collapse.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import * as React from "react";
import Box from "@mui/material/Box";
import InputLabel from "@mui/material/InputLabel";
import MenuItem from "@mui/material/MenuItem";
import FormControl from "@mui/material/FormControl";
import Select, { SelectProps } from "@mui/material/Select";
export interface IOption {
label: string;
value: string;
disabled?: boolean;
}
interface IProps
extends Omit<SelectProps, "value" | "options" | "onChange" | "title"> {
value?: IOption;
options: IOption[];
onChange?: (val: IOption) => void;
title?: string;
}
export default function BasicSelect(props: IProps) {
const { value, options, onChange, title, input } = props;
const handleChange = (event: any) => {
const newValue = options?.filter((item) => {
return item.value === event.target.value;
});
if (onChange) {
onChange(newValue[0] || { label: "", value: "" });
}
};
return (
<Box sx={{ minWidth: 120 }}>
<FormControl fullWidth>
{input ? null : (
<InputLabel id="demo-simple-select-label">
{title || "请选择"}
</InputLabel>
)}
<Select
labelId="demo-simple-select-label"
id="demo-simple-select"
label={title || "请选择"}
size="small"
{...props}
value={value?.value}
onChange={handleChange}
>
{options.length
? options?.map((item: IOption) => {
return (
<MenuItem value={item.value} disabled={item?.disabled}>
{item.label}
</MenuItem>
);
})
: null}
</Select>
</FormControl>
</Box>
);
}
This diff is collapsed.
This diff is collapsed.
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
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;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
monospace;
}
......@@ -7,6 +7,7 @@ import { Provider } from "mobx-react";
import { stores } from "@/store/index";
import { MySnackbarProvider } from "@/components/MySnackbar";
import "@/mocks/index";
import './assets/style/public.css'
const root = ReactDOM.createRoot(
document.getElementById("root") as HTMLElement
......
......@@ -30,6 +30,22 @@ const demo = [
icon: "",
type: "product",
routes: [
{
id: "PROJECT_SETTING",
type: "page",
name: "项目设置",
path: "/setting",
icon: "",
element: "ProjectSetting",
show: "true",
// children: [
// {
// id: "PROJECT_OVERIVEW_CREATE",
// type: "operation",
// name: "创建项目",
// },
// ],
},
{
id: "PROJECT_OVERIVEW",
type: "page",
......
This diff is collapsed.
This diff is collapsed.
......@@ -2,10 +2,11 @@ import * as React from "react";
import { configure } from "mobx";
import permissionStore from "./modules/permission";
import menuStore from "./modules/menu";
import currentProjectStore from "./modules/currentProject";
configure({ enforceActions: "always" });
export const stores = { permissionStore, menuStore };
export const stores = { permissionStore, menuStore, currentProjectStore };
export const CounterContext = React.createContext(stores);
export const useStores = () => React.useContext(CounterContext);
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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