lanjianrong 4 anni fa
parent
commit
aafe3194c7

+ 6 - 0
config/routes.js

@@ -15,6 +15,12 @@ export default [
     redirect: '/workbench'
   },
   {
+    path: '/account/settings',
+    name: 'settings',
+    hideInMenu: true,
+    component: './User/Account/Settings'
+  },
+  {
     path: '/workbench',
     name: 'workbench',
     icon: 'icon-chess',

+ 7 - 9
src/components/RightContent/AvatarDropdown.tsx

@@ -1,6 +1,6 @@
 /* eslint-disable */
 import React, { useCallback } from 'react'
-import { InfoCircleFilled, LogoutOutlined } from '@ant-design/icons'
+import { InfoCircleFilled, LogoutOutlined, SettingOutlined, UserOutlined } from '@ant-design/icons'
 import { Avatar, Menu, Spin, Modal } from 'antd'
 import { history, useModel } from 'umi'
 import { stringify } from 'querystring'
@@ -44,7 +44,7 @@ const AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({ menu }) => {
     }) => {
       const { key } = event
       if (key === 'logout' && initialState) {
-        Modal.confirm({
+        return Modal.confirm({
           icon: <InfoCircleFilled />,
           title: '温馨提示',
           content: '是否确认退出系统?',
@@ -57,7 +57,7 @@ const AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({ menu }) => {
           }
         })
       }
-      // history.push(`/account/${key}`)
+      return history.push(`/account/${key}`)
     },
     [initialState, setInitialState]
   )
@@ -86,13 +86,11 @@ const AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({ menu }) => {
 
   const menuHeaderDropdown = (
     <Menu className={styles.menu} selectedKeys={[]} onClick={onMenuClick}>
+      <Menu.Item key="settings">
+        <SettingOutlined />
+        个人设置
+      </Menu.Item>
       {/* {menu && (
-        <Menu.Item key="center">
-          <UserOutlined />
-          个人中心
-        </Menu.Item>
-      )}
-      {menu && (
         <Menu.Item key="settings">
           <SettingOutlined />
           个人设置

+ 3 - 1
src/locales/zh-CN/menu.js

@@ -31,5 +31,7 @@ export default {
   'menu.exception.server-error': '500',
   'menu.exception.trigger': '触发错误',
   'menu.account.trigger': '触发报错',
-  'menu.account.logout': '退出登录'
+  'menu.account.logout': '退出登录',
+  'menu.account.settings': '个人中心',
+  'menu.settings': '个人中心'
 }

+ 2 - 1
src/pages/Hr/Notification/index.jsx

@@ -56,7 +56,8 @@ const Notification = () => {
           hasMore={state.hasMore}
           loader={<Skeleton avatar paragraph={{ rows: 1 }} active />}
           endMessage={<Divider plain>别再滚啦,已是尽头</Divider>}
-          scrollableTarget="scrollableDiv">
+          scrollableTarget="scrollableDiv"
+        >
           <List
             itemLayout="horizontal"
             // pagination={{ pageSize: 5 }}

+ 217 - 0
src/pages/User/Account/Settings/components/BaseView.jsx

@@ -0,0 +1,217 @@
+import React from 'react'
+import { Input, Tabs } from 'antd'
+import ProForm, {
+  ProFormDependency,
+  ProFormFieldSet,
+  ProFormSelect,
+  ProFormText,
+  ProFormTextArea
+} from '@ant-design/pro-form'
+import styles from './BaseView.less'
+
+const { TabPane } = Tabs
+
+const validatorPhone = (rule, value, callback) => {
+  if (!value[0]) {
+    callback('Please input your area code!')
+  }
+  if (!value[1]) {
+    callback('Please input your phone number!')
+  }
+  callback()
+}
+// 头像组件 方便以后独立,增加裁剪之类的功能
+// const AvatarView = ({ avatar }) => (
+//   <>
+//     <div className={styles.avatar_title}>头像</div>
+//     <div className={styles.avatar}>
+//       <img src={avatar} alt="avatar" />
+//     </div>
+//     <Upload showUploadList={false}>
+//       <div className={styles.button_view}>
+//         <Button>
+//           <UploadOutlined />
+//           更换头像
+//         </Button>
+//       </div>
+//     </Upload>
+//   </>
+// )
+
+const BaseView = () => {
+  return (
+    <Tabs defaultActiveKey="1" onChange={callback}>
+      <TabPane tab="基本信息" key="1">
+        <div className={styles.baseView}>
+          <div className={styles.left}>
+            <ProForm
+              layout="vertical"
+              // onFinish={handleFinish}
+              submitter={{
+                resetButtonProps: {
+                  style: {
+                    display: 'none'
+                  }
+                },
+                submitButtonProps: {
+                  children: '更新基本信息'
+                }
+              }}
+              // initialValues={{
+              //   ...currentUser,
+              //   phone: currentUser?.phone.split('-'),
+              // }}
+              hideRequiredMark
+            >
+              <ProFormText
+                width="md"
+                name="email"
+                label="邮箱"
+                rules={[
+                  {
+                    required: true,
+                    message: '请输入您的邮箱!'
+                  }
+                ]}
+              />
+              <ProFormText
+                width="md"
+                name="name"
+                label="昵称"
+                rules={[
+                  {
+                    required: true,
+                    message: '请输入您的昵称!'
+                  }
+                ]}
+              />
+              <ProFormTextArea
+                name="profile"
+                label="个人简介"
+                rules={[
+                  {
+                    required: true,
+                    message: '请输入个人简介!'
+                  }
+                ]}
+                placeholder="个人简介"
+              />
+              <ProFormSelect
+                width="sm"
+                name="country"
+                label="国家/地区"
+                rules={[
+                  {
+                    required: true,
+                    message: '请输入您的国家或地区!'
+                  }
+                ]}
+                options={[
+                  {
+                    label: '中国',
+                    value: 'China'
+                  }
+                ]}
+              />
+
+              <ProForm.Group title="所在省市" size={8}>
+                <ProFormSelect
+                  rules={[
+                    {
+                      required: true,
+                      message: '请输入您的所在省!'
+                    }
+                  ]}
+                  width="sm"
+                  fieldProps={{
+                    labelInValue: true
+                  }}
+                  name="province"
+                  className={styles.item}
+                  request={async () => {
+                    return queryProvince().then(({ data }) => {
+                      return data.map(item => {
+                        return {
+                          label: item.name,
+                          value: item.id
+                        }
+                      })
+                    })
+                  }}
+                />
+                <ProFormDependency name={['province']}>
+                  {({ province }) => {
+                    return (
+                      <ProFormSelect
+                        params={{
+                          key: province?.value
+                        }}
+                        name="city"
+                        width="sm"
+                        rules={[
+                          {
+                            required: true,
+                            message: '请输入您的所在城市!'
+                          }
+                        ]}
+                        disabled={!province}
+                        className={styles.item}
+                        request={async () => {
+                          if (!province?.key) {
+                            return []
+                          }
+                          return queryCity(province.key || '').then(({ data }) => {
+                            return data.map(item => {
+                              return {
+                                label: item.name,
+                                value: item.id
+                              }
+                            })
+                          })
+                        }}
+                      />
+                    )
+                  }}
+                </ProFormDependency>
+              </ProForm.Group>
+              <ProFormText
+                width="md"
+                name="address"
+                label="街道地址"
+                rules={[
+                  {
+                    required: true,
+                    message: '请输入您的街道地址!'
+                  }
+                ]}
+              />
+              <ProFormFieldSet
+                name="phone"
+                label="联系电话"
+                rules={[
+                  {
+                    required: true,
+                    message: '请输入您的联系电话!'
+                  },
+                  { validator: validatorPhone }
+                ]}
+              >
+                <Input className={styles.area_code} />
+                <Input className={styles.phone_number} />
+              </ProFormFieldSet>
+            </ProForm>
+          </div>
+          <div className={styles.right}>{/* <AvatarView avatar={getAvatarURL()} /> */}</div>
+        </div>
+      </TabPane>
+      <TabPane tab="证件信息" key="2">
+        Content of Tab Pane 2
+      </TabPane>
+      <TabPane tab="财务信息" key="3">
+        Content of Tab Pane 3
+      </TabPane>
+    </Tabs>
+  )
+}
+
+export default BaseView

+ 65 - 0
src/pages/User/Account/Settings/components/BaseView.less

@@ -0,0 +1,65 @@
+@import '~antd/es/style/themes/default.less';
+
+.baseView {
+  display: flex;
+  padding-top: 12px;
+
+  :global {
+    .ant-legacy-form-item .ant-legacy-form-item-control-wrapper {
+      width: 100%;
+    }
+  }
+
+  .left {
+    min-width: 224px;
+    max-width: 448px;
+  }
+  .right {
+    flex: 1;
+    padding-left: 104px;
+    .avatar_title {
+      height: 22px;
+      margin-bottom: 8px;
+      color: @heading-color;
+      font-size: @font-size-base;
+      line-height: 22px;
+    }
+    .avatar {
+      width: 144px;
+      height: 144px;
+      margin-bottom: 12px;
+      overflow: hidden;
+      img {
+        width: 100%;
+      }
+    }
+    .button_view {
+      width: 144px;
+      text-align: center;
+    }
+  }
+}
+
+.area_code {
+  width: 72px;
+}
+.phone_number {
+  width: 214px;
+}
+
+@media screen and (max-width: @screen-xl) {
+  .baseView {
+    flex-direction: column-reverse;
+
+    .right {
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+      max-width: 448px;
+      padding: 20px;
+      .avatar_title {
+        display: none;
+      }
+    }
+  }
+}

+ 5 - 0
src/pages/User/Account/Settings/components/WxNotice.jsx

@@ -0,0 +1,5 @@
+const WxNotice = () => {
+  return <div>个人设置</div>
+}
+
+export default WxNotice

+ 98 - 0
src/pages/User/Account/Settings/index.jsx

@@ -0,0 +1,98 @@
+import React, { useState, useRef, useLayoutEffect } from 'react'
+import { GridContent } from '@ant-design/pro-layout'
+import { Menu } from 'antd'
+import styles from './style.less'
+import BaseView from './components/BaseView'
+import WxNotice from './components/WxNotice'
+
+const { Item } = Menu
+
+const Settings = () => {
+  const menuMap = {
+    base: '基本设置',
+    wxNotice: '微信通知'
+  }
+
+  const [initConfig, setInitConfig] = useState({
+    mode: 'inline',
+    selectKey: 'base'
+  })
+  const dom = useRef()
+
+  const resize = () => {
+    requestAnimationFrame(() => {
+      if (!dom.current) {
+        return
+      }
+      let mode = 'inline'
+      const { offsetWidth } = dom.current
+      if (dom.current.offsetWidth < 641 && offsetWidth > 400) {
+        mode = 'horizontal'
+      }
+      if (window.innerWidth < 768 && offsetWidth > 400) {
+        mode = 'horizontal'
+      }
+      setInitConfig({ ...initConfig, mode })
+    })
+  }
+
+  useLayoutEffect(() => {
+    if (dom.current) {
+      window.addEventListener('resize', resize)
+      resize()
+    }
+    return () => {
+      window.removeEventListener('resize', resize)
+    }
+  }, [dom.current])
+
+  const getMenu = () => {
+    return Object.keys(menuMap).map(item => <Item key={item}>{menuMap[item]}</Item>)
+  }
+
+  const renderChildren = () => {
+    const { selectKey } = initConfig
+    switch (selectKey) {
+      case 'base':
+        return <BaseView />
+      case 'wxNotice':
+        return <WxNotice />
+      default:
+        return null
+    }
+  }
+
+  return (
+    <GridContent>
+      <div
+        className={styles.main}
+        ref={ref => {
+          if (ref) {
+            dom.current = ref
+          }
+        }}
+      >
+        <div className={styles.leftMenu}>
+          <Menu
+            mode={initConfig.mode}
+            selectedKeys={[initConfig.selectKey]}
+            onClick={({ key }) => {
+              setInitConfig({
+                ...initConfig,
+                selectKey: key
+              })
+            }}
+          >
+            {getMenu()}
+          </Menu>
+        </div>
+        <div className={styles.right}>
+          {/* <div className={styles.title}>{menuMap[initConfig.selectKey]}</div> */}
+          {renderChildren()}
+        </div>
+      </div>
+    </GridContent>
+  )
+}
+
+export default Settings

+ 93 - 0
src/pages/User/Account/Settings/style.less

@@ -0,0 +1,93 @@
+@import '~antd/es/style/themes/default.less';
+
+.main {
+  display: flex;
+  width: 100%;
+  height: 100%;
+  padding-top: 16px;
+  padding-bottom: 16px;
+  background-color: @menu-bg;
+  .leftMenu {
+    width: 224px;
+    border-right: @border-width-base @border-style-base @border-color-split;
+    :global {
+      .ant-menu-inline {
+        border: none;
+      }
+      .ant-menu:not(.ant-menu-horizontal) .ant-menu-item-selected {
+        font-weight: bold;
+      }
+    }
+  }
+  .right {
+    flex: 1;
+    padding: 8px 40px;
+    .title {
+      margin-bottom: 12px;
+      color: @heading-color;
+      font-weight: 500;
+      font-size: 20px;
+      line-height: 28px;
+    }
+  }
+  :global {
+    .ant-list-split .ant-list-item:last-child {
+      border-bottom: 1px solid @border-color-split;
+    }
+    .ant-list-item {
+      padding-top: 14px;
+      padding-bottom: 14px;
+    }
+  }
+}
+:global {
+  .ant-list-item-meta {
+    // 账号绑定图标
+    .taobao {
+      display: block;
+      color: #ff4000;
+      font-size: 48px;
+      line-height: 48px;
+      border-radius: @border-radius-base;
+    }
+    .dingding {
+      margin: 2px;
+      padding: 6px;
+      color: white;
+      font-size: 32px;
+      line-height: 32px;
+      background-color: #2eabff;
+      border-radius: @border-radius-base;
+    }
+    .alipay {
+      color: #2eabff;
+      font-size: 48px;
+      line-height: 48px;
+      border-radius: @border-radius-base;
+    }
+  }
+
+  // 密码强度
+  font.strong {
+    color: @success-color;
+  }
+  font.medium {
+    color: @warning-color;
+  }
+  font.weak {
+    color: @error-color;
+  }
+}
+
+@media screen and (max-width: @screen-md) {
+  .main {
+    flex-direction: column;
+    .leftMenu {
+      width: 100%;
+      border: none;
+    }
+    .right {
+      padding: 40px;
+    }
+  }
+}