diff --git a/config/config.ts b/config/config.ts
index 672eeaf..aa833e0 100644
--- a/config/config.ts
+++ b/config/config.ts
@@ -1,11 +1,13 @@
import { defineConfig } from 'umi';
-import defaultSettings from './defaultSettings';
+import defaultSettings,{antdTheme} from './defaultSettings';
// import proxy from './proxy';
import PageRoutes from './router.config'
const { REACT_APP_ENV } = process.env;
export default defineConfig({
hash: true,
- antd: {},
+ antd: {
+
+ },
dva: {
hmr: true,
},
@@ -30,6 +32,8 @@ export default defineConfig({
'primary-color': defaultSettings.primaryColor,
'heading-color': defaultSettings.headingColor,
'text-color': defaultSettings.textColor,
+ // 更改antd 组件颜色
+ ...antdTheme
},
// @ts-ignore
title: false,
diff --git a/config/defaultSettings.ts b/config/defaultSettings.ts
index 6a852dc..76eba5b 100644
--- a/config/defaultSettings.ts
+++ b/config/defaultSettings.ts
@@ -2,15 +2,15 @@ import { Settings as ProSettings } from '@ant-design/pro-layout';
type DefaultSettings = ProSettings & {
pwa: boolean;
- headingColor:string;
- textColor:string;
+ headingColor: string;
+ textColor: string;
};
const proSettings: DefaultSettings = {
navTheme: 'light',
primaryColor: 'rgb(0,79,142)',
- headingColor:"#000",
- textColor:"#000",
+ headingColor: "#000",
+ textColor: "#000",
layout: 'side',
contentWidth: 'Fluid',
fixedHeader: false,
@@ -24,6 +24,15 @@ const proSettings: DefaultSettings = {
iconfontUrl: '',
};
+export const antdTheme = {
+ // 更改antd 组件颜色
+ 'table-header-bg': 'rgb(241,245,251)',
+ 'table-row-hover-bg': 'rgb(241,245,251)',
+ 'table-padding-vertical': '12px',
+ 'table-header-color': 'rgb(143,146,153)'
+}
+
export type { DefaultSettings };
+
export default proSettings;
diff --git a/config/router.config.ts b/config/router.config.ts
index 94ce732..16fbfb9 100644
--- a/config/router.config.ts
+++ b/config/router.config.ts
@@ -1,5 +1,21 @@
-
export default [
+ {
+ path: '/login',
+ component: '@/pages/login/login',
+ },
+ {
+ path: '/register',
+ routes: [
+ {
+ path: '/register/supplier',
+ component: '@/pages/register/supplier',
+ },
+ {
+ path: '/register/expert',
+ component: '@/pages/register/expert',
+ }
+ ]
+ },
{
path: '/',
component: '@/layouts/Index',
@@ -18,6 +34,11 @@ export default [
path: '/announce',
component: '@/pages/announce/announce',
},
+ {
+ name: 'announceInfo',
+ path: '/announce/announceInfo',
+ component: '@/pages/announce/announceInfo',
+ },
{
name: 'policy',
path: '/policy',
@@ -28,6 +49,12 @@ export default [
path: '/notice',
component: '@/pages/notice/notice',
},
+ {
+ name: 'noticeInfo',
+ path: '/notice/noticeInfo',
+ component: '@/pages/notice/noticeInfo',
+ activeMenu: 'notice'
+ },
{
name: 'download',
path: '/download',
diff --git a/src/assets/iconfont/demo.css b/src/assets/iconfont/demo.css
new file mode 100644
index 0000000..a67054a
--- /dev/null
+++ b/src/assets/iconfont/demo.css
@@ -0,0 +1,539 @@
+/* Logo 字体 */
+@font-face {
+ font-family: "iconfont logo";
+ src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
+ src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
+ url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
+ url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
+ url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
+}
+
+.logo {
+ font-family: "iconfont logo";
+ font-size: 160px;
+ font-style: normal;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+/* tabs */
+.nav-tabs {
+ position: relative;
+}
+
+.nav-tabs .nav-more {
+ position: absolute;
+ right: 0;
+ bottom: 0;
+ height: 42px;
+ line-height: 42px;
+ color: #666;
+}
+
+#tabs {
+ border-bottom: 1px solid #eee;
+}
+
+#tabs li {
+ cursor: pointer;
+ width: 100px;
+ height: 40px;
+ line-height: 40px;
+ text-align: center;
+ font-size: 16px;
+ border-bottom: 2px solid transparent;
+ position: relative;
+ z-index: 1;
+ margin-bottom: -1px;
+ color: #666;
+}
+
+
+#tabs .active {
+ border-bottom-color: #f00;
+ color: #222;
+}
+
+.tab-container .content {
+ display: none;
+}
+
+/* 页面布局 */
+.main {
+ padding: 30px 100px;
+ width: 960px;
+ margin: 0 auto;
+}
+
+.main .logo {
+ color: #333;
+ text-align: left;
+ margin-bottom: 30px;
+ line-height: 1;
+ height: 110px;
+ margin-top: -50px;
+ overflow: hidden;
+ *zoom: 1;
+}
+
+.main .logo a {
+ font-size: 160px;
+ color: #333;
+}
+
+.helps {
+ margin-top: 40px;
+}
+
+.helps pre {
+ padding: 20px;
+ margin: 10px 0;
+ border: solid 1px #e7e1cd;
+ background-color: #fffdef;
+ overflow: auto;
+}
+
+.icon_lists {
+ width: 100% !important;
+ overflow: hidden;
+ *zoom: 1;
+}
+
+.icon_lists li {
+ width: 100px;
+ margin-bottom: 10px;
+ margin-right: 20px;
+ text-align: center;
+ list-style: none !important;
+ cursor: default;
+}
+
+.icon_lists li .code-name {
+ line-height: 1.2;
+}
+
+.icon_lists .icon {
+ display: block;
+ height: 100px;
+ line-height: 100px;
+ font-size: 42px;
+ margin: 10px auto;
+ color: #333;
+ -webkit-transition: font-size 0.25s linear, width 0.25s linear;
+ -moz-transition: font-size 0.25s linear, width 0.25s linear;
+ transition: font-size 0.25s linear, width 0.25s linear;
+}
+
+.icon_lists .icon:hover {
+ font-size: 100px;
+}
+
+.icon_lists .svg-icon {
+ /* 通过设置 font-size 来改变图标大小 */
+ width: 1em;
+ /* 图标和文字相邻时,垂直对齐 */
+ vertical-align: -0.15em;
+ /* 通过设置 color 来改变 SVG 的颜色/fill */
+ fill: currentColor;
+ /* path 和 stroke 溢出 viewBox 部分在 IE 下会显示
+ normalize.css 中也包含这行 */
+ overflow: hidden;
+}
+
+.icon_lists li .name,
+.icon_lists li .code-name {
+ color: #666;
+}
+
+/* markdown 样式 */
+.markdown {
+ color: #666;
+ font-size: 14px;
+ line-height: 1.8;
+}
+
+.highlight {
+ line-height: 1.5;
+}
+
+.markdown img {
+ vertical-align: middle;
+ max-width: 100%;
+}
+
+.markdown h1 {
+ color: #404040;
+ font-weight: 500;
+ line-height: 40px;
+ margin-bottom: 24px;
+}
+
+.markdown h2,
+.markdown h3,
+.markdown h4,
+.markdown h5,
+.markdown h6 {
+ color: #404040;
+ margin: 1.6em 0 0.6em 0;
+ font-weight: 500;
+ clear: both;
+}
+
+.markdown h1 {
+ font-size: 28px;
+}
+
+.markdown h2 {
+ font-size: 22px;
+}
+
+.markdown h3 {
+ font-size: 16px;
+}
+
+.markdown h4 {
+ font-size: 14px;
+}
+
+.markdown h5 {
+ font-size: 12px;
+}
+
+.markdown h6 {
+ font-size: 12px;
+}
+
+.markdown hr {
+ height: 1px;
+ border: 0;
+ background: #e9e9e9;
+ margin: 16px 0;
+ clear: both;
+}
+
+.markdown p {
+ margin: 1em 0;
+}
+
+.markdown>p,
+.markdown>blockquote,
+.markdown>.highlight,
+.markdown>ol,
+.markdown>ul {
+ width: 80%;
+}
+
+.markdown ul>li {
+ list-style: circle;
+}
+
+.markdown>ul li,
+.markdown blockquote ul>li {
+ margin-left: 20px;
+ padding-left: 4px;
+}
+
+.markdown>ul li p,
+.markdown>ol li p {
+ margin: 0.6em 0;
+}
+
+.markdown ol>li {
+ list-style: decimal;
+}
+
+.markdown>ol li,
+.markdown blockquote ol>li {
+ margin-left: 20px;
+ padding-left: 4px;
+}
+
+.markdown code {
+ margin: 0 3px;
+ padding: 0 5px;
+ background: #eee;
+ border-radius: 3px;
+}
+
+.markdown strong,
+.markdown b {
+ font-weight: 600;
+}
+
+.markdown>table {
+ border-collapse: collapse;
+ border-spacing: 0px;
+ empty-cells: show;
+ border: 1px solid #e9e9e9;
+ width: 95%;
+ margin-bottom: 24px;
+}
+
+.markdown>table th {
+ white-space: nowrap;
+ color: #333;
+ font-weight: 600;
+}
+
+.markdown>table th,
+.markdown>table td {
+ border: 1px solid #e9e9e9;
+ padding: 8px 16px;
+ text-align: left;
+}
+
+.markdown>table th {
+ background: #F7F7F7;
+}
+
+.markdown blockquote {
+ font-size: 90%;
+ color: #999;
+ border-left: 4px solid #e9e9e9;
+ padding-left: 0.8em;
+ margin: 1em 0;
+}
+
+.markdown blockquote p {
+ margin: 0;
+}
+
+.markdown .anchor {
+ opacity: 0;
+ transition: opacity 0.3s ease;
+ margin-left: 8px;
+}
+
+.markdown .waiting {
+ color: #ccc;
+}
+
+.markdown h1:hover .anchor,
+.markdown h2:hover .anchor,
+.markdown h3:hover .anchor,
+.markdown h4:hover .anchor,
+.markdown h5:hover .anchor,
+.markdown h6:hover .anchor {
+ opacity: 1;
+ display: inline-block;
+}
+
+.markdown>br,
+.markdown>p>br {
+ clear: both;
+}
+
+
+.hljs {
+ display: block;
+ background: white;
+ padding: 0.5em;
+ color: #333333;
+ overflow-x: auto;
+}
+
+.hljs-comment,
+.hljs-meta {
+ color: #969896;
+}
+
+.hljs-string,
+.hljs-variable,
+.hljs-template-variable,
+.hljs-strong,
+.hljs-emphasis,
+.hljs-quote {
+ color: #df5000;
+}
+
+.hljs-keyword,
+.hljs-selector-tag,
+.hljs-type {
+ color: #a71d5d;
+}
+
+.hljs-literal,
+.hljs-symbol,
+.hljs-bullet,
+.hljs-attribute {
+ color: #0086b3;
+}
+
+.hljs-section,
+.hljs-name {
+ color: #63a35c;
+}
+
+.hljs-tag {
+ color: #333333;
+}
+
+.hljs-title,
+.hljs-attr,
+.hljs-selector-id,
+.hljs-selector-class,
+.hljs-selector-attr,
+.hljs-selector-pseudo {
+ color: #795da3;
+}
+
+.hljs-addition {
+ color: #55a532;
+ background-color: #eaffea;
+}
+
+.hljs-deletion {
+ color: #bd2c00;
+ background-color: #ffecec;
+}
+
+.hljs-link {
+ text-decoration: underline;
+}
+
+/* 代码高亮 */
+/* PrismJS 1.15.0
+https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
+/**
+ * prism.js default theme for JavaScript, CSS and HTML
+ * Based on dabblet (http://dabblet.com)
+ * @author Lea Verou
+ */
+code[class*="language-"],
+pre[class*="language-"] {
+ color: black;
+ background: none;
+ text-shadow: 0 1px white;
+ font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
+ text-align: left;
+ white-space: pre;
+ word-spacing: normal;
+ word-break: normal;
+ word-wrap: normal;
+ line-height: 1.5;
+
+ -moz-tab-size: 4;
+ -o-tab-size: 4;
+ tab-size: 4;
+
+ -webkit-hyphens: none;
+ -moz-hyphens: none;
+ -ms-hyphens: none;
+ hyphens: none;
+}
+
+pre[class*="language-"]::-moz-selection,
+pre[class*="language-"] ::-moz-selection,
+code[class*="language-"]::-moz-selection,
+code[class*="language-"] ::-moz-selection {
+ text-shadow: none;
+ background: #b3d4fc;
+}
+
+pre[class*="language-"]::selection,
+pre[class*="language-"] ::selection,
+code[class*="language-"]::selection,
+code[class*="language-"] ::selection {
+ text-shadow: none;
+ background: #b3d4fc;
+}
+
+@media print {
+
+ code[class*="language-"],
+ pre[class*="language-"] {
+ text-shadow: none;
+ }
+}
+
+/* Code blocks */
+pre[class*="language-"] {
+ padding: 1em;
+ margin: .5em 0;
+ overflow: auto;
+}
+
+:not(pre)>code[class*="language-"],
+pre[class*="language-"] {
+ background: #f5f2f0;
+}
+
+/* Inline code */
+:not(pre)>code[class*="language-"] {
+ padding: .1em;
+ border-radius: .3em;
+ white-space: normal;
+}
+
+.token.comment,
+.token.prolog,
+.token.doctype,
+.token.cdata {
+ color: slategray;
+}
+
+.token.punctuation {
+ color: #999;
+}
+
+.namespace {
+ opacity: .7;
+}
+
+.token.property,
+.token.tag,
+.token.boolean,
+.token.number,
+.token.constant,
+.token.symbol,
+.token.deleted {
+ color: #905;
+}
+
+.token.selector,
+.token.attr-name,
+.token.string,
+.token.char,
+.token.builtin,
+.token.inserted {
+ color: #690;
+}
+
+.token.operator,
+.token.entity,
+.token.url,
+.language-css .token.string,
+.style .token.string {
+ color: #9a6e3a;
+ background: hsla(0, 0%, 100%, .5);
+}
+
+.token.atrule,
+.token.attr-value,
+.token.keyword {
+ color: #07a;
+}
+
+.token.function,
+.token.class-name {
+ color: #DD4A68;
+}
+
+.token.regex,
+.token.important,
+.token.variable {
+ color: #e90;
+}
+
+.token.important,
+.token.bold {
+ font-weight: bold;
+}
+
+.token.italic {
+ font-style: italic;
+}
+
+.token.entity {
+ cursor: help;
+}
diff --git a/src/assets/iconfont/demo_index.html b/src/assets/iconfont/demo_index.html
new file mode 100644
index 0000000..ffe868c
--- /dev/null
+++ b/src/assets/iconfont/demo_index.html
@@ -0,0 +1,258 @@
+
+
+
+
+ iconfont Demo
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - Unicode
+ - Font class
+ - Symbol
+
+
+
查看项目
+
+
+
+
+
+
+ -
+
+
地址
+ 
+
+
+ -
+
+
电话
+ 
+
+
+ -
+
+
邮箱
+ 
+
+
+
+
+
Unicode 引用
+
+
+
Unicode 是字体在网页端最原始的应用方式,特点是:
+
+ - 支持按字体的方式去动态调整图标大小,颜色等等。
+ - 默认情况下不支持多色,直接添加多色图标会自动去色。
+
+
+ 注意:新版 iconfont 支持两种方式引用多色图标:SVG symbol 引用方式和彩色字体图标模式。(使用彩色字体图标需要在「编辑项目」中开启「彩色」选项后并重新生成。)
+
+
Unicode 使用步骤如下:
+
第一步:拷贝项目下面生成的 @font-face
+
@font-face {
+ font-family: 'iconfont';
+ src: url('iconfont.woff2?t=1750055522436') format('woff2'),
+ url('iconfont.woff?t=1750055522436') format('woff'),
+ url('iconfont.ttf?t=1750055522436') format('truetype'),
+ url('iconfont.svg?t=1750055522436#iconfont') format('svg');
+}
+
+
第二步:定义使用 iconfont 的样式
+
.iconfont {
+ font-family: "iconfont" !important;
+ font-size: 16px;
+ font-style: normal;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+
第三步:挑选相应图标并获取字体编码,应用于页面
+
+<span class="iconfont">3</span>
+
+
+ "iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。
+
+
+
+
+
+
+ -
+
+
+ 地址
+
+ .icon-dizhi
+
+
+
+ -
+
+
+ 电话
+
+ .icon-dianhua
+
+
+
+ -
+
+
+ 邮箱
+
+ .icon-youxiang
+
+
+
+
+
+
font-class 引用
+
+
+
font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode 书写不直观,语意不明确的问题。
+
与 Unicode 使用方式相比,具有如下特点:
+
+ - 相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。
+ - 因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。
+
+
使用步骤如下:
+
第一步:引入项目下面生成的 fontclass 代码:
+
<link rel="stylesheet" href="./iconfont.css">
+
+
第二步:挑选相应图标并获取类名,应用于页面:
+
<span class="iconfont icon-xxx"></span>
+
+
+ "
+ iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。
+
+
+
+
+
+
+ -
+
+
地址
+ #icon-dizhi
+
+
+ -
+
+
电话
+ #icon-dianhua
+
+
+ -
+
+
邮箱
+ #icon-youxiang
+
+
+
+
+
Symbol 引用
+
+
+
这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇文章
+ 这种用法其实是做了一个 SVG 的集合,与另外两种相比具有如下特点:
+
+ - 支持多色图标了,不再受单色限制。
+ - 通过一些技巧,支持像字体那样,通过
font-size
, color
来调整样式。
+ - 兼容性较差,支持 IE9+,及现代浏览器。
+ - 浏览器渲染 SVG 的性能一般,还不如 png。
+
+
使用步骤如下:
+
第一步:引入项目下面生成的 symbol 代码:
+
<script src="./iconfont.js"></script>
+
+
第二步:加入通用 CSS 代码(引入一次就行):
+
<style>
+.icon {
+ width: 1em;
+ height: 1em;
+ vertical-align: -0.15em;
+ fill: currentColor;
+ overflow: hidden;
+}
+</style>
+
+
第三步:挑选相应图标并获取类名,应用于页面:
+
<svg class="icon" aria-hidden="true">
+ <use xlink:href="#icon-xxx"></use>
+</svg>
+
+
+
+
+
+
+
+
+
diff --git a/src/assets/iconfont/iconfont.css b/src/assets/iconfont/iconfont.css
new file mode 100644
index 0000000..39fcad3
--- /dev/null
+++ b/src/assets/iconfont/iconfont.css
@@ -0,0 +1,28 @@
+@font-face {
+ font-family: "iconfont"; /* Project id 4950533 */
+ src: url('iconfont.woff2?t=1750055522436') format('woff2'),
+ url('iconfont.woff?t=1750055522436') format('woff'),
+ url('iconfont.ttf?t=1750055522436') format('truetype'),
+ url('iconfont.svg?t=1750055522436#iconfont') format('svg');
+}
+
+.iconfont {
+ font-family: "iconfont" !important;
+ font-size: 16px;
+ font-style: normal;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+.icon-dizhi:before {
+ content: "\e60c";
+}
+
+.icon-dianhua:before {
+ content: "\e603";
+}
+
+.icon-youxiang:before {
+ content: "\e645";
+}
+
diff --git a/src/assets/iconfont/iconfont.js b/src/assets/iconfont/iconfont.js
new file mode 100644
index 0000000..8b6d17b
--- /dev/null
+++ b/src/assets/iconfont/iconfont.js
@@ -0,0 +1 @@
+window._iconfont_svg_string_4950533='',(n=>{var t=(e=(e=document.getElementsByTagName("script"))[e.length-1]).getAttribute("data-injectcss"),e=e.getAttribute("data-disable-injectsvg");if(!e){var i,o,c,d,s,a=function(t,e){e.parentNode.insertBefore(t,e)};if(t&&!n.__iconfont__svg__cssinject__){n.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(t){console&&console.log(t)}}i=function(){var t,e=document.createElement("div");e.innerHTML=n._iconfont_svg_string_4950533,(e=e.getElementsByTagName("svg")[0])&&(e.setAttribute("aria-hidden","true"),e.style.position="absolute",e.style.width=0,e.style.height=0,e.style.overflow="hidden",e=e,(t=document.body).firstChild?a(e,t.firstChild):t.appendChild(e))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(i,0):(o=function(){document.removeEventListener("DOMContentLoaded",o,!1),i()},document.addEventListener("DOMContentLoaded",o,!1)):document.attachEvent&&(c=i,d=n.document,s=!1,r(),d.onreadystatechange=function(){"complete"==d.readyState&&(d.onreadystatechange=null,l())})}function l(){s||(s=!0,c())}function r(){try{d.documentElement.doScroll("left")}catch(t){return void setTimeout(r,50)}l()}})(window);
\ No newline at end of file
diff --git a/src/assets/iconfont/iconfont.json b/src/assets/iconfont/iconfont.json
new file mode 100644
index 0000000..158ad82
--- /dev/null
+++ b/src/assets/iconfont/iconfont.json
@@ -0,0 +1,30 @@
+{
+ "id": "4950533",
+ "name": "中远",
+ "font_family": "iconfont",
+ "css_prefix_text": "icon-",
+ "description": "",
+ "glyphs": [
+ {
+ "icon_id": "5093357",
+ "name": "地址",
+ "font_class": "dizhi",
+ "unicode": "e60c",
+ "unicode_decimal": 58892
+ },
+ {
+ "icon_id": "6682217",
+ "name": "电话",
+ "font_class": "dianhua",
+ "unicode": "e603",
+ "unicode_decimal": 58883
+ },
+ {
+ "icon_id": "7140587",
+ "name": "邮箱",
+ "font_class": "youxiang",
+ "unicode": "e645",
+ "unicode_decimal": 58949
+ }
+ ]
+}
diff --git a/src/assets/iconfont/iconfont.svg b/src/assets/iconfont/iconfont.svg
new file mode 100644
index 0000000..0b7d8f8
--- /dev/null
+++ b/src/assets/iconfont/iconfont.svg
@@ -0,0 +1,25 @@
+
+
+
diff --git a/src/assets/iconfont/iconfont.ttf b/src/assets/iconfont/iconfont.ttf
new file mode 100644
index 0000000..27ea4a7
Binary files /dev/null and b/src/assets/iconfont/iconfont.ttf differ
diff --git a/src/assets/iconfont/iconfont.woff b/src/assets/iconfont/iconfont.woff
new file mode 100644
index 0000000..4f93e5a
Binary files /dev/null and b/src/assets/iconfont/iconfont.woff differ
diff --git a/src/assets/iconfont/iconfont.woff2 b/src/assets/iconfont/iconfont.woff2
new file mode 100644
index 0000000..9fed9bb
Binary files /dev/null and b/src/assets/iconfont/iconfont.woff2 differ
diff --git a/src/assets/img/loginBg.jpg b/src/assets/img/loginBg.jpg
new file mode 100644
index 0000000..4ec2706
Binary files /dev/null and b/src/assets/img/loginBg.jpg differ
diff --git a/src/baseStyle.less b/src/baseStyle.less
index 237f02d..4459fc1 100644
--- a/src/baseStyle.less
+++ b/src/baseStyle.less
@@ -1,6 +1,8 @@
//定义主题颜色
@main-color: rgb(0, 79, 142);
@main-text-color: #000;
+@main-text-color-1: #333;
+@main-text-color-2: #666;
@main-danger-color: rgb(214, 0, 14);
//灰色
diff --git a/src/components/IconFont/IconFont.tsx b/src/components/IconFont/IconFont.tsx
new file mode 100644
index 0000000..3f37bca
--- /dev/null
+++ b/src/components/IconFont/IconFont.tsx
@@ -0,0 +1,18 @@
+import { createFromIconfontCN } from '@ant-design/icons';
+import React from 'react';
+
+interface IconFontProps {
+ type: string;
+ [key: string]: any;
+}
+const IconFont: React.FC = (props) => {
+ const Icon = createFromIconfontCN({
+ // 线上
+ // scriptUrl: '//at.alicdn.com/t/c/font_4950533_qp1wyf22tmb.js',
+ // 本地
+ scriptUrl: require('@/assets/iconfont/iconfont.js'),
+ });
+ return ;
+};
+
+export default IconFont;
diff --git a/src/components/SpaceBlock/SpaceBlock.less b/src/components/SpaceBlock/SpaceBlock.less
new file mode 100644
index 0000000..e164270
--- /dev/null
+++ b/src/components/SpaceBlock/SpaceBlock.less
@@ -0,0 +1,7 @@
+@import '../../baseStyle.less';
+.spaceBlock {
+ height: 10px;
+ margin: 0 -15px;
+ margin-top: 20px;
+ background: rgba(@gray, 0.3);
+}
diff --git a/src/components/SpaceBlock/SpaceBlock.tsx b/src/components/SpaceBlock/SpaceBlock.tsx
new file mode 100644
index 0000000..28ba7c6
--- /dev/null
+++ b/src/components/SpaceBlock/SpaceBlock.tsx
@@ -0,0 +1,7 @@
+import React from 'react';
+import './SpaceBlock.less';
+const SpaceBlock: React.FC = () => {
+ return ;
+};
+
+export default SpaceBlock;
diff --git a/src/global.less b/src/global.less
index a200c83..249efaa 100644
--- a/src/global.less
+++ b/src/global.less
@@ -6,7 +6,19 @@ body,
#root {
height: 100%;
}
-
+.layout-content {
+ box-sizing: border-box;
+ height: calc(100% - 60px);
+ overflow: auto;
+ padding: 15px 0;
+ background: rgba(@gray, 0.3);
+ .layout-content-main {
+ width: @width;
+ margin: 0 auto;
+ background: #fff;
+ padding: 15px;
+ }
+}
.colorWeak {
filter: invert(80%);
}
diff --git a/src/layouts/Header.less b/src/layouts/Header.less
index 282441e..74e0d65 100644
--- a/src/layouts/Header.less
+++ b/src/layouts/Header.less
@@ -1,9 +1,27 @@
@import '../baseStyle.less';
.header {
+ position: relative;
+ z-index: 1;
display: flex;
- align-items: flex-end;
+ align-items: center;
justify-content: space-between;
width: @width;
margin: 0 auto;
+ .logo {
+ height: 45px;
+ }
+}
+.header-menu {
+ display: flex;
+ flex: 1;
+ align-items: center;
+ justify-content: flex-end;
+ .ant-menu-horizontal {
+ line-height: 58px;
+ border: none;
+ }
+}
+.user {
+ margin-left: 15px;
}
diff --git a/src/layouts/Header.tsx b/src/layouts/Header.tsx
index 0e53255..45edb02 100644
--- a/src/layouts/Header.tsx
+++ b/src/layouts/Header.tsx
@@ -8,7 +8,7 @@ import HeaderMenu from './HeaderMenu';
const Header: React.FC = (props) => {
return (
-

+
);
diff --git a/src/layouts/HeaderMenu.less b/src/layouts/HeaderMenu.less
deleted file mode 100644
index 9b564e7..0000000
--- a/src/layouts/HeaderMenu.less
+++ /dev/null
@@ -1,7 +0,0 @@
-.header-menu{
- display: flex;
- align-items: center;
- .ant-menu-horizontal{
- border: none;
- }
-}
\ No newline at end of file
diff --git a/src/layouts/HeaderMenu.tsx b/src/layouts/HeaderMenu.tsx
index 57f2d3e..3ec067b 100644
--- a/src/layouts/HeaderMenu.tsx
+++ b/src/layouts/HeaderMenu.tsx
@@ -2,13 +2,13 @@ import React, { useEffect, useState } from 'react';
import { Menu } from 'antd';
import Language from './Language';
import { useIntl, Link, useHistory } from 'umi';
+import User from './User';
interface IMenuItem {
label: string;
key: string;
path: string;
}
// 引入样式文件 useIntl().formatMessage({ id: 'menu.首页' }),
-import './HeaderMenu.less';
const items: IMenuItem[] = [
{
label: 'menu.首页',
@@ -53,6 +53,10 @@ const HeaderMenu: React.FC = (props) => {
const menu = items.find((item) => item.path === path);
if (menu) {
setCurrent(menu.key);
+ }else{
+ // 如果跳转的详情页面获取根级激活菜单
+ const rootActiveMenu = path.split('/')[1];
+ setCurrent(rootActiveMenu);
}
}, [history.location.pathname]);
return (
@@ -65,6 +69,7 @@ const HeaderMenu: React.FC = (props) => {
))}
+
);
};
diff --git a/src/layouts/Index.tsx b/src/layouts/Index.tsx
index 3f65b1f..a80afd1 100644
--- a/src/layouts/Index.tsx
+++ b/src/layouts/Index.tsx
@@ -5,7 +5,9 @@ const LayoutIndex: React.FC = (props) => {
return (
<>
- {children}
+
>
);
};
diff --git a/src/layouts/User.tsx b/src/layouts/User.tsx
new file mode 100644
index 0000000..43f1c27
--- /dev/null
+++ b/src/layouts/User.tsx
@@ -0,0 +1,11 @@
+import React from 'react';
+import { Link, useIntl } from 'umi';
+const User: React.FC = (props) => {
+ const intl = useIntl();
+ return (
+
+ {intl.formatMessage({ id: '登录/注册' })}
+
+ );
+};
+export default User;
diff --git a/src/locales/en-US.ts b/src/locales/en-US.ts
index b069e53..0fb2bfc 100644
--- a/src/locales/en-US.ts
+++ b/src/locales/en-US.ts
@@ -1,9 +1,90 @@
-
export default {
- 'menu.首页': 'home',
+ 'menu.首页': 'Home',
'menu.公告公示': 'Public Announcement',
- 'menu.政策法规': 'Policies and regulations',
+ 'menu.政策法规': 'Policies and Regulations',
'menu.通知中心': 'Notifications',
'menu.下载中心': 'Download Center',
- 'menu.关于我们': 'About Us'
+ 'menu.关于我们': 'About Us',
+ "查看":"Info",
+ "采购需求公示":"Procurement Demand Announcement",
+ "招标采购公告":"Bidding Procurement Announcement",
+ "非招标采购公告":"Non-bidding Procurement Announcement",
+ "资格预审公告":"Pre-qualification Announcement",
+ "招募公告":"Recruitment Announcement",
+ "变更公告":"Change Announcement",
+ "中标(中选)候选人公示":"Bid Winner Candidate Announcement",
+ "中标(中选)结果公示":"Bid Result Announcement",
+ "采购失败(流标)公告":"Failed Procurement Announcement",
+ "加载更多":"Load More",
+ "登录/注册":"Login/Register",
+
+ // Login page
+ "login.title": "E-Bidding Platform",
+ "login.tab.supplier": "Supplier",
+ "login.tab.expert": "Expert",
+ "login.tab.agent": "Bidding Agent",
+ "login.username.placeholder": "Please enter username",
+ "login.password.placeholder": "Please enter password",
+ "login.remember": "Remember me",
+ "login.forgot": "Forgot password?",
+ "login.button": "Login",
+ "login.register.tip": "Don't have an account?",
+ "login.register.action": "Register now",
+ "login.back.home": "Back to home",
+
+ // Registration common text
+ "register.submit": "Complete Registration",
+ "register.hasAccount": "Already have an account?",
+ "register.login": "Login now",
+
+ // Username and password common text
+ "register.username.label": "Username",
+ "register.username.placeholder": "Please enter username",
+ "register.username.required": "Please enter username",
+ "register.username.min": "Username must be at least 4 characters",
+ "register.password.label": "Password",
+ "register.password.placeholder": "Please enter password (6-16 characters with letters and numbers)",
+ "register.password.required": "Please enter password",
+ "register.password.min": "Password must be at least 6 characters",
+ "register.password.pattern": "Password must be 6-16 characters with letters and numbers",
+ "register.confirmPassword.label": "Confirm Password",
+ "register.confirmPassword.placeholder": "Please confirm password, must match the password above",
+ "register.confirmPassword.required": "Please confirm password",
+ "register.confirmPassword.notMatch": "The two passwords do not match",
+ "register.phone.label": "Phone Number",
+ "register.phone.placeholder": "Please enter phone number",
+ "register.phone.required": "Please enter phone number",
+ "register.phone.invalid": "Please enter a valid phone number",
+ "register.email.label": "Email",
+ "register.email.placeholder": "Please enter email",
+ "register.email.required": "Please enter email",
+ "register.email.invalid": "Please enter a valid email",
+ "register.captcha.label": "SMS Verification Code",
+ "register.captcha.placeholder": "Please enter verification code",
+ "register.captcha.required": "Please enter verification code",
+ "register.captcha.get": "Get Code",
+
+ // Supplier registration text
+ "register.supplier.title": "Supplier Registration",
+ "register.supplier.companyName.label": "Company Name",
+ "register.supplier.companyName.placeholder": "Please enter company name",
+ "register.supplier.companyName.required": "Please enter company name",
+ "register.supplier.contactPerson.label": "Contact Person",
+ "register.supplier.contactPerson.placeholder": "Please enter contact person",
+ "register.supplier.contactPerson.required": "Please enter contact person",
+
+ // Expert registration text
+ "register.expert.title": "Expert Registration",
+ "register.expert.realName.label": "Real Name",
+ "register.expert.realName.placeholder": "Please enter real name",
+ "register.expert.realName.required": "Please enter real name",
+ "register.expert.idType.label": "ID Type",
+ "register.expert.idType.placeholder": "Please select ID type",
+ "register.expert.idCard.label": "ID Number",
+ "register.expert.idCard.placeholder": "Please enter ID number",
+ "register.expert.idCard.required": "Please enter ID number",
+ "register.expert.idCard.invalid": "Please enter a valid ID number",
+ "register.expert.specialty.label": "Specialty Field",
+ "register.expert.specialty.placeholder": "Please select specialty field",
+ "register.expert.specialty.required": "Please select specialty field"
};
diff --git a/src/locales/zh-CN.ts b/src/locales/zh-CN.ts
index 58abf3a..bb7c434 100644
--- a/src/locales/zh-CN.ts
+++ b/src/locales/zh-CN.ts
@@ -1,9 +1,90 @@
-
export default {
'menu.首页': '首页',
'menu.公告公示': '公告公示',
'menu.政策法规': '政策法规',
'menu.通知中心': '通知中心',
'menu.下载中心': '下载中心',
- 'menu.关于我们': '关于我们'
+ 'menu.关于我们': '关于我们',
+ "查看":"查看",
+ "采购需求公示":"采购需求公示",
+ "招标采购公告":"招标采购公告",
+ "非招标采购公告":"非招标采购公告",
+ "资格预审公告":"资格预审公告",
+ "招募公告":"招募公告",
+ "变更公告":"变更公告",
+ "中标(中选)候选人公示":"中标(中选)候选人公示",
+ "中标(中选)结果公示":"中标(中选)结果公示",
+ "采购失败(流标)公告":"采购失败(流标)公告",
+ "加载更多":"加载更多",
+ "登录/注册":"登录/注册",
+
+ // 登录页文案
+ "login.title": "电子招投标平台",
+ "login.tab.supplier": "供应商",
+ "login.tab.expert": "专家",
+ "login.tab.agent": "招标代理",
+ "login.username.placeholder": "请输入用户名",
+ "login.password.placeholder": "请输入密码",
+ "login.remember": "记住密码",
+ "login.forgot": "忘记密码?",
+ "login.button": "登录",
+ "login.register.tip": "还没有账号?",
+ "login.register.action": "立即注册",
+ "login.back.home": "返回首页",
+
+ // 注册页通用文案
+ "register.submit": "注册完成",
+ "register.hasAccount": "已有账号?",
+ "register.login": "立即登录",
+
+ // 用户名密码通用文案
+ "register.username.label": "用户名",
+ "register.username.placeholder": "请输入用户名",
+ "register.username.required": "请输入用户名",
+ "register.username.min": "用户名至少4个字符",
+ "register.password.label": "输入密码",
+ "register.password.placeholder": "请输入密码,应为6-16位的英文加数字组合",
+ "register.password.required": "请输入密码",
+ "register.password.min": "密码至少6个字符",
+ "register.password.pattern": "密码应为6-16位的英文加数字组合",
+ "register.confirmPassword.label": "确认密码",
+ "register.confirmPassword.placeholder": "请再次输入密码,两次输入保持一致",
+ "register.confirmPassword.required": "请确认密码",
+ "register.confirmPassword.notMatch": "两次输入的密码不一致",
+ "register.phone.label": "手机号",
+ "register.phone.placeholder": "请输入手机号",
+ "register.phone.required": "请输入手机号",
+ "register.phone.invalid": "请输入有效的手机号",
+ "register.email.label": "电子邮箱",
+ "register.email.placeholder": "请输入电子邮箱",
+ "register.email.required": "请输入电子邮箱",
+ "register.email.invalid": "请输入有效的电子邮箱",
+ "register.captcha.label": "短信验证码",
+ "register.captcha.placeholder": "请输入短信验证码",
+ "register.captcha.required": "请输入短信验证码",
+ "register.captcha.get": "获取验证码",
+
+ // 供应商注册文案
+ "register.supplier.title": "供应商注册",
+ "register.supplier.companyName.label": "公司名称",
+ "register.supplier.companyName.placeholder": "请输入公司名称",
+ "register.supplier.companyName.required": "请输入公司名称",
+ "register.supplier.contactPerson.label": "联系人",
+ "register.supplier.contactPerson.placeholder": "请输入联系人姓名",
+ "register.supplier.contactPerson.required": "请输入联系人姓名",
+
+ // 专家注册文案
+ "register.expert.title": "专家注册",
+ "register.expert.realName.label": "真实姓名",
+ "register.expert.realName.placeholder": "请输入真实姓名",
+ "register.expert.realName.required": "请输入真实姓名",
+ "register.expert.idType.label": "证件类型",
+ "register.expert.idType.placeholder": "请选择证件类型",
+ "register.expert.idCard.label": "证件号",
+ "register.expert.idCard.placeholder": "请输入证件号",
+ "register.expert.idCard.required": "请输入证件号",
+ "register.expert.idCard.invalid": "请输入有效的证件号",
+ "register.expert.specialty.label": "专业领域",
+ "register.expert.specialty.placeholder": "请选择专业领域",
+ "register.expert.specialty.required": "请选择专业领域"
};
diff --git a/src/pages/announce/announceInfo.tsx b/src/pages/announce/announceInfo.tsx
new file mode 100644
index 0000000..9e09575
--- /dev/null
+++ b/src/pages/announce/announceInfo.tsx
@@ -0,0 +1,8 @@
+import React from 'react';
+import { useLocation } from 'umi';
+const AnnounceInfo: React.FC = () => {
+ const location = useLocation();
+ const id = new URLSearchParams(location.search).get("id")
+ return <>AnnounceInfo -------- {id}>;
+};
+export default AnnounceInfo;
diff --git a/src/pages/index/Link.tsx b/src/pages/index/Link.tsx
new file mode 100644
index 0000000..567b11c
--- /dev/null
+++ b/src/pages/index/Link.tsx
@@ -0,0 +1,17 @@
+import React from 'react';
+const LinkComponent: React.FC = () => {
+ return (
+
+ );
+};
+
+export default LinkComponent;
diff --git a/src/pages/index/index.less b/src/pages/index/index.less
new file mode 100644
index 0000000..1a528f6
--- /dev/null
+++ b/src/pages/index/index.less
@@ -0,0 +1,53 @@
+@import '../../baseStyle.less';
+.lastDate {
+ color: @main-danger-color;
+}
+.tableAddress {
+ color: @main-color;
+ font-weight: 600;
+}
+.tableLoadMore {
+ margin-top: 15px;
+ text-align: center;
+}
+.blockTitle {
+ font-weight: 600;
+ font-size: 16px;
+ line-height: 30px;
+}
+.questionItem {
+ line-height: 40px;
+ .icon {
+ margin-right: 10px;
+ font-size: 18px;
+ }
+}
+.cardContent {
+ color: @main-text-color-2;
+}
+.card {
+ .ant-card-head {
+ min-height: 40px;
+ padding: 0 15px;
+ .ant-card-head-title,
+ .ant-card-extra {
+ padding: 10px 0;
+ }
+ }
+ .ant-card-body {
+ min-height: 150px;
+ text-indent: 26px;
+ }
+}
+.link {
+ display: flex;
+ margin-top: 10px;
+ .flex {
+ margin-left: 10px;
+ display: flex;
+ flex: 1;
+ a{
+ margin: 0 10px;
+ }
+ }
+}
diff --git a/src/pages/index/index.tsx b/src/pages/index/index.tsx
index e31b061..5829cd6 100644
--- a/src/pages/index/index.tsx
+++ b/src/pages/index/index.tsx
@@ -1,10 +1,247 @@
+import React, { useState } from 'react';
+import { Card, Row, Col, Tabs, Table } from 'antd';
+import { useIntl, Link } from 'umi';
+import SpaceBlock from '@/components/SpaceBlock/SpaceBlock';
+import './index.less';
+import IconFont from '@/components/IconFont/IconFont';
+import LinkComponent from './Link';
+const IndexPage: React.FC = () => {
+ const intl = useIntl();
+ const [noticeLoading, setNoticeLoading] = useState(false);
+ const [noticeList, setNoticeList] = useState([
+ {
+ title: 'CA使用通知',
+ id: '1',
+ content: '系统将于2022年5月27日期开始对全流程使用CA服务,届时全部投标供应商需办理CA。',
+ },
+ {
+ title: '5月27日系统优化升级通知',
+ id: '2',
+ content:
+ '系统将于2022年5月27日(周五)22:00--2022年5月28日(周六)6:00进行系统优化升级,届时系统将暂停服务。',
+ },
+ {
+ title: '测试标题123123',
+ id: '3',
+ content: '测试内容124145',
+ },
+ {
+ title: '测试标题45435',
+ id: '4',
+ content: '测试内容6666',
+ },
+ ]);
+ const tabList = [
+ {
+ key: '1',
+ label: intl.formatMessage({ id: '采购需求公示' }),
+ },
+ {
+ key: '2',
+ label: intl.formatMessage({ id: '招标采购公告' }),
+ },
+ {
+ key: '3',
+ label: intl.formatMessage({ id: '非招标采购公告' }),
+ },
+ {
+ key: '4',
+ label: intl.formatMessage({ id: '资格预审公告' }),
+ },
+ {
+ key: '5',
+ label: intl.formatMessage({ id: '招募公告' }),
+ },
+ {
+ key: '6',
+ label: intl.formatMessage({ id: '变更公告' }),
+ },
+ {
+ key: '7',
+ label: intl.formatMessage({ id: '中标(中选)候选人公示' }),
+ },
+ {
+ key: '8',
+ label: intl.formatMessage({ id: '中标(中选)结果公示' }),
+ },
+ {
+ key: '9',
+ label: intl.formatMessage({ id: '采购失败(流标)公告' }),
+ },
+ ];
+ //tab 切换事件
+ const tabChange = (key: string) => {
+ console.log(key);
+ };
+ const [tableLoading, setTableLoading] = useState(false);
+ const dataSource = [
+ {
+ key: '1',
+ title: '中远海运空运北方物流基地标识制作及安装服务',
+ address: '西湖区湖底公园1号',
+ date: '2025年01月23日',
+ lastDate: '剩余3天4小时',
+ },
+ {
+ key: '2',
+ title: '中远海运空运北方物流基地标识制作及安装服务',
+ address: '西湖区湖底公园1号',
+ date: '2025年01月23日',
+ lastDate: '剩余3天4小时',
+ },
+ {
+ key: '2',
+ title: '中远海运空运北方物流基地标识制作及安装服务',
+ address: '西湖区湖底公园1号',
+ date: '2025年01月23日',
+ lastDate: '剩余3天4小时',
+ },
+ {
+ key: '2',
+ title: '中远海运空运北方物流基地标识制作及安装服务',
+ address: '西湖区湖底公园1号',
+ date: '2025年01月23日',
+ lastDate: '剩余3天4小时',
+ },
+ {
+ key: '2',
+ title: '中远海运空运北方物流基地标识制作及安装服务',
+ address: '西湖区湖底公园1号',
+ date: '2025年01月23日',
+ lastDate: '剩余3天4小时',
+ },
+ {
+ key: '2',
+ title: '中远海运空运北方物流基地标识制作及安装服务',
+ address: '西湖区湖底公园1号',
+ date: '2025年01月23日',
+ lastDate: '剩余3天4小时',
+ },
+ ];
+
+ const columns = [
+ {
+ title: '项目所在地',
+ dataIndex: 'address',
+ key: 'address',
+ },
+ {
+ title: '公告标题',
+ dataIndex: 'title',
+ key: 'title',
+ render: (text: string, record) => (
+
+ {text}
+
+ ),
+ },
+ {
+ title: '发布时间',
+ dataIndex: 'date',
+ key: 'date',
+ },
+ {
+ title: '文件购买截止时间',
+ dataIndex: 'lastDate',
+ key: 'lastDate',
+ render: (text: string) => {text},
+ },
+ ];
-import React from 'react';
-const IndexPage:React.FC = () => {
return (
- IndexPage
- )
-}
+
+ {/* 通知列表 */}
+
+ {noticeList.map((item) => (
+
+
+ {intl.formatMessage({ id: '查看' })}
+
+ }
+ >
+ {item.content}
+
+
+ ))}
+
+
+
+ {tabList.map((item) => (
+
+ ))}
+
+
-export default IndexPage;
\ No newline at end of file
+
+
+ {intl.formatMessage({ id: '加载更多' })}
+
+
+
+
+
+ 紧急问题咨询
+
+
+
+ 北京市前门大街173号
+
+
+
+ 17676373746
+
+
+
+ i723648723@383.com
+
+
+
+ CA服务
+
+
+ CA办理
+
+
+ CA客服
+
+
+
+ 联系方式
+ 客服1: 400-300-9989
+ 客服1: 400-300-9989
+ 客服1: 400-300-9989
+ 客服1: 400-300-9989
+
+
+
+
+
+
+
+
+ );
+};
+
+export default IndexPage;
diff --git a/src/pages/login.tsx b/src/pages/login.tsx
deleted file mode 100644
index 609c9f0..0000000
--- a/src/pages/login.tsx
+++ /dev/null
@@ -1,10 +0,0 @@
-
-import React from 'react';
-const LoginPage:React.FC = () => {
- return (
- LoginPage
- )
-}
-
-
-export default LoginPage;
\ No newline at end of file
diff --git a/src/pages/login/login.less b/src/pages/login/login.less
new file mode 100644
index 0000000..59e3140
--- /dev/null
+++ b/src/pages/login/login.less
@@ -0,0 +1,194 @@
+@import '~@/baseStyle.less';
+
+// 登录页面整体布局
+.login-page {
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
+ min-height: 100vh;
+ padding-right: 10%;
+ background: #f0f2f5;
+ background-image: url('~@/assets/img/loginBg.jpg');
+ background-position: center;
+ background-size: cover;
+}
+
+// 登录容器
+.login-container {
+ position: relative;
+ width: 400px;
+ padding: 30px;
+ background: #fff;
+ border-radius: 8px;
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
+}
+
+// 标题样式
+.login-title {
+ margin-bottom: 20px;
+ color: @main-color;
+ font-weight: bold;
+ font-size: 24px;
+ text-align: center;
+}
+
+// 返回首页链接
+.back-home {
+ position: absolute;
+ top: 10px;
+ left: 10px;
+
+ a {
+ display: flex;
+ align-items: center;
+ color: @main-color;
+ font-size: 14px;
+
+ &:hover {
+ color: lighten(@main-color, 10%);
+ }
+
+ .anticon {
+ margin-right: 4px;
+ }
+ }
+}
+
+// Tab 容器
+.login-tab-container {
+ margin-bottom: 30px;
+}
+
+// Tab 样式
+.login-tabs {
+ border-radius: 15px;
+ .ant-tabs-nav {
+ margin: 0;
+ }
+
+ .ant-tabs-nav::before {
+ display: none;
+ }
+
+ .ant-tabs-tab {
+ flex: 1;
+ height: 44px;
+ margin: 0;
+ padding: 0;
+ font-weight: bold;
+ font-size: 16px;
+ line-height: 44px;
+ text-align: center;
+ background-color: #f5f5f5;
+ border: none;
+ transition: none;
+
+ .ant-tabs-tab-btn {
+ width: 100%;
+ height: 100%;
+ color: #333;
+ }
+ }
+
+ .ant-tabs-nav-list {
+ display: flex;
+ width: 100%;
+ overflow: hidden;
+ }
+
+ .ant-tabs-tab-active {
+ background-color: @main-color;
+ border-radius: 15px;
+
+ .ant-tabs-tab-btn {
+ color: #fff !important;
+ font-weight: bold;
+ }
+ }
+
+ .ant-tabs-ink-bar {
+ display: none;
+ }
+}
+
+// 登录表单
+.login-form {
+ .ant-form-item {
+ margin-bottom: 20px;
+ }
+
+ .ant-input-affix-wrapper {
+ border-radius: 10px;
+
+ &:focus,
+ &-focused,
+ &:hover {
+ border-color: @main-color;
+ }
+ }
+}
+
+// 登录选项区域(记住密码和忘记密码)
+.login-options {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+
+ .ant-checkbox-checked .ant-checkbox-inner {
+ background-color: @main-color;
+ border-color: @main-color;
+ }
+
+ .login-form-forgot {
+ color: @main-color;
+
+ &:hover {
+ color: lighten(@main-color, 10%);
+ }
+ }
+}
+
+// 登录按钮
+.login-form-button {
+ width: 100%;
+ height: 40px;
+ margin-top: 10px;
+ background-color: @main-color;
+ border-color: @main-color;
+ border-radius: 4px;
+
+ &:hover,
+ &:focus {
+ background-color: lighten(@main-color, 10%);
+ border-color: lighten(@main-color, 10%);
+ }
+}
+
+// 注册链接
+.register-link {
+ margin-top: 15px;
+ text-align: center;
+
+ a {
+ margin-left: 5px;
+ color: @main-color;
+
+ &:hover {
+ color: lighten(@main-color, 10%);
+ }
+ }
+}
+
+// 响应式布局
+@media (max-width: 768px) {
+ .login-page {
+ justify-content: center;
+ padding-right: 0;
+ }
+
+ .login-container {
+ width: 90%;
+ max-width: 400px;
+ padding: 20px;
+ }
+}
diff --git a/src/pages/login/login.tsx b/src/pages/login/login.tsx
new file mode 100644
index 0000000..993a82f
--- /dev/null
+++ b/src/pages/login/login.tsx
@@ -0,0 +1,134 @@
+import React, { useState } from 'react';
+import { Form, Input, Button, Checkbox, Tabs, message } from 'antd';
+import { UserOutlined, LockOutlined, EyeInvisibleOutlined, EyeTwoTone, HomeOutlined } from '@ant-design/icons';
+import { history, useIntl } from 'umi';
+import './login.less';
+
+const { TabPane } = Tabs;
+
+const LoginPage: React.FC = () => {
+ const [activeKey, setActiveKey] = useState('supplier');
+ const [form] = Form.useForm();
+ const [loading, setLoading] = useState(false);
+ const intl = useIntl();
+
+ const onFinish = (values: any) => {
+ setLoading(true);
+ console.log('登录信息:', values);
+ // 这里添加登录逻辑
+ setTimeout(() => {
+ setLoading(false);
+ message.success('登录成功');
+ history.push('/index');
+ }, 1000);
+ };
+
+ const handleTabChange = (key: string) => {
+ setActiveKey(key);
+ form.resetFields();
+ };
+
+ // 根据当前选中的Tab决定跳转到哪个注册页面
+ const handleRegister = () => {
+ switch(activeKey) {
+ case 'supplier':
+ history.push('/register/supplier');
+ break;
+ case 'expert':
+ history.push('/register/expert');
+ break;
+ default:
+ // 招标代理不提供注册功能
+ break;
+ }
+ };
+
+ // 渲染注册链接(只在供应商和专家Tab下显示)
+ const renderRegisterLink = () => {
+ if (activeKey === 'agent') {
+ return null; // 招标代理不显示注册链接
+ }
+
+ return (
+
+ );
+ };
+
+ return (
+
+
+
+
+
{intl.formatMessage({ id: 'login.title' })}
+
+
+
+
+
+
+
+
+
+
+ }
+ placeholder={intl.formatMessage({ id: 'login.username.placeholder' })}
+ size="large"
+ />
+
+
+
+ }
+ placeholder={intl.formatMessage({ id: 'login.password.placeholder' })}
+ iconRender={visible => (visible ? : )}
+ size="large"
+ />
+
+
+
+
+
+
+
+
+ {renderRegisterLink()}
+
+
+
+
+ );
+};
+
+export default LoginPage;
diff --git a/src/pages/notice/noticeInfo.tsx b/src/pages/notice/noticeInfo.tsx
new file mode 100644
index 0000000..602b462
--- /dev/null
+++ b/src/pages/notice/noticeInfo.tsx
@@ -0,0 +1,8 @@
+import React from 'react';
+import { useLocation } from 'umi';
+const NoticeInfo: React.FC = () => {
+ const location = useLocation();
+ const id = new URLSearchParams(location.search).get("id")
+ return <>NoticeInfo -------- {id}>;
+};
+export default NoticeInfo;
diff --git a/src/pages/register/expert.tsx b/src/pages/register/expert.tsx
new file mode 100644
index 0000000..7d0c1d2
--- /dev/null
+++ b/src/pages/register/expert.tsx
@@ -0,0 +1,190 @@
+import React, { useState } from 'react';
+import { useIntl, history } from 'umi';
+import { Form, Input, Button, message, Card, Select, Row, Col } from 'antd';
+import { UserOutlined, LockOutlined, MobileOutlined, IdcardOutlined, HomeOutlined } from '@ant-design/icons';
+import './register.less';
+
+const { Option } = Select;
+
+const ExpertRegister: React.FC = () => {
+ const [form] = Form.useForm();
+ const intl = useIntl();
+ const [loading, setLoading] = useState(false);
+ const [countdown, setCountdown] = useState(0);
+
+ // 获取短信验证码
+ const handleGetCaptcha = () => {
+ form.validateFields(['phone']).then(values => {
+ message.success(`验证码已发送至 ${values.phone}`);
+ let count = 60;
+ setCountdown(count);
+
+ const timer = setInterval(() => {
+ count--;
+ setCountdown(count);
+ if (count === 0) {
+ clearInterval(timer);
+ }
+ }, 1000);
+ }).catch(errorInfo => {
+ message.error('请先输入正确的手机号');
+ });
+ };
+
+ const onFinish = (values: any) => {
+ setLoading(true);
+ console.log('专家注册信息:', values);
+ // 这里添加注册逻辑
+ setTimeout(() => {
+ setLoading(false);
+ message.success('注册成功,请登录');
+ history.push('/login');
+ }, 1000);
+ };
+
+ return (
+
+
+
+
+
+ {intl.formatMessage({ id: 'register.expert.title' })}
+
+
+
+ {intl.formatMessage({ id: 'register.username.label' })}}
+ rules={[
+ { required: true, message: intl.formatMessage({ id: 'register.username.required' }) },
+ { min: 4, message: intl.formatMessage({ id: 'register.username.min' }) }
+ ]}
+ >
+ } placeholder={intl.formatMessage({ id: 'register.username.placeholder' })} />
+
+
+ {intl.formatMessage({ id: 'register.phone.label' })}}
+ rules={[
+ { required: true, message: intl.formatMessage({ id: 'register.phone.required' }) },
+ { pattern: /^1[3-9]\d{9}$/, message: intl.formatMessage({ id: 'register.phone.invalid' }) }
+ ]}
+ >
+ } placeholder={intl.formatMessage({ id: 'register.phone.placeholder' })} />
+
+
+
+
+
+
+ {intl.formatMessage({ id: 'register.expert.idCard.label' })}}
+ rules={[
+ { required: true, message: intl.formatMessage({ id: 'register.expert.idCard.required' }) }
+ ]}
+ >
+ } placeholder={intl.formatMessage({ id: 'register.expert.idCard.placeholder' })} />
+
+
+ {intl.formatMessage({ id: 'register.password.label' })}}
+ rules={[
+ { required: true, message: intl.formatMessage({ id: 'register.password.required' }) },
+ { min: 6, message: intl.formatMessage({ id: 'register.password.min' }) },
+ { pattern: /^[a-zA-Z0-9]{6,16}$/, message: intl.formatMessage({ id: 'register.password.pattern' }) }
+ ]}
+ >
+ }
+ placeholder={intl.formatMessage({ id: 'register.password.placeholder' })}
+ />
+
+
+ {intl.formatMessage({ id: 'register.confirmPassword.label' })}}
+ dependencies={['password']}
+ rules={[
+ { required: true, message: intl.formatMessage({ id: 'register.confirmPassword.required' }) },
+ ({ getFieldValue }) => ({
+ validator(_, value) {
+ if (!value || getFieldValue('password') === value) {
+ return Promise.resolve();
+ }
+ return Promise.reject(new Error(intl.formatMessage({ id: 'register.confirmPassword.notMatch' })));
+ },
+ }),
+ ]}
+ >
+ }
+ placeholder={intl.formatMessage({ id: 'register.confirmPassword.placeholder' })}
+ />
+
+
+ {intl.formatMessage({ id: 'register.captcha.label' })}}
+ rules={[{ required: true, message: intl.formatMessage({ id: 'register.captcha.required' }) }]}
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default ExpertRegister;
diff --git a/src/pages/register/register.less b/src/pages/register/register.less
new file mode 100644
index 0000000..31692c8
--- /dev/null
+++ b/src/pages/register/register.less
@@ -0,0 +1,162 @@
+@import '~@/baseStyle.less';
+
+// 注册页面整体布局
+.register-page {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ min-height: 100vh;
+ background: #f0f2f5;
+ background-image: url('~@/assets/img/loginBg.jpg');
+ background-size: cover;
+ background-position: center;
+}
+
+// 注册容器
+.register-container {
+ width: 600px;
+ padding: 30px;
+ background: #fff;
+ border-radius: 8px;
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
+ position: relative;
+ margin: 40px 0;
+}
+
+// 标题样式
+.register-title {
+ margin-bottom: 20px;
+ color: @main-color;
+ font-weight: bold;
+ font-size: 24px;
+ text-align: center;
+}
+
+// 返回首页链接
+.back-home {
+ position: absolute;
+ top: 10px;
+ left: 10px;
+
+ a {
+ display: flex;
+ align-items: center;
+ color: @main-color;
+ font-size: 14px;
+
+ &:hover {
+ color: lighten(@main-color, 10%);
+ }
+
+ .anticon {
+ margin-right: 4px;
+ }
+ }
+}
+
+// 注册卡片
+.register-card {
+ border-radius: 8px;
+ box-shadow: none;
+
+ .ant-card-body {
+ padding: 20px 0;
+ }
+}
+
+// 必填字段标记
+.required-label::before {
+ display: inline-block;
+ margin-right: 4px;
+ color: #ff4d4f;
+ font-size: 14px;
+ font-family: SimSun, sans-serif;
+ line-height: 1;
+ content: '*';
+}
+
+// 注册表单
+.register-form {
+ .ant-form-item {
+ margin-bottom: 20px;
+ }
+
+ .ant-input,
+ .ant-input-affix-wrapper,
+ .ant-select-selector {
+ border-radius: 6px;
+
+ &:focus,
+ &-focused,
+ &:hover {
+ border-color: @main-color;
+ }
+ }
+
+ .ant-form-item-label > label {
+ font-weight: 500;
+ }
+}
+
+// 验证码按钮
+.captcha-button {
+ width: 100%;
+ height: 40px;
+ background-color: @main-color;
+ border-color: @main-color;
+ color: #fff;
+
+ &:hover,
+ &:focus {
+ background-color: lighten(@main-color, 10%);
+ border-color: lighten(@main-color, 10%);
+ color: #fff;
+ }
+
+ &:disabled {
+ color: rgba(0, 0, 0, 0.25);
+ background-color: #f5f5f5;
+ border-color: #d9d9d9;
+ }
+}
+
+// 注册按钮
+.register-button {
+ width: 100%;
+ height: 40px;
+ margin-top: 10px;
+ background-color: @main-color;
+ border-color: @main-color;
+ border-radius: 6px;
+
+ &:hover,
+ &:focus {
+ background-color: lighten(@main-color, 10%);
+ border-color: lighten(@main-color, 10%);
+ }
+}
+
+// 登录链接
+.login-link {
+ margin-top: 15px;
+ text-align: center;
+
+ a {
+ margin-left: 5px;
+ color: @main-color;
+
+ &:hover {
+ color: lighten(@main-color, 10%);
+ }
+ }
+}
+
+// 响应式布局
+@media (max-width: 768px) {
+ .register-container {
+ width: 90%;
+ max-width: 500px;
+ padding: 20px;
+ margin: 20px 0;
+ }
+}
diff --git a/src/pages/register/supplier.tsx b/src/pages/register/supplier.tsx
new file mode 100644
index 0000000..86c35e0
--- /dev/null
+++ b/src/pages/register/supplier.tsx
@@ -0,0 +1,136 @@
+import React from 'react';
+import { useIntl, history } from 'umi';
+import { Form, Input, Button, message, Card } from 'antd';
+import { UserOutlined, LockOutlined, MobileOutlined, MailOutlined, HomeOutlined } from '@ant-design/icons';
+import './register.less';
+
+const SupplierRegister: React.FC = () => {
+ const [form] = Form.useForm();
+ const intl = useIntl();
+
+ const onFinish = (values: any) => {
+ console.log('供应商注册信息:', values);
+ // 这里添加注册逻辑
+ message.success('注册成功,请登录');
+ history.push('/login');
+ };
+
+ return (
+
+ );
+};
+
+export default SupplierRegister;