no message
This commit is contained in:
parent
489804ca80
commit
d95220763a
@ -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",
|
||||
|
396
resources/assets/js/components/DragInput.vue
Normal file
396
resources/assets/js/components/DragInput.vue
Normal 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>
|
97
resources/assets/js/components/ScrollerY.vue
Normal file
97
resources/assets/js/components/ScrollerY.vue
Normal 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>
|
@ -152,6 +152,7 @@
|
||||
}
|
||||
.manage-box-new {
|
||||
width: 80%;
|
||||
height: 38px;
|
||||
margin-top: 16px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user