no message

This commit is contained in:
kuaifan 2021-05-31 15:44:33 +08:00
parent 489804ca80
commit d95220763a
7 changed files with 1178 additions and 23 deletions

View File

@ -26,7 +26,9 @@
"vue": "^2.6.12",
"vue-loader": "^15.9.7",
"vue-router": "^3.4.2",
"vue-template-compiler": "^2.6.11"
"vue-template-compiler": "^2.6.11",
"webpack": "^5.38.1",
"webpack-cli": "^4.7.0"
},
"dependencies": {
"echarts": "^5.1.1",

View File

@ -0,0 +1,396 @@
<template>
<div :class="wrapClasses">
<template v-if="type !== 'textarea'">
<div :class="[prefixCls + '-group-prepend']" v-if="prepend" v-show="slotReady"><slot name="prepend"></slot></div>
<i class="ivu-icon" :class="['ivu-icon-ios-close-circle', prefixCls + '-icon', prefixCls + '-icon-clear' , prefixCls + '-icon-normal']" v-if="clearable && currentValue && !itemDisabled" @click="handleClear"></i>
<i class="ivu-icon" :class="['ivu-icon-' + icon, prefixCls + '-icon', prefixCls + '-icon-normal']" v-else-if="icon" @click="handleIconClick"></i>
<i class="ivu-icon ivu-icon-ios-search" :class="[prefixCls + '-icon', prefixCls + '-icon-normal', prefixCls + '-search-icon']" v-else-if="search && enterButton === false" @click="handleSearch"></i>
<span class="ivu-input-suffix" v-else-if="showSuffix"><slot name="suffix"><i class="ivu-icon" :class="['ivu-icon-' + suffix]" v-if="suffix"></i></slot></span>
<span class="ivu-input-word-count" v-else-if="showWordLimit">{{ textLength }}/{{ upperLimit }}</span>
<span class="ivu-input-suffix" v-else-if="password" @click="handleToggleShowPassword">
<i class="ivu-icon ivu-icon-ios-eye-off-outline" v-if="showPassword"></i>
<i class="ivu-icon ivu-icon-ios-eye-outline" v-else></i>
</span>
<transition name="fade">
<i class="ivu-icon ivu-icon-ios-loading ivu-load-loop" :class="[prefixCls + '-icon', prefixCls + '-icon-validate']" v-if="!icon"></i>
</transition>
<input
:id="elementId"
:autocomplete="autocomplete"
:spellcheck="spellcheck"
ref="input"
:type="currentType"
:class="inputClasses"
:placeholder="placeholder"
:disabled="itemDisabled"
:maxlength="maxlength"
:readonly="readonly"
:name="name"
:value="currentValue"
:number="number"
:autofocus="autofocus"
@keyup.enter="handleEnter"
@keyup="handleKeyup"
@keypress="handleKeypress"
@keydown="handleKeydown"
@focus="handleFocus"
@blur="handleBlur"
@compositionstart="handleComposition"
@compositionupdate="handleComposition"
@compositionend="handleComposition"
@input="handleInput"
@change="handleChange"
@paste="handlePaste">
<div :class="[prefixCls + '-group-append']" v-if="append" v-show="slotReady"><slot name="append"></slot></div>
<div :class="[prefixCls + '-group-append', prefixCls + '-search']" v-else-if="search && enterButton" @click="handleSearch">
<i class="ivu-icon ivu-icon-ios-search" v-if="enterButton === true"></i>
<template v-else>{{ enterButton }}</template>
</div>
<span class="ivu-input-prefix" v-else-if="showPrefix"><slot name="prefix"><i class="ivu-icon" :class="['ivu-icon-' + prefix]" v-if="prefix"></i></slot></span>
</template>
<template v-else>
<textarea
:id="elementId"
:wrap="wrap"
:autocomplete="autocomplete"
:spellcheck="spellcheck"
ref="textarea"
:class="textareaClasses"
:style="textareaStyles"
:placeholder="placeholder"
:disabled="itemDisabled"
:rows="rows"
:maxlength="maxlength"
:readonly="readonly"
:name="name"
:value="currentValue"
:autofocus="autofocus"
@keyup.enter="handleEnter"
@keyup="handleKeyup"
@keypress="handleKeypress"
@keydown="handleKeydown"
@focus="handleFocus"
@blur="handleBlur"
@compositionstart="handleComposition"
@compositionupdate="handleComposition"
@compositionend="handleComposition"
@input="handleInput"
@paste="handlePaste">
</textarea>
<span class="ivu-input-word-count" v-if="showWordLimit">{{ textLength }}/{{ upperLimit }}</span>
</template>
</div>
</template>
<script>
import { oneOf, findComponentUpward } from 'view-design-hi/src/utils/assist';
import calcTextareaHeight from 'view-design-hi/src/utils/calcTextareaHeight';
import Emitter from 'view-design-hi/src/mixins/emitter';
import mixinsForm from 'view-design-hi/src/mixins/form';
const prefixCls = 'ivu-input';
export default {
name: 'DragInput',
mixins: [ Emitter, mixinsForm ],
props: {
type: {
validator (value) {
return oneOf(value, ['text', 'textarea', 'password', 'url', 'email', 'date', 'number', 'tel']);
},
default: 'text'
},
value: {
type: [String, Number],
default: ''
},
size: {
validator (value) {
return oneOf(value, ['small', 'large', 'default']);
},
default () {
return !this.$IVIEW || this.$IVIEW.size === '' ? 'default' : this.$IVIEW.size;
}
},
placeholder: {
type: String,
default: ''
},
maxlength: {
type: [String, Number]
},
disabled: {
type: Boolean,
default: false
},
icon: String,
autosize: {
type: [Boolean, Object],
default: false
},
rows: {
type: Number,
default: 2
},
readonly: {
type: Boolean,
default: false
},
name: {
type: String
},
number: {
type: Boolean,
default: false
},
autofocus: {
type: Boolean,
default: false
},
spellcheck: {
type: Boolean,
default: false
},
autocomplete: {
type: String,
default: 'off'
},
clearable: {
type: Boolean,
default: false
},
elementId: {
type: String
},
wrap: {
validator (value) {
return oneOf(value, ['hard', 'soft']);
},
default: 'soft'
},
prefix: {
type: String,
default: ''
},
suffix: {
type: String,
default: ''
},
search: {
type: Boolean,
default: false
},
enterButton: {
type: [Boolean, String],
default: false
},
// 4.0.0
showWordLimit: {
type: Boolean,
default: false
},
// 4.0.0
password: {
type: Boolean,
default: false
}
},
data () {
return {
currentValue: this.value,
prefixCls: prefixCls,
slotReady: false,
textareaStyles: {},
isOnComposition: false,
showPassword: false
};
},
computed: {
currentType () {
let type = this.type;
if (type === 'password' && this.password && this.showPassword) type = 'text';
return type;
},
prepend () {
let state = false;
if (this.type !== 'textarea') state = this.$slots.prepend !== undefined;
return state;
},
append () {
let state = false;
if (this.type !== 'textarea') state = this.$slots.append !== undefined;
return state;
},
showPrefix () {
let state = false;
if (this.type !== 'textarea') state = this.prefix !== '' || this.$slots.prefix !== undefined;
return state;
},
showSuffix () {
let state = false;
if (this.type !== 'textarea') state = this.suffix !== '' || this.$slots.suffix !== undefined;
return state;
},
wrapClasses () {
return [
`${prefixCls}-wrapper`,
{
[`${prefixCls}-wrapper-${this.size}`]: !!this.size,
[`${prefixCls}-type-${this.type}`]: this.type,
[`${prefixCls}-group`]: this.prepend || this.append || (this.search && this.enterButton),
[`${prefixCls}-group-${this.size}`]: (this.prepend || this.append || (this.search && this.enterButton)) && !!this.size,
[`${prefixCls}-group-with-prepend`]: this.prepend,
[`${prefixCls}-group-with-append`]: this.append || (this.search && this.enterButton),
[`${prefixCls}-hide-icon`]: this.append, // #554
[`${prefixCls}-with-search`]: (this.search && this.enterButton)
}
];
},
inputClasses () {
return [
`${prefixCls}`,
{
[`${prefixCls}-${this.size}`]: !!this.size,
[`${prefixCls}-disabled`]: this.itemDisabled,
[`${prefixCls}-with-prefix`]: this.showPrefix,
[`${prefixCls}-with-suffix`]: this.showSuffix || (this.search && this.enterButton === false)
}
];
},
textareaClasses () {
return [
`${prefixCls}`,
{
[`${prefixCls}-disabled`]: this.itemDisabled
}
];
},
upperLimit () {
return this.maxlength;
},
textLength () {
if (typeof this.value === 'number') {
return String(this.value).length;
}
return (this.value || '').length;
}
},
methods: {
handleEnter (event) {
this.$emit('on-enter', event);
if (this.search) this.$emit('on-search', this.currentValue);
},
handleKeydown (event) {
this.$emit('on-keydown', event);
},
handleKeypress(event) {
this.$emit('on-keypress', event);
},
handleKeyup (event) {
this.$emit('on-keyup', event);
},
handleIconClick (event) {
this.$emit('on-click', event);
},
handleFocus (event) {
this.$emit('on-focus', event);
},
handleBlur (event) {
this.$emit('on-blur', event);
if (!findComponentUpward(this, ['DatePicker', 'TimePicker', 'Cascader', 'Search'])) {
this.dispatch('FormItem', 'on-form-blur', this.currentValue);
}
},
handleComposition(event) {
if (event.type === 'compositionstart') {
this.isOnComposition = true;
}
if (event.type === 'compositionend') {
this.isOnComposition = false;
this.handleInput(event);
}
},
handleInput (event) {
if (this.isOnComposition) return;
let value = event.target.value;
if (this.number && value !== '') value = Number.isNaN(Number(value)) ? value : Number(value);
this.$emit('input', value);
this.setCurrentValue(value);
this.$emit('on-change', event);
},
handleChange (event) {
this.$emit('on-input-change', event);
},
handlePaste (event) {
this.$emit('on-input-paste', event);
},
setCurrentValue (value) {
if (value === this.currentValue) return;
this.$nextTick(() => {
this.resizeTextarea();
});
this.currentValue = value;
if (!findComponentUpward(this, ['DatePicker', 'TimePicker', 'Cascader', 'Search'])) {
this.dispatch('FormItem', 'on-form-change', value);
}
},
resizeTextarea () {
const autosize = this.autosize;
if (!autosize || this.type !== 'textarea') {
return false;
}
const minRows = autosize.minRows;
const maxRows = autosize.maxRows;
this.textareaStyles = calcTextareaHeight(this.$refs.textarea, minRows, maxRows);
},
focus () {
if (this.type === 'textarea') {
this.$refs.textarea.focus();
} else {
this.$refs.input.focus();
}
},
blur () {
if (this.type === 'textarea') {
this.$refs.textarea.blur();
} else {
this.$refs.input.blur();
}
},
handleClear () {
const e = { target: { value: '' } };
this.$emit('input', '');
this.setCurrentValue('');
this.$emit('on-change', e);
this.$emit('on-clear');
},
handleSearch () {
if (this.itemDisabled) return false;
this.$refs.input.focus();
this.$emit('on-search', this.currentValue);
},
handleToggleShowPassword () {
if (this.itemDisabled) return false;
this.showPassword = !this.showPassword;
this.focus();
const len = this.currentValue.length;
setTimeout(() => {
this.$refs.input.setSelectionRange(len, len);
}, 0);
}
},
watch: {
value (val) {
this.setCurrentValue(val);
}
},
mounted () {
this.slotReady = true;
this.resizeTextarea();
}
};
</script>

View File

@ -0,0 +1,97 @@
<template>
<div ref="scrollerView" class="app-scroller" :class="[static ? 'app-scroller-static' : '']">
<slot/>
</div>
</template>
<style lang="scss" scoped>
.app-scroller {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
overflow-x: hidden;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}
.app-scroller-static {
position: static;
flex: 1;
}
</style>
<script>
export default {
name: 'ScrollerY',
props: {
static: {
type: Boolean,
default: false
},
},
data() {
return {
scrollY: 0,
scrollDiff: 0,
scrollInfo: {},
}
},
mounted() {
this.$nextTick(() => {
let scrollListener = typeof this.$listeners['on-scroll'] === "function";
let scrollerView = $A(this.$refs.scrollerView);
scrollerView.scroll(() => {
let wInnerH = Math.round(scrollerView.innerHeight());
let wScrollY = scrollerView.scrollTop();
let bScrollH = this.$refs.scrollerView.scrollHeight;
this.scrollY = wScrollY;
if (scrollListener) {
let direction = 'static';
let directionreal = 'static';
if (this.scrollDiff - wScrollY > 50) {
this.scrollDiff = wScrollY;
direction = 'down';
} else if (this.scrollDiff - wScrollY < -100) {
this.scrollDiff = wScrollY;
direction = 'up';
}
if (this.scrollDiff - wScrollY > 1) {
this.scrollDiff = wScrollY;
directionreal = 'down';
} else if (this.scrollDiff - wScrollY < -1) {
this.scrollDiff = wScrollY;
directionreal = 'up';
}
this.$emit('on-scroll', {
scale: wScrollY / (bScrollH - wInnerH), //
scrollY: wScrollY, //
scrollE: bScrollH - wInnerH - wScrollY, //
direction: direction, //
directionreal: directionreal, //
});
}
});
});
},
activated() {
if (this.scrollY > 0) {
this.$nextTick(() => {
this.scrollTo(this.scrollY);
});
}
},
methods: {
scrollTo(top, animate) {
if (animate === false) {
$A(this.$refs.scrollerView).stop().scrollTop(top);
} else {
$A(this.$refs.scrollerView).stop().animate({"scrollTop": top});
}
},
scrollToBottom(animate) {
this.scrollTo(this.$refs.scrollerView.scrollHeight, animate);
}
}
}
</script>

View File

@ -152,6 +152,7 @@
}
.manage-box-new {
width: 80%;
height: 38px;
margin-top: 16px;
margin-bottom: 20px;
}

