diff --git a/public/index.html b/public/index.html index d867705b3..c3f49b752 100644 --- a/public/index.html +++ b/public/index.html @@ -1,19 +1,145 @@ - - - - + + + + Halo Dashboard - +
-
Loading
+
+
+
+
+
+
+
+
+
+
+
+
Loading
+
diff --git a/src/App.vue b/src/App.vue index 8b333c890..ba3a4bca9 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,7 +1,7 @@ @@ -11,12 +11,12 @@ import zhCN from 'ant-design-vue/lib/locale-provider/zh_CN' import { deviceEnquire, DEVICE_TYPE } from '@/utils/device' export default { - data () { + data() { return { locale: zhCN } }, - mounted () { + mounted() { const { $store } = this deviceEnquire(deviceType => { switch (deviceType) { @@ -39,7 +39,7 @@ export default { } diff --git a/src/components/FooterToolbar/index.md b/src/components/FooterToolbar/index.md index c1aec2c4c..a8c911c22 100644 --- a/src/components/FooterToolbar/index.md +++ b/src/components/FooterToolbar/index.md @@ -2,14 +2,11 @@ 固定在底部的工具栏。 - - ## 何时使用 固定在内容区域的底部,不随滚动条移动,常用于长页面的数据搜集和提交工作。 - 引用方式: ```javascript @@ -22,8 +19,6 @@ export default { } ``` - - ## 代码演示 ```html @@ -31,7 +26,9 @@ export default { 提交 ``` + 或 + ```html 提交 @@ -41,8 +38,8 @@ export default { ## API -参数 | 说明 | 类型 | 默认值 -----|------|-----|------ -children (slot) | 工具栏内容,向右对齐 | - | - -extra | 额外信息,向左对齐 | String, Object | - +| 参数 | 说明 | 类型 | 默认值 | +| --------------- | -------------------- | -------------- | ------ | +| children (slot) | 工具栏内容,向右对齐 | - | - | +| extra | 额外信息,向左对齐 | String, Object | - | diff --git a/src/components/tools/setting.js b/src/components/tools/setting.js index 863aa0e2f..50085124b 100644 --- a/src/components/tools/setting.js +++ b/src/components/tools/setting.js @@ -5,28 +5,36 @@ let lessNodesAppended const colorList = [ { - key: '薄暮', color: '#F5222D' + key: '薄暮', + color: '#F5222D' }, { - key: '火山', color: '#FA541C' + key: '火山', + color: '#FA541C' }, { - key: '日暮', color: '#FAAD14' + key: '日暮', + color: '#FAAD14' }, { - key: '明青', color: '#13C2C2' + key: '明青', + color: '#13C2C2' }, { - key: '极光绿', color: '#52C41A' + key: '极光绿', + color: '#52C41A' }, { - key: '拂晓蓝(默认)', color: '#1890FF' + key: '拂晓蓝(默认)', + color: '#1890FF' }, { - key: '极客蓝', color: '#2F54EB' + key: '极客蓝', + color: '#2F54EB' }, { - key: '酱紫', color: '#722ED1' + key: '酱紫', + color: '#722ED1' } ] @@ -40,7 +48,7 @@ const updateTheme = primaryColor => { return } const hideMessage = message.loading('正在编译主题!', 0) - function buildIt () { + function buildIt() { if (!window.less) { return } diff --git a/src/core/bootstrap.js b/src/core/bootstrap.js index 440e4d5a8..2bbb7f6ef 100644 --- a/src/core/bootstrap.js +++ b/src/core/bootstrap.js @@ -15,7 +15,7 @@ import { } from '@/store/mutation-types' import config from '@/config/defaultSettings' -export default function Initializer () { +export default function Initializer() { store.commit('SET_SIDEBAR_TYPE', Vue.ls.get(SIDEBAR_TYPE, true)) store.commit('TOGGLE_THEME', Vue.ls.get(DEFAULT_THEME, config.navTheme)) store.commit('TOGGLE_LAYOUT_MODE', Vue.ls.get(DEFAULT_LAYOUT_MODE, config.layout)) diff --git a/src/router/README.md b/src/router/README.md index 897be9539..5bd882dfb 100644 --- a/src/router/README.md +++ b/src/router/README.md @@ -36,25 +36,25 @@ `{ Route }` 对象 -| 参数 | 说明 | 类型 | 默认值 | -| -------- | ----------------------------------------- | ------- | ------ | -| hidden | 控制路由是否显示在 sidebar | boolean | false | -| redirect | 重定向地址, 访问这个路由时,自定进行重定向 | string | - | -| name | 路由名称, 必须设置,且不能重名 | string | - | -| meta | 路由元信息(路由附带扩展信息) | object | {} | -| hideChildrenInMenu | 强制菜单显示为Item而不是SubItem(配合 meta.hidden) | boolean | - | +| 参数 | 说明 | 类型 | 默认值 | +| ------------------ | ------------------------------------------------- | ------- | ------ | +| hidden | 控制路由是否显示在 sidebar | boolean | false | +| redirect | 重定向地址, 访问这个路由时,自定进行重定向 | string | - | +| name | 路由名称, 必须设置,且不能重名 | string | - | +| meta | 路由元信息(路由附带扩展信息) | object | {} | +| hideChildrenInMenu | 强制菜单显示为Item而不是SubItem(配合 meta.hidden) | boolean | - | `{ Meta }` 路由元信息对象 -| 参数 | 说明 | 类型 | 默认值 | -| ------------------- | ------------------------------------------------------------ | ------- | ------ | -| title | 路由标题, 用于显示面包屑, 页面标题 *推荐设置 | string | - | -| icon | 路由在 menu 上显示的图标 | [string,svg] | - | -| keepAlive | 缓存该路由 | boolean | false | -| hidden | 配合`alwaysShow`使用,用于隐藏菜单时,提供递归到父菜单显示 选中菜单项_(可参考 个人页 配置方式)_ | boolean | false | -| hiddenHeaderContent | *特殊 隐藏 [PageHeader](https://github.com/sendya/ant-design-pro-vue/blob/master/src/components/layout/PageHeader.vue#L14) 组件中的页面带的 面包屑和页面标题栏 | boolean | false | -| permission | 与项目提供的权限拦截匹配的权限,如果不匹配,则会被禁止访问该路由页面 | array | [] | +| 参数 | 说明 | 类型 | 默认值 | +| ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | ------ | +| title | 路由标题, 用于显示面包屑, 页面标题 *推荐设置 | string | - | +| icon | 路由在 menu 上显示的图标 | [string,svg] | - | +| keepAlive | 缓存该路由 | boolean | false | +| hidden | 配合`alwaysShow`使用,用于隐藏菜单时,提供递归到父菜单显示 选中菜单项_(可参考 个人页 配置方式)_ | boolean | false | +| hiddenHeaderContent | *特殊 隐藏 [PageHeader](https://github.com/sendya/ant-design-pro-vue/blob/master/src/components/layout/PageHeader.vue#L14) 组件中的页面带的 面包屑和页面标题栏 | boolean | false | +| permission | 与项目提供的权限拦截匹配的权限,如果不匹配,则会被禁止访问该路由页面 | array | [] | > 路由自定义 `Icon` 请引入自定义 `svg` Icon 文件,然后传递给路由的 `meta.icon` 参数即可 @@ -129,12 +129,10 @@ const asyncRouterMap = [ ] ``` -> 1. 请注意 `component: () => import('..') ` 方式引入路由的页面组件为 懒加载模式。具体可以看 [Vue 官方文档](https://router.vuejs.org/zh/guide/advanced/lazy-loading.html) +> 1. 请注意 `component: () => import('..')` 方式引入路由的页面组件为 懒加载模式。具体可以看 [Vue 官方文档](https://router.vuejs.org/zh/guide/advanced/lazy-loading.html) > 2. 增加新的路由应该增加在 '/' (index) 路由的 `children` 内 > 3. `permission` 可以进行自定义修改,只需要对这个模块进行自定义修改即可 [src/store/modules/permission.js#L10](https://github.com/sendya/ant-design-pro-vue/blob/master/src/store/modules/permission.js#L10) - - 附权限路由结构: ![权限结构](https://static-2.loacg.com/open/static/github/permissions.png) \ No newline at end of file diff --git a/src/utils/device.js b/src/utils/device.js index 0f350f365..1244595e9 100644 --- a/src/utils/device.js +++ b/src/utils/device.js @@ -6,7 +6,7 @@ export const DEVICE_TYPE = { MOBILE: 'mobile' } -export const deviceEnquire = function (callback) { +export const deviceEnquire = function(callback) { const matchDesktop = { match: () => { callback && callback(DEVICE_TYPE.DESKTOP) diff --git a/src/utils/filter.js b/src/utils/filter.js index 45702c620..7c74fa05d 100644 --- a/src/utils/filter.js +++ b/src/utils/filter.js @@ -1,9 +1,10 @@ import Vue from 'vue' import moment from 'moment' import 'moment/locale/zh-cn' +import { timeAgo } from '@/utils/util' moment.locale('zh-cn') -Vue.filter('NumberFormat', function (value) { +Vue.filter('NumberFormat', function(value) { if (!value) { return '0' } @@ -11,10 +12,12 @@ Vue.filter('NumberFormat', function (value) { return intPartFormat }) -Vue.filter('dayjs', function (dataStr, pattern = 'YYYY-MM-DD HH:mm:ss') { +Vue.filter('dayjs', function(dataStr, pattern = 'YYYY-MM-DD HH:mm:ss') { return moment(dataStr).format(pattern) }) -Vue.filter('moment', function (dataStr, pattern = 'YYYY-MM-DD HH:mm:ss') { +Vue.filter('moment', function(dataStr, pattern = 'YYYY-MM-DD HH:mm:ss') { return moment(dataStr).format(pattern) }) + +Vue.filter('timeAgo', timeAgo) diff --git a/src/utils/helper/permission.js b/src/utils/helper/permission.js index 347cdf7ad..2fa21b273 100644 --- a/src/utils/helper/permission.js +++ b/src/utils/helper/permission.js @@ -1,52 +1,57 @@ const PERMISSION_ENUM = { - 'add': { key: 'add', label: '新增' }, - 'delete': { key: 'delete', label: '删除' }, - 'edit': { key: 'edit', label: '修改' }, - 'query': { key: 'query', label: '查询' }, - 'get': { key: 'get', label: '详情' }, - 'enable': { key: 'enable', label: '启用' }, - 'disable': { key: 'disable', label: '禁用' }, - 'import': { key: 'import', label: '导入' }, - 'export': { key: 'export', label: '导出' } + add: { key: 'add', label: '新增' }, + delete: { key: 'delete', label: '删除' }, + edit: { key: 'edit', label: '修改' }, + query: { key: 'query', label: '查询' }, + get: { key: 'get', label: '详情' }, + enable: { key: 'enable', label: '启用' }, + disable: { key: 'disable', label: '禁用' }, + import: { key: 'import', label: '导入' }, + export: { key: 'export', label: '导出' } } -function plugin (Vue) { +function plugin(Vue) { if (plugin.installed) { return } - !Vue.prototype.$auth && Object.defineProperties(Vue.prototype, { - $auth: { - get () { - const _this = this - return (permissions) => { - const [permission, action] = permissions.split('.') - const permissionList = _this.$store.getters.roles.permissions - permissionList.find((val) => { - return val.permissionId === permission - }).actionList.findIndex((val) => { - return val === action - }) - return false + !Vue.prototype.$auth && + Object.defineProperties(Vue.prototype, { + $auth: { + get() { + const _this = this + return permissions => { + const [permission, action] = permissions.split('.') + const permissionList = _this.$store.getters.roles.permissions + permissionList + .find(val => { + return val.permissionId === permission + }) + .actionList.findIndex(val => { + return val === action + }) + return false + } } } - } - }) + }) - !Vue.prototype.$enum && Object.defineProperties(Vue.prototype, { - $enum: { - get () { - // const _this = this; - return (val) => { - let result = PERMISSION_ENUM - val && val.split('.').forEach(v => { - result = result && result[v] || null - }) - return result + !Vue.prototype.$enum && + Object.defineProperties(Vue.prototype, { + $enum: { + get() { + // const _this = this; + return val => { + let result = PERMISSION_ENUM + val && + val.split('.').forEach(v => { + result = (result && result[v]) || null + }) + return result + } } } - } - }) + }) } export default plugin diff --git a/src/utils/mixin.js b/src/utils/mixin.js index 57c49290d..63dc1c8c9 100644 --- a/src/utils/mixin.js +++ b/src/utils/mixin.js @@ -22,10 +22,10 @@ const mixin = { }) }, methods: { - isTopMenu () { + isTopMenu() { return this.layoutMode === 'topmenu' }, - isSideMenu () { + isSideMenu() { return !this.isTopMenu() } } @@ -38,13 +38,13 @@ const mixinDevice = { }) }, methods: { - isMobile () { + isMobile() { return this.device === DEVICE_TYPE.MOBILE }, - isDesktop () { + isDesktop() { return this.device === DEVICE_TYPE.DESKTOP }, - isTablet () { + isTablet() { return this.device === DEVICE_TYPE.TABLET } } diff --git a/src/utils/util.js b/src/utils/util.js index 70fed5152..e34d79518 100644 --- a/src/utils/util.js +++ b/src/utils/util.js @@ -33,3 +33,25 @@ export function removeLoadingAnimate(id = '', timeout = 1500) { document.body.removeChild(document.getElementById(id)) }, timeout) } + +function pluralize(time, label) { + if (time === 1) { + return time + label + } + return time + label +} + +/** + * time ago + * @param {*} time + */ +export function timeAgo(time) { + const between = (Date.now() - Number(time)) / 1000 + if (between < 3600) { + return pluralize(~~(between / 60), ' 分钟前') + } else if (between < 86400) { + return pluralize(~~(between / 3600), ' 小时前') + } else { + return pluralize(~~(between / 86400), ' 天前') + } +} diff --git a/src/views/Home.vue b/src/views/Home.vue index 4df245f7e..74722dd56 100644 --- a/src/views/Home.vue +++ b/src/views/Home.vue @@ -1,11 +1,15 @@ @@ -130,19 +190,20 @@ export default { AvatarList, AvatarListItem }, - data () { + data() { return { targetTime: new Date().getTime() + 3900000 } }, methods: { - onEndHandle () { + onEndHandle() { this.$message.success('CountDown callback!!!') }, - onEndHandle2 () { + onEndHandle2() { this.$notification.open({ message: 'Notification Title', - description: 'This is the content of the notification. This is the content of the notification. This is the content of the notification.' + description: + 'This is the content of the notification. This is the content of the notification. This is the content of the notification.' }) } } @@ -150,14 +211,14 @@ export default { diff --git a/src/views/dashboard/Dashboard.vue b/src/views/dashboard/Dashboard.vue index 3f08a4eb8..9d09d922e 100644 --- a/src/views/dashboard/Dashboard.vue +++ b/src/views/dashboard/Dashboard.vue @@ -16,9 +16,22 @@ > + + {{ status.statusText }} + + + + {{ editTime | timeAgo }} + @@ -62,11 +75,13 @@ const postColumns = [ { title: '状态', className: 'status', - dataIndex: 'status' + dataIndex: 'status', + scopedSlots: { customRender: 'status' } }, { - title: '发布时间', - dataIndex: 'date' + title: '最后编辑时间', + dataIndex: 'editTime', + scopedSlots: { customRender: 'editTime' } } ] @@ -92,6 +107,13 @@ const commentColumns = [ } ] +const postStatus = { + PUBLISHED: { + status: 'success', + statusText: '已发布' + } +} + export default { name: 'Dashboard', components: {}, @@ -115,6 +137,15 @@ export default { this.listLatestComments() this.listLatestLogs() }, + computed: { + formattedPostData() { + return Object.assign([], this.postData).map(post => { + // Format the status + post.status = postStatus[post.status] + return post + }) + } + }, methods: { listLatestPosts() { postApi.listLatest().then(response => {