diff --git a/README.md b/README.md index 84f7585..5df34c9 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,17 @@ Composer 1. 修改./src/config.js,将crossDomain 值改为‘false’ 2. 修改./vue.config.js,将DEV_URL的值改为接口的访问地址 3. 重启启动项目 +8. 消息推送 + 1. 后端 + 1. 进入application/common/Plugins/GateWayWorker + 2. 修改config.php,修改 SERVER_ADDRESS 的值为内网IP地址。端口号根据情况需改,注意服务器要放行对应的端口 + 3. 如果是HTTPS协议,需要开启SSL支持 + 4. Windows环境下,直接运行start_for_win.bat文件 + 5. Linux环境下,运行 bash start.sh 启动服务,运行 bash stop.sh 终止服务 + 2. 前端 + 1. 进入 src/config/config.js + 2.WS_URI 地址修改为相应的ip地址。如果使用https,不能写ip需要写域名 + ### 鼓励一下 ### Sample diff --git a/src/api/common/common.js b/src/api/common/common.js index 59ae8fc..f863d9f 100644 --- a/src/api/common/common.js +++ b/src/api/common/common.js @@ -8,6 +8,14 @@ export function checkInstall() { return $http.post('index/index/checkInstall'); } +export function inviteInfo(inviteCode) { + return $http.post('project/invite_link/_read', {inviteCode: inviteCode}); +} +export function createInviteLink(data) { + return $http.post('project/invite_link/save', data); +} + + export function notifyOverview(to) { return $http.post('index/notify/listTypeFormat', {to: to}); } diff --git a/src/api/projectMember.js b/src/api/projectMember.js index 46c131a..743483f 100644 --- a/src/api/projectMember.js +++ b/src/api/projectMember.js @@ -7,6 +7,9 @@ export function searchInviteMember(keyword, code) { export function inviteMember(memberCode, code) { return $http.post('project/project_member/inviteMember', {memberCode: memberCode, projectCode: code}); } +export function _joinByInviteLink(inviteCode) { + return $http.post('project/project_member/_joinByInviteLink', {inviteCode: inviteCode}); +} export function removeMember(memberCode, code) { return $http.post('project/project_member/removeMember', {memberCode: memberCode, projectCode: code}); } diff --git a/src/api/task.js b/src/api/task.js index af4df5a..b4ab347 100644 --- a/src/api/task.js +++ b/src/api/task.js @@ -7,6 +7,7 @@ export function list(data) { export function selfList(data) { return $http.post('project/task/selfList', data); } + export function taskSources(data) { return $http.post('project/task/taskSources', data); } @@ -39,6 +40,10 @@ export function assignTask(data) { return $http.post('project/task/assignTask', data); } +export function batchAssignTask(data) { + return $http.post('project/task/batchAssignTask', data); +} + export function read(code) { return $http.post('project/task/read', {taskCode: code}); } @@ -47,9 +52,14 @@ export function taskDone(code, done) { return $http.post('project/task/taskDone', {taskCode: code, done: done}); } +export function setPrivate(code, isPrivate) { + return $http.post('project/task/setPrivate', {taskCode: code, private: isPrivate}); +} + export function recycle(code) { return $http.post('project/task/recycle', {taskCode: code}); } + export function recycleBatch(data) { return $http.post('project/task/recycleBatch', data); } diff --git a/src/api/user.js b/src/api/user.js index 7663ede..2a7cc75 100644 --- a/src/api/user.js +++ b/src/api/user.js @@ -3,19 +3,23 @@ import $http from '@/assets/js/http' export async function Login(data) { return $http.post('project/login', data); } + export function register(data) { return $http.post('project/login/register', data); } + export function getCaptcha() { return $http.post('project/login/getCaptcha'); } + export function changeCurrentOrganization(organizationCode) { - return $http.post('project/index/changeCurrentOrganization', {organizationCode:organizationCode}); + return $http.post('project/index/changeCurrentOrganization', {organizationCode: organizationCode}); } export function list(data) { return $http.post('project/account', data); } + export function forbid(accountCode) { return $http.post('project/account/forbid', {accountCode: accountCode, status: 0}); } @@ -23,26 +27,43 @@ export function forbid(accountCode) { export function resume(accountCode) { return $http.post('project/account/resume', {accountCode: accountCode, status: 1}); } + export function doAccount(data) { let url = 'project/account/add'; - if (data.id) { + if (data.code) { url = 'project/account/edit'; } return $http.post(url, data); } + export function auth(id, auth) { return $http.post('project/account/auth', {id: id, auth: auth}); } + export function del(accountCode) { return $http.post('project/account/del', {accountCode: accountCode}); } + export function info($id) { return $http.post('project/index/info', {id: $id}); } +export function read(code) { + return $http.post('project/account/read', {code: code}); +} + +export function editAccount(data) { + return $http.post('project/account/edit', data); +} + export function editPersonal(data) { return $http.post('project/index/editPersonal', data); } + export function editPassword(data) { return $http.post('project/index/editPassword', data); } + +export function _joinByInviteLink(inviteCode) { + return $http.post('project/account/_joinByInviteLink', {inviteCode: inviteCode}); +} diff --git a/src/assets/css/components/base.less b/src/assets/css/components/base.less index 6b1818c..8f65939 100644 --- a/src/assets/css/components/base.less +++ b/src/assets/css/components/base.less @@ -15,49 +15,64 @@ body { color: rgba(0, 0, 0, 0.45); font-weight: 400; } -.text-grey{ + +.text-grey { color: grey; } -.text-default{ + +.text-default { color: #333; } -.text-primary{ + +.text-primary { color: @primary-color; } -.text-info{ + +.text-info { color: @info-color; } -.text-success{ + +.text-success { color: @success-color; } -.text-processing{ + +.text-processing { color: @processing-color; } -.text-error{ + +.text-error { color: @error-color; } -.text-highlight{ + +.text-highlight { color: @highlight-color; } -.text-warning{ + +.text-warning { color: @warning-color; } -.text-normal{ + +.text-normal { color: @normal-color; } -.text-center{ + +.text-center { text-align: center; } -.text-right{ + +.text-right { text-align: right; } -.text-left{ + +.text-left { text-align: left; } + //Input -.ant-input-lg{ +.ant-input-lg { font-size: 14px; } + .ant-select-lg { font-size: 14px; } @@ -65,18 +80,21 @@ body { //Button .action-btn { margin-top: 12px; - .cancel-text{ + + .cancel-text { margin-right: 12px; } + button { margin-right: 4px; } } -.group-btn,.submit-set { - .cancel-text{ +.group-btn, .submit-set { + .cancel-text { margin-right: 12px; } + button { margin-right: 4px; } @@ -84,10 +102,12 @@ body { .middle-btn { min-width: 66px; + //min-height: 42px; //min-width: 90px; //height: 35px !important; } -.ant-btn-lg{ + +.ant-btn-lg { font-size: 14px; } @@ -106,18 +126,22 @@ body { .table-list { .item { display: inline-block; + &.row-img { img { width: 85px; height: 85px; } } + &.row-title { margin-left: 12px; vertical-align: middle; width: 75%; + .title { margin-bottom: 0; + &.title-name { padding: 5px 24px 5px 5px; color: @primary-color; @@ -125,14 +149,17 @@ body { } } } + .edit-content { .prefix { position: absolute; line-height: 2.3; } + .editable-cell { width: 115px; } + &.price { .editable-cell-input-wrapper, .editable-cell-text-wrapper { padding-left: 15px; @@ -142,9 +169,10 @@ body { } //Drowdown -.ant-dropdown-menu-item{ +.ant-dropdown-menu-item { color: grey; } + .field-right-menu { width: 240px; @@ -186,19 +214,22 @@ body { } //Modal -.ant-modal{ +.ant-modal { top: 50px; } -.scroll-modal{ - .ant-modal-body{ + +.scroll-modal { + .ant-modal-body { padding-bottom: 24px; height: 70vh; } - .modal-content{ + + .modal-content { padding: 0 24px; height: 100%; } - .modal-footer{ + + .modal-footer { position: fixed; bottom: 13vh; background: #FFF; @@ -206,11 +237,26 @@ body { } } -.hidden{ +.task-detail-modal { + width: 1200px; + + &.ant-modal { + padding-bottom: 0; + } + + .ant-modal-content { + .ant-modal-body { + padding: 0; + } + + } +} + +.hidden { display: block; } -.project-navigation{ +.project-navigation { border-bottom: 1px solid #D9D9D9; z-index: 1; background-color: #F5F5F5; @@ -218,35 +264,42 @@ body { position: fixed; width: 100%; } -.project-navigation .ivu-breadcrumb-item-separator{ + +.project-navigation .ivu-breadcrumb-item-separator { color: #383838; } -.project-navigation .ivu-breadcrumb > span:last-child{ - font-weight:normal; + +.project-navigation .ivu-breadcrumb > span:last-child { + font-weight: normal; } -.project-navigation .project-nav-header{ + +.project-navigation .project-nav-header { position: absolute; z-index: 2; left: 0; height: 50px; margin: 0; padding: 15px; - .nav-title{ + + .nav-title { font-size: 15px; margin-right: 12px; } - .actions{ + + .actions { cursor: pointer; margin-right: 12px; } } + .project-navigation .nav-underscore { position: relative; height: 50px; border: none; margin-bottom: 0; } -.project-navigation .nav-body{ + +.project-navigation .nav-body { position: relative; white-space: nowrap; z-index: 1; @@ -257,14 +310,17 @@ body { -ms-flex-pack: center; justify-content: center; } + .project-navigation .nav-body .nav-wrapper.nav > li { z-index: 2; padding: 0 20px; } + .project-navigation .nav-underscore > li { list-style: none; float: left; } + .project-navigation .nav-underscore > li a { display: inline-block; position: relative; @@ -275,6 +331,7 @@ body { font-size: 15px; font-weight: normal; } + .project-navigation .nav-body .nav-wrapper.nav > li .app[data-app=tasks] { position: relative; float: left; @@ -283,9 +340,11 @@ body { text-overflow: ellipsis; white-space: nowrap; } + .project-navigation .nav-underscore > li > a:hover { background-color: inherit; } + .project-navigation .nav-underscore > li > a:after { position: absolute; left: 0; @@ -296,6 +355,7 @@ body { content: ''; opacity: 0; } + .project-navigation .nav-underscore > li > a:hover:after, .project-navigation .nav-underscore > .actives > a:after { border-width: 3px; opacity: 1; diff --git a/src/assets/css/components/task.less b/src/assets/css/components/task.less index ee5382b..a636491 100644 --- a/src/assets/css/components/task.less +++ b/src/assets/css/components/task.less @@ -581,6 +581,11 @@ border-radius: 50%; } +.disabled { + cursor: not-allowed; + color: rgba(0, 0, 0, 0.45); +} + .task.task-card.done .check-box, .task.task-card.done .task-content-set { opacity: 0.64; filter: alpha(opacity=64); @@ -602,6 +607,7 @@ .task .check-box.disabled { border-color: #ccc !important; background-color: #f5f5f5; + cursor: not-allowed; } .children-task-list .task .check-box { diff --git a/src/assets/js/notify.js b/src/assets/js/notify.js index ac541b9..171bc2c 100644 --- a/src/assets/js/notify.js +++ b/src/assets/js/notify.js @@ -2,87 +2,87 @@ * Created by vilson on 17/6/4. */ export const showMsgNotification = (title, msg, $opt = {}) => { - let options = { - body: msg, - icon: $opt.icon || "http://static.vilson.xyz/preview.jpg", - showTime: $opt.showTime || 15000, - onclick: $opt.onclick, - onshow: $opt.onshow, - onerror: $opt.onerror, - onclose: $opt.onclose, - }; - let Notification = window.Notification || window.mozNotification || window.webkitNotification; - console.log(Notification.permission) - if (Notification && Notification.permission === "granted") { - let instance = new Notification(title, options); - instance.onclick = function () { - // Something to do - if (typeof options.onclick === 'function') { - options.onclick(instance) - } - // window.location.href = instance.icon + let options = { + body: msg, + icon: $opt.icon || "http://static.vilson.xyz/preview.jpg", + showTime: $opt.showTime || 15000, + onclick: $opt.onclick, + onshow: $opt.onshow, + onerror: $opt.onerror, + onclose: $opt.onclose, }; - instance.onerror = function () { - // Something to do - if (typeof options.onerror === 'function') { - options.onerror(instance) - } - }; - instance.onshow = function () { - // Something to do - if (typeof options.onshow === 'function') { - options.onshow(instance) - } - setTimeout(function () { - instance.close(); - }, options.showTime) - }; - instance.onclose = function () { - // Something to do - if (typeof options.onclose === 'function') { - options.onclose(instance) - } - }; - } else if (Notification && Notification.permission !== "denied") { - Notification.requestPermission(function (status) { - if (Notification.permission !== status) { - Notification.permission = status; - } - // If the user said okay - if (status === "granted") { + let Notification = window.Notification || window.mozNotification || window.webkitNotification; + console.log(Notification.permission); + if (Notification && Notification.permission === "granted") { let instance = new Notification(title, options); instance.onclick = function () { - // Something to do - if (typeof options.onclick === 'function') { - options.onclick(instance) - } + // Something to do + if (typeof options.onclick === 'function') { + options.onclick(instance) + } + // window.location.href = instance.icon }; instance.onerror = function () { - // Something to do - if (typeof options.onerror === 'function') { - options.onerror(instance) - } + // Something to do + if (typeof options.onerror === 'function') { + options.onerror(instance) + } }; instance.onshow = function () { - // Something to do - if (typeof options.onshow === 'function') { - options.onshow(instance) - } - setTimeout(function () { - instance.close(); - }, options.showTime) + // Something to do + if (typeof options.onshow === 'function') { + options.onshow(instance) + } + setTimeout(function () { + instance.close(); + }, options.showTime) }; instance.onclose = function () { - // Something to do - if (typeof options.onclose === 'function') { - options.onclose(instance) - } + // Something to do + if (typeof options.onclose === 'function') { + options.onclose(instance) + } }; - } else { - return false - } - }); - } else { - return false; - } -} + } else if (Notification && Notification.permission !== "denied") { + Notification.requestPermission(function (status) { + if (Notification.permission !== status) { + Notification.permission = status; + } + // If the user said okay + if (status === "granted") { + let instance = new Notification(title, options); + instance.onclick = function () { + // Something to do + if (typeof options.onclick === 'function') { + options.onclick(instance) + } + }; + instance.onerror = function () { + // Something to do + if (typeof options.onerror === 'function') { + options.onerror(instance) + } + }; + instance.onshow = function () { + // Something to do + if (typeof options.onshow === 'function') { + options.onshow(instance) + } + setTimeout(function () { + instance.close(); + }, options.showTime) + }; + instance.onclose = function () { + // Something to do + if (typeof options.onclose === 'function') { + options.onclose(instance) + } + }; + } else { + return false + } + }); + } else { + return false; + } +}; diff --git a/src/components/Trend/Trend.vue b/src/components/Trend/Trend.vue new file mode 100644 index 0000000..1be8e91 --- /dev/null +++ b/src/components/Trend/Trend.vue @@ -0,0 +1,41 @@ + + + + + \ No newline at end of file diff --git a/src/components/Trend/index.js b/src/components/Trend/index.js new file mode 100644 index 0000000..761366d --- /dev/null +++ b/src/components/Trend/index.js @@ -0,0 +1,3 @@ +import Trend from './Trend.vue' + +export default Trend \ No newline at end of file diff --git a/src/components/Trend/index.less b/src/components/Trend/index.less new file mode 100644 index 0000000..d020c06 --- /dev/null +++ b/src/components/Trend/index.less @@ -0,0 +1,42 @@ +@import "../index"; + +@trend-prefix-cls: ~"@{ant-pro-prefix}-trend"; + +.@{trend-prefix-cls} { + display: inline-block; + font-size: @font-size-base; + line-height: 22px; + + .up, + .down { + margin-left: 4px; + position: relative; + top: 1px; + + i { + font-size: 12px; + transform: scale(0.83); + } + } + + .item-text { + display: inline-block; + margin-left: 8px; + color: rgba(0,0,0,.85); + } + + .up { + color: @red-6; + } + .down { + color: @green-6; + top: -1px; + } + + &.reverse-color .up { + color: @green-6; + } + &.reverse-color .down { + color: @red-6; + } +} diff --git a/src/components/Trend/index.md b/src/components/Trend/index.md new file mode 100644 index 0000000..8881f0e --- /dev/null +++ b/src/components/Trend/index.md @@ -0,0 +1,45 @@ +# Trend 趋势标记 + +趋势符号,标记上升和下降趋势。通常用绿色代表“好”,红色代表“不好”,股票涨跌场景除外。 + + + +引用方式: + +```javascript +import Trend from '@/components/Trend' + +export default { + components: { + Trend + } +} +``` + + + +## 代码演示 [demo](https://pro.loacg.com/test/home) + +```html +5% +``` +或 +```html + + 工资 + 5% + +``` +或 +```html +5% +``` + + +## API + +| 参数 | 说明 | 类型 | 默认值 | +|----------|------------------------------------------|-------------|-------| +| flag | 上升下降标识:`up|down` | string | - | +| reverseColor | 颜色反转 | Boolean | false | + diff --git a/src/components/chart/ChartCard.vue b/src/components/chart/ChartCard.vue new file mode 100644 index 0000000..0d83f98 --- /dev/null +++ b/src/components/chart/ChartCard.vue @@ -0,0 +1,111 @@ + + + + + \ No newline at end of file diff --git a/src/components/chart/MiniProgress.vue b/src/components/chart/MiniProgress.vue new file mode 100644 index 0000000..3e548bb --- /dev/null +++ b/src/components/chart/MiniProgress.vue @@ -0,0 +1,75 @@ + + + + + diff --git a/src/components/chart/RankList.vue b/src/components/chart/RankList.vue new file mode 100644 index 0000000..e62adb6 --- /dev/null +++ b/src/components/chart/RankList.vue @@ -0,0 +1,77 @@ + + + + + \ No newline at end of file diff --git a/src/components/index.less b/src/components/index.less new file mode 100644 index 0000000..df1feb4 --- /dev/null +++ b/src/components/index.less @@ -0,0 +1,4 @@ +@import "~ant-design-vue/lib/style/index"; + +// The prefix to use on all css classes from ant-pro. +@ant-pro-prefix : ant-pro; diff --git a/src/components/layout/header/HeaderNotice.vue b/src/components/layout/header/HeaderNotice.vue index 32a0db8..24f21f4 100644 --- a/src/components/layout/header/HeaderNotice.vue +++ b/src/components/layout/header/HeaderNotice.vue @@ -1,79 +1,88 @@