diff --git a/resources/assets/js/functions/web.js b/resources/assets/js/functions/web.js
index cb9b98c41..46140abcc 100755
--- a/resources/assets/js/functions/web.js
+++ b/resources/assets/js/functions/web.js
@@ -385,7 +385,25 @@
*/
getDialogUnread(dialog) {
return dialog ? (dialog.unread || dialog.is_mark_unread || 0) : 0
- }
+ },
+
+ /**
+ * 克隆对象
+ * @param myObj
+ * @returns {*}
+ */
+ cloneData(myObj) {
+ if (typeof (myObj) !== 'object') return myObj;
+ if (myObj === null) return myObj;
+ //
+ if (typeof myObj.length === 'number') {
+ let [...myNewObj] = myObj;
+ return myNewObj;
+ } else {
+ let {...myNewObj} = myObj;
+ return myNewObj;
+ }
+ },
});
/**
diff --git a/resources/assets/js/pages/manage/components/GanttView.vue b/resources/assets/js/pages/manage/components/GanttView.vue
new file mode 100644
index 000000000..c9901b088
--- /dev/null
+++ b/resources/assets/js/pages/manage/components/GanttView.vue
@@ -0,0 +1,359 @@
+
+
+
+
+
+ -
+
{{$L('已超期')}}
+ {{item.label}}
+
+
+
+
+
+
+
+ -
+
{{monthFormat(key)}}
+
+
+
+
+
+
+
+
+
+
diff --git a/resources/assets/js/pages/manage/components/ProjectGantt.vue b/resources/assets/js/pages/manage/components/ProjectGantt.vue
new file mode 100644
index 000000000..7d8b80330
--- /dev/null
+++ b/resources/assets/js/pages/manage/components/ProjectGantt.vue
@@ -0,0 +1,270 @@
+
+
+
+
+
+
+ {{$L('全部')}}
+
+ {{item.name}}
+ ({{item.tasks.length}})
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{$L('未保存计划时间')}}: {{editData.length}}
+
+
+
+
+
+
+
+
diff --git a/resources/assets/js/pages/manage/components/ProjectList.vue b/resources/assets/js/pages/manage/components/ProjectList.vue
index 60bf4a4d6..c9bfa2afc 100644
--- a/resources/assets/js/pages/manage/components/ProjectList.vue
+++ b/resources/assets/js/pages/manage/components/ProjectList.vue
@@ -85,6 +85,12 @@
+
+
+ {{ $L('甘特图') }}
+
@@ -311,7 +317,15 @@
-
+
li {
+ height: 40px;
+ border-bottom: 1px solid rgba(237, 241, 242, 0.75);
+ position: relative;
+ display: flex;
+ align-items: center;
+ padding-left: 12px;
+ &:hover {
+ .item-icon {
+ display: flex;
+ }
+ }
+ .item-overdue {
+ flex-grow:0;
+ flex-shrink:0;
+ color: #ffffff;
+ margin-right: 4px;
+ background-color: #ff0000;
+ padding: 1px 3px;
+ border-radius: 3px;
+ font-size: 12px;
+ line-height: 18px;
+ }
+ .item-title {
+ flex: 1;
+ padding-right: 12px;
+ cursor: default;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ &.complete {
+ text-decoration: line-through;
+ }
+ &.overdue {
+ font-weight: 600;
+ }
+ }
+ .item-icon {
+ display: none;
+ align-items: center;
+ justify-content: center;
+ width: 32px;
+ margin-right: 2px;
+ font-size: 16px;
+ color: #888888;
+ }
+ }
+ }
+ }
+ .gantt-right {
+ flex: 1;
+ height: 100%;
+ background-color: #ffffff;
+ position: relative;
+ overflow: hidden;
+ .gantt-chart {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ transform: translateZ(0);
+ .gantt-month {
+ display: flex;
+ align-items: center;
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ z-index: 1;
+ height: 26px;
+ line-height: 20px;
+ font-size: 14px;
+ background-color: #F9FAFB;
+ > li {
+ flex-grow: 0;
+ flex-shrink: 0;
+ height: 100%;
+ position: relative;
+ overflow: hidden;
+ &:after {
+ content: "";
+ position: absolute;
+ top: 0;
+ right: 0;
+ width: 1px;
+ height: 100%;
+ background-color: rgba(237, 241, 242, 0.75);
+ }
+ .month-format {
+ overflow: hidden;
+ white-space: nowrap;
+ padding: 6px 6px 0;
+ }
+ }
+ }
+ .gantt-date {
+ display: flex;
+ align-items: center;
+ position: absolute;
+ top: 26px;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ z-index: 2;
+ cursor: move;
+ &:before {
+ content: "";
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ height: 50px;
+ background-color: #F9FAFB;
+ }
+ > li {
+ flex-grow: 0;
+ flex-shrink: 0;
+ height: 100%;
+ position: relative;
+ overflow: hidden;
+ &:after {
+ content: "";
+ position: absolute;
+ top: 0;
+ right: 0;
+ width: 1px;
+ height: 100%;
+ background-color: rgba(237, 241, 242, 0.75);
+ }
+ .date-format {
+ overflow: hidden;
+ white-space: nowrap;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ height: 44px;
+ .format-day {
+ line-height: 28px;
+ font-size: 18px;
+ }
+ .format-wook {
+ line-height: 16px;
+ font-weight: 300;
+ font-size: 13px;
+ }
+ }
+ }
+ }
+ .gantt-timeline {
+ position: absolute;
+ top: 76px;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ z-index: 3;
+ overflow-x: hidden;
+ overflow-y: auto;
+ > li {
+ cursor: default;
+ height: 40px;
+ border-bottom: 1px solid rgba(237, 241, 242, 0.75);
+ position: relative;
+ .timeline-item {
+ position: absolute;
+ top: 0;
+ touch-action: none;
+ pointer-events: auto;
+ padding: 4px;
+ margin-top: 4px;
+ background: #e74c3c;
+ border-radius: 18px;
+ color: #fff;
+ display: flex;
+ align-items: center;
+ will-change: contents;
+ height: 32px;
+ .timeline-title {
+ touch-action: none;
+ flex-grow: 1;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ margin-left: 4px;
+ margin-right: 10px;
+ }
+ .timeline-resizer {
+ height: 22px;
+ touch-action: none;
+ width: 8px;
+ background: rgba(255,255,255,0.1);
+ cursor: ew-resize;
+ flex-shrink: 0;
+ will-change: visibility;
+ position: absolute;
+ top: 5px;
+ right: 5px;
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/resources/assets/sass/pages/components/project-gantt.scss b/resources/assets/sass/pages/components/project-gantt.scss
new file mode 100644
index 000000000..350fbb39b
--- /dev/null
+++ b/resources/assets/sass/pages/components/project-gantt.scss
@@ -0,0 +1,135 @@
+.project-gstc-gantt {
+ position: absolute;
+ top: 15px;
+ left: 15px;
+ right: 15px;
+ bottom: 15px;
+ z-index: 1;
+ transform: translateZ(0);
+ background-color: #fdfdfd;
+ border-radius: 3px;
+ overflow: hidden;
+
+ .project-gstc-dropdown-filtr {
+ position: absolute;
+ top: 38px;
+ left: 222px;
+
+ .project-gstc-dropdown-icon {
+ cursor: pointer;
+ color: #999;
+ font-size: 20px;
+
+ &.filtr {
+ color: #058ce4;
+ }
+ }
+ }
+
+ .project-gstc-close {
+ position: absolute;
+ top: 8px;
+ left: 12px;
+ cursor: pointer;
+
+ &:hover {
+ i {
+ transform: scale(1) rotate(45deg);
+ }
+ }
+
+ i {
+ color: #666666;
+ font-size: 28px;
+ transform: scale(0.92);
+ transition: all .2s;
+ }
+ }
+
+ .project-gstc-edit {
+ position: absolute;
+ bottom: 6px;
+ right: 6px;
+ background: #ffffff;
+ border-radius: 4px;
+ opacity: 0;
+ transform: translate(120%, 0);
+ transition: all 0.2s;
+
+ &.visible {
+ opacity: 1;
+ transform: translate(0, 0);
+ }
+
+ &.info {
+ .project-gstc-edit-info {
+ display: block;
+ }
+
+ .project-gstc-edit-small {
+ display: none;
+ }
+ }
+
+ .project-gstc-edit-info {
+ display: none;
+ border: 1px solid #e4e4e4;
+ background: #ffffff;
+ padding: 6px;
+ border-radius: 4px;
+ width: 500px;
+
+ .project-gstc-edit-btns {
+ margin: 12px 6px 4px;
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
+
+ .ivu-btn {
+ margin-right: 8px;
+ font-size: 13px;
+ }
+
+ .zoom {
+ font-size: 20px;
+ color: #444444;
+ cursor: pointer;
+
+ &:hover {
+ color: #57a3f3;
+ }
+ }
+ }
+ }
+
+ .project-gstc-edit-small {
+ border: 1px solid #e4e4e4;
+ background: #ffffff;
+ padding: 6px 12px;
+ display: flex;
+ align-items: center;
+
+ .project-gstc-edit-text {
+ cursor: pointer;
+ text-decoration: underline;
+ color: #444444;
+ margin-right: 8px;
+
+ &:hover {
+ color: #57a3f3;
+ }
+ }
+
+ .ivu-btn {
+ margin-left: 4px;
+ font-size: 13px;
+ }
+ }
+ }
+
+ .ivu-dropdown-item {
+ &.dropdown-active {
+ color: #058ce4;
+ }
+ }
+}
diff --git a/resources/assets/sass/pages/components/project-list.scss b/resources/assets/sass/pages/components/project-list.scss
index 02770cc4b..0f990d207 100644
--- a/resources/assets/sass/pages/components/project-list.scss
+++ b/resources/assets/sass/pages/components/project-list.scss
@@ -240,6 +240,17 @@
}
}
}
+ .project-gantt-item{
+ padding-left:5px;
+ &.active{
+ color: $primary-color;
+ }
+ .force-right{
+ &.act{
+ color: #2A53FF;
+ }
+ }
+ }
}
}
}