This commit is contained in:
weipengfei 2024-01-08 18:13:44 +08:00
parent 32e9f798da
commit 99cb6a6e16
8 changed files with 2010 additions and 1542 deletions

View File

@ -42,8 +42,8 @@ export function star(code, star) {
return $http.post('project/task/star', {star: star, taskCode: code}); return $http.post('project/task/star', {star: star, taskCode: code});
} }
export function createComment(code, comment, mentions) { export function createComment(code, comment, mentions, type=0) {
return $http.post('project/task/createComment', {taskCode: code, comment: comment, mentions: mentions}); return $http.post('project/task/createComment', {taskCode: code, comment: comment, mentions: mentions, type: type});
} }
export function assignTask(data) { export function assignTask(data) {

View File

@ -6,7 +6,7 @@
<a-badge> <a-badge>
<a href="/"> <a href="/">
<img src="../../assets/image/common/logo.png" class="logo" alt="logo"> <img src="../../assets/image/common/logo.png" class="logo" alt="logo">
<span class="title">Pear Project</span> <span class="title">工单系统</span>
</a> </a>
</a-badge> </a-badge>
</div> </div>

View File

@ -743,8 +743,11 @@
}, },
// //
addTask(){ addTask(){
if(!this.task.name) return notice({title: '请输入工单名称'}, 'error', 5000);
if(!this.task.description) return notice({title: '请输入工作内容'}, 'error', 5000);
if(!this.task.end_time) return notice({title: '请选择完成期限'}, 'error', 5000);
if(!this.department.code) return notice({title: '请选择处理部门'}, 'error', 5000);
this.createTask(); this.createTask();
return console.log(this.task);
}, },
// //
createTask(){ createTask(){
@ -758,6 +761,8 @@
}) })
task.copied_list = task.copied_list.join(','); task.copied_list = task.copied_list.join(',');
task.assign_to = ""; task.assign_to = "";
task.department_code = this.department.code;
task.liasion_code = this.liasionMan.code;
// task.executor = task.executor.code; // task.executor = task.executor.code;
task.stage_code = this.$route.query.stage_code; task.stage_code = this.$route.query.stage_code;
task.project_code = this.$route.params.code; task.project_code = this.$route.params.code;
@ -773,7 +778,7 @@
}, },
detailClose() { detailClose() {
this.$emit('close', this.task); this.$emit('close', this.task);
this.$router.push(`/project/space/task/${this.$route.params.code}?re=1&from=${this.$route.query.from}`); // this.$router.push(`/project/space/task/${this.$route.params.code}?re=1&from=${this.$route.query.from}`);
// this.$router.push(`/project/space/task/${this.task.project_code}`); // this.$router.push(`/project/space/task/${this.task.project_code}`);
}, },
clearMemberMenu() { clearMemberMenu() {

View File

@ -27,7 +27,7 @@
<a class="action-item muted" v-clipboard="taskLink" @success="copyLink"><a-icon <a class="action-item muted" v-clipboard="taskLink" @success="copyLink"><a-icon
type="link"/></a> type="link"/></a>
</a-tooltip> </a-tooltip>
<a-tooltip :mouseEnterDelay="0.5"> <!-- <a-tooltip :mouseEnterDelay="0.5">
<template slot="title"> <template slot="title">
<span>点个赞</span> <span>点个赞</span>
</template> </template>
@ -35,8 +35,8 @@
<a-icon type="like"/> <a-icon type="like"/>
<span v-show="task.like">{{task.like}}</span> <span v-show="task.like">{{task.like}}</span>
</a> </a>
</a-tooltip> </a-tooltip> -->
<a-dropdown :trigger="['click']" placement="bottomCenter" v-model="visibleTaskMenu"> <!-- <a-dropdown :trigger="['click']" placement="bottomCenter" v-model="visibleTaskMenu">
<a-tooltip :mouseEnterDelay="0.5"> <a-tooltip :mouseEnterDelay="0.5">
<template slot="title"> <template slot="title">
<span>打开菜单</span> <span>打开菜单</span>
@ -80,7 +80,7 @@
</div> </div>
</a-menu-item> </a-menu-item>
</a-menu> </a-menu>
</a-dropdown> </a-dropdown> -->
</template> </template>
<template v-else> <template v-else>
<a class="action-item muted" @click="recoveryTask"> <a class="action-item muted" @click="recoveryTask">
@ -102,7 +102,7 @@
<div class="task-content"> <div class="task-content">
<div class="content-left"> <div class="content-left">
<vue-scroll :ops="scrollOps"> <vue-scroll :ops="scrollOps">
<div class="task-title" :class="{'disabled': task.deleted}"> <div class="task-title" :class="{'disabled': task.deleted}" :style="{'pointer-events': userInfo.code==task.create_by? 'all':'none'}">
<a-input ref="inputTitle" auto-focus @blur="doName" v-model="task.name" size="large" <a-input ref="inputTitle" auto-focus @blur="doName" v-model="task.name" size="large"
v-show="showEditName"/> v-show="showEditName"/>
<a-tooltip :mouseEnterDelay="0.5" v-if="!task.deleted"> <a-tooltip :mouseEnterDelay="0.5" v-if="!task.deleted">
@ -117,7 +117,7 @@
{{task.name}} {{task.name}}
</div> </div>
</div> </div>
<div class="task-basic-attrs-view muted"> <div class="task-basic-attrs-view muted" :style="{'pointer-events': userInfo.code==task.create_by? 'all':'none'}">
<div class="field-list" :class="{'disabled': task.deleted}"> <div class="field-list" :class="{'disabled': task.deleted}">
<div class="component-mount pink-bg"> <div class="component-mount pink-bg">
<div class="field"> <div class="field">
@ -160,7 +160,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="component-mount"> <div class="component-mount" :style="{'pointer-events': userInfo.code==task.create_by? 'all':'none'}">
<div class="field"> <div class="field">
<div class="field-left"> <div class="field-left">
<a-icon type="calendar"/> <a-icon type="calendar"/>
@ -209,7 +209,7 @@
</a-dropdown> </a-dropdown>
<span class="m-l-sm m-r-sm">-</span> <span class="m-l-sm m-r-sm">-</span>
</template> </template>
<a-dropdown :trigger="['click']" v-model="showEndTime" <a-dropdown :trigger="['click']" v-model="showEndTime"
:disabled="!!task.deleted"> :disabled="!!task.deleted">
<a-tooltip :mouseEnterDelay="0.5" v-if="!task.deleted"> <a-tooltip :mouseEnterDelay="0.5" v-if="!task.deleted">
<template slot="title"> <template slot="title">
@ -249,7 +249,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="component-mount"> <div class="component-mount" style="pointer-events:none">
<div class="field"> <div class="field">
<div class="field-left"> <div class="field-left">
<a-icon type="check-square"/> <a-icon type="check-square"/>
@ -291,7 +291,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="component-mount"> <div class="component-mount" style="pointer-events:none">
<div class="field"> <div class="field">
<div class="field-left"> <div class="field-left">
<a-icon type="deployment-unit"/> <a-icon type="deployment-unit"/>
@ -316,7 +316,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="component-mount"> <div class="component-mount" :style="{'pointer-events': task.liasion_info&&userInfo.code==task.liasion_info.code? 'all':'none'}">
<div class="field"> <div class="field">
<div class="field-left"> <div class="field-left">
<a-icon type="user"/> <a-icon type="user"/>
@ -415,6 +415,22 @@
</div> </div>
</div> </div>
</div> </div>
<div class="component-mount">
<div class="field">
<div class="field-left">
<a-icon type="apartment"/>
<span class="field-name">处理部门</span>
</div>
<div class="field-right">
<div class="field-flex" v-if="task.liasion_info" style="flex-wrap: wrap;align-items: center;">
<span style="padding-right: 10px">{{ task.department_info.name }} </span>
<span style="padding-right: 10px">{{ '/' }} </span>
<a-avatar :src="task.liasion_info.avatar" icon="user" size="small"/>
<a class="muted name">{{task.liasion_info.name}}</a>
</div>
</div>
</div>
</div>
<div class="component-mount"> <div class="component-mount">
<div class="field"> <div class="field">
<div class="field-left"> <div class="field-left">
@ -422,7 +438,7 @@
<span class="field-name">工作流转</span> <span class="field-name">工作流转</span>
</div> </div>
<div class="field-right field-flex" style="flex-wrap: wrap;"> <div class="field-right field-flex" style="flex-wrap: wrap;">
<div v-for="(exc, index) in task.exchange_info" :key="exc.code" style="pointer-events: none;"> <div v-for="(exc, index) in task.exchange_info" :key="index" style="pointer-events: none;">
<a-dropdown <a-dropdown
:trigger="['click']" :trigger="['click']"
v-model="exc.show" v-model="exc.show"
@ -485,7 +501,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="component-mount"> <div class="component-mount" :style="{'pointer-events': userInfo.code==task.create_by? 'all':'none'}" >
<div class="field"> <div class="field">
<div class="field-left"> <div class="field-left">
<a-icon type="bulb"/> <a-icon type="bulb"/>
@ -534,7 +550,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="component-mount"> <div class="component-mount" v-if="userInfo.code==task.create_by">
<div class="field"> <div class="field">
<div class="block-field width-block"> <div class="block-field width-block">
<div class="task-child"> <div class="task-child">
@ -580,7 +596,6 @@
<a class="action-item muted"> <a class="action-item muted">
<a-icon type="down"/> <a-icon type="down"/>
</a> </a>
<!--</a-tooltip>-->
<a-menu v-clipboard="item.sourceDetail.file_url" <a-menu v-clipboard="item.sourceDetail.file_url"
@click="doSource($event,item)" @click="doSource($event,item)"
class="field-right-menu" class="field-right-menu"
@ -628,7 +643,7 @@
@click="routerLink('/members/profile/' + member.membar_account_code + '?key=3')" @click="routerLink('/members/profile/' + member.membar_account_code + '?key=3')"
/> />
</a-tooltip> </a-tooltip>
<a-dropdown :trigger="['click']" placement="bottomCenter" <!-- <a-dropdown :trigger="['click']" placement="bottomCenter"
v-model="visibleProjectMemberMenu"> v-model="visibleProjectMemberMenu">
<a-tooltip :mouseEnterDelay="0.5"> <a-tooltip :mouseEnterDelay="0.5">
<template slot="title"> <template slot="title">
@ -648,7 +663,7 @@
visibleProjectMemberMenu = false" visibleProjectMemberMenu = false"
></project-member-menu> ></project-member-menu>
</div> </div>
</a-dropdown> </a-dropdown> -->
</div> </div>
</div> </div>
<div class="log-wrap"> <div class="log-wrap">
@ -667,7 +682,7 @@
</a-menu-item> </a-menu-item>
<a-menu-item key="comment"> <a-menu-item key="comment">
<div class="menu-item-content"> <div class="menu-item-content">
<span>评论</span> <span>审核</span>
</div> </div>
</a-menu-item> </a-menu-item>
<a-menu-item key="log"> <a-menu-item key="log">
@ -685,7 +700,7 @@
<a-icon type="ellipsis"/> <a-icon type="ellipsis"/>
显示较早的 {{taskLogTotal - taskLogList.length}} 条动态 显示较早的 {{taskLogTotal - taskLogList.length}} 条动态
</a> </a>
<div :class="{'log-comment': log.is_comment,'list-item': !log.is_comment}" <div :class="{'log-comment': log.is_comment,'list-item': !log.is_comment, 'log-pass': log.type=='pass', 'log-reject': log.type=='reject', 'log-add': log.type=='add'}"
v-for="log in taskLogList" :key="log.code"> v-for="log in taskLogList" :key="log.code">
<template v-if="!log.is_comment"> <template v-if="!log.is_comment">
<a-icon class="log-item" :type="log.icon"/> <a-icon class="log-item" :type="log.icon"/>
@ -695,11 +710,14 @@
v-html="log.content"></div> v-html="log.content"></div>
</div> </div>
</template> </template>
<template v-if="log.is_comment"> <div v-if="log.is_comment">
<div class="log-txt text-default" style="width:100%; display: flex;justify-content: space-between"> <div class="log-txt text-default" style="width:100%; display: flex;justify-content: space-between">
<div style="display: flex;align-items: center"> <div style="display: flex;align-items: center">
<a-avatar :size="24" :src="log.member.avatar" class="m-r-sm" style="margin-left: -5px"/> <a-avatar :size="24" :src="log.member.avatar" class="m-r-sm" />
<div>{{log.member.name}}</div> <div>{{log.member.name}}</div>
<div v-if="log.type=='add'" class="log-add-tips">提交</div>
<div v-if="log.type=='pass'" class="log-pass-tips">通过</div>
<div v-if="log.type=='reject'" class="log-reject-tips">驳回</div>
</div> </div>
<a-tooltip :mouseEnterDelay="0.5"> <a-tooltip :mouseEnterDelay="0.5">
<template slot="title"> <template slot="title">
@ -711,7 +729,7 @@
<div class="log-txt text-default" style="padding: 0 0 0 30px;"> <div class="log-txt text-default" style="padding: 0 0 0 30px;">
<div class="m-t-xs" v-html="checkLink(log.content)" ></div> <div class="m-t-xs" v-html="checkLink(log.content)" ></div>
</div> </div>
</template> </div>
<a-tooltip v-if="!log.is_comment" :mouseEnterDelay="0.5"> <a-tooltip v-if="!log.is_comment" :mouseEnterDelay="0.5">
<template slot="title"> <template slot="title">
<span>{{log.create_time}}</span> <span>{{log.create_time}}</span>
@ -723,7 +741,7 @@
</vue-scroll> </vue-scroll>
</div> </div>
<div class="footer" id="footer"> <div class="footer" id="footer">
<a-popover trigger="click" placement="top" :visible="showMentions" arrowPointAtCenter :getPopupContainer="getPopup"> <a-popover v-if="userInfo.code==task.create_by||userInfo.code==task.assign_to" trigger="click" placement="top" :visible="showMentions" arrowPointAtCenter :getPopupContainer="getPopup">
<template slot="content"> <template slot="content">
<div class="mentions-content" style="width: 200px;"> <div class="mentions-content" style="width: 200px;">
<div class="mentions-wrapper" v-for="member in taskMemberList" :key="member.id" @click="selectMentionMember(member)"> <div class="mentions-wrapper" v-for="member in taskMemberList" :key="member.id" @click="selectMentionMember(member)">
@ -732,11 +750,16 @@
</div> </div>
</div> </div>
</template> </template>
<!-- <span slot="title">Title</span>--> <a-textarea @focus="commenting = true" @blur="commenting = false" ref="commentText" v-model="comment" :rows="1" placeholder="@提及任务成员Ctrl+Enter发送"
<a-textarea @focus="commenting = true" @blur="commenting = false" ref="commentText" v-model="comment" :rows="1" placeholder="@提及任务成员Ctrl+Enter发表评论" style="margin-right: 15px;"/>
style="margin-right: 24px;"/>
</a-popover> </a-popover>
<a-button class="middle-btn" type="primary" @click="createComment">评论</a-button> <template v-if="userInfo.code == task.create_by">
<a-button class="middle-btn" type="danger" @click="createComment(2)">驳回</a-button>
<a-button class="middle-btn" type="primary" style="margin-left: 15px;" @click="createComment(1)">通过</a-button>
</template>
<template v-if="userInfo.code == task.assign_to">
<a-button class="middle-btn" type="primary" @click="createComment(3)">提交</a-button>
</template>
</div> </div>
</div> </div>
</div> </div>
@ -1091,6 +1114,7 @@
}, },
created() { created() {
this.init(); this.init();
console.log(this.userInfo);
}, },
mounted() { mounted() {
this.$nextTick(()=>{ this.$nextTick(()=>{
@ -1102,13 +1126,13 @@
})() })()
}; };
document.onkeydown = (event) => { document.onkeydown = (event) => {
console.log(event); // console.log(event);
var e = event || window.event || arguments.callee.caller.arguments[0]; var e = event || window.event || arguments.callee.caller.arguments[0];
if (13 == e.keyCode && e.ctrlKey) { if (13 == e.keyCode && e.ctrlKey) {
// //
this.createComment(); this.createComment(1);
} }
if ('@' == e.key && this.commenting) { if (('@' == e.key || (e.code=='Digit2'&&e.key=='Process'&&e.shiftKey)) && this.commenting) {
this.showMentions = true; this.showMentions = true;
}else{ }else{
this.showMentions = false; this.showMentions = false;
@ -1526,14 +1550,18 @@
this.initContent(this.task.description) this.initContent(this.task.description)
}, },
initContent(value) { initContent(value) {
if (value) { try {
this.$refs.vueWangeditor.setHtml(value) if (value) {
} else { this.$refs.vueWangeditor.setHtml(value)
this.$refs.vueWangeditor.setHtml('') } else {
this.$refs.vueWangeditor.setHtml('')
}
this.$nextTick(() => {
this.checkShowMoreDesc(false, true);
});
} catch (error) {
} }
this.$nextTick(() => {
this.checkShowMoreDesc(false, true);
});
}, },
doContent() { doContent() {
let content = this.$refs.vueWangeditor.getHtml(); let content = this.$refs.vueWangeditor.getHtml();
@ -1550,7 +1578,7 @@
this.getTaskLog(); this.getTaskLog();
}); });
}, },
createComment() { createComment(type=0) {
let comment = this.comment.trim(); let comment = this.comment.trim();
if (!comment) { if (!comment) {
return false; return false;
@ -1566,7 +1594,7 @@
} }
}); });
} }
createComment(this.code, this.comment, JSON.stringify(this.mentionsList)).then(() => { createComment(this.code, this.comment, JSON.stringify(this.mentionsList), type).then(() => {
this.comment = ''; this.comment = '';
this.mentionsList = []; this.mentionsList = [];
this.getTaskLog(); this.getTaskLog();
@ -2159,7 +2187,7 @@
.content-right { .content-right {
//width: 37%; //width: 37%;
width: 410px; width: 510px;
.header { .header {
padding: 15px 20px 20px 20px; padding: 15px 20px 20px 20px;
@ -2199,7 +2227,7 @@
} }
.log-comment { .log-comment {
max-width: 405px; max-width: 100%;
align-items: end; align-items: end;
margin-bottom: 15px; margin-bottom: 15px;
} }
@ -2236,6 +2264,55 @@
flex: 1 1; flex: 1 1;
} }
} }
.log-pass{
border: 1px solid green;
background-color: rgba(green, 0.05);
border-radius: 10px;
color: #fff !important;
padding: 10px;
}
.log-reject{
border: 1px solid #ff4d4f;
background-color: rgba(#ff4d4f, 0.1);
border-radius: 10px;
color: #fff !important;
padding: 10px;
}
.log-add{
border: 1px solid #1890ff;
background-color: rgba(#1890ff, 0.1);
border-radius: 10px;
color: #fff !important;
padding: 10px;
}
.log-pass-tips{
margin-left: 10px;
color: #fff;
font-size: 12px;
padding: 0px 6px;
border-radius: 2px;
background-color: green;
}
.log-reject-tips{
margin-left: 10px;
color: #fff;
font-size: 12px;
padding: 0px 6px;
border-radius: 2px;
background-color: #ff4d4f;
}
.log-add-tips{
margin-left: 10px;
color: #fff;
font-size: 12px;
padding: 0px 6px;
border-radius: 2px;
background-color: #1890ff;
}
} }
} }

