commit 36c4b55d978f0e6267f7c2a2248475d1136574b0 Author: pengYYYYY Date: Thu Aug 26 11:25:15 2021 +0800 develop (merge request !2) Squash merge branch 'develop' into 'master' Co-author: pengYYYYY diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..4fc13c7 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,14 @@ +root = true + +[*] +indent_style = space +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false + +[*.{ts,js,vue,css}] +indent_size = 2 diff --git a/.env b/.env new file mode 100644 index 0000000..ead7728 --- /dev/null +++ b/.env @@ -0,0 +1 @@ +VITE_SOME_KEY=123 diff --git a/.env.development b/.env.development new file mode 100644 index 0000000..a97f050 --- /dev/null +++ b/.env.development @@ -0,0 +1 @@ + VITE_SOME_KEY=456 diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..9313def --- /dev/null +++ b/.eslintignore @@ -0,0 +1,30 @@ +snapshot* +dist +lib +es +node_modules +common +static +cypress +script/test/cypress +_site +temp* +static/ + +examples +site/* +!site/v3.js +src/addon +src/calendar +src/locale +src/upload +src/dropdown +src/transfer +src/time-picker +src/utils +src/textarea +typings +dist +es +lib +types \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100755 index 0000000..1fda54c --- /dev/null +++ b/.gitignore @@ -0,0 +1,31 @@ +node_modules +.vscode +.DS_Store +.vscode + +# build files +es/ +lib/ +dist/ +typings/ + +_site +package +tmp* +temp* +coverage +test-report.html +.idea/ +yarn.lock +*.zip +.history +script/test/cypress/screenshots +script/test/cypress/videos +script/test/cypress/results +script/test/cypress/support +results/ +yarn-error.log +cypress +cypress.json +Dockerfile +robotMsg.json diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 0000000..5e92232 --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,39 @@ +module.exports = { + // 一行最多 120 字符 + printWidth: 120, + // 使用 2 个空格缩进 + tabWidth: 2, + // 不使用缩进符,而使用空格 + useTabs: false, + // 行尾需要有分号 + semi: true, + // 使用单引号 + singleQuote: true, + // 对象的 key 仅在必要时用引号 + quoteProps: 'as-needed', + // jsx 不使用单引号,而使用双引号 + jsxSingleQuote: false, + // 末尾需要有逗号 + trailingComma: 'all', + // 大括号内的首尾需要空格 + bracketSpacing: true, + // jsx 标签的反尖括号需要换行 + jsxBracketSameLine: false, + // 箭头函数,只有一个参数的时候,也需要括号 + arrowParens: 'always', + // 每个文件格式化的范围是文件的全部内容 + rangeStart: 0, + rangeEnd: Infinity, + // 不需要写文件开头的 @prettier + requirePragma: false, + // 不需要自动在文件开头插入 @prettier + insertPragma: false, + // 使用默认的折行标准 + proseWrap: 'preserve', + // 根据显示样式决定 html 要不要折行 + htmlWhitespaceSensitivity: 'css', + // vue 文件中的 script 和 style 内不用缩进 + vueIndentScriptAndStyle: false, + // 换行符使用 lf + endOfLine: 'lf', +}; diff --git a/commitlint.config.js b/commitlint.config.js new file mode 100644 index 0000000..422b194 --- /dev/null +++ b/commitlint.config.js @@ -0,0 +1 @@ +module.exports = { extends: ['@commitlint/config-conventional'] }; diff --git a/docker/nginx.conf b/docker/nginx.conf new file mode 100644 index 0000000..62b7d40 --- /dev/null +++ b/docker/nginx.conf @@ -0,0 +1,20 @@ +server { + if ($request_method = HEAD) { + return 200; + } + + location / { + alias /usr/share/nginx/html/; + index index.html index.htm; + try_files $uri $uri/ /index.html; + } + + access_log /var/log/nginx/access.log main; + error_log /var/log/nginx/error.log error; + + + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/share/nginx/html; + } +} \ No newline at end of file diff --git a/docs/20210627-114325.png b/docs/20210627-114325.png new file mode 100644 index 0000000..4013e37 Binary files /dev/null and b/docs/20210627-114325.png differ diff --git a/globals.d.ts b/globals.d.ts new file mode 100644 index 0000000..1756ddc --- /dev/null +++ b/globals.d.ts @@ -0,0 +1,13 @@ +// 通用声明 +declare type ClassName = { [className: string]: any } | ClassName[] | string; + +declare interface ImportMeta { + env: { + MODE: 'mock' | 'development' | 'test' | 'release'; + }; +} + +declare module '*.svg' { + const content: string; + export default content; +} diff --git a/index.html b/index.html new file mode 100644 index 0000000..a7f9882 --- /dev/null +++ b/index.html @@ -0,0 +1,13 @@ + + + + + + + TDesign Pro + + +
+ + + diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..cacf9d3 Binary files /dev/null and b/public/favicon.ico differ diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..59cb0aa --- /dev/null +++ b/src/App.vue @@ -0,0 +1,6 @@ + + + diff --git a/src/components/card/index.vue b/src/components/card/index.vue new file mode 100644 index 0000000..7d7a686 --- /dev/null +++ b/src/components/card/index.vue @@ -0,0 +1,88 @@ + + + diff --git a/src/components/result/index.vue b/src/components/result/index.vue new file mode 100644 index 0000000..0b0fd9d --- /dev/null +++ b/src/components/result/index.vue @@ -0,0 +1,83 @@ + + + diff --git a/src/components/thumbnail/index.vue b/src/components/thumbnail/index.vue new file mode 100644 index 0000000..2815888 --- /dev/null +++ b/src/components/thumbnail/index.vue @@ -0,0 +1,51 @@ + + + diff --git a/src/config/global.ts b/src/config/global.ts new file mode 100644 index 0000000..537adf6 --- /dev/null +++ b/src/config/global.ts @@ -0,0 +1,11 @@ +export const prefix = 'tdesign-pro'; +export const theme = 'light'; +// 登录方式设定,authenticationMethod取值有:smartProxy(走智能网关内网登录,要求.oa.co../.woa.co.. 等域名,且要求域名申请接入智能网关) +// customize(自定义登录,外网域名,统一重定向到登录页面) +// export const authenticationMethod = 'smartProxy'; +export const authenticationMethod = 'customize'; +export default { + prefix, + theme, + authenticationMethod, +}; diff --git a/src/config/proxy.ts b/src/config/proxy.ts new file mode 100644 index 0000000..42284bb --- /dev/null +++ b/src/config/proxy.ts @@ -0,0 +1,20 @@ +export default { + development: { + // 开发环境接口请求 + host: 'https://service-exndqyuk-1257786608.gz.apigw.tencentcs.com', + // 开发环境 cdn 路径 + cdn: '', + }, + test: { + // 测试环境接口地址 + host: 'https://service-exndqyuk-1257786608.gz.apigw.tencentcs.com', + // 测试环境 cdn 路径 + cdn: '', + }, + release: { + // 正式环境接口地址 + host: 'https://service-bv448zsw-1257786608.gz.apigw.tencentcs.com', + // 正式环境 cdn 路径 + cdn: '', + }, +}; diff --git a/src/config/routes.ts b/src/config/routes.ts new file mode 100644 index 0000000..d788c8f --- /dev/null +++ b/src/config/routes.ts @@ -0,0 +1,174 @@ +export default [ + { + path: '/dashboard', + icon: 'dashboard', + title: '仪表盘', + component: '../layouts/td-layout.tsx', + redirect: '/dashboard/base', + children: [ + { + title: '概览仪表盘', + path: 'base', + component: '../pages/dashboard/base/index.vue', + }, + { + title: '统计报表', + path: 'detail', + component: '../pages/dashboard/detail/index.vue', + }, + ], + }, + { + path: '/list', + icon: 'view-module', + title: '列表页', + component: '../layouts/td-layout.tsx', + redirect: '/list/base', + children: [ + { + title: '基础列表页', + path: 'base', + component: '../pages/list/base/index.vue', + }, + { + title: '卡片列表页', + path: 'card', + component: '../pages/list/card/index.vue', + }, + { + title: '筛选列表页', + path: 'select', + component: '../pages/list/select/index.vue', + }, + { + title: '树状筛选列表页', + path: 'tree', + component: '../pages/list/tree/index.vue', + }, + ], + }, + { + path: '/form', + icon: 'queue', + title: '表单页', + component: '../layouts/td-layout.tsx', + redirect: '/form/base', + children: [ + { + title: '基础表单页', + path: 'base', + component: '../pages/form/base/index.vue', + }, + { + title: '分步表单页', + path: 'step', + component: '../pages/form/step/index.vue', + }, + ], + }, + { + path: '/detail', + icon: 'layers', + title: '详情页', + component: '../layouts/td-layout.tsx', + redirect: '/detail/base', + children: [ + { + title: '基础详情页', + path: 'base', + component: '../pages/detail/base/index.vue', + // 默认不填,则需要每个页面都会经过登录的校验,若不需要进行登录校验则将needLogin:设为false + meta: { needLogin: false, title: '基础详情页' }, + }, + { + title: '多卡片详情页', + path: 'advanced', + component: '../pages/detail/advanced/index.vue', + }, + { + title: '数据详情页', + path: 'deploy', + component: '../pages/detail/deploy/index.vue', + }, + { + title: '二级详情页', + path: 'secondary', + component: '../pages/detail/secondary/index.vue', + }, + ], + }, + { + path: '/result', + icon: 'check-circle', + title: '结果页', + component: '../layouts/td-layout.tsx', + redirect: '/result/success', + children: [ + { + title: '成功页', + path: 'success', + component: '../pages/result/success/index.vue', + }, + { + title: '失败页', + path: 'fail', + component: '../pages/result/fail/index.vue', + }, + { + title: '网络异常', + path: 'network-error', + component: '../pages/result/network-error/index.vue', + }, + { + title: '无权限', + path: '403', + component: '../pages/result/403/index.vue', + }, + { + title: '访问页面不存在页', + path: '404', + component: '../pages/result/404/index.vue', + }, + { + title: '服务器出错页', + path: '500', + component: '../pages/result/500/index.vue', + }, + { + title: '浏览器不兼容页', + path: 'browser-incompatible', + component: '../pages/result/browser-incompatible/index.vue', + }, + ], + }, + { + path: '/user', + icon: 'user-circle', + title: '个人页', + component: '../layouts/td-layout.tsx', + redirect: '/user/index', + children: [ + { + title: '个人中心', + path: 'index', + component: '../pages/user/index.vue', + }, + ], + }, + // 自定义登录页面 + { + path: '/login', + title: '登录页', + component: '../layouts/blank.vue', + icon: 'chevron-right-rectangle', + redirect: '/login/index', + children: [ + { + title: '登录中心', + path: 'index', + meta: { needLogin: false }, + component: '../pages/login/index.vue', + }, + ], + }, +]; diff --git a/src/config/style.ts b/src/config/style.ts new file mode 100644 index 0000000..6d184d1 --- /dev/null +++ b/src/config/style.ts @@ -0,0 +1,12 @@ +export default { + showFooter: true, + isSidebarCompact: false, + showBreadcrumb: false, + theme: 'dark', + layout: 'side', + splitMenu: false, + isFooterAside: false, + isSidebarFixed: true, + isHeaderFixed: true, + showHeader: true, +}; diff --git a/src/constants/index.ts b/src/constants/index.ts new file mode 100644 index 0000000..18b4bbc --- /dev/null +++ b/src/constants/index.ts @@ -0,0 +1,35 @@ +// 合同状态枚举 +export const CONTRACT_STATUS = { + FAIL: 0, + AUDIT_PENDING: 1, + EXEC_PENDING: 2, + EXECUTING: 3, + FINISH: 4, +}; + +export const CONTRACT_STATUS_OPTIONS = [ + { value: CONTRACT_STATUS.FAIL, label: '审核失败' }, + { value: CONTRACT_STATUS.AUDIT_PENDING, label: '待审核' }, + { value: CONTRACT_STATUS.EXEC_PENDING, label: '待履行' }, + { value: CONTRACT_STATUS.EXECUTING, label: '审核成功' }, + { value: CONTRACT_STATUS.FINISH, label: '已完成' }, +]; + +// 合同类型枚举 +export const CONTRACT_TYPES = { + MAIN: 0, + SUB: 1, + SUPPLEMENT: 2, +}; + +export const CONTRACT_TYPE_OPTIONS = [ + { value: CONTRACT_TYPES.MAIN, label: '主合同' }, + { value: CONTRACT_TYPES.SUB, label: '子合同' }, + { value: CONTRACT_TYPES.SUPPLEMENT, label: '补充合同' }, +]; + +// 合同收付类型枚举 +export const CONTRACT_PAYMENT_TYPES = { + PAYMENT: 0, + RECIPT: 1, +}; diff --git a/src/pages/dashboard/base/index.less b/src/pages/dashboard/base/index.less new file mode 100644 index 0000000..0ad0f33 --- /dev/null +++ b/src/pages/dashboard/base/index.less @@ -0,0 +1,309 @@ +@import '@/style/index'; + +@media (max-width: @screen-md-max) { + .dashboard-panel .t-col-3 { + min-width: 50%; + &:first-child { + margin-bottom: 16px; + } + } + } + +.dashboard-panel .t-col { + .card-container { + margin: 0; + } +} +.t-tabs__content { + padding-top: @spacer-3; +} + +.dashboard-panel { + padding: 0; + border-radius: @border-radius; + + .card-container { + .card-content { + &-label-title { + color: @text-color-primary; + padding-bottom: 4px; + } + } + .t-table th, .t-table td { + padding: 10px 8px; + } + .t-table tr { + color: @text-color-primary; + } + } +} + + .dashboard-item-perfix { + margin-right: 0 !important; + } + + + .dashboard-item-bottom { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: flex-end; + + .dashboard-item-bottom-left { + display: flex; + flex-direction: row; + align-items:flex-start; + + &-unit { + font-size: 14px; + color: rgba(0,0,0,0.90); + padding-left: 4px; + padding-top: 17px; + } + + &-number { + display: inline-block; + color: black; + font-size: 36px; + line-height: 44px; + } + } + } + + .dashboard-item-bottom-right { + display: flex; + flex-direction: row; + justify-content: space-between; + height: 55px; + + .dashboard-item-bottom-emergency { + width: 96px; + height: 32px; + background: #FFE9E9; + border-radius: 16px; + font-size: 14px; + color: #E34D59; + display: flex; + align-items: center; + justify-content: center; + margin-top: 15px; + } + + .dashboard-item-bottom-right-top { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + + h1 { + font-size: 14px; + color: rgba(0,0,0,0.60); + padding-right: 8px; + } + div { + height: 24px; + // font-weight: bold; + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + padding-top: 14px; + + > span { + color: #00A870; + } + } + } + .dashboard-item-bottom-right-bottom { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + + h1 { + font-size: 14px; + color: rgba(0,0,0,0.60); + padding-right: 8px; + } + div { + height: 24px; + background: #FFE9E9; + border-radius: @border-radius; + color: #E34D59; + // font-weight: bold; + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + padding: 1px 8px; + + .t-icon-caret-up { + margin-left: 5px !important; + } + } + } + + } + + + +.dashboard-bottom { + margin-top: 16px; + display: flex; + flex-direction: row; + + // 左边图表 + .dashboard-bottom-left { + width: 100%; + height: 100%; + + .dashboard-bottom-left-top { + display: flex; + flex-direction: row; + width: 100%; + height: 100%; + + // 计量统计 + .dashboard-bottom-left-top-count-chart { + padding: 20px 24px; + background-color: white; + border-radius: @border-radius; + width: 100%; + min-width: 300px; + height: 320px; + } + // 动态监测 + .dashboard-bottom-left-top-monitor-chart { + padding: 20px 24px; + background-color: white; + border-radius: @border-radius; + margin-left: 16px; + width: 100%; + // min-width: 300px; + height: 320px; + + } + } + + // 出入库概览() + .dashboard-bottom-left-bottom { + background-color: white; + padding: 20px 24px; + border-radius: @border-radius; + margin-top: 16px; + width: 100%; + display: flex; + flex-direction: column; + justify-content: center; + min-height: 366px; + } + } + + // 右边列表-实时热度趋势 + .dashboard-bottom-right { + padding: 20px 24px; + background-color: white; + border-radius: @border-radius; + margin-left: 16px; + width: 426px; + min-height: 690px; + + ul { + padding-top: 16px; + + li { + .dashboard-chart-tend-item-title { + color: grey !important; + } + + .dashboard-chart-tend-sep { + padding: 0 0 17px 0 !important; + } + + .dashboard-chart-tend-item-line { + border-bottom: solid 1px #dedede; + padding: 9px 0; + } + + .dashboard-chart-tend-item { + display: flex; + flex-direction: row; + justify-content: space-between; + + .dashboard-chart-tend-left { + display: flex; + flex-direction: row; + .dashboard-chart-tend-num { + width: 48px; + } + + .dashboard-chart-tend-rante { + width: 48px; + } + } + } + } + } + } +} + +// 标题内容 +.dashboard-chart-title { + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + font-weight: bold; + + &-describe { + font-size: 14px !important; + color: rgba(0,0,0,0.60) !important; + text-align: left; + line-height: 22px; + } + &-container { + .t-date-picker { + width: 240px; + } + } + + span { + font-size: 16px; + color: rgba(0,0,0,0.90); + overflow: hidden; + text-overflow: ellipsis; + } + + .dashboard-chart-title-search { + display: flex; + flex-direction: row; + border: 1px solid #DDDDDD; + border-radius: @border-radius; + padding: 0; + align-items: center; + justify-content: center; + font-weight: normal; + + input { + border: solid 0px #ffffff !important; + } + } + + label { + font-weight: normal !important; + padding: 5px 15px !important; + + .t-radio-button__label { + font-size: 10px !important; + } + } +} +.dashboard-chart-container { + margin: 0 auto; +} + +.dashboard-item-block { + display: flex; + align-items: center; + justify-content: center; +} diff --git a/src/pages/dashboard/base/index.ts b/src/pages/dashboard/base/index.ts new file mode 100644 index 0000000..edaa17c --- /dev/null +++ b/src/pages/dashboard/base/index.ts @@ -0,0 +1,270 @@ +import dayjs from 'dayjs'; + +export class DashboardBase { + /** 更新容器尺寸 */ + setContainerSize(containerCopyValue: HTMLElement, absWidth = 0, absHeight = 0): void { + const container = containerCopyValue; + try { + if (container && container.style && container.parentElement) { + container.style.width = `${container.parentElement.clientWidth - absWidth}px`; + container.style.height = `${container.parentElement.clientHeight - absHeight}px`; + } + } catch (error) { + // hook + } + } +} + +/** + * 获取随机数 + * + * @param {number} [num=100] + * @returns + * + * @memberOf DashboardBase + */ +export function getRandomNum(num = 100): number { + let resultNum = Number((Math.random() * num).toFixed(0)); + + if (resultNum <= 1) { + resultNum = 1; + } + + return resultNum; +} + +/** 柱状图数据源 */ +export function constructInitDataset(dateTime: Array = []) { + const dataset: Array> = [['时间'], ['入库'], ['出库']]; + const divideNum = 10; + + for (let i = 0; i < divideNum; i++) { + const [timeArray, inArray, outArray] = dataset; + if (dateTime.length > 0) { + const dateAbsTime: number = (new Date(dateTime[1]).getTime() - new Date(dateTime[0]).getTime()) / divideNum; + const enhandTime: number = new Date(dateTime[0]).getTime() + dateAbsTime * i; + // console.log('dateAbsTime..', dateAbsTime, enhandTime); + timeArray.push(dayjs(enhandTime).format('YYYY-MM-DD')); + } else { + timeArray.push( + dayjs() + .subtract(divideNum - i, 'day') + .format('YYYY-MM-DD'), + ); + } + + inArray.push(getRandomNum().toString()); + outArray.push(getRandomNum().toString()); + } + return dataset; +} + +/** + * 线性图表数据源 + * + * @export + * @param {Array} [dateTime=[]] + * @returns {*} + */ +export function getLineChartDataSet(dateTime: Array = []): any { + if (dateTime.length > 0) { + const devideNum = 10; + const dateArray: Array = getDateArray(dateTime, devideNum); + return [ + dateArray, + getSelftItemList('杯子', devideNum), + getSelftItemList('茶叶', devideNum), + getSelftItemList('蜂蜜', devideNum), + getSelftItemList('面粉', devideNum), + ]; + } + return [ + [ + '日期', + '2020-01-16', + '2020-01-17', + '2020-01-18', + '2020-01-19', + '2020-01-20', + '2020-01-21', + '2020-01-22', + '2020-01-23', + '2020-01-24', + '2020-01-25', + ], + ['杯子', 5, 15, 15, 25, 24, 13, 32, 37, 43, 35], + ['茶叶', 1, 6, 13, 38, 39, 44, 48, 75, 62, 52], + ['蜂蜜', 16, 22, 27, 22, 32, 35, 23, 32, 33, 25], + ['面粉', 12, 12, 25, 29, 21, 30, 37, 47, 40, 47], + ]; +} +/** 图表颜色 */ +export const chartListColor: Array = ['#0052D9', '#00A870', '#7D46BD', '#0594FA', '#ED7B2F']; + +/** + * 获取表头数据 + * + * @export + * @param {string[]} dateTime + * @param {number} divideNum + * @returns {string[]} + */ +export function getDateArray(dateTime: string[] = [], divideNum = 10): string[] { + const timeArray: string[] = ['日期']; + if (dateTime.length > 0) { + for (let i = 0; i < divideNum; i++) { + const dateAbsTime: number = (new Date(dateTime[1]).getTime() - new Date(dateTime[0]).getTime()) / divideNum; + const enhandTime: number = new Date(dateTime[0]).getTime() + dateAbsTime * i; + timeArray.push(dayjs(enhandTime).format('YYYY-MM-DD')); + } + } + + return timeArray; +} + +/** + * 获取表行数据 + * + * @export + * @param {string} productName + * @param {number} devideNum + */ +export function getSelftItemList(productName: string, devideNum: number): string[] { + const productArray: string[] = [productName]; + for (let i = 0; i < devideNum; i++) { + productArray.push(getRandomNum(100 * i).toString()); + } + + return productArray; +} + +/** + * 散点图数据 + * + * @export + * @returns {any[]} + */ +export function getScattlerDataSet(): any[] { + const scatterData = [...Array(40)].map(() => [ + getRandomNum(Math.random() * 100), + getRandomNum(Math.random() * 200), + getRandomNum(Math.random() * 30), + getRandomNum(Math.random() * 400), + ]); + + return [ + ['咖啡机质量', '咖啡机效果', '按摩仪质量', '按摩仪效果'], + [getRandomNum(100), getRandomNum(200), getRandomNum(100), getRandomNum(500)], + ...scatterData, + ]; +} + +/** + * 获域图数据结构 + * + * @export + * @returns {any[]} + */ +export function getAreaChartDataSet(text = ''): any { + return { + title: { + text, + }, + dataset: [ + ['时间', '00:00', '02:00', '04:00', '06:00', '08:00'], + [ + '测试', + getRandomNum(Math.random() * 100), + getRandomNum(Math.random() * 200), + getRandomNum(Math.random() * 300), + getRandomNum(Math.random() * 400), + getRandomNum(Math.random() * 500), + ], + [ + '上线', + getRandomNum(Math.random() * 100), + getRandomNum(Math.random() * 200), + getRandomNum(Math.random() * 300), + getRandomNum(Math.random() * 400), + getRandomNum(Math.random() * 500), + ], + ], + area: { + smooth: true, + }, + injectOption: (option) => ({ ...option, color: chartListColor }), + }; +} + +/** + * 柱状图数据结构 + * + * @export + * @param {boolean} [isMonth=false] + * @returns {*} + */ +export function getColumnChartDataSet(isMonth = false): any { + if (isMonth) { + return { + title: { + text: '', + }, + dataset: [ + ['日期', '1', '4', '8', '12', '16', '20', '24'], + [ + '告警', + getRandomNum(Math.random() * 800), + getRandomNum(Math.random() * 700), + getRandomNum(Math.random() * 600), + getRandomNum(Math.random() * 500), + getRandomNum(Math.random() * 400), + getRandomNum(Math.random() * 300), + getRandomNum(Math.random() * 100), + ], + ], + injectOption: (option) => ({ ...option, color: chartListColor }), + }; + } + return { + title: { + text: '', + }, + dataset: [ + ['时间', '周一', '周二', '周三', '周四', '周五', '周六', '周日'], + [ + '告警', + getRandomNum(Math.random() * 200), + getRandomNum(Math.random() * 300), + getRandomNum(Math.random() * 600), + getRandomNum(Math.random() * 500), + getRandomNum(Math.random() * 100), + getRandomNum(Math.random() * 300), + getRandomNum(Math.random() * 100), + ], + ], + injectOption: (option) => ({ ...option, color: chartListColor }), + }; +} + +/** + * 获取饼图数据 + * + * @export + * @param {number} [radius=1] + * @returns {*} + */ +export function getPieChartDataSet(radius = 42): any { + return { + title: { + text: '', + }, + dataset: [ + ['状态', '审核中', '待履行', '履行中', '已完成'], + ['数量', 67, 45, radius, 36], + ], + injectOption: (option) => ({ ...option, color: chartListColor }), + pie: { + radius: ['45%', '60%'], // 设置内圆和外圆半径 + }, + }; +} diff --git a/src/pages/dashboard/detail/index.less b/src/pages/dashboard/detail/index.less new file mode 100644 index 0000000..a188fd5 --- /dev/null +++ b/src/pages/dashboard/detail/index.less @@ -0,0 +1,147 @@ +@import '@/style/index'; +.t-tabs__content { + padding-top: @spacer-3; +} + +.dashboard-panel-detail { + padding: 0; + border-radius: @border-radius; + } + +// 标题内容 +.dashboard-chart-title { + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + font-weight: bold; + + span { + font-size: 16px; + color: rgba(0,0,0,0.90); + overflow: hidden; + text-overflow: ellipsis; + } + + .dashboard-chart-title-date { + display: flex; + flex-direction: row; + border: 1px solid #DDDDDD; + border-radius: @border-radius; + padding: 5px 8px; + align-items: center; + justify-content: center; + font-weight: normal; + + .dashboard-chart-title-to { + color: rgba(0,0,0,0.30); + padding: 0 10px; + } + + .t-icon-creditcard { + margin-left: 20px !important; + } + } + + .dashboard-chart-title-search { + display: flex; + flex-direction: row; + border: 1px solid #DDDDDD; + border-radius: @border-radius; + padding: 0; + align-items: center; + justify-content: center; + font-weight: normal; + + input { + border: solid 0px #ffffff !important; + } + } + + label { + font-weight: normal !important; + padding: 5px 15px !important; + + .t-radio-button__label { + font-size: 10px !important; + } + } +} + + +.dashboard-detail-top-container { + padding: 20px 24px; + background-color: white; + border-radius: @border-radius; + + .dashboard-detail-box { + .dashboard-detail-container-item:not(:last-child) { + border-right: solid 1px #EBEBEB; + margin-right: 22.5px; + } + @media screen and (min-width: @screen-md-max) { + .dashboard-detail-container-item-perfix { + border-right: solid 1px #EBEBEB; + margin-right: 22.5px; + } + display: flex; + } + @media screen and (max-width: @screen-md-max - 1px) and (min-width: 0) { + display: normal; + } + } + .dashboard-detail-container { + display: flex; + flex: 1; + flex-direction: row; + padding-top: 20px; + + .dashboard-detail-container-item { + min-width: 108px; + width: 100%; + height: 106px; + + span { + font-size: 14px; + color: rgba(0,0,0,0.60); + } + + h1 { + font-size: 36px; + color: rgba(0,0,0,0.90); + font-weight: 500; + padding-top: 8px; + + span { + font-size: 14px; + color: rgba(0,0,0,0.30); + padding-left: 8px; + } + } + + .dashboard-detail-container-item-text { + // color: #E34D59; + display: flex; + flex-direction: row; + align-items: center; + justify-items: center; + font-size: 12px; + color: rgba(0,0,0,0.40); + text-align: left; + line-height: 20px; + } + } + } +} + +.dashboard-detail-bottom-container { + padding: 20px 24px; + background-color: white; + border-radius: @border-radius; + margin-top: 16px; + min-height: 400px; + + .dashboard-chart-title-container { + width: 240px; + } +} diff --git a/src/pages/detail/advanced/index.less b/src/pages/detail/advanced/index.less new file mode 100644 index 0000000..22dc4c3 --- /dev/null +++ b/src/pages/detail/advanced/index.less @@ -0,0 +1,176 @@ +@import '@/style/index'; +.t-tabs__content { + padding-top: @spacer-3; +} +.t-layout--content-replace { + color: rgba(0, 0, 0, 0.6) !important; +} + +.row-padding { + padding-top: 30px; + padding-left: 20px; +} +.operater-block-container { + padding: 10px 0 30px; +} +.operater-add { + width: 100%; + height: 210px; + display: flex; + align-items: center; + justify-items: center; + padding: 20px 10px 24px 20px; + border: dashed 1px #dedede; + + .operater-sub { + font-size: 14px; + color: @text-color-secondary; + margin: 0 auto; + text-align: center; + line-height: 22px; + display: flex; + align-items: center; + cursor: pointer; + .t-icon { + color: @brand-color-8; + } + } + + span { + padding-left: 10px; + } +} + +.operater-gap { + margin-left: 20px; +} + +.operater-block { + background-color: #EBEDF1; + padding: 20px 10px 24px 20px; + height: 210px; + + .operater-title { + display: flex; + align-items: center; + margin-bottom: 25px; + + h1 { + display: inline-block; + padding-left: 20px; + font-weight: bold; + font-size: 14px; + } + } + .operater-item { + padding-left: 48px; + padding-top: 8px; + padding-bottom: 8px; + display: flex; + h1 { + display: inline-block; + width: 136px; + text-align: left; + font-size: 14px; + color: rgba(0,0,0,0.60); + } + span { + width: 100%; + } + } +} + +.@{prefix} { + &-panel { + background-color: white; + padding: @spacer-3; + border-radius: @border-radius; + margin-top: 16px; + } + + &-search-input { + width: 360px; + margin-right: 8px; + } + + &-operater-row { + margin-bottom: 12px; + } + + &-operater-title { + font-size: 16px; + color: rgba(0, 0, 0, 0.9); + font-weight: bold; + } + + &-operater-label { + color: #000; + padding-left: 112px; + } +} + +.info-block { + column-count: 2; + + .info-item { + padding: 12px 0; + display: flex; + + h1 { + width: 84px; + font-family: PingFangSC-Regular; + font-size: 14px; + color: @text-color-secondary; + text-align: left; + line-height: 22px; + } + span { + margin-left: 24px; + } + i { + display: inline-block; + width: 8px; + height: 8px; + border-radius: @border-radius-50; + background: @success-color-5; + } + .inProgress { + color: @success-color-5; + } + .pdf { + color: @brand-color-8; + } + } +} +.dialog-info-block { + + .info-item { + padding: 12px 0; + display: flex; + + h1 { + width: 84px; + font-family: PingFangSC-Regular; + font-size: 14px; + color: @text-color-secondary; + text-align: left; + line-height: 22px; + } + span { + margin-left: 24px; + } + i { + display: inline-block; + width: 8px; + height: 8px; + border-radius: @border-radius-50; + background: @success-color-5; + } + .green { + color: @success-color-5; + } + .blue { + color: @brand-color-8; + } + } +} diff --git a/src/pages/detail/advanced/index.vue b/src/pages/detail/advanced/index.vue new file mode 100644 index 0000000..0b996d8 --- /dev/null +++ b/src/pages/detail/advanced/index.vue @@ -0,0 +1,285 @@ + + + diff --git a/src/pages/detail/base/index.less b/src/pages/detail/base/index.less new file mode 100644 index 0000000..06b11e6 --- /dev/null +++ b/src/pages/detail/base/index.less @@ -0,0 +1,57 @@ +@import '@/style/index'; +.t-tabs__content { + padding-top: @spacer-3; +} + +.@{prefix} { + &-panel { + background-color: white; + padding: @spacer-3; + border-radius: @border-radius; + } + + &-operater-row { + margin-bottom: 12px; + } + + &-operater-title { + font-size: 16px; + color: @text-color-primary; + font-family: PingFangSC-Medium; + } +} + +.info-block { + column-count: 2; + + .info-item { + padding: 12px 0; + display: flex; + + h1 { + font-weight: normal; + width: 84px; + font-family: PingFangSC-Regular; + font-size: 14px; + color: @text-color-secondary; + text-align: left; + line-height: 22px; + } + span { + margin-left: 24px; + } + i { + display: inline-block; + width: 8px; + height: 8px; + border-radius: @border-radius-50; + background: @success-color-5; + } + .inProgress { + color: @success-color-5; + } + .pdf { + color: @brand-color-8; + } + } +} \ No newline at end of file diff --git a/src/pages/detail/base/index.vue b/src/pages/detail/base/index.vue new file mode 100644 index 0000000..d928488 --- /dev/null +++ b/src/pages/detail/base/index.vue @@ -0,0 +1,84 @@ + + + diff --git a/src/pages/detail/secondary/index.less b/src/pages/detail/secondary/index.less new file mode 100644 index 0000000..8014358 --- /dev/null +++ b/src/pages/detail/secondary/index.less @@ -0,0 +1,64 @@ +@import '@/style/variables.less'; + +.secondary-notification { + background-color: white; + border-radius: @border-radius; + margin-top: 16px; + + .t-tabs__content { + padding-top: 0; + } +} +.secondary-msg-list { + min-height: 443px; + max-height: calc(100vh - 400px); + + .t-list-item { + cursor: pointer; + + &:hover { + background-color: @bg-color-container-hover; + .msg-date { + display: none; + } + .msg-action { + display: flex; + align-items: center; + + &-icon { + display: flex; + align-items: center; + } + } + } + } + .content { + font-family: PingFangSC-Medium; + font-size: 14px; + color:@text-color-placeholder; + text-align: left; + line-height: 22px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + + span { + font-family: PingFangSC-Regular; + } + } + .unread { + color: @brand-color-8; + } + .msg-action { + display: none; + + .set-read-icon { + margin-right: 24px; + } + } + &__empty-list { + min-height: 443px; + padding-top: 170px; + text-align: center; + } +} diff --git a/src/pages/detail/secondary/index.vue b/src/pages/detail/secondary/index.vue new file mode 100644 index 0000000..d30d846 --- /dev/null +++ b/src/pages/detail/secondary/index.vue @@ -0,0 +1,276 @@ + + diff --git a/src/pages/form/base/index.less b/src/pages/form/base/index.less new file mode 100644 index 0000000..2b390e3 --- /dev/null +++ b/src/pages/form/base/index.less @@ -0,0 +1,29 @@ +@import '@/style/index'; +.t-tabs__content { + padding-top: @spacer-3; +} + +.@{prefix} { + &-panel { + background-color: white; + padding: @spacer-3; + border-radius: @border-radius; + + .base-form { + .t-form__label { + min-width: 108px; + } + } + } + &-form { + padding-right: 50px; + padding-top: 30px; + border-top: solid 1px #EEEEEE; + } +} +.upload-tips { + margin-left: 16px; + font-size: 12px; + color: @text-level-2-color; + line-height: 20px; +} diff --git a/src/pages/form/step/index.less b/src/pages/form/step/index.less new file mode 100644 index 0000000..6e7e797 --- /dev/null +++ b/src/pages/form/step/index.less @@ -0,0 +1,62 @@ +@import '@/style/index'; +.t-tabs__content { + padding-top: @spacer-3; +} + +.@{prefix} { + &-panel { + background-color: white; + + &.@{prefix}-step-panel { + padding: 0; + } + } + &-step { + padding: 14px 0 24px 0; + } + &-form { + padding-right: 50px; + padding-top: 30px; + border-top: solid 1px #eeeeee; + } +} + +.rule-tips { + padding: 24px 24px 0 24px; +} + +.step-top { + padding: 24px; + border-bottom: #eeeeee solid 1px; +} + +.step-form { + padding: 24px; + + .t-form__label { + min-width: 108px; + } +} + +.step-form-4 { + height: 365px; + margin-top: 72px; + text-align: center; + + .t-icon { + margin: 6px; + } + .text { + margin: 16px 0 8px 0; + font-weight: bold; + font-size: 20px; + color: @text-level-1-color; + line-height: 30px; + } + .tips { + margin-bottom: 24px; + font-size: 14px; + color: @text-level-2-color; + line-height: 22px; + } +} diff --git a/src/pages/form/step/index.vue b/src/pages/form/step/index.vue new file mode 100644 index 0000000..60c50e6 --- /dev/null +++ b/src/pages/form/step/index.vue @@ -0,0 +1,420 @@ + + + diff --git a/src/pages/list/select/index.vue b/src/pages/list/select/index.vue new file mode 100644 index 0000000..08b195f --- /dev/null +++ b/src/pages/list/select/index.vue @@ -0,0 +1,19 @@ + + + diff --git a/src/pages/login/index.less b/src/pages/login/index.less new file mode 100644 index 0000000..162e602 --- /dev/null +++ b/src/pages/login/index.less @@ -0,0 +1,247 @@ +@import '@/style/index'; +.login-wrapper { + width: 100%; + height: 100%; + background-image: url(https://tdesign.gtimg.com/pro-template/login-bg-img.jpg); + background-size: cover; + background-position: 50%; + position: relative; +} +.login-container { + position: absolute; + top: 28%; + left: 12%; + min-height: 500px; + line-height: 22px; +} +.title-container { + .icon { + width: 290px; + height: 60px; + } + .side-title { + margin-top: 24.9px; + .tip1, .tip2 { + display: inline-block; + margin-right: 8px; + } + .tip1 { + font-size: 14px; + color: rgba(0,0,0,0.60); + } + .tip2 { + font-size: 14px; + color: @brand-color-8; + cursor: pointer; + } + } +} + +.login-step1 { + .input-container { + margin-top: 72px; + + .t-input { + display: block; + } + .t-popup-reference { + margin: 24px 0; + } + } + .check-container { + .t-checkbox__label { + color: @text-color-secondary; + span { + color: @brand-color-8; + } + } + } +} +.login-step3 { + .input-container { + margin-top: 34px; + } +} +.input-container { + .tip-container { + margin-bottom: 16px; + .tip1 { + font-size: 14px; + color: rgba(0,0,0,0.60); + } + .tip2 { + float: right; + font-size: 14px; + color: @brand-color-8; + + .t-icon { + height: 20px; + vertical-align: text-bottom; + } + } + } + .button-container { + margin-top: 16px; + } + .check-container { + font-size: 14px; + color: rgba(0,0,0,0.60); + + .tip { + float: right; + font-size: 14px; + color: @brand-color-8; + } + } +} + +.login-step1 { + .bottom-container { + margin-top: 72px; + } +} +.login-step3 { + .bottom-container { + margin-top: 32px; + } + .input-container .tip-container { + width: 192px; + } +} +.login-step2 { + .input-container { + margin-top: 108.9px; + .tip1 { + cursor: pointer; + } + } +} +.bottom-container { + margin-top: 66px; + .tip { + font-size: 14px; + color: @brand-color-8; + cursor: pointer; + } + i { + font-style: normal; + color: @gray-color-3; + margin: 0 14px; + } + +} +.rex-check { + font-family: PingFangSC-Regular; + font-size: 14px; + color: @text-color-placeholder; + line-height: 22px; +} +.format-correct { + color: @text-color-primary; + + .t-icon { + color: @success-color-5; + } +} + +.login-step4 { + .input-container { + margin-top: 64px; + + .t-input { + display: block; + } + .t-popup-reference { + margin: 24px 0; + } + .verification-code { + margin-bottom: 24px; + + .t-input { + display: inline-block; + } + button { + width: 102px; + height: 40px; + margin-left: 11px; + } + } + } + .bottom-container { + margin-top: 66px; + } + .check-container { + .t-checkbox__label { + color: @text-color-secondary; + + span { + color: @brand-color-8; + } + } + } +} + +.login-step5 { + .input-container { + margin-top: 64px; + + .t-input { + display: block; + } + .t-popup-reference { + margin: 24px 0; + } + .t-select-popup-reference { + margin: 0; + } + } + .bottom-container { + margin-top: 66px; + } + .check-container { + .t-checkbox__label { + color: @text-color-secondary; + + span { + color: @brand-color-8; + } + } + } +} + +.login-step6 { + .input-container { + margin-top: 64px; + + .t-input { + display: block; + } + .t-popup-reference { + margin: 24px 0; + } + .verification-code { + margin: 24px 0; + + .t-input { + display: inline-block; + } + button { + width: 102px; + height: 40px; + margin-left: 11px; + } + } + } + .bottom-container { + margin-top: 66px; + } + .check-container { + .t-checkbox__label { + color: @text-color-secondary; + + span { + color: @brand-color-8; + } + } + } +} \ No newline at end of file diff --git a/src/pages/result/403/index.vue b/src/pages/result/403/index.vue new file mode 100644 index 0000000..ac93963 --- /dev/null +++ b/src/pages/result/403/index.vue @@ -0,0 +1,17 @@ + + + diff --git a/src/pages/result/404/index.vue b/src/pages/result/404/index.vue new file mode 100644 index 0000000..4d07692 --- /dev/null +++ b/src/pages/result/404/index.vue @@ -0,0 +1,17 @@ + + + diff --git a/src/pages/result/500/index.vue b/src/pages/result/500/index.vue new file mode 100644 index 0000000..809148b --- /dev/null +++ b/src/pages/result/500/index.vue @@ -0,0 +1,17 @@ + + + diff --git a/src/pages/result/browser-incompatible/index.vue b/src/pages/result/browser-incompatible/index.vue new file mode 100644 index 0000000..2f315bb --- /dev/null +++ b/src/pages/result/browser-incompatible/index.vue @@ -0,0 +1,17 @@ + + + diff --git a/src/pages/result/fail/index.vue b/src/pages/result/fail/index.vue new file mode 100644 index 0000000..9e4fa96 --- /dev/null +++ b/src/pages/result/fail/index.vue @@ -0,0 +1,62 @@ + + + + + diff --git a/src/pages/result/network-error/index.vue b/src/pages/result/network-error/index.vue new file mode 100644 index 0000000..96fa1e2 --- /dev/null +++ b/src/pages/result/network-error/index.vue @@ -0,0 +1,17 @@ + + + diff --git a/src/pages/result/success/index.vue b/src/pages/result/success/index.vue new file mode 100644 index 0000000..e0d8665 --- /dev/null +++ b/src/pages/result/success/index.vue @@ -0,0 +1,68 @@ + + + + + diff --git a/src/pages/user/index.less b/src/pages/user/index.less new file mode 100644 index 0000000..aa95d03 --- /dev/null +++ b/src/pages/user/index.less @@ -0,0 +1,298 @@ +@import '@/style/index'; +.user-panel { + + @media (max-width: @screen-sm-max) { + .user-right { + min-width: 100%; + } + } + + @media (min-width: @screen-md-min) { + .user-right { + min-width: 33.33%; + } + } + .user-right { + transition: width .3s linear; + &-greeting { + margin-bottom: 16px; + background: #fff; + border-radius: @border-radius; + } + &-trend { + margin-bottom: 16px; + background: #fff; + border-radius: @border-radius; + } + &-todo { + margin-bottom: 16px; + background: #fff; + border-radius: @border-radius; + } + } + .head-bar { + display: flex; + justify-content: space-between; + margin-bottom: 8px; + + .title { + line-height: 24px; + font-family: PingFangSC-Medium; + font-size: 16px; + color: @text-level-1-color; + text-align: left; + } + .more { + display: flex; + align-items: center; + justify-content: center; + line-height: 22px; + font-family: PingFangSC-Regular; + font-size: 14px; + color: @text-level-1-color; + cursor: pointer; + + .t-icon { + vertical-align: bottom; + font-size: 20px; + } + &:hover { + color: @brand-color-8; + } + } + } + + .user-left { + .user-top { + padding: 24px; + margin: 0 16px 16px 0; + background: #fff; + border-radius: @border-radius; + + .account { + text-align: center; + margin-bottom: 48px; + color: @text-level-1-color; + + .img { + display: block; + width: 122px; + height: 122px; + border-radius: @border-radius-50; + background: #EBEDF1; + margin-top: 16px; + margin-left: 50%; + transform: translateX(-50%); + } + .name { + line-height: 37px; + font-family: PingFangSC-Semibold; + font-size: 26px; + margin-top: 16px; + } + .position { + line-height: 24px; + font-family: PingFangSC-Regular; + font-size: 14px; + margin-top: 8px; + } + } + .user-info { + line-height: 24px; + font-family: PingFangSC-Regular; + font-size: 14px; + color: @text-level-1-color; + .hiredate, .del, .mail { + display: flex; + } + .t-icon { + height: 24px; + margin-right: 8px; + } + .del { + margin: 16px 0; + } + } + } + .user-bottom { + padding: 24px 24px 0 24px; + margin: 0 16px 16px 0; + background: #fff; + border-radius: @border-radius; + + .t-list-item { + height: 64px; + min-width: 230px; + margin: 8px 0 16px 0; + background: #F3F3F3; + border-radius: @border-radius; + + .t-list-item__meta-avatar { + height: 32px; + width: 32px; + margin: auto; + } + .t-list-item__meta-content { + line-height: 22px; + margin-left: 10px; + padding: 5px 0; + } + .t-list-item__meta-title { + display: inline-block; + margin: 0 7px 0 0; + } + .t-list-item__meta-description { + display: inline-block; + color: @text-color-secondary; + font-size: 12px; + } + .t-list-item__action { + li { + margin-right: 16px; + cursor: pointer; + } + .t-icon { + color: @text-level-1-color; + + &:hover { + color: @brand-color-8; + } + } + } + } + } + } + .user-right { + .user-top { + .user-right-greeting { + padding: 24px; + line-height: 28px; + font-family: PingFangSC-Semibold; + font-size: 20px; + color: @text-level-1-color; + text-align: left; + .regular { + vertical-align: bottom; + font-family: PingFangSC-Regular; + font-size: 14px; + } + } + .user-right-trend { + padding: 24px; + + .t-list-item { + padding: 8px 0; + cursor: pointer; + + .text { + display: flex; + line-height: 20px; + font-family: PingFangSC-Regular; + font-size: 14px; + color: @text-level-1-color; + + .t-icon { + margin-right: 8px; + height: 20px; + font-size: 16px; + color: @text-level-3-color; + } + p { + display: inline-block; + } + } + .t-list-item__action { + line-height: 20px; + font-family: PingFangSC-Regular; + font-size: 12px; + color: @text-level-2-color; + } + &:hover { + .text { + color: @brand-color-8; + + .t-icon { + color: @brand-color-8; + } + } + } + } + .t-list-item:last-child { + padding-bottom: 0; + } + } + .user-right-todo { + padding: 24px; + + .empty-list { + margin-top: 18px; + line-height: 20px; + font-family: PingFangSC-Regular; + font-size: 14px; + color: @text-level-3-color; + text-align: center; + + img { + margin-bottom: 2px; + width: 42px; + } + } + } + } + .user-bottom { + padding: 24px; + background: #fff; + border-radius: @border-radius; + + .contract { + width: 340px; + height: 88px; + border-radius: @border-radius; + margin: 8px 0; + cursor: pointer; + + &-type { + position: relative; + float: left; + margin: 13px 16px; + + img { + width: 64px; + height: 64px; + } + } + &-title { + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + line-height: 24px; + margin: 20px 0 6px 0; + font-family: PingFangSC-Medium; + font-size: 16px; + color: @text-level-1-color; + } + &-date { + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + line-height: 22px; + font-family: PingFangSC-Regular; + font-size: 14px; + color: @text-level-3-color; + } + &:hover { + background: #f7f7f7; + } + } + .contract:last-child, + .contract:nth-last-child(2) { + margin-bottom: 0; + } + } + } + .user-bottom .user-right{ + height: 447px; + background: #fff; + border-radius: @border-radius; + } +} diff --git a/src/router/index.ts b/src/router/index.ts new file mode 100644 index 0000000..4569f35 --- /dev/null +++ b/src/router/index.ts @@ -0,0 +1,47 @@ +import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router' +import routeConfig from '@/config/routes'; + +const layoutModules = import.meta.glob('../layouts/*'); +const pagesModules = import.meta.glob('../pages/**/*.vue'); +const fristPagesModules = import.meta.glob('../pages/*.vue'); + +const modules = Object.assign({}, layoutModules, fristPagesModules, pagesModules); + +const getMenuRoutes = (list) => { + if (!list) { + return []; + } + return list.map((item) => { + const { path = '', component, meta = { title: item.title }, redirect = '' } = item; + return { + path, + component: modules[component], + children: getMenuRoutes(item.children), + meta, + redirect, + }; + }); +}; + +const routes: Array = [ + ...getMenuRoutes(routeConfig), + { + path: '', + redirect: '/dashboard/base', + component: () => import('@/pages/dashboard/base/index.vue'), + }, +]; + +const router = createRouter({ + history: createWebHistory(''), + routes, + scrollBehavior(to, from, savedPosition) { + return { + el: '#app', + top: 0, + behavior: 'smooth', + } + }, +}) +export default router + diff --git a/src/shims-vue.d.ts b/src/shims-vue.d.ts new file mode 100644 index 0000000..c458ab5 --- /dev/null +++ b/src/shims-vue.d.ts @@ -0,0 +1,6 @@ +declare module '*.vue' { + import { DefineComponent } from 'vue' + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types + const component: DefineComponent<{}, {}, any> + export default component +} diff --git a/src/store/index.ts b/src/store/index.ts new file mode 100644 index 0000000..9118eb2 --- /dev/null +++ b/src/store/index.ts @@ -0,0 +1,20 @@ +import { InjectionKey } from 'vue' +import { createStore, Store } from 'vuex' +import user from './modules/user'; +import notification from './modules/notification'; +import setting from './modules/setting'; +export interface State { + count: number +} + +export const key: InjectionKey> = Symbol() + +export const store = createStore({ + modules: { + user, + setting, + notification, + }, +}) + +export default store; diff --git a/src/store/modules/notification.ts b/src/store/modules/notification.ts new file mode 100644 index 0000000..13e753f --- /dev/null +++ b/src/store/modules/notification.ts @@ -0,0 +1,68 @@ +// 定义的state初始值 +const state = { + msgData: [ + { + id: '123', + content: '腾讯大厦一楼改造施工项目 已通过审核!', + type: '合同动态', + status: true, + date: '2021-01-01 08:00', + }, + { + id: '124', + content: '三季度生产原材料采购项目 开票成功!', + type: '票务动态', + status: true, + date: '2021-01-01 08:00', + }, + { + id: '125', + content: '2021-01-01 10:00的【国家电网线下签约】会议即将开始,请提前10分钟前往 会议室1 进行签到!', + type: '会议通知', + status: true, + date: '2021-01-01 08:00', + }, + { + id: '126', + content: '一季度生产原材料采购项目 开票成功!', + type: '票务动态', + status: true, + date: '2021-01-01 08:00', + }, + { + id: '127', + content: '二季度生产原材料采购项目 开票成功!', + type: '票务动态', + status: true, + date: '2021-01-01 08:00', + }, + { + id: '128', + content: '三季度生产原材料采购项目 开票成功!', + type: '票务动态', + status: true, + date: '2021-01-01 08:00', + }, + ], +}; + +const mutations = { + setMsgData(state, data) { + state.msgData = data; + }, +}; + +const getters = { + unreadMsg: (state) => state.msgData.filter((item) => item.status), + readMsg: (state) => state.msgData.filter((item) => !item.status), +}; + +const actions = {}; + +export default { + namespaced: true, + state, + mutations, + actions, + getters, +}; diff --git a/src/style/font-family.less b/src/style/font-family.less new file mode 100644 index 0000000..c677a52 --- /dev/null +++ b/src/style/font-family.less @@ -0,0 +1,6 @@ +@font-face { + font-family: "TencentSansW7"; + src: url("data:application/font-woff;charset=utf-8;base64,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") format("woff"); + font-weight: normal; + font-style: normal; + } \ No newline at end of file diff --git a/src/style/index.less b/src/style/index.less new file mode 100644 index 0000000..6554dc3 --- /dev/null +++ b/src/style/index.less @@ -0,0 +1,167 @@ +@import "./common.less"; +@import "./variables.less"; +@import "./rewrite.less"; +@import "./font-family.less"; +@import "./sidenav.less"; + +body { + color: @text-level-2-color; + font-family: -apple-system, BlinkMacSystemFont, @font-family; + font-size: @font-size-base; + line-height: 1.5; + -webkit-font-smoothing: antialiased; + padding: 0; + min-width: @screen-sm-min; + } + pre { + font-family: @font-family; + } + + ul, + dl, + li, + dd, + dt { + margin: 0; + padding: 0; + list-style: none; + } + + figure, + h1, + h2, + h3, + h4, + h5, + h6, + p { + margin-top: 0; + margin-bottom: 0; + margin: 0; + } + + * { + box-sizing: border-box; + } + + .@{prefix}-text-ellipsis { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + .@{prefix}-text-tip { + font-size: 12px; + color: @text-level-3-color; + } + + .@{prefix}-pic { + background-position: center; + background-repeat: no-repeat; + background-size: 100%; + } + + .@{prefix}-main-link { + color: @text-level-1-color; + text-decoration: none; + cursor: pointer; + + &:hover { + color: @text-level-1-color; + } + + &:active { + color: @text-level-1-color; + } + + &--active { + color: #000; + } + + &:focus { + text-decoration: none; + } + } + + .@{prefix}-link { + color: @primary-color; + + text-decoration: none; + margin-right: @spacer-3; + + cursor: pointer; + + &:hover { + color: @primary-color; + } + + &:active { + color: @primary-color; + } + + &--active { + color: @primary-color; + } + + &:focus { + text-decoration: none; + } + } + + // 布局元素调整 + .@{prefix}-wrapper { + height: 100vh; + display: flex; + flex-direction: column; + } + .@{prefix}-sidenav-layout { + + &-relative { + height: 100%; + } + } + .@{prefix}-content-layout { + margin: @spacer-3; + } + + .@{prefix}-footer-layout { + padding: 0; + margin-bottom: @spacer-2; + } + + .@{prefix}-footer { + color: rgba(0, 0, 0, 0.3); + line-height: 20px; + text-align: center; + } + + .@{prefix}-icon-container { + width: 16px; + height: 16px; + margin-left: 4px; + display: inline-flex; + align-items: center; + justify-content: center; + } + + .@{prefix}-flat-icon { + width: 10px; + height: 3px; + background: rgba(0,0,0,0.60); + } + + .@{prefix}-up-triangle { + width: 0; + height: 0; + border-style: solid; + border-width: 0 6px 8px 6px; + border-color: transparent transparent #00A870 transparent; + } + + .@{prefix}-down-triangle { + width: 0; + height: 0; + border-style: solid; + border-width: 8px 6px 0 6px; + border-color: #E34D59 transparent transparent transparent; + } \ No newline at end of file diff --git a/src/style/sidenav.less b/src/style/sidenav.less new file mode 100644 index 0000000..d5686b3 --- /dev/null +++ b/src/style/sidenav.less @@ -0,0 +1,96 @@ +@import './variables.less'; +@import './font-family.less'; + +.@{prefix} { + &-sidebar-layout { + height: 100%; + } + + &-sidebar-compact { + width: 64px; + .@{prefix}-sidenav-logo-wrapper { + padding-left: 16px; + } + } + &-sidebar-layout-side { + z-index: 100; + } + + &-sidenav{ + position: fixed; + top: 0; + bottom: 0; + z-index: 10; + transition: all .3s; + min-height: 100%; + + &-mix { + top: 64px; + + &-fixed { + top: 64px; + z-index: 0; + } + } + + &-no-fixed { + position: relative; + z-index: 1; + } + + &-no-logo { + z-index: 1; + } + + &-logo-wrapper { + display: flex; + align-items: center; + width: 100%; + } + &-logo-t-logo { + width: 32px; + } + &-logo-tdesign-logo { + width: 112px; + } + &-logo-normal { + font-family: TencentSansKoreanW7; + color: @primary-color; + font-size: @font-size-l; + transition: all .3s; + } + } + + + &-sidenav-placeholder { + flex: 1 1 232px; + min-width: 232px; + transition: all .3s; + + &-hidden { + flex: 1 1 72px; + min-width: 72px; + transition: all .3s; + } + } + +} +.t-menu--dark .t-menu__options:not(:empty) .t-icon-menu-unfold { + color: rgba(255, 255, 255, 0.55) +} + +.logo-container { + cursor: pointer; + display: inline-flex; + height: 64px; + margin-left: 24px; + } + + .optional-icon { + color: #000000; + cursor: pointer; + + &:hover { + color: @primary-color; + } + } \ No newline at end of file diff --git a/src/utils/date.ts b/src/utils/date.ts new file mode 100644 index 0000000..c6be642 --- /dev/null +++ b/src/utils/date.ts @@ -0,0 +1,6 @@ +// 获取常用时间 +import dayjs, { Dayjs } from 'dayjs'; + +export const LAST_7_DAYS: [Dayjs, Dayjs] = [dayjs().subtract(7, 'day'), dayjs().subtract(1, 'day')]; + +export const LAST_30_DAYS: [Dayjs, Dayjs] = [dayjs().subtract(30, 'day'), dayjs().subtract(1, 'day')]; diff --git a/src/utils/request.js b/src/utils/request.js new file mode 100644 index 0000000..e276b96 --- /dev/null +++ b/src/utils/request.js @@ -0,0 +1,57 @@ +import axios from 'axios'; +import proxy from '../config/proxy'; + +const env = import.meta.env.MODE || 'development'; + +const host = env === 'mock' ? '/' : proxy[env].host; // 如果是mock模式 就不配置host 会走本地Mock拦截 + +const CODE = { + LOGIN_TIMEOUT: 1000, + REQUEST_SUCCESS: 0, + REQUEST_FOBID: 1001, +}; + +const instance = axios.create({ + baseURL: host, + timeout: 1000, + withCredentials: true, +}); + +instance.interceptors.request.use((config) => config); + +instance.defaults.retry = 3; + +instance.interceptors.response.use( + (response) => { + if (response.status === 200) { + const { data } = response; + if (data.code === CODE.REQUEST_SUCCESS) { + return data; + } + return response; + } + }, + (err) => { + const { config } = err; + + if (!config || !config.retry) return Promise.reject(err); + + config.retryCount = config.retryCount || 0; + + if (config.retryCount >= config.retry) { + return Promise.reject(err); + } + + config.retryCount += 1; + + const backoff = new Promise((resolve) => { + setTimeout(() => { + resolve(); + }, config.retryDelay || 1); + }); + + return backoff.then(() => instance(config)); + }, +); + +export default instance; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..5de7b38 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "esnext", + "module": "esnext", + "moduleResolution": "node", + "strict": false, + "jsx": "preserve", + "sourceMap": true, + "resolveJsonModule": true, + "esModuleInterop": true, + "lib": ["esnext", "dom"], + "noEmit": true, + "baseUrl": "./", + "paths": { + "@/*": ["./src/*"] + } + }, + "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue", "src/config/proxy.ts", "src/pages/detail/base/index.js"] +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..c66be59 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,27 @@ +import { defineConfig } from 'vite' +import { viteMockServe } from 'vite-plugin-mock'; +const HttpProxyAgent = require('http-proxy-agent'); +import vueJsx from '@vitejs/plugin-vue-jsx'; + +import vue from '@vitejs/plugin-vue' +const path = require('path'); + +import proxy from './src/config/proxy'; + +// https://vitejs.dev/config/ +export default defineConfig({ + base: './', + resolve: { + alias: { + '~': path.resolve(__dirname, './'), + '@': path.resolve(__dirname, './src'), + }, + }, + plugins: [ + vue(), + vueJsx() + ], + server: { + port: 3002, + }, +})