View File

@ -1,6 +1,239 @@
<template>
<div class="project-list">
list
<div class="project-head">
<div class="project-titbox">
<div class="project-title"> Daily Task</div>
<div class="project-subtitle">Click + New To create new list and wait for project manager card Don't Create a card by yourself to manage a good colaboration.</div>
</div>
<ul class="project-icons">
<li class="project-icon">
<Icon type="ios-search-outline" />
</li>
<li class="project-icon">
<Icon type="ios-chatbubbles-outline" />
<Badge :count="999"></Badge>
</li>
<li class="project-avatar online">
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
</ul>
</div>
<div class="project-column">
<ul>
<li>
<div class="column-head">
<div class="column-head-title">Next Up</div>
<div class="column-head-num">3</div>
</div>
<ul>
<li>
<div class="task-head">
<div class="task-title">Maxxis Tyres</div>
<Icon type="ios-more" />
</div>
<div class="task-desc">These project will need a new brand Identity where they will get recognise.</div>
<div class="task-tags">
<Tag color="red">red</Tag>
<Tag color="volcano">volcano</Tag>
</div>
<div class="task-member">
<ul>
<li class="online">
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
<li class="online">
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
<li>
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
</ul>
<div class="task-icon">5<Icon type="ios-link-outline" /></div>
<div class="task-icon">5<Icon type="ios-chatbubbles-outline" /></div>
</div>
<div class="task-progress">
<Progress :percent="25" :stroke-width="6" />
<div class="task-time today"><Icon type="ios-time-outline" />Mar 30</div>
</div>
</li>
<li>
<div class="task-head">
<div class="task-title">Maxxis Tyres</div>
<Icon type="ios-more" />
</div>
<div class="task-desc">These project will need a new brand Identity where they will get recognise.</div>
<div class="task-member">
<ul>
<li class="online">
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
<li class="online">
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
<li>
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
</ul>
<div class="task-icon">5<Icon type="ios-link-outline" /></div>
<div class="task-icon">5<Icon type="ios-chatbubbles-outline" /></div>
</div>
<div class="task-progress">
<Progress :percent="25" :stroke-width="6" />
<div class="task-time"><Icon type="ios-time-outline" />Mar 30</div>
</div>
</li>
</ul>
<div class="column-add">
<Icon type="md-add" />
</div>
</li>
<li>
<div class="column-head">
<div class="column-head-title">Hi Progress</div>
<div class="column-head-num">3</div>
</div>
<ul>
<li>
<div class="task-head">
<div class="task-title">Maxxis Tyres</div>
<Icon type="ios-more" />
</div>
<div class="task-desc">These project will need a new brand Identity where they will get recognise.</div>
<div class="task-tags">
<Tag color="magenta">magenta</Tag>
<Tag color="red">red</Tag>
<Tag color="volcano">volcano</Tag>
</div>
<div class="task-member">
<ul>
<li class="online">
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
<li class="online">
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
<li>
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
</ul>
<div class="task-icon">5<Icon type="ios-link-outline" /></div>
<div class="task-icon">5<Icon type="ios-chatbubbles-outline" /></div>
</div>
<div class="task-progress">
<Progress :percent="25" :stroke-width="6" />
<div class="task-time"><Icon type="ios-time-outline" />Mar 30</div>
</div>
</li>
<li>
<div class="task-head">
<div class="task-title">Maxxis Tyres</div>
<Icon type="ios-more" />
</div>
<div class="task-desc">These project will need a new brand Identity where they will get recognise.</div>
<div class="task-tags">
<Tag color="magenta">magenta</Tag>
<Tag color="red">red</Tag>
<Tag color="volcano">volcano</Tag>
</div>
<div class="task-member">
<ul>
<li class="online">
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
<li class="online">
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
<li>
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
</ul>
<div class="task-icon">5<Icon type="ios-link-outline" /></div>
<div class="task-icon">5<Icon type="ios-chatbubbles-outline" /></div>
</div>
<div class="task-progress">
<Progress :percent="25" :stroke-width="6" />
<div class="task-time tomorrow"><Icon type="ios-time-outline" />Mar 30</div>
</div>
</li>
</ul>
<div class="column-add">
<Icon type="md-add" />
</div>
</li>
<li>
<div class="column-head">
<div class="column-head-title">Complete</div>
<div class="column-head-num">3</div>
</div>
<ul>
<li>
<div class="task-head">
<div class="task-title">Maxxis Tyres</div>
<Icon type="ios-more" />
</div>
<div class="task-desc">These project will need a new brand Identity where they will get recognise.</div>
<div class="task-member">
<ul>
<li class="online">
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
<li class="online">
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
<li>
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
</ul>
<div class="task-icon">5<Icon type="ios-link-outline" /></div>
<div class="task-icon">5<Icon type="ios-chatbubbles-outline" /></div>
</div>
<div class="task-progress">
<Progress :percent="25" :stroke-width="6" />
<div class="task-time"><Icon type="ios-time-outline" />Mar 30</div>
</div>
</li>
<li>
<div class="task-head">
<div class="task-title">Maxxis Tyres</div>
<Icon type="ios-more" />
</div>
<div class="task-desc">These project will need a new brand Identity where they will get recognise.</div>
<div class="task-tags">
<Tag color="primary">primary</Tag>
<Tag color="success">success</Tag>
<Tag color="error">error</Tag>
<Tag color="warning">warning</Tag>
<Tag color="magenta">magenta</Tag>
<Tag color="red">red</Tag>
<Tag color="volcano">volcano</Tag>
</div>
<div class="task-member">
<ul>
<li class="online">
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
<li class="online">
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
<li>
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" />
</li>
</ul>
<div class="task-icon">5<Icon type="ios-link-outline" /></div>
<div class="task-icon">5<Icon type="ios-chatbubbles-outline" /></div>
</div>
<div class="task-progress">
<Progress :percent="25" :stroke-width="6" />
<div class="task-time"><Icon type="ios-time-outline" />Mar 30</div>
</div>
</li>
</ul>
<div class="column-add">
<Icon type="md-add" />
</div>
</li>
</ul>
</div>
</div>
</template>
@ -8,7 +241,235 @@
:global {
.project-list {
display: flex;
align-items: flex-start;
flex-direction: column;
.project-head {
display: flex;
align-items: flex-start;
margin: 32px;
.project-titbox {
.project-title {
flex: 1;
color: #333333;
font-size: 28px;
font-weight: 600;
}
.project-subtitle {
color: #999999;
margin-top: 18px;
line-height: 24px;
}
}
.project-icons {
display: flex;
align-items: center;
margin-top: 2px;
margin-left: 80px;
flex-shrink: 0;
> li {
list-style: none;
display: flex;
align-items: center;
justify-content: center;
width: 36px;
height: 36px;
position: relative;
margin-left: 16px;
&.project-icon {
border-radius: 50%;
background-color: #F2F3F5;
.ivu-icon {
font-size: 20px;
}
.ivu-badge {
position: absolute;
top: -6px;
left: 20px;
transform: scale(0.8);
}
}
&.project-avatar {
.ivu-avatar {
width: 36px;
height: 36px;
}
&:before {
content: "";
position: absolute;
right: 0;
bottom: 0;
width: 9px;
height: 9px;
border-radius: 50%;
background-color: #ff0000;
border: 1px solid #ffffff;
z-index: 1;
}
&.online {
&:before {
background-color: #509E76;
}
}
}
}
}
}
.project-column {
display: flex;
height: 100%;
overflow-x: auto;
> ul {
display: inline-flex;
justify-content: space-between;
align-items: center;
> li {
flex-shrink: 0;
list-style: none;
width: 260px;
height: 100%;
display: flex;
flex-direction: column;
&:first-child {
margin-left: 22px;
}
&:last-child {
margin-right: 22px;
}
.column-head {
display: flex;
align-items: center;
padding: 6px 10px;
margin: 0 10px;
background-color: #F2F3F5;
border-radius: 4px;
.column-head-title {
flex: 1;
font-size: 16px;
font-weight: 600;
}
.column-head-num {
font-size: 12px;
padding: 2px 7px;
line-height: 16px;
border-radius: 3px;
color: #ffffff;
background-color: #1C1D1E;
}
}
> ul {
flex: 1;
height: 0;
overflow: auto;
> li {
list-style: none;
margin: 0 10px 16px;
background-color: #ffffff;
border-radius: 12px;
padding: 12px;
transition: box-shadow 0.3s;
&:hover {
box-shadow: 0 0 10px #e6ecfa;
}
&:first-child {
margin-top: 16px;
}
.task-head {
display: flex;
align-items: center;
.task-title {
flex: 1;
font-weight: 600;
}
.ivu-icon {
font-size: 22px;
color: #666666;
}
}
.task-desc {
color: #999999;
margin-top: 10px;
line-height: 18px;
}
.task-tags {
margin-top: 10px;
.ivu-tag {
}
}
.task-member {
margin-top: 10px;
display: flex;
align-items: center;
> ul {
flex: 1;
width: 0;
display: flex;
align-items: center;
margin-right: 12px;
> li {
list-style: none;
margin-left: -5px;
&:first-child {
margin-left: 0;
}
.ivu-avatar {
width: 28px;
height: 28px;
border: 2px solid #ffffff;
}
}
}
.task-icon {
margin-left: 6px;
font-size: 12px;
.ivu-icon {
margin-left: 1px;
font-size: 14px;
}
}
}
.task-progress {
margin-top: 10px;
display: flex;
align-items: center;
.task-time {
flex-shrink: 0;
background-color: #EAEDF2;
padding: 1px 4px;
font-size: 12px;
font-weight: 500;
border-radius: 3px;
display: flex;
align-items: center;
&.today {
color: #ffffff;
background-color: #ed4014;
}
&.tomorrow {
color: #ffffff;
background-color: #ff9900;
}
.ivu-icon {
margin-right: 2px;
font-size: 14px;
}
}
}
}
}
.column-add {
border-radius: 6px;
border: 2px dashed #F1f1f1;
padding: 5px 12px;
text-align: center;
margin: 0 10px 18px;
.ivu-icon {
color: #cccccc;
font-size: 22px;
}
}
}
}
}
}
}
</style>