View File

@ -9,7 +9,7 @@
:form="form" :form="form"
@submit.prevent="handleSubmit"> @submit.prevent="handleSubmit">
<a-form-item <a-form-item
label='标题' label='工单名称'
:colon="false" :colon="false"
:labelCol="{ span: 6 }" :labelCol="{ span: 6 }"
:wrapperCol="{ span: 18 }" :wrapperCol="{ span: 18 }"
@ -76,7 +76,7 @@
</a-select-option> </a-select-option>
</a-select> </a-select>
</a-form-item> </a-form-item>
<a-form-item <!-- <a-form-item
label='参与者' label='参与者'
:colon="false" :colon="false"
:labelCol="{ span: 6 }" :labelCol="{ span: 6 }"
@ -102,7 +102,7 @@
</div> </div>
</a-select-option> </a-select-option>
</a-select> </a-select>
</a-form-item> </a-form-item> -->
<a-form-item <a-form-item
label='是否完成' label='是否完成'
:colon="false" :colon="false"

View File

@ -1,6 +1,6 @@
export const COMMON = { export const COMMON = {
PAGE_SIZE: 20, PAGE_SIZE: 20,
PAGE_NUM: 1, PAGE_NUM: 1,
TASK_STATUS: [{id: 0, name: '未开始', color: 'rgba(0, 0, 0, 0.65)'},{id: 1, name: '已完成', color: '#1890ff'},{id: 2, name: '进行中', color: '#52c41a'},{id: 3, name: '挂起', color: '#f5222d'},{id: 4, name: '测试中', color: '#faad14'},] TASK_STATUS: [{id: 0, name: '未开始', color: 'rgba(0, 0, 0, 0.65)'},{id: 1, name: '已完成', color: '#1890ff'},{id: 2, name: '进行中', color: '#52c41a'},{id: 3, name: '挂起', color: '#f5222d'},{id: 4, name: '验收中', color: '#faad14'},]
}; };

View File

@ -27,6 +27,46 @@ moment.locale('zh-cn');
Vue.use(VueRouter); Vue.use(VueRouter);
Vue.use(store); Vue.use(store);
Vue.directive('disable-click', {
inserted(el, binding) {
binding.value = !!binding.value;
console.log('binding', binding);
if(binding.value){
el.addEventListener('click', (event) => {
if (binding.value) {
event.preventDefault();
event.stopPropagation();
}
});
el.querySelectorAll('*').forEach((child) => {
child.addEventListener('click', (event) => {
event.preventDefault();
event.stopPropagation();
});
});
}
},
update(el, binding) {
binding.value = !!binding.value;
console.log('binding', binding);
if(binding.value){
el.addEventListener('click', (event) => {
if (binding.value) {
event.preventDefault();
event.stopPropagation();
}
});
el.querySelectorAll('*').forEach((child) => {
child.addEventListener('click', (event) => {
event.preventDefault();
event.stopPropagation();
});
});
}
},
});
Vue.config.productionTip = false; Vue.config.productionTip = false;
Vue.use(Antd); Vue.use(Antd);
Vue.component('WrapperContent', WrapperContent); Vue.component('WrapperContent', WrapperContent);

File diff suppressed because it is too large Load Diff