feat:工作流 - 前端进度 50%

This commit is contained in:
weifs 2023-04-17 18:46:57 +08:00
parent 644a986747
commit 18758421fd
7 changed files with 502 additions and 125 deletions

View File

@ -879,6 +879,7 @@
if (typeof config === "string") config = {title:config}; if (typeof config === "string") config = {title:config};
let inputId = "modalInput_" + $A.randomString(6); let inputId = "modalInput_" + $A.randomString(6);
let inputProps = { let inputProps = {
type: config.type || "text",
value: config.value, value: config.value,
placeholder: $A.L(config.placeholder), placeholder: $A.L(config.placeholder),
elementId: inputId, elementId: inputId,

View File

@ -1,20 +1,28 @@
<template> <template>
<div class="review-details"> <div class="review-details">
<div class="review-details-box"> <div class="review-details-box">
<h2 class="review-details-title">请假<Tag color="success">已通过</Tag></h2> <h2 class="review-details-title">
<h3 class="review-details-subtitle"><Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" size="24"/><span>请假名字</span></h3> <span>{{data.proc_def_name}}</span>
<Tag v-if="datas.state == 0" color="cyan">{{$L('待审批')}}</Tag>
<Tag v-if="datas.state == 1" color="cyan">{{$L('审批中')}}</Tag>
<Tag v-if="datas.state == 2" color="green">{{$L('已通过')}}</Tag>
<Tag v-if="datas.state == 3" color="red">{{$L('已拒绝')}}</Tag>
<Tag v-if="datas.state == 4" color="red">{{$L('已撤回')}}</Tag>
</h2>
<h3 class="review-details-subtitle"><Avatar :src="data.userimg" size="24"/><span>请假名字</span></h3>
<h3 class="review-details-subtitle"><span>{{$L('提交于')}} {{data.start_time}}</span></h3>
<Divider/> <Divider/>
<div class="review-details-text"> <div class="review-details-text">
<h4>{{$L('假期类型')}}</h4> <h4>{{$L('假期类型')}}</h4>
<p>{{$L('事假')}}</p> <p>{{data.var?.type}}</p>
</div> </div>
<div class="review-details-text"> <div class="review-details-text">
<h4>{{$L('开始时间')}}</h4> <h4>{{$L('开始时间')}}</h4>
<p>{{$L('2023年1月1日')}}</p> <p>{{data.var?.start_time}}</p>
</div> </div>
<div class="review-details-text"> <div class="review-details-text">
<h4>{{$L('结束时间')}}</h4> <h4>{{$L('结束时间')}}</h4>
<p>{{$L('2023年1月2日')}}</p> <p>{{data.var?.end_time}}</p>
</div> </div>
<div class="review-details-text"> <div class="review-details-text">
<h4>{{$L('时长')}}小时</h4> <h4>{{$L('时长')}}小时</h4>
@ -22,71 +30,214 @@
</div> </div>
<div class="review-details-text"> <div class="review-details-text">
<h4>{{$L('请假事由')}}</h4> <h4>{{$L('请假事由')}}</h4>
<p>{{$L('什么什么什么的')}}</p> <p>{{data.var?.description}}</p>
</div> </div>
<Divider/> <Divider/>
<h3 class="review-details-subtitle">{{$L('审批进程')}}</h3> <h3 class="review-details-subtitle">{{$L('审批记录')}}</h3>
<div class="review-details-process"> <Timeline style="margin-top: 20px;">
<div class="review-details-line"></div> <!-- 提交 -->
<TimelineItem v-for="(item,key) in datas.node_infos" :key="key" v-if="item.type == 'starter'" color="green">
<div class="review-process"> <p class="timeline-title">{{$L('提交')}}</p>
<div class="review-process-left"> <div style="display: flex;">
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" size="48"/> <Avatar :src="data.userimg" size="38"/>
<div class="review-process-text"> <div style="margin-left: 10px;flex: 1;">
<p class="review-process-name">审核人名字</p> <p class="review-process-name">{{item.approver}}</p>
<p class="review-process-state">已通过</p> <p class="review-process-state">{{$L('已提交')}}</p>
</div>
<div class="review-process-right">
<p>{{ getTimeAgo(item.claim_time) }}</p>
<p>{{item.claim_time?.substr(0,16)}}</p>
</div> </div>
</div> </div>
<div class="review-process-right"> </TimelineItem>
2023-1-1 12:32:32 <!-- 审批 -->
</div> <TimelineItem v-for="(item,key) in datas.node_infos" :key="key" v-if="item.type == 'approver' && item._show"
</div> :color="item.identitylink ? (item.identitylink?.state > 1 ? '#f03f3f' :'green') : '#ccc'"
>
<div class="review-process"> <p class="timeline-title">{{$L('审批')}}</p>
<div class="review-process-left"> <div style="display: flex;">
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" size="48"/> <Avatar :src="item.node_user_list[0]?.userimg" size="38"/>
<div class="review-process-text"> <div style="margin-left: 10px;flex: 1;">
<p class="review-process-name">审核人名字</p> <p class="review-process-name">{{item.approver}}</p>
<p class="review-process-state">已通过</p> <p class="review-process-state" style="color: #6d6d6d;" v-if="!item.identitylink">待审批</p>
<p class="review-process-state" v-if="item.identitylink">
<span v-if="item.identitylink.state==0" style="color:#496dff;">{{$L('审批中')}}</span>
<span v-if="item.identitylink.state==1" >{{$L('已通过')}}</span>
<span v-if="item.identitylink.state==2" style="color:#f03f3f;">{{$L('已拒绝')}}</span>
<span v-if="item.identitylink.state==3" style="color:#f03f3f;">{{$L('已撤回')}}</span>
</p>
</div>
<div class="review-process-right">
<p>
{{ item.identitylink?.state==0 ?
($L('已等待') + " " + getTimeAgo( datas.node_infos[key-1].claim_time,2)) :
(item.claim_time ? getTimeAgo(item.claim_time) : '')
}}
</p>
<p>{{item.claim_time?.substr(0,16)}}</p>
</div> </div>
</div> </div>
<div class="review-process-right"> </TimelineItem>
2023-1-1 12:32:32 <!-- 抄送 -->
</div> <TimelineItem v-for="(item,key) in datas.node_infos" :key="key" :color="item.is_finished ? 'green' : '#ccc'" v-if="item.type == 'notifier' && item._show">
</div> <p class="timeline-title">{{$L('抄送')}}</p>
<div style="display: flex;">
<div class="review-process"> <Avatar :src="'/images/avatar/default_bot.png'" size="38"/>
<div class="review-process-left"> <div style="margin-left: 10px;flex: 1;">
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" size="48"/> <p class="review-process-name">{{$L('系统')}}</p>
<div class="review-process-text"> <p style="font-size: 12px;">自动抄送
<p class="review-process-name">抄送人</p> <span style="color: #486fed;">
<p class="review-process-state">已抄送</p> {{ item.node_user_list?.map(h=>h.name).join(',') }}
{{item.node_user_list?.length}}
</span>
</p>
</div> </div>
</div> </div>
<div class="review-process-right"> </TimelineItem>
2023-1-1 12:32:32 <!-- 结束 -->
<TimelineItem v-for="(item,key) in datas.node_infos" :key="key" :color="item.is_finished ? 'green' : '#ccc'" v-if="item.aprover_type == 'end'">
<p class="timeline-title">{{$L('结束')}}</p>
<div style="display: flex;">
<Avatar :src="'/images/avatar/default_bot.png'" size="38"/>
<div style="margin-left: 10px;flex: 1;">
<p class="review-process-name">{{$L('系统')}}</p>
<p style="font-size: 12px;"> {{ datas.is_finished ? $L('已结束') : $L('未结束') }}</p>
</div>
</div> </div>
</div> </TimelineItem>
</div> </Timeline>
<div class="review-copy">
<div class="review-copy-member">
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" size="24"/>抄送人
</div>
</div>
</div> </div>
<div class="review-operation" v-if="datas.state<=1">
<div class="review-operation"> <Button type="success" v-if="(datas.candidate || '').split(',').indexOf(userId + '') != -1" @click="approve(1)">{{$L('同意')}}</Button>
<Button type="text">通过</Button> <Button type="error" v-if="(datas.candidate || '').split(',').indexOf(userId + '') != -1" @click="approve(2)">{{$L('拒绝')}}</Button>
<Button type="text">拒绝</Button> <Button type="warning" v-if="userId == datas.start_user_id" @click="revocation">{{$L('撤销')}}</Button>
<Button type="text">撤销</Button>
<Button type="text">删除</Button>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
export default { export default {
name: "details" name: "details",
props: {
data: {
type: Object,
default() {
return {};
}
}
},
data() {
return {
datas:{
}
}
},
watch: {
data: {
handler(newValue,oldValue) {
if(newValue.id){
this.getInfo()
}
},
deep: true
},
},
methods:{
//
getTimeAgo(time,type) {
const currentTime = new Date();
const timeDiff = (currentTime - new Date(time)) / 1000; // convert to seconds
if (timeDiff < 60) {
return type == 2 ? "0"+this.$L('分钟') : this.$L('刚刚');
} else if (timeDiff < 3600) {
const minutes = Math.floor(timeDiff / 60);
return type == 2 ? `${minutes}${this.$L('分钟')}` : `${minutes} ${this.$L('分钟前')}`;
} else {
const hours = Math.floor(timeDiff / 3600);
return type == 2 ? `${hours}${this.$L('小时')}` : `${hours} ${this.$L('小时前')}`;
}
},
//
getInfo(){
this.$store.dispatch("call", {
method: 'get',
url: 'workflow/process/detail',
data: {
id:this.data.id,
}
}).then(({data}) => {
var show = true;
data.node_infos = data.node_infos.map(item=>{
item._show = show;
if( item.identitylink?.state==2 || item.identitylink?.state==3 ){
show = false;
}
return item;
})
this.datas = data
}).catch(({msg}) => {
$A.modalError(msg);
}).finally(_ => {
this.loadIng--;
});
},
//
approve(type){
$A.modalInput({
title: `审批`,
placeholder: `请输入审批意见`,
type:"textarea",
okText: type == 1 ? "同意" : "拒绝",
onOk: (desc) => {
if (!desc) {
return `请输入审批意见`
}
this.$store.dispatch("call", {
url: 'workflow/task/complete',
data: {
task_id: this.data.task_id,
pass: type == 1,
comment: desc,
}
}).then(({msg}) => {
this.getInfo()
this.$emit('approve')
}).catch(({msg}) => {
$A.modalError(msg);
});
return false
}
});
},
//
revocation(){
$A.modalConfirm({
content: "你确定要撤销吗?",
loading: true,
onOk: () => {
return new Promise((resolve, reject) => {
this.$store.dispatch("call", {
url: 'workflow/task/withdraw',
data: {
task_id: this.data.task_id,
proc_inst_id: this.data.id,
}
}).then(({msg}) => {
resolve();
this.getInfo()
this.$emit('revocation')
}).catch(({msg}) => {
$A.modalError(msg);
reject(msg);
});
return false
})
},
});
}
}
} }
</script> </script>

View File

@ -2,13 +2,17 @@
<div class="page-review"> <div class="page-review">
<PageTitle :title="$L('审批中心')"/> <PageTitle :title="$L('审批中心')"/>
<div class="review-wrapper" ref="fileWrapper"> <div class="review-wrapper" ref="fileWrapper">
<div class="review-head"> <div class="review-head">
<div class="review-nav"> <div class="review-nav">
<h1>{{$L('审批中心')}}</h1> <h1>{{$L('审批中心')}}</h1>
</div> </div>
<Button :loading="loadIng > 0" type="primary" @click="" style="margin-right:10px;">{{$L('发起请假')}}</Button>
<Button :loading="loadIng > 0" type="primary" @click="">{{$L('加班申请')}}</Button>
</div> </div>
<div class="review-main">
<div class="review-main-left"> <Tabs :value="tabsValue" @on-click="tabsClick" style="margin: 0 20px;height: 100%;">
<TabPane :label="$L('待办')" name="backlog" style="height: 100%;">
<div class="review-main-search"> <div class="review-main-search">
<div> <div>
<Dropdown @on-click="changeTime" trigger="click"> <Dropdown @on-click="changeTime" trigger="click">
@ -53,44 +57,126 @@
</DropdownMenu> </DropdownMenu>
</template> </template>
</Dropdown> </Dropdown>
</div>
<div class="review-mains">
<div class="review-main-left">
<div class="review-main-list">
<list></list>
<list></list>
</div>
</div>
<div class="review-main-right">
<listDetails></listDetails>
</div>
</div>
</TabPane>
<TabPane label="已办" name="name2">2</TabPane>
<TabPane label="抄送我" name="name3">3</TabPane>
<TabPane :label="$L('已发起')" name="initiated">
<div class="review-main-search">
<div>
<Dropdown @on-click="changeTime" trigger="click">
<a href="javascript:void(0)">
{{ timeChose }}<Icon type="ios-arrow-down"></Icon>
</a>
<template #list>
<DropdownMenu>
<DropdownItem name="all">{{$L('全部审批')}}</DropdownItem>
<DropdownItem name="24">{{$L('最近24小时')}}</DropdownItem>
<DropdownItem name="7">{{$L('最近7天')}}</DropdownItem>
<DropdownItem name="30">{{$L('最近30天')}}</DropdownItem>
<DropdownItem name="customize">{{$L('自定义时间')}}</DropdownItem>
</DropdownMenu>
</template>
</Dropdown>
<Dropdown @on-click="" trigger="click">
<a href="javascript:void(0)">
{{ timeChose }}<Icon type="ios-arrow-down"></Icon>
</a>
<template #list>
<DropdownMenu>
<DropdownItem name="all">{{$L('全部状态')}}</DropdownItem>
<DropdownItem name="0">{{$L('审批中')}}</DropdownItem>
<DropdownItem name="1">{{$L('已通过')}}</DropdownItem>
<DropdownItem name="-1">{{$L('已拒绝')}}</DropdownItem>
<DropdownItem name="-2">{{$L('已撤回')}}</DropdownItem>
<DropdownItem name="-3">{{$L('已删除')}}</DropdownItem>
</DropdownMenu>
</template>
</Dropdown>
</div>
<Dropdown @on-click="" trigger="click">
<a href="javascript:void(0)">
<Icon type="ios-arrow-down" />
</a>
<template #list>
<DropdownMenu>
<DropdownItem name="all">{{$L('最新发起优先')}}</DropdownItem>
<DropdownItem name="24">{{$L('最早发起优先')}}</DropdownItem>
</DropdownMenu>
</template>
</Dropdown>
</div> </div>
<div class="review-main-list"> <div v-if="initiatedList.length==0" style="text-align: center;line-height: 150px;">{{$L('暂无数据')}}</div>
<list></list> <div v-else class="review-mains">
<list></list> <div class="review-main-left">
<list></list> <div class="review-main-list">
<list></list> <div @click.stop="clickList(item,key)" v-for="(item,key) in initiatedList">
<list></list> <list :class="{ 'review-list-active': item._active }" :data="item"></list>
<list></list> </div>
<list></list> </div>
<list></list> </div>
<list></list> <div class="review-main-right">
<list></list> <listDetails :data="details" @approve="tabsClick" @revocation="tabsClick"></listDetails>
<list></list> </div>
<list></list>
<list></list>
</div> </div>
</div> </TabPane>
<div class="review-main-right"> </Tabs>
<listDetails></listDetails>
</div>
</div>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import list from "./list"; import list from "./list.vue";
import listDetails from "./details"; import listDetails from "./details.vue";
export default { export default {
components:{list,listDetails}, components:{list,listDetails},
name: "review", name: "review",
data(){ data(){
return{ return{
timeChose:this.$L('所有时间'), timeChose:this.$L('所有时间'),
list: [],
page: 1,
pageSize: 250,
total: 0,
noText: '',
loadIng:false,
tabsValue:"",
backlogList: [],
initiatedList: [],
details:{}
} }
}, },
mounted() {
this.tabsValue = "initiated"
this.tabsClick()
},
methods:{ methods:{
tabsClick(){
if(this.tabsValue == 'backlog'){
this.getBacklogList();
}
if(this.tabsValue == 'initiated'){
this.getInitiatedList();
}
},
changeTime(e){ changeTime(e){
switch (e) { switch (e) {
case 'all': case 'all':
@ -110,6 +196,57 @@ export default {
return; return;
} }
}, },
//
clickList(item){
this.initiatedList.map(h=>{
h._active = false;
})
item._active = true;
this.details = item
},
//
getBacklogList(){
this.$store.dispatch("call", {
method: 'get',
url: 'workflow/process/startByMyself',
data: {
page:this.page,
page_size: this.pageSize,
}
}).then(({data}) => {
this.backlogList = []
}).catch(({msg}) => {
$A.modalError(msg);
}).finally(_ => {
this.loadIng--;
});
},
//
getInitiatedList(){
this.$store.dispatch("call", {
method: 'get',
url: 'workflow/process/startByMyself',
data: {
page:this.page,
page_size: this.pageSize,
}
}).then(({data}) => {
this.initiatedList = data.rows.map((h,index)=>{
h._active = index == 0;
return h;
})
this.details = this.initiatedList[0]
}).catch(({msg}) => {
$A.modalError(msg);
}).finally(_ => {
this.loadIng--;
});
}
}, },
} }
</script> </script>

View File

@ -1,16 +1,23 @@
<template> <template>
<div class="review-list review-list-active"> <div class="review-list">
<h2><span class="list-name">请假类型</span> <Tag color="success">已通过</Tag></h2> <h2>
<p>{{$L('假期类型:')}}<span>{{$L('事假')}}</span></p> <span class="list-name">{{data.proc_def_name}}</span>
<p>{{$L('开始时间:')}}<span>{{$L('2023年1月1日')}}</span></p> <Tag v-if="data.state == 0" color="cyan">{{$L('待审批')}}</Tag>
<p>{{$L('结束时间:')}}<span>{{$L('2023年1月2日')}}</span></p> <Tag v-if="data.state == 1" color="cyan">{{$L('审批中')}}</Tag>
<Tag v-if="data.state == 2" color="green">{{$L('已通过')}}</Tag>
<Tag v-if="data.state == 3" color="red">{{$L('已拒绝')}}</Tag>
<Tag v-if="data.state == 4" color="red">{{$L('已撤回')}}</Tag>
</h2>
<p>{{$L('假期类型')}}<span>{{data.var?.type}}</span></p>
<p>{{$L('开始时间')}}<span>{{data.var?.start_time}}</span></p>
<p>{{$L('结束时间')}}<span>{{data.var?.end_time}}</span></p>
<div class="list-member"> <div class="list-member">
<span> <span>
<Avatar src="https://i.loli.net/2017/08/21/599a521472424.jpg" size="18"/> <Avatar :src="data.userimg" size="18"/>
请假名字 {{ data.start_user_name }}
</span> </span>
<span> <span>
发起时间2023年1月2日 {{$L('发起时间')}}{{data.start_time}}
</span> </span>
</div> </div>
</div> </div>
@ -18,7 +25,22 @@
<script> <script>
export default { export default {
name: "list" name: "list",
props: {
data: {
type: Object,
default() {
return {};
}
}
},
data() {
return {
}
}
} }
</script> </script>

View File

@ -12,10 +12,9 @@
<Divider style="margin: 12px 0;"/> <Divider style="margin: 12px 0;"/>
<div class="approve-button-box" @click.stop="edit(item)"> <div class="approve-button-box" @click.stop="edit(item)">
<p>{{$L('是否发布')}} </p> <p>{{$L('是否发布')}} </p>
<p> <p @click.stop="!item.issue ? edit(item) : ''">
<i-switch v-model="item.issue" :disabled="true" /> <i-switch v-model="item.issue" @on-change="change(item)" :disabled="true" />
<!-- <Icon type="md-create" /> <!-- <Icon type="md-trash" /> -->
<Icon type="md-trash" /> -->
</p> </p>
</div> </div>
</div> </div>
@ -45,8 +44,8 @@ export default {
iframeSrc:"", iframeSrc:"",
name:"", name:"",
list:[ list:[
{name:"请假",issue:false}, {id:0,name:"请假",issue:false,version:''},
{name:"加班申请",issue:false}, {id:0,name:"加班申请",issue:false,version:''},
] ]
} }
}, },
@ -57,16 +56,39 @@ export default {
}, },
mounted() { mounted() {
window.addEventListener('message', this.saveSuccess) window.addEventListener('message', this.saveSuccess)
this.getList();
}, },
beforeDestroy() { beforeDestroy() {
window.removeEventListener("message", this.saveSuccess); window.removeEventListener("message", this.saveSuccess);
}, },
methods: { methods: {
//
getList(){
this.$store.dispatch("call", {
url: 'workflow/procdef/all',
method: 'post',
}).then(({data}) => {
data.rows.forEach((h,index) => {
this.list.forEach((o,index) => {
if(o.name == h.name){
o.issue = true;
o.id = h.id;
o.version = h.version;
}
})
})
}).catch(({msg}) => {
$A.modalError(msg);
}).finally(_ => {
this.loadIng--;
});
},
// //
saveSuccess(e){ saveSuccess(e){
if (typeof e.data === 'string') { if (typeof e.data === 'string') {
let propsBody = JSON.parse(e.data); let propsBody = JSON.parse(e.data);
if( propsBody.method == "saveSuccess" ) { if( propsBody.method == "saveSuccess" ) {
this.getList();
this.list.forEach((h,index) => { this.list.forEach((h,index) => {
if(h.name == this.name){ if(h.name == this.name){
h.issue = true; h.issue = true;
@ -85,12 +107,41 @@ export default {
}, },
// //
edit(item){ edit(item){
console.log(item.issue) this.name = item.name
if(!item.issue){ this.approvalSettingShow = true;
this.name = item.name },
this.approvalSettingShow = true; //
change(item){
this.$nextTick(()=>{
item.issue = true;
$A.modalConfirm({
title: '取消发布',
content: '将会清空流程数据,确定要取消发布?',
onOk: () => {
this.del(item)
}
});
});
},
//
del(item){
if(!item.id){
item.issue = false;
return true;
} }
} this.$store.dispatch("call", {
url: 'workflow/procdef/del',
data: {id: item.id},
method: 'post',
}).then(({data}) => {
item.issue = false;
$A.messageSuccess('成功');
}).catch(({msg}) => {
$A.modalError(msg);
}).finally(_ => {
this.loadIng--;
});
},
} }
} }
</script> </script>

View File

@ -73,7 +73,6 @@ export default {
const menu = [ const menu = [
{path: 'personal', name: '个人设置'}, {path: 'personal', name: '个人设置'},
{path: 'checkin', name: '签到设置', desc: ' (Beta)'}, {path: 'checkin', name: '签到设置', desc: ' (Beta)'},
{path: 'approve', name: '审批设置', desc: ' (Beta)'},
{path: 'language', name: '语言设置'}, {path: 'language', name: '语言设置'},
{path: 'theme', name: '主题设置'}, {path: 'theme', name: '主题设置'},
{path: 'password', name: '密码设置'}, {path: 'password', name: '密码设置'},
@ -94,6 +93,7 @@ export default {
if (this.userIsAdmin) { if (this.userIsAdmin) {
menu.push(...[ menu.push(...[
{path: 'system', name: '系统设置', divided: true}, {path: 'system', name: '系统设置', divided: true},
{path: 'approve', name: '审批设置', desc: ' (Beta)'},
{path: 'license', name: 'License Key'}, {path: 'license', name: 'License Key'},
]) ])
} }

View File

@ -26,10 +26,21 @@
} }
} }
} }
.review-main{ .review-main-search{
display: flex;
justify-content: space-between;
margin: 0 10px;
margin-bottom: 10px;
> div{
.ivu-dropdown{
margin-right: 8px;
}
}
}
.review-mains{
display: flex; display: flex;
flex: 1 1 auto; flex: 1 1 auto;
margin: 0 32px; height: calc(100vh - 190px);
position: relative; position: relative;
.review-main-left{ .review-main-left{
display: flex; display: flex;
@ -40,22 +51,14 @@
left: 0; left: 0;
top: 0; top: 0;
bottom: 12px; bottom: 12px;
.review-main-search{
display: flex;
justify-content: space-between;
> div{
.ivu-dropdown{
margin-right: 8px;
}
}
}
.review-main-list{ .review-main-list{
display: flex; display: flex;
flex-direction: column; flex-direction: column;
flex: 1 1 auto; flex: 1 1 auto;
overflow: scroll; overflow: scroll;
.review-list{ .review-list{
margin-top: 8px; margin-bottom: 8px;
padding: 12px; padding: 12px;
border-radius: 8px; border-radius: 8px;
border: 1px solid #eeeeee; border: 1px solid #eeeeee;
@ -69,7 +72,7 @@
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
> .list-name{ > .list-name{
font-size: 16px; font-size: 14px;
font-weight: bold; font-weight: bold;
} }
} }
@ -130,7 +133,7 @@
} }
} }
.review-details-subtitle{ .review-details-subtitle{
margin-top: 16px; margin-top: 8px;
display: flex; display: flex;
.ivu-avatar{ .ivu-avatar{
margin-right: 8px; margin-right: 8px;
@ -139,14 +142,34 @@
font-size: 14px; font-size: 14px;
} }
} }
.timeline-title{
font-weight: bold;
padding-bottom: 10px;
}
.review-process-name{
margin-bottom: 4px;
}
.review-process-state{
font-size: 12px;
color: #19be6b;
}
.review-process-right{
text-align: right;
}
.review-details-text{ .review-details-text{
margin-bottom: 16px; margin-bottom: 12px;
> h4{ > h4{
color: #999; color: #999;
} }
> p{ > p{
font-size: 16px; font-size: 14px;
margin-top: 4px; margin-top: 2px;
font-weight: 500; font-weight: 500;
} }
} }
@ -180,14 +203,6 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
margin-left: 8px; margin-left: 8px;
.review-process-name{
margin-bottom: 4px;
}
.review-process-state{
font-size: 16px;
color: #19be6b;
font-weight: 500;
}
} }
} }
} }
@ -197,13 +212,12 @@
} }
.review-copy{ .review-copy{
margin-top: 8px; margin-top: 8px;
padding-left: 56px;
display: flex; display: flex;
.review-copy-member{ .review-copy-member{
display: flex; display: flex;
align-items: center; align-items: center;
background: #F4F4F5; background: #F4F4F5;
padding:4px 8px; padding:2px 8px;
border-radius: 20px; border-radius: 20px;
.ivu-avatar{ .ivu-avatar{
margin-right: 4px; margin-right: 4px;
@ -221,6 +235,7 @@
border-top: 1px solid #F4F4F5; border-top: 1px solid #F4F4F5;
display: flex; display: flex;
align-items: center; align-items: center;
gap: 10px;
} }
} }