View File

@ -16,23 +16,104 @@
<li><Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" /></li>
</ul>
</div>
<div class="group-chat">
<div class="group-title">Group Chat</div>
</div>
<div class="group-input">
<div class="group-title">Group Chat</div>
<ScrollerY ref="groupChat" class="group-chat" @on-scroll="groupChatScroll">
<div ref="manageList" class="message-list">
<ul>
<li>
<div class="message-avatar online"><Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" /></div>
<div class="message-item">
<div class="message-text">Selamat pagi, Mas!</div>
<div class="message-time">08:00 AM</div>
</div>
</li>
<li class="self">
<div class="message-avatar"><Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" /></div>
<div class="message-item">
<div class="message-text">Selamat pagi, Mas!</div>
<div class="message-time">08:00 AM</div>
</div>
</li>
<li>
<div class="message-avatar offline"><Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" /></div>
<div class="message-item">
<div class="message-text">Pagi Mas Piko, Langsung saja Ada apa Gerangan mas?</div>
<div class="message-time">08:00 AM</div>
</div>
</li>
<li class="self">
<div class="message-avatar"><Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" /></div>
<div class="message-item">
<div class="message-text">Pagi Mas Piko, Langsung saja Ada apa Gerangan mas?</div>
<div class="message-time">08:00 AM</div>
</div>
</li>
<li>
<div class="message-avatar online"><Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" /></div>
<div class="message-item">
<div class="message-text">Selamat pagi, Mas!</div>
<div class="message-time">08:00 AM</div>
</div>
</li>
<li class="self">
<div class="message-avatar"><Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" /></div>
<div class="message-item">
<div class="message-text">Selamat pagi, Mas!</div>
<div class="message-time">08:00 AM</div>
</div>
</li>
<li>
<div class="message-avatar offline"><Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" /></div>
<div class="message-item">
<div class="message-text">Pagi Mas Piko, Langsung saja Ada apa Gerangan mas?</div>
<div class="message-time">08:00 AM</div>
</div>
</li>
<li class="self">
<div class="message-avatar"><Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" /></div>
<div class="message-item">
<div class="message-text">Pagi Mas Piko, Langsung saja Ada apa Gerangan mas?</div>
<div class="message-time">08:00 AM</div>
</div>
</li>
</ul>
</div>
</ScrollerY>
<div class="group-footer">
<DragInput class="group-input" v-model="groupText" type="textarea" :rows="1" :autosize="{ minRows: 1, maxRows: 3 }" :maxlength="255" @on-keydown="groupKeydown" @on-input-paste="groupPasteDrag" :placeholder="$L('输入消息...')" />
</div>
</div>
</template>
<style lang="scss">
:global {
.project-message {
.group-footer {
.group-input {
background-color: #F4F5F7;
padding: 10px 12px;
border-radius: 10px;
.ivu-input {
border: 0;
resize: none;
background-color: transparent;
&:focus {
box-shadow: none;
}
}
}
}
}
}
</style>
<style lang="scss" scoped>
:global {
.project-message {
display: flex;
flex-direction: column;
padding: 36px 24px;
.group-member {
padding: 0 8px;
margin-top: 36px;
padding: 0 32px;
.member-head {
display: flex;
align-items: center;
@ -42,7 +123,7 @@
font-weight: 600;
> span {
padding-left: 6px;
color: #4E60CC;
color: #2d8cf0;
}
}
.member-view-all {
@ -57,10 +138,10 @@
> li {
position: relative;
list-style: none;
margin-right: 13px;
margin-right: 14px;
.ivu-avatar {
width: 38px;
height: 38px;
width: 36px;
height: 36px;
}
&:before {
content: "";
@ -82,32 +163,146 @@
}
}
}
.group-title {
padding: 0 32px;
margin-top: 28px;
font-size: 18px;
font-weight: 600;
}
.group-chat {
flex: 1;
padding: 0 8px;
margin-top: 24px;
.group-title {
font-size: 18px;
font-weight: 600;
padding: 0 32px;
margin-top: 18px;
overflow: auto;
.message-list {
> ul {
> li {
display: flex;
flex-direction: row;
align-items: flex-end;
list-style: none;
margin-bottom: 16px;
.message-avatar {
position: relative;
margin-bottom: 20px;
.ivu-avatar {
width: 28px;
height: 28px;
flex-shrink: 0;
}
&.online,
&.offline {
&:before {
content: "";
position: absolute;
transform: scale(0.8);
right: 0;
bottom: 0;
width: 9px;
height: 9px;
border-radius: 50%;
background-color: #ff0000;
border: 1px solid #ffffff;
z-index: 1;
}
}
&.online {
&:before {
background-color: #509E76;
}
}
}
.message-item {
max-width: 70%;
display: flex;
flex-direction: column;
align-items: flex-start;
margin: 0 0 0 8px;
.message-text {
color: #333333;
background-color: #F4F5F7;
padding: 8px;
border-radius: 6px 6px 6px 0;
}
.message-time {
color: #bbbbbb;
font-size: 12px;
padding-top: 3px;
}
}
&.self {
flex-direction: row-reverse;
.message-item {
align-items: flex-end;
margin: 0 8px 0 0;
.message-text {
color: #ffffff;
background-color: #2d8cf0;
border-radius: 6px 6px 0 6px;
}
}
}
}
}
}
}
.group-input {
.group-footer {
padding: 0 28px;
margin-bottom: 20px;
}
}
}
</style>
<script>
import DragInput from "../../../components/DragInput";
import ScrollerY from "../../../components/ScrollerY";
export default {
name: "ProjectMessage",
components: {ScrollerY, DragInput},
data() {
return {
groupText: '',
autoBottom: true
}
},
mounted() {
this.groupChatGoAuto();
this.groupChatGoBottom();
},
methods: {
groupKeydown() {
},
groupPasteDrag() {
},
groupChatScroll(res) {
if (res.directionreal === 'up') {
if (res.scrollE < 10) {
this.autoBottom = true;
}
} else if (res.directionreal === 'down') {
this.autoBottom = false;
}
},
groupChatGoAuto() {
clearTimeout(this.groupChatGoTimeout);
this.groupChatGoTimeout = setTimeout(() => {
if (this.autoBottom) {
this.groupChatGoBottom();
}
this.groupChatGoAuto();
}, 1000);
},
groupChatGoBottom(animation = false) {
this.$nextTick(() => {
if (typeof this.$refs.groupChat !== "undefined") {
this.$refs.groupChat.scrollTo(this.$refs.manageList.clientHeight, animation);
this.autoBottom = true;
}
});
},
}
}
</script>

View File

@ -13,13 +13,16 @@
align-items: flex-start;
.project-list {
flex: 1;
width: 0;
height: 100%;
background-color: #fafafa;
}
.project-message {
position: relative;
height: 100%;
width: 40%;
max-width: 410px;
flex-shrink: 0;
&:before {
content: "";
position: absolute;