feat: 增加左侧菜单的所有主页面文件,首页样式修改

master
钟良源 6 months ago
parent c2f606078b
commit 9f8bebccfb

@ -22,6 +22,8 @@
"bizcharts": "^4.1.15",
"classnames": "^2.3.1",
"copy-to-clipboard": "^3.3.1",
"echarts": "^6.0.0",
"echarts-for-react": "^3.0.2",
"install": "^0.13.0",
"lodash": "^4.17.21",
"mockjs": "^1.1.0",

@ -41,6 +41,12 @@ importers:
copy-to-clipboard:
specifier: ^3.3.1
version: 3.3.3
echarts:
specifier: ^6.0.0
version: 6.0.0
echarts-for-react:
specifier: ^3.0.2
version: 3.0.2(echarts@6.0.0)(react@17.0.2)
install:
specifier: ^0.13.0
version: 0.13.0
@ -2273,6 +2279,15 @@ packages:
earcut@2.2.4:
resolution: {integrity: sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==}
echarts-for-react@3.0.2:
resolution: {integrity: sha512-DRwIiTzx8JfwPOVgGttDytBqdp5VzCSyMRIxubgU/g2n9y3VLUmF2FK7Icmg/sNVkv4+rktmrLN9w22U2yy3fA==}
peerDependencies:
echarts: ^3.0.0 || ^4.0.0 || ^5.0.0
react: ^15.0.0 || >=16.0.0
echarts@6.0.0:
resolution: {integrity: sha512-Tte/grDQRiETQP4xz3iZWSvoHrkCQtwqd6hs+mifXcjrCuo2iKWbajFObuLJVBlDIJlOzgQPd1hsaKt/3+OMkQ==}
electron-to-chromium@1.5.200:
resolution: {integrity: sha512-rFCxROw7aOe4uPTfIAx+rXv9cEcGx+buAF4npnhtTqCJk5KDFRnh3+KYj7rdVh6lsFt5/aPs+Irj9rZ33WMA7w==}
@ -4242,6 +4257,9 @@ packages:
tslib@1.14.1:
resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
tslib@2.3.0:
resolution: {integrity: sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==}
tslib@2.8.1:
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
@ -4500,6 +4518,9 @@ packages:
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
engines: {node: '>=10'}
zrender@6.0.0:
resolution: {integrity: sha512-41dFXEEXuJpNecuUQq6JlbybmnHaqqpGlbH1yxnA5V9MMP4SbohSVZsJIwz+zdjQXSSlR1Vc34EgH1zxyTDvhg==}
zustand@4.5.7:
resolution: {integrity: sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw==}
engines: {node: '>=12.7.0'}
@ -7599,6 +7620,18 @@ snapshots:
earcut@2.2.4: {}
echarts-for-react@3.0.2(echarts@6.0.0)(react@17.0.2):
dependencies:
echarts: 6.0.0
fast-deep-equal: 3.1.3
react: 17.0.2
size-sensor: 1.0.2
echarts@6.0.0:
dependencies:
tslib: 2.3.0
zrender: 6.0.0
electron-to-chromium@1.5.200: {}
elliptic@6.6.1:
@ -9841,6 +9874,8 @@ snapshots:
tslib@1.14.1: {}
tslib@2.3.0: {}
tslib@2.8.1: {}
tsutils@3.21.0(typescript@4.4.4):
@ -10138,6 +10173,10 @@ snapshots:
yocto-queue@0.1.0: {}
zrender@6.0.0:
dependencies:
tslib: 2.3.0
zustand@4.5.7(@types/react@17.0.2)(react@17.0.2):
dependencies:
use-sync-external-store: 1.5.0(react@17.0.2)

