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 引用

+
+ +

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">&#x33;</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 @@ + + + + Created by iconfont + + + + + + + + + + + + + + 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 (
- logo + logo
); 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} +
+
{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}, + }, + ]; -import React from 'react'; -const IndexPage:React.FC = () => { return ( -
IndexPage
- ) -} +
+ {/* 通知列表 */} + + {noticeList.map((item) => ( + + + } + > +

{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 ( +
+ {intl.formatMessage({ id: 'login.register.tip' })} + + {intl.formatMessage({ id: 'login.register.action' })} + +
+ ); + }; + + 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" + /> + + + +
+ + {intl.formatMessage({ id: 'login.remember' })} + + + {intl.formatMessage({ id: 'login.forgot' })} + +
+
+ + + + {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' }) }]} + > + +
+ + + + + + + + + + +
+ {intl.formatMessage({ id: 'register.hasAccount' })} + history.push('/login')}> + {intl.formatMessage({ id: 'register.login' })} + +
+
+ + + + + ); +}; + +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 ( +
+
+ + +
+ {intl.formatMessage({ id: 'register.supplier.title' })} +
+ + +
+ + } placeholder={intl.formatMessage({ id: 'register.username.placeholder' })} /> + + + + } placeholder={intl.formatMessage({ id: 'register.password.placeholder' })} /> + + + ({ + 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' })} /> + + + + + + + + + + + + } placeholder={intl.formatMessage({ id: 'register.phone.placeholder' })} /> + + + + } placeholder={intl.formatMessage({ id: 'register.email.placeholder' })} /> + + + + +
+ {intl.formatMessage({ id: 'register.hasAccount' })} + history.push('/login')}> + {intl.formatMessage({ id: 'register.login' })} + +
+
+ +
+
+
+ ); +}; + +export default SupplierRegister;