@ -8,7 +8,7 @@ import {
Menu,
Divider,
Message,
Button,
Button
} from '@arco-design/web-react';
import {
IconLanguage,
@ -22,13 +22,12 @@ import {
IconDashboard,
IconInteraction,
IconTag,
IconLoading,
IconLoading
} from '@arco-design/web-react/icon';
import { useSelector, useDispatch } from 'react-redux';
import { GlobalState } from '@/store';
import { GlobalContext } from '@/context';
import useLocale from '@/utils/useLocale';
import Logo from '@/assets/logo.svg';
import MessageBox from '@/components/MessageBox';
import IconButton from './IconButton';
import Settings from '../Settings';
@ -36,6 +35,8 @@ import styles from './style/index.module.less';
import defaultLocale from '@/locale';
import useStorage from '@/utils/useStorage';
import { generatePermission } from '@/routes';
import { Image } from '@arco-design/web-react';
import logoImage from '@/public/assets/logo.png';
function Navbar({ show }: { show: boolean }) {
const t = useLocale();
@ -66,9 +67,9 @@ function Navbar({ show }: { show: boolean }) {
payload: {
userInfo: {
...userInfo,
permissions: generatePermission(role),
},
},
permissions: generatePermission(role)
}
}
});
}, [role]);
@ -144,8 +145,12 @@ function Navbar({ show }: { show: boolean }) {
<div className={styles.navbar}>
<div className={styles.left}>
<div className={styles.logo}>
<Logo />
<div className={styles['logo-name']}>Arco Pro</div>
<img
width={50}
height={50}
src={logoImage.src}
/>
<div className={styles['logo-name']}></div>
</div>
</div>
<ul className={styles.right}>
@ -160,13 +165,13 @@ function Navbar({ show }: { show: boolean }) {
triggerElement={<IconButton icon={<IconLanguage />} />}
options={[
{ label: '中文', value: 'zh-CN' },
{ label: 'English', value: 'en-US' },
{ label: 'English', value: 'en-US' }
]}
value={lang}
triggerProps={{
autoAlignPopupWidth: false,
autoAlignPopupMinWidth: true,
position: 'br',
position: 'br'
}}
trigger="hover"
onChange={(value) => {

@ -15,7 +15,7 @@
.logo {
display: flex;
align-items: center;
width: 200px;
//width: 200px;
padding-left: 20px;
box-sizing: border-box;
}

@ -27,7 +27,7 @@ const i18n = {
'menu.user.switchRoles': 'Switch Roles',
'menu.user.role.admin': 'Admin',
'menu.user.role.user': 'General User',
'menu.dashboard.workplace': 'Workplace',
'menu.dashboard.workplace': 'Home',
'menu.scene': 'All Engineering',
'menu.application': 'All Applications',
'menu.instance': 'Application Instance',
@ -92,7 +92,7 @@ const i18n = {
'menu.user.switchRoles': '切换角色',
'menu.user.role.admin': '管理员',
'menu.user.role.user': '普通用户',
'menu.dashboard.workplace': '工作台',
'menu.dashboard.workplace': '首页',
'menu.scene': '所有工程',
'menu.application': '所有应用',
'menu.instance': '应用实例',

@ -1,88 +0,0 @@
import React, { useState, useEffect } from 'react';
import { Card, Spin, Typography } from '@arco-design/web-react';
import { DonutChart } from 'bizcharts';
import axios from 'axios';
import useLocale from '@/utils/useLocale';
import locale from './locale';
function PopularContent() {
const t = useLocale(locale);
const [data, setData] = useState([]);
const [loading, setLoading] = useState(true);
const fetchData = () => {
setLoading(true);
axios
.get('/api/workplace/content-percentage')
.then((res) => {
setData(res.data);
})
.finally(() => {
setLoading(false);
});
};
useEffect(() => {
fetchData();
}, []);
return (
<Card>
<Typography.Title heading={6}>
{t['workplace.contentPercentage']}
</Typography.Title>
<Spin loading={loading} style={{ display: 'block' }}>
<DonutChart
autoFit
height={340}
data={data}
radius={0.7}
innerRadius={0.65}
angleField="count"
colorField="type"
color={['#21CCFF', '#313CA9', '#249EFF']}
interactions={[
{
type: 'element-single-selected',
},
]}
tooltip={{ showMarkers: false }}
label={{
visible: true,
type: 'spider',
formatter: (v) => `${(v.percent * 100).toFixed(0)}%`,
style: {
fill: '#86909C',
fontSize: 14,
},
}}
legend={{
position: 'bottom',
}}
statistic={{
title: {
style: {
fontSize: '14px',
lineHeight: 2,
color: 'rgb(--var(color-text-1))',
},
formatter: () => '内容量',
},
content: {
style: {
fontSize: '16px',
color: 'rgb(--var(color-text-1))',
},
formatter: (_, data) => {
const sum = data.reduce((a, b) => a + b.count, 0);
return Number(sum).toLocaleString();
},
},
}}
/>
</Spin>
</Card>
);
}
export default PopularContent;

@ -1,33 +0,0 @@
import React from 'react';
import { Link, Card, Typography } from '@arco-design/web-react';
import useLocale from '@/utils/useLocale';
import locale from './locale';
import styles from './style/docs.module.less';
const links = {
react: 'https://arco.design/react/docs/start',
vue: 'https://arco.design/vue/docs/start',
designLab: 'https://arco.design/themes',
materialMarket: 'https://arco.design/material/',
};
function QuickOperation() {
const t = useLocale(locale);
return (
<Card>
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
<Typography.Title heading={6}>{t['workplace.docs']}</Typography.Title>
<Link suppressHydrationWarning>{t['workplace.seeMore']}</Link>
</div>
<div className={styles.docs}>
{Object.entries(links).map(([key, value]) => (
<Link className={styles.link} key={key} href={value} target="_blank" suppressHydrationWarning>
{t[`workplace.${key}`]}
</Link>
))}
</div>
</Card>
);
}
export default QuickOperation;

@ -1,17 +1,12 @@
import React from 'react';
import { Grid, Space } from '@arco-design/web-react';
import Overview from './overview';
import PopularContents from './popular-contents';
import ContentPercentage from './content-percentage';
import Shortcuts from './shortcuts';
import Announcement from './announcement';
import Carousel from './carousel';
import Docs from './docs';
import styles from './style/index.module.less';
import './mock';
const { Row, Col } = Grid;
const gutter = 16;
function Workplace() {
@ -19,20 +14,11 @@ function Workplace() {
<div className={styles.wrapper}>
<Space size={16} direction="vertical" className={styles.left}>
<Overview />
<Row gutter={gutter}>
<Col span={12}>
<PopularContents />
</Col>
<Col span={12}>
<ContentPercentage />
</Col>
</Row>
</Space>
<Space className={styles.right} size={16} direction="vertical">
<Shortcuts />
<Carousel />
<Announcement />
<Docs />
</Space>
</div>
);

@ -34,7 +34,7 @@ const i18n = {
'workplace.designLab': 'DesignLab',
'workplace.materialMarket': 'MaterialMarket',
'workplace.react': 'React Quick Start',
'workplace.vue': 'Vue Quick Start',
'workplace.vue': 'Vue Quick Start'
},
'zh-CN': {
'workplace.welcomeBack': '欢迎回来,',
@ -63,7 +63,7 @@ const i18n = {
'workplace.marketing': '内容投放',
'workplace.recent': '最近访问',
'workplace.announcement': '公告',
'workplace.activity': '活动',
'workplace.activity': '上新',
'workplace.info': '消息',
'workplace.notice': '通知',
'workplace.docs': '文档中心',
@ -71,8 +71,8 @@ const i18n = {
'workplace.designLab': '风格配置平台',
'workplace.materialMarket': '物料市场',
'workplace.react': 'React 组件库',
'workplace.vue': 'Vue 组件库',
},
'workplace.vue': 'Vue 组件库'
}
};
export default i18n;

@ -13,10 +13,10 @@ setupMock({
}));
};
return {
allContents: '373.5w+',
liveContents: '368',
increaseComments: '8874',
growthRate: '2.8%',
allContents: '15',
liveContents: '174',
increaseComments: '82',
growthRate: '4,888',
chartData: getLineData(),
};
});
@ -89,12 +89,12 @@ setupMock({
{
type: 'activity',
key: '1',
content: '内容最新优惠活动',
content: '组件库新增10+个组件'
},
{
type: 'info',
key: '2',
content: '新增内容尚未通过审核,详情请点击查看。',
content: '定时任务执行成功1次失败0次。'
},
{
type: 'notice',

@ -5,7 +5,7 @@ import {
Typography,
Divider,
Skeleton,
Link,
Link
} from '@arco-design/web-react';
import { useSelector } from 'react-redux';
import { IconCaretUp } from '@arco-design/web-react/icon';
@ -90,7 +90,7 @@ function Overview() {
<Col flex={1}>
<StatisticItem
icon={<IconCalendar />}
title={t['workplace.totalOnlyData']}
title="工程数量"
count={data.allContents}
loading={loading}
unit={t['workplace.pecs']}
@ -100,7 +100,7 @@ function Overview() {
<Col flex={1}>
<StatisticItem
icon={<IconContent />}
title={t['workplace.contentInMarket']}
title="组件数量"
count={data.liveContents}
loading={loading}
unit={t['workplace.pecs']}
@ -110,7 +110,7 @@ function Overview() {
<Col flex={1}>
<StatisticItem
icon={<IconComments />}
title={t['workplace.comments']}
title="应用数量"
count={data.increaseComments}
loading={loading}
unit={t['workplace.pecs']}
@ -120,15 +120,8 @@ function Overview() {
<Col flex={1}>
<StatisticItem
icon={<IconIncrease />}
title={t['workplace.growth']}
count={
<span>
{data.growthRate}{' '}
<IconCaretUp
style={{ fontSize: 18, color: 'rgb(var(--green-6))' }}
/>
</span>
}
title="应用实例数量"
count={data.growthRate}
loading={loading}
/>
</Col>
@ -138,16 +131,12 @@ function Overview() {
<div className={styles.ctw}>
<Typography.Paragraph
className={styles['chart-title']}
style={{ marginBottom: 0 }}
style={{ margin: '0 auto 1em' }}
>
{t['workplace.contentData']}
<span className={styles['chart-sub-title']}>
({t['workplace.1year']})
</span>
</Typography.Paragraph>
<Link suppressHydrationWarning>{t['workplace.seeMore']}</Link>
</div>
<OverviewAreaLine data={data.chartData} loading={loading} />
{/*<OverviewAreaLine data={data.chartData} loading={loading} />*/}
</div>
</Card>
);

@ -1,115 +0,0 @@
import React, { useState, useEffect, useCallback } from 'react';
import { Link, Card, Radio, Table, Typography } from '@arco-design/web-react';
import { IconCaretDown, IconCaretUp } from '@arco-design/web-react/icon';
import axios from 'axios';
import useLocale from '@/utils/useLocale';
import locale from './locale';
import styles from './style/popular-contents.module.less';
function PopularContent() {
const t = useLocale(locale);
const [type, setType] = useState(0);
const [data, setData] = useState([]);
const [loading, setLoading] = useState(true);
const [page, setPage] = useState(1);
const [total, setTotal] = useState(0);
const fetchData = useCallback(() => {
setLoading(true);
axios
.get(
`/api/workplace/popular-contents?page=${page}&pageSize=5&category=${type}`
)
.then((res) => {
setData(res.data.list);
setTotal(res.data.total);
})
.finally(() => {
setLoading(false);
});
}, [page, type]);
useEffect(() => {
fetchData();
}, [page, fetchData]);
const columns = [
{
title: t['workplace.column.rank'],
dataIndex: 'rank',
width: 65,
},
{
title: t['workplace.column.title'],
dataIndex: 'title',
render: (x) => (
<Typography.Paragraph style={{ margin: 0 }} ellipsis>
{x}
</Typography.Paragraph>
),
},
{
title: t['workplace.column.pv'],
dataIndex: 'pv',
width: 100,
render: (text) => {
return `${text / 1000}k`;
},
},
{
title: t['workplace.column.increase'],
dataIndex: 'increase',
sorter: (a, b) => a.increase - b.increase,
width: 110,
render: (text) => {
return (
<span>
{`${(text * 100).toFixed(2)}%`}
<span className={styles['symbol']}>
{text < 0 ? (
<IconCaretUp style={{ color: 'rgb(var(--green-6))' }} />
) : (
<IconCaretDown style={{ color: 'rgb(var(--red-6))' }} />
)}
</span>
</span>
);
},
},
];
return (
<Card>
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
<Typography.Title heading={6}>
{t['workplace.popularContents']}
</Typography.Title>
<Link suppressHydrationWarning>{t['workplace.seeMore']}</Link>
</div>
<Radio.Group
type="button"
value={type}
onChange={setType}
options={[
{ label: t['workplace.text'], value: 0 },
{ label: t['workplace.image'], value: 1 },
{ label: t['workplace.video'], value: 2 },
]}
style={{ marginBottom: 16 }}
/>
<Table
rowKey="rank"
columns={columns}
data={data}
loading={loading}
tableLayoutFixed
onChange={(pagination) => {
setPage(pagination.current);
}}
pagination={{ total, current: page, pageSize: 5, simple: true }}
/>
</Card>
);
}
export default PopularContent;

@ -4,14 +4,19 @@ import {
Card,
Divider,
Message,
Typography,
Typography
} from '@arco-design/web-react';
import {
IconArchive,
IconCustomerService,
IconSelectAll,
IconBook,
IconApps,
IconFile,
IconStorage,
IconSettings,
IconMobile,
IconFire,
IconFire
} from '@arco-design/web-react/icon';
import useLocale from '@/utils/useLocale';
import locale from './locale';
@ -24,46 +29,61 @@ function Shortcuts() {
{
title: t['workplace.contentMgmt'],
key: 'Content Management',
icon: <IconFile />,
icon: <IconFile />
},
{
title: t['workplace.contentStatistic'],
key: 'Content Statistic',
icon: <IconStorage />,
icon: <IconStorage />
},
{
title: t['workplace.advancedMgmt'],
key: 'Advanced Management',
icon: <IconSettings />,
icon: <IconSettings />
},
{
title: t['workplace.onlinePromotion'],
key: 'Online Promotion',
icon: <IconMobile />,
icon: <IconMobile />
},
{
title: t['workplace.marketing'],
key: 'Marketing',
icon: <IconFire />,
},
icon: <IconFire />
}
];
const recentShortcuts = [
{
title: t['workplace.contentStatistic'],
key: 'Content Statistic',
icon: <IconStorage />,
title: '工程页',
key: 1,
icon: <IconArchive />
},
{
title: t['workplace.contentMgmt'],
key: 'Content Management',
icon: <IconFile />,
title: '应用页',
key: 2,
icon: <IconApps />
},
{
title: t['workplace.advancedMgmt'],
key: 'Advanced Management',
icon: <IconSettings />,
title: '应用编排',
key: 3,
icon: <IconSelectAll />
},
{
title: '新手指引',
key: 4,
icon: <IconCustomerService />
},
{
title: '常见问题',
key: 5,
icon: <IconSettings />
},
{
title: '用户文档',
key: 6,
icon: <IconBook />
}
];
function onClickShortcut(key) {
@ -72,31 +92,31 @@ function Shortcuts() {
<span>
You clicked <b>{key}</b>
</span>
),
)
});
}
return (
<Card>
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
<Typography.Title heading={6}>
{t['workplace.shortcuts']}
</Typography.Title>
<Link suppressHydrationWarning>{t['workplace.seeMore']}</Link>
</div>
<div className={styles.shortcuts}>
{shortcuts.map((shortcut) => (
<div
className={styles.item}
key={shortcut.key}
onClick={() => onClickShortcut(shortcut.key)}
>
<div className={styles.icon}>{shortcut.icon}</div>
<div className={styles.title}>{shortcut.title}</div>
</div>
))}
</div>
<Divider />
{/*<div style={{ display: 'flex', justifyContent: 'space-between' }}>*/}
{/* <Typography.Title heading={6}>*/}
{/* {t['workplace.shortcuts']}*/}
{/* </Typography.Title>*/}
{/* <Link suppressHydrationWarning>{t['workplace.seeMore']}</Link>*/}
{/*</div>*/}
{/*<div className={styles.shortcuts}>*/}
{/* {shortcuts.map((shortcut) => (*/}
{/* <div*/}
{/* className={styles.item}*/}
{/* key={shortcut.key}*/}
{/* onClick={() => onClickShortcut(shortcut.key)}*/}
{/* >*/}
{/* <div className={styles.icon}>{shortcut.icon}</div>*/}
{/* <div className={styles.title}>{shortcut.title}</div>*/}
{/* </div>*/}
{/* ))}*/}
{/*</div>*/}
{/*<Divider />*/}
<div className={styles.recent}>{t['workplace.recent']}</div>
<div className={styles.shortcuts}>
{recentShortcuts.map((shortcut) => (

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Loading…
Cancel
Save