Merge branch 'master' of http://gitea.xxhhcty.xyz:8080/zcdsj/factory_web
This commit is contained in:
commit
562b6bda4a
|
|
@ -42,3 +42,142 @@
|
|||
.common-main .yzm .el-button {margin-left: 10px;}
|
||||
.common-main .link {color: var(--el-color-primary);cursor: pointer;}
|
||||
.common-main .link:hover {color: var(--el-color-primary-light-3);}
|
||||
|
||||
/* ============================================================
|
||||
* 工作流表单结构化样式
|
||||
* 抽屉内打开的所有 *_form.vue 流程表单统一布局规范
|
||||
* - 主区: el-main > el-form 内容卡片化、分组分区
|
||||
* - 底部: 操作按钮 sticky 底栏
|
||||
* - 侧栏: 提升与正文的视觉区分
|
||||
* ============================================================ */
|
||||
.el-drawer__body {
|
||||
.el-container {
|
||||
height: 100%;
|
||||
background: var(--el-fill-color-light);
|
||||
}
|
||||
|
||||
.el-main {
|
||||
padding: 18px 20px 0 20px;
|
||||
overflow-y: auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* 表单卡片化 */
|
||||
.el-main > .el-form {
|
||||
background: var(--el-bg-color);
|
||||
border: 1px solid var(--el-border-color-lighter);
|
||||
border-radius: 12px;
|
||||
padding: 22px 26px 8px 22px;
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.02);
|
||||
margin-bottom: 76px; /* 给 sticky footer 让位 */
|
||||
max-width: 1240px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.el-main > .el-form .el-form-item {
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
.el-main > .el-form .el-form-item__label {
|
||||
font-weight: 500;
|
||||
color: var(--el-text-color-regular);
|
||||
}
|
||||
|
||||
/* 关键:除非显式 grid(el-row/el-col)或表格类输入,单列 form-item 内容控件不拉满 */
|
||||
.el-main > .el-form > .el-form-item .el-form-item__content > .el-input,
|
||||
.el-main > .el-form > .el-form-item .el-form-item__content > .el-input-number,
|
||||
.el-main > .el-form > .el-form-item .el-form-item__content > .el-select,
|
||||
.el-main > .el-form > .el-form-item .el-form-item__content > .el-cascader,
|
||||
.el-main > .el-form > .el-form-item .el-form-item__content > .el-date-editor:not(.el-date-editor--datetimerange):not(.el-date-editor--daterange) {
|
||||
max-width: 460px;
|
||||
width: 100%;
|
||||
}
|
||||
/* textarea 单独放宽,便于书写多行 */
|
||||
.el-main > .el-form > .el-form-item .el-form-item__content > .el-input.el-input--textarea,
|
||||
.el-main > .el-form > .el-form-item .el-form-item__content > .el-textarea {
|
||||
max-width: 720px;
|
||||
}
|
||||
/* 复选/单选组保持自然宽度 */
|
||||
|
||||
/* 复用:表单内分区标题 */
|
||||
.wf-form-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin: 6px 0 14px;
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 1px solid var(--el-border-color-lighter);
|
||||
}
|
||||
.wf-form-section::before {
|
||||
content: "";
|
||||
width: 3px;
|
||||
height: 14px;
|
||||
border-radius: 2px;
|
||||
background: var(--el-color-primary);
|
||||
}
|
||||
.wf-form-section > .title {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: var(--el-text-color-primary);
|
||||
letter-spacing: 0.4px;
|
||||
}
|
||||
.wf-form-section > .desc {
|
||||
font-size: 12px;
|
||||
color: var(--el-text-color-secondary);
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
/* sticky 底部操作栏 */
|
||||
.el-main > .el-footer,
|
||||
.el-main > .el-form + .el-footer,
|
||||
.el-main > .el-form .el-footer {
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: auto !important;
|
||||
padding: 12px 22px;
|
||||
background: var(--el-bg-color);
|
||||
border-top: 1px solid var(--el-border-color-lighter);
|
||||
box-shadow: 0 -4px 16px -10px rgba(0, 0, 0, 0.15);
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
z-index: 5;
|
||||
margin: 0 -20px -18px;
|
||||
}
|
||||
.el-main > .el-footer .el-button + .el-button,
|
||||
.el-main > .el-form + .el-footer .el-button + .el-button {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
/* 右侧审批栏 */
|
||||
.el-aside {
|
||||
background: var(--el-fill-color-light);
|
||||
border-left: 1px solid var(--el-border-color-lighter);
|
||||
padding: 14px 10px 14px 14px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* 抽屉头部美化(所有工单详情)
|
||||
* ============================================================ */
|
||||
.el-drawer__header {
|
||||
padding: 14px 22px !important;
|
||||
margin-bottom: 0 !important;
|
||||
border-bottom: 1px solid var(--el-border-color-lighter);
|
||||
background: linear-gradient(
|
||||
180deg,
|
||||
var(--el-bg-color) 0%,
|
||||
var(--el-fill-color-light) 100%
|
||||
);
|
||||
}
|
||||
.el-drawer__header > h4 {
|
||||
font-size: 16px !important;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.4px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
<template>
|
||||
<el-container>
|
||||
<el-main class="nopadding">
|
||||
<el-form label-width="110px" :model="formData" style="padding: 20px;">
|
||||
<el-form label-width="110px" :model="formData">
|
||||
<div class="wf-form-section">
|
||||
<span class="title">入库基本信息</span>
|
||||
</div>
|
||||
<el-form-item label="创建时间" v-if="localMode !== 'add'">
|
||||
{{ formData.create_time }}
|
||||
</el-form-item>
|
||||
|
|
@ -36,6 +39,10 @@
|
|||
:disabled="localMode !== 'add'"
|
||||
></el-date-picker>
|
||||
</el-form-item>
|
||||
<div class="wf-form-section">
|
||||
<span class="title">入库明细</span>
|
||||
<span class="desc">逐项录入资产</span>
|
||||
</div>
|
||||
<el-form-item label="入库明细" required>
|
||||
<sc-form-table
|
||||
v-model="formData.items"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,11 @@
|
|||
<template>
|
||||
<el-container>
|
||||
<el-main class="nopadding">
|
||||
<el-form label-width="110px" :model="formData" style="padding: 20px;">
|
||||
<el-form label-width="110px" :model="formData">
|
||||
<div class="wf-form-section">
|
||||
<span class="title">报修信息</span>
|
||||
<span class="desc" v-if="localMode === 'add'">填写设备及报修事由</span>
|
||||
</div>
|
||||
<el-form-item label="创建时间" v-if="localMode !== 'add'">
|
||||
{{ formData.create_time }}
|
||||
</el-form-item>
|
||||
|
|
@ -28,28 +32,32 @@
|
|||
:readonly="localMode === 'show'"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="故障分类" required v-if="localMode != 'add'">
|
||||
<template v-if="localMode != 'add'">
|
||||
<div class="wf-form-section">
|
||||
<span class="title">分派与维修</span>
|
||||
</div>
|
||||
<el-form-item label="故障分类" required>
|
||||
<el-select
|
||||
v-model="ticket_data.fault_cate"
|
||||
placeholder="请选择故障分类"
|
||||
v-if="formData.ticket && formData.ticket_.state_.name == '条保负责人分派'"
|
||||
v-if="formData.ticket && formData.ticket_.state_.name == '条保负责人分派'"
|
||||
>
|
||||
<el-option label="机械" value="机械"></el-option>
|
||||
<el-option label="电气" value="电气"></el-option>
|
||||
</el-select>
|
||||
<span v-else>{{ formData.fault_cate }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="维修人" required v-if="localMode != 'add'">
|
||||
<xtSelect :apiObj="$API.system.user.list"
|
||||
<el-form-item label="维修人" required>
|
||||
<xtSelect :apiObj="$API.system.user.list"
|
||||
v-if="formData.ticket && formData.ticket_.state_.name == '条保负责人分派'" v-model="ticket_data.repair_user">
|
||||
<el-table-column prop="name" label="姓名"></el-table-column>
|
||||
<el-table-column prop="belong_dept_name" label="部门"></el-table-column>
|
||||
</xtSelect>
|
||||
<span v-else>{{ formData.repair_user_name }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="维修开始时间" required v-if="localMode != 'add'">
|
||||
<el-form-item label="维修开始时间" required>
|
||||
<el-date-picker
|
||||
v-if="formData.ticket && formData.ticket_.state_.name == '维修人员处理'"
|
||||
v-if="formData.ticket && formData.ticket_.state_.name == '维修人员处理'"
|
||||
v-model="ticket_data.repair_start_time"
|
||||
type="datetime"
|
||||
placeholder="请选择维修开始时间"
|
||||
|
|
@ -57,12 +65,12 @@
|
|||
></el-date-picker>
|
||||
<span v-else>{{ formData.repair_start_time }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="维修工时" required v-if="localMode != 'add'">
|
||||
<el-input-number v-model="ticket_data.repair_duration" :min="0" :precision="1"
|
||||
<el-form-item label="维修工时" required>
|
||||
<el-input-number v-model="ticket_data.repair_duration" :min="0" :precision="1"
|
||||
v-if="formData.ticket && formData.ticket_.state_.name == '维修人员处理'" ></el-input-number>
|
||||
<span v-else>{{ formData.repair_duration }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="维修描述" required v-if="localMode != 'add'">
|
||||
<el-form-item label="维修描述" required>
|
||||
<el-input
|
||||
type="textarea"
|
||||
:rows="3"
|
||||
|
|
@ -72,6 +80,7 @@
|
|||
></el-input>
|
||||
<span v-else>{{ formData.repair_description }}</span>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-form>
|
||||
<el-footer>
|
||||
<el-button type="danger"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
<template>
|
||||
<el-container>
|
||||
<el-main class="nopadding">
|
||||
<el-form label-width="130px" :model="formData" style="padding: 20px;" :disabled="localMode === 'show'">
|
||||
<el-form label-width="130px" :model="formData" :disabled="localMode === 'show'">
|
||||
<div class="wf-form-section">
|
||||
<span class="title">员工信息</span>
|
||||
</div>
|
||||
<el-form-item label="员工信息" required>
|
||||
<xtSelect
|
||||
v-model="formData.employee"
|
||||
|
|
@ -57,6 +60,9 @@
|
|||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<div class="wf-form-section">
|
||||
<span class="title">调岗信息</span>
|
||||
</div>
|
||||
<el-form-item label="原部门" required>
|
||||
<el-cascader
|
||||
v-model="formData.original_dept"
|
||||
|
|
@ -127,6 +133,9 @@
|
|||
<el-form-item label="调岗原因">
|
||||
<el-input v-model="formData.reason" type="textarea" :rows="2" style="width: 300px;"/>
|
||||
</el-form-item>
|
||||
<div class="wf-form-section">
|
||||
<span class="title">薪资调整</span>
|
||||
</div>
|
||||
<el-form-item label="原岗位薪资">
|
||||
<el-input-number
|
||||
v-model="formData.original_slary"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
<template>
|
||||
<el-container>
|
||||
<el-main class="nopadding">
|
||||
<el-form label-width="120px" :model="formData" style="padding: 20px;" :disabled="localMode === 'show'">
|
||||
<el-form label-width="120px" :model="formData" :disabled="localMode === 'show'">
|
||||
<div class="wf-form-section">
|
||||
<span class="title">合同变更</span>
|
||||
</div>
|
||||
<el-form-item label="申请部门" required>
|
||||
<el-cascader
|
||||
v-model="formData.dept_need"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
<template>
|
||||
<el-container>
|
||||
<el-main class="nopadding">
|
||||
<el-form label-width="80px" :model="formData" style="padding: 20px;" :disabled="localMode === 'show'">
|
||||
<el-form label-width="80px" :model="formData" :disabled="localMode === 'show'">
|
||||
<div class="wf-form-section">
|
||||
<span class="title">人员交接</span>
|
||||
</div>
|
||||
<el-form-item label="需求部门" required>
|
||||
<el-cascader
|
||||
v-model="formData.dept_need"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
<template>
|
||||
<el-container>
|
||||
<el-main class="nopadding">
|
||||
<el-form label-width="130px" :model="formData" style="padding: 20px;" :disabled="localMode === 'show'">
|
||||
<el-form label-width="130px" :model="formData" :disabled="localMode === 'show'">
|
||||
<div class="wf-form-section">
|
||||
<span class="title">用人需求</span>
|
||||
</div>
|
||||
<el-form-item label="需求部门" required>
|
||||
<el-cascader
|
||||
v-model="formData.dept_need"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
<template>
|
||||
<el-container>
|
||||
<el-main class="nopadding">
|
||||
<el-form label-width="80px" :model="formData" style="padding: 20px;">
|
||||
<el-form label-width="80px" :model="formData">
|
||||
<div class="wf-form-section">
|
||||
<span class="title">离职申请</span>
|
||||
</div>
|
||||
<el-form-item label="员工信息" required>
|
||||
<xtSelect
|
||||
v-model="formData.employee"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
<template>
|
||||
<el-container>
|
||||
<el-main class="nopadding">
|
||||
<el-form label-width="130px" :model="formData" style="padding: 20px;" :disabled="localMode === 'show'">
|
||||
<el-form label-width="130px" :model="formData" :disabled="localMode === 'show'">
|
||||
<div class="wf-form-section">
|
||||
<span class="title">员工信息</span>
|
||||
</div>
|
||||
<el-form-item label="员工信息" required>
|
||||
<xtSelect
|
||||
v-model="formData.employee"
|
||||
|
|
|
|||
|
|
@ -7,7 +7,11 @@
|
|||
ref="addForm"
|
||||
label-width="100px"
|
||||
label-position="left"
|
||||
>
|
||||
>
|
||||
<div class="wf-form-section">
|
||||
<span class="title">档案借阅申请</span>
|
||||
<span class="desc">填写档案、用途与时间</span>
|
||||
</div>
|
||||
<el-form-item label="档案名称" prop="borrow_file">
|
||||
<xtSelect
|
||||
:apiObj="apiObjM2"
|
||||
|
|
|
|||
|
|
@ -6,7 +6,11 @@
|
|||
:rules="rules"
|
||||
ref="addForm"
|
||||
label-width="100px"
|
||||
>
|
||||
>
|
||||
<div class="wf-form-section">
|
||||
<span class="title">会议基本信息</span>
|
||||
<span class="desc">填写会议名称、会议室、参会人员等</span>
|
||||
</div>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="会议名称" prop="title">
|
||||
|
|
@ -57,6 +61,10 @@
|
|||
</el-form-item>
|
||||
</el-col> -->
|
||||
</el-row>
|
||||
<div class="wf-form-section">
|
||||
<span class="title">选择会议时间段</span>
|
||||
<span class="desc">点击空闲时段进行预定</span>
|
||||
</div>
|
||||
<el-row>
|
||||
<div v-for="(item,$index) in timesList" :key="item.value">
|
||||
<div v-if="item.sloted" class="timeBlock slotedTimeBlock" @click="slotMessage">{{ item.label }}</div>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,11 @@
|
|||
:rules="rules"
|
||||
ref="addForm"
|
||||
label-position="left"
|
||||
>
|
||||
>
|
||||
<div class="wf-form-section">
|
||||
<span class="title">稿件信息</span>
|
||||
<span class="desc">标题、文件及作者</span>
|
||||
</div>
|
||||
<el-form-item label="送审稿件标题" prop="title">
|
||||
<el-input v-model="addForm.title" clearable :disabled="localMode ==='show'"></el-input>
|
||||
</el-form-item>
|
||||
|
|
@ -28,6 +32,9 @@
|
|||
<el-form-item label="部室/研究院" prop="pub_dept">
|
||||
<el-input v-model="addForm.pub_dept" clearable :disabled="localMode ==='show'"></el-input>
|
||||
</el-form-item>
|
||||
<div class="wf-form-section">
|
||||
<span class="title">涉密与内容</span>
|
||||
</div>
|
||||
<el-form-item label="第一撰稿人涉密等级" prop="level">
|
||||
<el-radio-group v-model="addForm.level" :disabled="localMode ==='show'">
|
||||
<el-radio label="重要"></el-radio>
|
||||
|
|
@ -52,6 +59,9 @@
|
|||
<el-form-item label="宣传报道目的" prop="report_purpose">
|
||||
<el-input v-model="addForm.report_purpose" clearable :disabled="localMode ==='show'"></el-input>
|
||||
</el-form-item>
|
||||
<div class="wf-form-section">
|
||||
<span class="title">宣传渠道</span>
|
||||
</div>
|
||||
<el-form-item label="宣传渠道" prop="channel">
|
||||
<el-checkbox-group v-model="addForm.channel" :disabled="localMode ==='show'">
|
||||
<el-checkbox label="互联网"></el-checkbox>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,10 @@
|
|||
<el-container>
|
||||
<el-main>
|
||||
<el-form :model="localForm" label-width="100px" label-position="left" :rules="rules">
|
||||
<div class="wf-form-section">
|
||||
<span class="title">印章使用申请</span>
|
||||
<span class="desc">填写文件信息与印章类型</span>
|
||||
</div>
|
||||
<el-form-item label="文件名称" prop="filename">
|
||||
<el-input v-model="localForm.filename" clearable :disabled="localMode ==='show'"></el-input>
|
||||
</el-form-item>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,11 @@
|
|||
:rules="rules"
|
||||
ref="addForm"
|
||||
label-width="100px"
|
||||
>
|
||||
>
|
||||
<div class="wf-form-section">
|
||||
<span class="title">用车需求</span>
|
||||
<span class="desc">填写用车事由、目的地及车辆</span>
|
||||
</div>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="用车事由" prop="reason">
|
||||
|
|
@ -76,6 +80,9 @@
|
|||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<div class="wf-form-section">
|
||||
<span class="title">选择用车时段</span>
|
||||
</div>
|
||||
<el-row>
|
||||
<div v-for="(item,$index) in timesList" :key="item.value">
|
||||
<div v-if="item.sloted" class="timeBlock slotedTimeBlock" @click="slotMessage">{{ item.label }}</div>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
<template>
|
||||
<el-container>
|
||||
<el-main class="nopadding">
|
||||
<el-form label-width="100px" :model="formData" style="padding: 20px;">
|
||||
<el-form label-width="100px" :model="formData">
|
||||
<div class="wf-form-section">
|
||||
<span class="title">供应商信息</span>
|
||||
</div>
|
||||
<el-form-item label="供应商名称" required>
|
||||
<el-input v-model="formData.name" placeholder="请输入供应商名称" :readonly="localMode === 'show'"></el-input>
|
||||
</el-form-item>
|
||||
|
|
@ -11,6 +14,10 @@
|
|||
<el-form-item label="物料名称" required>
|
||||
<el-input v-model="formData.material_name" :readonly="localMode === 'show'"></el-input>
|
||||
</el-form-item>
|
||||
<div class="wf-form-section">
|
||||
<span class="title">资质文件</span>
|
||||
<span class="desc">上传调查表、营业执照、质量证书</span>
|
||||
</div>
|
||||
<el-form-item label="调查表" required>
|
||||
<sc-upload-filed
|
||||
v-model="formData.survery_form"
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@
|
|||
<el-container>
|
||||
<el-main>
|
||||
<el-form :model="localForm" label-width="150px" label-position="left" :rules="rules">
|
||||
<div class="wf-form-section">
|
||||
<span class="title">论文基本信息</span>
|
||||
</div>
|
||||
<el-form-item label="拟发表论文名称" prop="paper_name">
|
||||
<el-input v-model="localForm.paper_name" clearable :disabled="localMode ==='show'"></el-input>
|
||||
</el-form-item>
|
||||
|
|
@ -14,6 +17,9 @@
|
|||
<el-form-item label="作者" prop="author" >
|
||||
<el-input v-model="localForm.author" clearable ></el-input>
|
||||
</el-form-item>
|
||||
<div class="wf-form-section">
|
||||
<span class="title">发表详情</span>
|
||||
</div>
|
||||
<el-form-item label="拟发表文章类型" prop="paper_type">
|
||||
<el-select v-model="localForm.paper_type" placeholder="请选择拟发表文章类型" :disabled="localMode ==='show'">
|
||||
<el-option label="研究论文" value="research"></el-option>
|
||||
|
|
|
|||
|
|
@ -1,91 +1,133 @@
|
|||
<template>
|
||||
<el-container>
|
||||
<el-main>
|
||||
<el-form :model="localForm" label-width="150px" label-position="left" :rules="rules">
|
||||
<el-form-item label="拟申请专利名称" prop="name">
|
||||
<el-input v-model="localForm.name" clearable :disabled="localMode ==='show'"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="申请部门" prop="organization">
|
||||
<el-input v-model="localForm.organization" clearable :disabled="localMode ==='show'"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="发明人(设计人)"
|
||||
prop="author"
|
||||
>
|
||||
<el-input v-model="localForm.author" clearable ></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="专利类型" prop="type">
|
||||
<el-form :model="localForm" label-width="130px" label-position="left" :rules="rules">
|
||||
<div class="wf-form-section">
|
||||
<span class="title">专利基本信息</span>
|
||||
<span class="desc">名称、申请部门、发明人</span>
|
||||
</div>
|
||||
<el-row :gutter="24">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="拟申请专利名称" prop="name">
|
||||
<el-input v-model="localForm.name" clearable :disabled="localMode ==='show'" placeholder="请输入专利名称"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="申请部门" prop="organization">
|
||||
<el-input v-model="localForm.organization" clearable :disabled="localMode ==='show'" placeholder="请输入申请部门"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="发明人(设计人)" prop="author">
|
||||
<el-input v-model="localForm.author" clearable placeholder="多人请用顿号分隔"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<div class="wf-form-section">
|
||||
<span class="title">申请详情</span>
|
||||
</div>
|
||||
<el-row :gutter="24">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="专利类型" prop="type">
|
||||
<el-select v-model="localForm.type" placeholder="请选择专利类型" :disabled="localMode ==='show'">
|
||||
<el-option label="发明专利" value="invention"></el-option>
|
||||
<el-option label="实用新型专利" value="utility"></el-option>
|
||||
<el-option label="外观设计专利" value="design"></el-option>
|
||||
<el-option label="发明专利" value="invention"></el-option>
|
||||
<el-option label="实用新型专利" value="utility"></el-option>
|
||||
<el-option label="外观设计专利" value="design"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否公开" prop="is_public">
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="是否公开" prop="is_public">
|
||||
<el-radio-group v-model="localForm.is_public" :disabled="localMode ==='show'">
|
||||
<el-radio :label="true">是</el-radio>
|
||||
<el-radio :label="false">否</el-radio>
|
||||
<el-radio :label="true">是</el-radio>
|
||||
<el-radio :label="false">否</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="拟申请地域" prop="area">
|
||||
<el-radio-group v-model="localForm.area" :disabled="localMode ==='show'">
|
||||
<el-radio label="国内申请" value="Domestic"></el-radio>
|
||||
<el-radio label="国外申请" value="Foreign"></el-radio>
|
||||
<el-radio label="PCT申请" value="PCT"></el-radio>
|
||||
</el-radio-group>
|
||||
<el-input
|
||||
v-if="localForm.area && (localForm.area.includes('Foreign') || localForm.area.includes('PCT'))"
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="拟申请地域" prop="area">
|
||||
<el-radio-group v-model="localForm.area" :disabled="localMode ==='show'">
|
||||
<el-radio label="国内申请" value="Domestic"></el-radio>
|
||||
<el-radio label="国外申请" value="Foreign"></el-radio>
|
||||
<el-radio label="PCT申请" value="PCT"></el-radio>
|
||||
</el-radio-group>
|
||||
<el-input
|
||||
v-if="localForm.area && (localForm.area.includes('Foreign') || localForm.area.includes('PCT'))"
|
||||
v-model="localForm.other_area"
|
||||
placeholder = "请输入申请的国家"
|
||||
size = "small"
|
||||
style="margin-top: 10;"
|
||||
placeholder="请输入申请的国家"
|
||||
size="small"
|
||||
style="margin-top: 8px; max-width: 320px;"
|
||||
:disabled="localMode ==='show'"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="技术状态" prop="tech_status">
|
||||
<el-row>
|
||||
<el-col :span="12" v-for="(item, index) in localForm.tech_status || []" :key="index">
|
||||
<div class="class-row">
|
||||
<span>{{ item.name }}</span>
|
||||
<el-radio-group v-model="item.status" @change="handleStatusChange(item)" style="margin-left: 20px;" :disabled="localMode ==='show'">
|
||||
<el-radio label="是">是</el-radio>
|
||||
<el-radio label="否">否</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<div class="wf-form-section">
|
||||
<span class="title">技术状态与文件</span>
|
||||
</div>
|
||||
<el-form-item label="技术状态" prop="tech_status" class="patent-tech-status">
|
||||
<div class="patent-tech-grid">
|
||||
<div
|
||||
v-for="(item, index) in localForm.tech_status || []"
|
||||
:key="index"
|
||||
class="patent-tech-item"
|
||||
:class="{ 'is-yes': item.status === '是' }"
|
||||
>
|
||||
<div class="patent-tech-item__row">
|
||||
<span class="patent-tech-item__label">{{ item.name }}</span>
|
||||
<el-radio-group
|
||||
v-model="item.status"
|
||||
@change="handleStatusChange(item)"
|
||||
:disabled="localMode ==='show'"
|
||||
size="small"
|
||||
>
|
||||
<el-radio label="是">是</el-radio>
|
||||
<el-radio label="否">否</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div v-if="item.status === '是'" class="upload-section">
|
||||
<sc-upload-file
|
||||
multiple
|
||||
:limit="1"
|
||||
:accept="['.xlsx', '.xls','.pdf','.docx', '.doc', '.jpg', '.png', '.jpeg']"
|
||||
@success = "(res)=>fileUPSuccess(res, item)"
|
||||
:disabled="localMode ==='show'"
|
||||
>
|
||||
<el-button type="primary" size="small" icon="el-icon-upload"> </el-button>
|
||||
</sc-upload-file>
|
||||
<div v-if="item.file && localMode ==='show'" class="file-list">
|
||||
<div v-if="item.status === '是'" class="patent-tech-item__upload">
|
||||
<sc-upload-file
|
||||
multiple
|
||||
:limit="1"
|
||||
:accept="['.xlsx', '.xls','.pdf','.docx', '.doc', '.jpg', '.png', '.jpeg']"
|
||||
@success="(res)=>fileUPSuccess(res, item)"
|
||||
:disabled="localMode ==='show'"
|
||||
>
|
||||
<el-button type="primary" size="small" plain>
|
||||
<el-icon><Upload /></el-icon><span style="margin-left:4px">上传证明</span>
|
||||
</el-button>
|
||||
</sc-upload-file>
|
||||
<div v-if="item.file && localMode ==='show'" class="file-list">
|
||||
<el-link type="primary" :href="item.file" target="_blank">
|
||||
{{ item.file.split('/').pop() }}
|
||||
{{ item.file.split('/').pop() }}
|
||||
</el-link>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
<el-form-item label="技术文件" prop="tech_file">
|
||||
<div class="file-item" v-for="(item, index) in localForm.tech_file || []" :key="index">
|
||||
<el-checkbox class="file-checkbox" v-model="item.checked" @change="handleCheckChange(item)" :disabled="localMode ==='show'">
|
||||
{{ item.name }}
|
||||
</el-checkbox>
|
||||
<el-input
|
||||
class="page-input"
|
||||
v-model="item.pages"
|
||||
placeholder="页数"
|
||||
:disabled="!item.checked || localMode ==='show'"
|
||||
type="number"
|
||||
min="0">
|
||||
<template v-slot:append>页</template>
|
||||
</el-input>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="技术文件" prop="tech_file">
|
||||
<div class="patent-tech-files">
|
||||
<div class="patent-file-item" v-for="(item, index) in localForm.tech_file || []" :key="index">
|
||||
<el-checkbox v-model="item.checked" @change="handleCheckChange(item)" :disabled="localMode ==='show'">
|
||||
{{ item.name }}
|
||||
</el-checkbox>
|
||||
<el-input
|
||||
class="patent-file-pages"
|
||||
v-model="item.pages"
|
||||
placeholder="页数"
|
||||
:disabled="!item.checked || localMode ==='show'"
|
||||
type="number"
|
||||
min="0"
|
||||
size="small"
|
||||
>
|
||||
<template v-slot:append>页</template>
|
||||
</el-input>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-footer>
|
||||
<ticketd_b
|
||||
|
|
@ -114,6 +156,7 @@
|
|||
<script>
|
||||
import ticketd_b from "@/views/wf/ticketd_b.vue";
|
||||
import ticketd from '@/views/wf/ticketd.vue'
|
||||
import { Upload } from "@element-plus/icons-vue";
|
||||
export default {
|
||||
props: {
|
||||
mode: {
|
||||
|
|
@ -125,7 +168,7 @@ export default {
|
|||
default: null
|
||||
},
|
||||
},
|
||||
components: {ticketd, ticketd_b},
|
||||
components: {ticketd, ticketd_b, Upload},
|
||||
data() {
|
||||
return {
|
||||
ticket_data: {},
|
||||
|
|
@ -225,4 +268,68 @@ export default {
|
|||
},
|
||||
};
|
||||
|
||||
</script>
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 技术状态网格 */
|
||||
.patent-tech-status :deep(.el-form-item__content) {
|
||||
display: block;
|
||||
width: 100%;
|
||||
line-height: 1.4;
|
||||
}
|
||||
.patent-tech-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||
gap: 12px;
|
||||
width: 100%;
|
||||
}
|
||||
.patent-tech-item {
|
||||
border: 1px solid var(--el-border-color-lighter);
|
||||
background: var(--el-fill-color-light);
|
||||
border-radius: 8px;
|
||||
padding: 10px 12px;
|
||||
transition: background-color 0.2s ease, border-color 0.2s ease;
|
||||
}
|
||||
.patent-tech-item.is-yes {
|
||||
background: var(--el-color-primary-light-9);
|
||||
border-color: var(--el-color-primary-light-5);
|
||||
}
|
||||
.patent-tech-item__row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
.patent-tech-item__label {
|
||||
font-size: 13px;
|
||||
color: var(--el-text-color-primary);
|
||||
}
|
||||
.patent-tech-item__upload {
|
||||
margin-top: 10px;
|
||||
padding-top: 10px;
|
||||
border-top: 1px dashed var(--el-border-color);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.file-list {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
/* 技术文件列表 */
|
||||
.patent-tech-files {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
|
||||
gap: 10px 24px;
|
||||
width: 100%;
|
||||
}
|
||||
.patent-file-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
.patent-file-pages {
|
||||
max-width: 110px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,10 @@
|
|||
<el-container>
|
||||
<el-main>
|
||||
<el-form :model="localForm" label-width="150px" label-position="left" :rules="rules">
|
||||
<div class="wf-form-section">
|
||||
<span class="title">平台审批</span>
|
||||
<span class="desc">填写平台名称、申请部门及日期</span>
|
||||
</div>
|
||||
<el-form-item label="名称" prop="name">
|
||||
<el-input v-model="localForm.name" clearable :disabled="localMode ==='show'"></el-input>
|
||||
</el-form-item>
|
||||
|
|
|
|||
|
|
@ -141,31 +141,140 @@
|
|||
@success="handleSuccess"></component>
|
||||
</el-drawer>
|
||||
</el-container>
|
||||
<el-dialog v-model="dialogVisible" title="选择流程">
|
||||
<div v-for="group in wfOptions" :key="group.category" class="category-group">
|
||||
<h3 style="margin: 16px 0 8px 0; color: #606266;">{{ group.category }}</h3>
|
||||
<el-card
|
||||
v-for="item in group.items"
|
||||
:key="item.id"
|
||||
:body-style="{ padding: '10px', cursor: 'pointer' }"
|
||||
style="width: 180px; display: inline-block; margin: 4px; background-color: #f5f7fa;"
|
||||
shadow="hover"
|
||||
@click="startTicket(item)"
|
||||
>
|
||||
{{ item.name }}
|
||||
</el-card>
|
||||
</div>
|
||||
<el-dialog
|
||||
v-model="dialogVisible"
|
||||
title="选择流程"
|
||||
width="960px"
|
||||
top="6vh"
|
||||
class="wf-picker-dialog"
|
||||
:close-on-click-modal="false"
|
||||
destroy-on-close
|
||||
>
|
||||
<div class="wf-picker">
|
||||
<aside class="wf-picker__aside">
|
||||
<div class="wf-picker__search">
|
||||
<el-input
|
||||
v-model="wfKeyword"
|
||||
placeholder="搜索流程"
|
||||
clearable
|
||||
:prefix-icon="Search"
|
||||
/>
|
||||
</div>
|
||||
<nav class="wf-picker__nav">
|
||||
<a
|
||||
v-for="group in filteredWfOptions"
|
||||
:key="group.category"
|
||||
class="wf-picker__nav-item"
|
||||
:class="{ active: activeCategory === group.category }"
|
||||
@click="scrollToCategory(group.category)"
|
||||
>
|
||||
<el-icon class="wf-picker__nav-icon">
|
||||
<component :is="categoryIcon(group.category)" />
|
||||
</el-icon>
|
||||
<span class="wf-picker__nav-text">{{ group.category }}</span>
|
||||
<span class="wf-picker__nav-count">{{ group.items.length }}</span>
|
||||
</a>
|
||||
</nav>
|
||||
</aside>
|
||||
|
||||
<section ref="wfScroll" class="wf-picker__body" @scroll="onPickerScroll">
|
||||
<template v-if="filteredWfOptions.length">
|
||||
<div
|
||||
v-for="group in filteredWfOptions"
|
||||
:key="group.category"
|
||||
class="wf-picker__group"
|
||||
:data-category="group.category"
|
||||
:ref="el => setGroupRef(group.category, el)"
|
||||
>
|
||||
<header class="wf-picker__group-header">
|
||||
<el-icon class="wf-picker__group-icon">
|
||||
<component :is="categoryIcon(group.category)" />
|
||||
</el-icon>
|
||||
<h3 class="wf-picker__group-title">{{ group.category }}</h3>
|
||||
<span class="wf-picker__group-divider"></span>
|
||||
<span class="wf-picker__group-meta">{{ group.items.length }} 项</span>
|
||||
</header>
|
||||
<div class="wf-picker__grid">
|
||||
<button
|
||||
v-for="item in group.items"
|
||||
:key="item.id"
|
||||
type="button"
|
||||
class="wf-picker__card"
|
||||
@click="startTicket(item)"
|
||||
>
|
||||
<span class="wf-picker__card-icon">
|
||||
<el-icon><component :is="itemIcon(item.name, group.category)" /></el-icon>
|
||||
</span>
|
||||
<span class="wf-picker__card-name">{{ item.name }}</span>
|
||||
<span class="wf-picker__card-arrow">
|
||||
<el-icon><ArrowRight /></el-icon>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<el-empty v-else description="未找到匹配的流程" :image-size="80" />
|
||||
</section>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineAsyncComponent, markRaw } from 'vue'; // 异步组件加载
|
||||
import { actStateEnum, interveneTypeEnum } from "@/utils/enum.js";
|
||||
import {
|
||||
Search, ArrowRight,
|
||||
UserFilled, SwitchButton, CircleClose,
|
||||
Tools, Box, Postcard, Promotion, ChatLineRound,
|
||||
Van, Monitor, OfficeBuilding, Document, Briefcase, ShoppingCart,
|
||||
Cpu, Files, Grid, Tickets
|
||||
} from "@element-plus/icons-vue";
|
||||
|
||||
const CATEGORY_ICON_MAP = {
|
||||
"人事": UserFilled,
|
||||
"设备": Tools,
|
||||
"固资": Box,
|
||||
"行政": Briefcase,
|
||||
"科研": Cpu,
|
||||
"采购": ShoppingCart,
|
||||
"未分组": Grid,
|
||||
};
|
||||
|
||||
const ITEM_ICON_RULES = [
|
||||
[/合同|协议/, Document],
|
||||
[/调岗|调动|交接/, SwitchButton],
|
||||
[/用人|招聘|入职/, UserFilled],
|
||||
[/离职|辞职/, CircleClose],
|
||||
[/维修|检修|故障/, Tools],
|
||||
[/入库|出库|盘点|资产/, Box],
|
||||
[/档案|文件|借阅/, Files],
|
||||
[/印章|盖章/, Postcard],
|
||||
[/宣传|报道|发布/, Promotion],
|
||||
[/会议|预定/, ChatLineRound],
|
||||
[/用车|车辆|出行/, Van],
|
||||
[/平台|系统|监控/, Monitor],
|
||||
[/供应商|采购|订单/, OfficeBuilding],
|
||||
[/请假|加班|考勤/, Tickets],
|
||||
[/审批|报销|申请/, Document],
|
||||
];
|
||||
|
||||
export default {
|
||||
name: "myticket",
|
||||
components: {
|
||||
Search, ArrowRight,
|
||||
UserFilled, SwitchButton, CircleClose,
|
||||
Tools, Box, Postcard, Promotion, ChatLineRound,
|
||||
Van, Monitor, OfficeBuilding, Document, Briefcase, ShoppingCart,
|
||||
Cpu, Files, Grid, Tickets
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
Search: markRaw(Search),
|
||||
ArrowRight: markRaw(ArrowRight),
|
||||
actStateEnum, interveneTypeEnum,
|
||||
wfKeyword: "",
|
||||
activeCategory: "",
|
||||
wfGroupRefs: {},
|
||||
drawerName: "工单详情",
|
||||
drawer: false,
|
||||
tvalue: "待办",
|
||||
|
|
@ -217,7 +326,65 @@ export default {
|
|||
}
|
||||
this.getWfOptions();
|
||||
},
|
||||
computed: {
|
||||
filteredWfOptions() {
|
||||
const kw = (this.wfKeyword || "").trim().toLowerCase();
|
||||
if (!kw) return this.wfOptions;
|
||||
return this.wfOptions
|
||||
.map(g => ({
|
||||
category: g.category,
|
||||
items: g.items.filter(it =>
|
||||
(it.name || "").toLowerCase().includes(kw) ||
|
||||
(g.category || "").toLowerCase().includes(kw)
|
||||
)
|
||||
}))
|
||||
.filter(g => g.items.length);
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
dialogVisible(v) {
|
||||
if (v) {
|
||||
this.wfKeyword = "";
|
||||
this.$nextTick(() => {
|
||||
this.activeCategory = this.filteredWfOptions[0]?.category || "";
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
categoryIcon(cate) {
|
||||
return CATEGORY_ICON_MAP[cate] || Grid;
|
||||
},
|
||||
itemIcon(name, cate) {
|
||||
for (const [re, icon] of ITEM_ICON_RULES) {
|
||||
if (re.test(name)) return icon;
|
||||
}
|
||||
return CATEGORY_ICON_MAP[cate] || Document;
|
||||
},
|
||||
setGroupRef(category, el) {
|
||||
if (el) this.wfGroupRefs[category] = el;
|
||||
},
|
||||
scrollToCategory(category) {
|
||||
const el = this.wfGroupRefs[category];
|
||||
const scroller = this.$refs.wfScroll;
|
||||
if (!el || !scroller) return;
|
||||
this.activeCategory = category;
|
||||
scroller.scrollTo({
|
||||
top: el.offsetTop - 8,
|
||||
behavior: "smooth",
|
||||
});
|
||||
},
|
||||
onPickerScroll() {
|
||||
const scroller = this.$refs.wfScroll;
|
||||
if (!scroller) return;
|
||||
const top = scroller.scrollTop;
|
||||
let current = this.filteredWfOptions[0]?.category || "";
|
||||
for (const g of this.filteredWfOptions) {
|
||||
const el = this.wfGroupRefs[g.category];
|
||||
if (el && el.offsetTop - 24 <= top) current = g.category;
|
||||
}
|
||||
if (current !== this.activeCategory) this.activeCategory = current;
|
||||
},
|
||||
async getWfOptions() {
|
||||
let permissions = this.$TOOL.data.get("PERMISSIONS");
|
||||
let userInfo = this.$TOOL.data.get("USER_INFO");
|
||||
|
|
@ -303,4 +470,267 @@ export default {
|
|||
};
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
<style scoped>
|
||||
/* ===== 选择流程对话框 ===== */
|
||||
:deep(.wf-picker-dialog) {
|
||||
border-radius: 14px;
|
||||
overflow: hidden;
|
||||
}
|
||||
:deep(.wf-picker-dialog .el-dialog__header) {
|
||||
padding: 18px 24px;
|
||||
margin-right: 0;
|
||||
border-bottom: 1px solid var(--el-border-color-lighter);
|
||||
background: linear-gradient(
|
||||
180deg,
|
||||
var(--el-fill-color-blank) 0%,
|
||||
var(--el-fill-color-light) 100%
|
||||
);
|
||||
}
|
||||
:deep(.wf-picker-dialog .el-dialog__title) {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
:deep(.wf-picker-dialog .el-dialog__body) {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.wf-picker {
|
||||
display: flex;
|
||||
height: 66vh;
|
||||
min-height: 440px;
|
||||
max-height: 640px;
|
||||
background: var(--el-bg-color);
|
||||
}
|
||||
|
||||
/* 左侧分类导航 */
|
||||
.wf-picker__aside {
|
||||
width: 200px;
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-right: 1px solid var(--el-border-color-lighter);
|
||||
background: var(--el-fill-color-light);
|
||||
}
|
||||
.wf-picker__search {
|
||||
padding: 14px 12px 10px;
|
||||
}
|
||||
.wf-picker__nav {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 4px 8px 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
}
|
||||
.wf-picker__nav-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 9px 12px;
|
||||
border-radius: 8px;
|
||||
font-size: 13.5px;
|
||||
color: var(--el-text-color-regular);
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
transition:
|
||||
background-color 0.18s ease,
|
||||
color 0.18s ease,
|
||||
transform 0.18s ease;
|
||||
position: relative;
|
||||
}
|
||||
.wf-picker__nav-item::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 4px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%) scaleY(0);
|
||||
width: 3px;
|
||||
height: 18px;
|
||||
background: var(--el-color-primary);
|
||||
border-radius: 2px;
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
.wf-picker__nav-item:hover {
|
||||
background: var(--el-fill-color);
|
||||
color: var(--el-text-color-primary);
|
||||
}
|
||||
.wf-picker__nav-item.active {
|
||||
background: var(--el-color-primary-light-9);
|
||||
color: var(--el-color-primary);
|
||||
font-weight: 600;
|
||||
}
|
||||
.wf-picker__nav-item.active::before {
|
||||
transform: translateY(-50%) scaleY(1);
|
||||
}
|
||||
.wf-picker__nav-icon {
|
||||
font-size: 16px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.wf-picker__nav-text {
|
||||
flex: 1;
|
||||
}
|
||||
.wf-picker__nav-count {
|
||||
font-size: 12px;
|
||||
padding: 1px 7px;
|
||||
border-radius: 10px;
|
||||
background: var(--el-fill-color-darker);
|
||||
color: var(--el-text-color-secondary);
|
||||
font-weight: 500;
|
||||
}
|
||||
.wf-picker__nav-item.active .wf-picker__nav-count {
|
||||
background: var(--el-color-primary);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* 右侧主体 */
|
||||
.wf-picker__body {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 18px 24px 24px;
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
.wf-picker__group + .wf-picker__group {
|
||||
margin-top: 22px;
|
||||
}
|
||||
.wf-picker__group-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-bottom: 12px;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
.wf-picker__group-icon {
|
||||
color: var(--el-color-primary);
|
||||
font-size: 16px;
|
||||
}
|
||||
.wf-picker__group-title {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: var(--el-text-color-primary);
|
||||
margin: 0;
|
||||
letter-spacing: 0.4px;
|
||||
}
|
||||
.wf-picker__group-divider {
|
||||
flex: 1;
|
||||
height: 1px;
|
||||
background: linear-gradient(
|
||||
to right,
|
||||
var(--el-border-color-lighter),
|
||||
transparent
|
||||
);
|
||||
}
|
||||
.wf-picker__group-meta {
|
||||
font-size: 12px;
|
||||
color: var(--el-text-color-secondary);
|
||||
}
|
||||
|
||||
/* 卡片网格 */
|
||||
.wf-picker__grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(168px, 1fr));
|
||||
gap: 10px;
|
||||
}
|
||||
.wf-picker__card {
|
||||
all: unset;
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 12px 14px;
|
||||
border-radius: 10px;
|
||||
background: var(--el-bg-color);
|
||||
border: 1px solid var(--el-border-color-lighter);
|
||||
transition:
|
||||
border-color 0.18s ease,
|
||||
box-shadow 0.18s ease,
|
||||
transform 0.18s ease,
|
||||
background-color 0.18s ease;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.wf-picker__card::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 3px;
|
||||
background: var(--el-color-primary);
|
||||
transform: scaleY(0);
|
||||
transform-origin: center;
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
.wf-picker__card:hover {
|
||||
border-color: var(--el-color-primary-light-5);
|
||||
box-shadow: 0 6px 16px -10px var(--el-color-primary);
|
||||
transform: translateY(-1px);
|
||||
background: var(--el-color-primary-light-9);
|
||||
}
|
||||
.wf-picker__card:hover::before {
|
||||
transform: scaleY(1);
|
||||
}
|
||||
.wf-picker__card:active {
|
||||
transform: translateY(0);
|
||||
}
|
||||
.wf-picker__card-icon {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
flex-shrink: 0;
|
||||
border-radius: 8px;
|
||||
background: var(--el-color-primary-light-9);
|
||||
color: var(--el-color-primary);
|
||||
font-size: 16px;
|
||||
transition: background-color 0.18s ease, color 0.18s ease;
|
||||
}
|
||||
.wf-picker__card:hover .wf-picker__card-icon {
|
||||
background: var(--el-color-primary);
|
||||
color: #fff;
|
||||
}
|
||||
.wf-picker__card-name {
|
||||
flex: 1;
|
||||
font-size: 13.5px;
|
||||
color: var(--el-text-color-primary);
|
||||
font-weight: 500;
|
||||
line-height: 1.4;
|
||||
text-align: left;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.wf-picker__card-arrow {
|
||||
color: var(--el-text-color-placeholder);
|
||||
font-size: 14px;
|
||||
opacity: 0;
|
||||
transform: translateX(-4px);
|
||||
transition: opacity 0.18s ease, transform 0.18s ease, color 0.18s ease;
|
||||
}
|
||||
.wf-picker__card:hover .wf-picker__card-arrow {
|
||||
color: var(--el-color-primary);
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
/* 响应式 */
|
||||
@media (max-width: 768px) {
|
||||
:deep(.wf-picker-dialog) {
|
||||
--el-dialog-width: 92vw !important;
|
||||
}
|
||||
.wf-picker {
|
||||
height: 72vh;
|
||||
}
|
||||
.wf-picker__aside {
|
||||
width: 140px;
|
||||
}
|
||||
.wf-picker__nav-text {
|
||||
font-size: 13px;
|
||||
}
|
||||
.wf-picker__body {
|
||||
padding: 14px 14px 20px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,139 +1,191 @@
|
|||
<template>
|
||||
<el-collapse v-model="activeNames" style="padding-left: 2px; padding-right: 2px;">
|
||||
<el-collapse-item title="基本信息" name="1">
|
||||
<el-descriptions :column="1">
|
||||
<el-descriptions-item>
|
||||
<span style="color:darkblue;margin-right: 4px;">({{ ticketDetail.sn }})</span>{{ ticketDetail.title
|
||||
}}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="提交人:">
|
||||
{{ ticketDetail.create_by_name }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="当前:">
|
||||
<el-tag type="info" effect="plain">{{ ticketDetail.state_.name }}</el-tag>
|
||||
<el-tag :type="actStateEnum[ticketDetail.act_state]?.type" effect="plain">
|
||||
{{ actStateEnum[ticketDetail.act_state]?.text }}
|
||||
</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="可处理人:"
|
||||
v-if="ticketDetail.participant_type == 2 || ticketDetail.participant_type == 1">
|
||||
<span v-for="item in ticketDetail.participant_" :key="item.id">{{ item.name }}/</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="操作:">
|
||||
<el-button v-if="ticketDetail.state_.enable_retreat && isOwn" type="danger" size="small"
|
||||
@click="handleRetreat">撤回</el-button>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="审批历史" name="2">
|
||||
<div style="padding:1px"><el-timeline>
|
||||
<el-timeline-item v-for="item in ticketLog" :key="item.id" :timestamp="item.create_time"
|
||||
:color="getColor(item)">
|
||||
<div>
|
||||
<strong>{{ item.state_?.name || "未知状态" }}</strong>
|
||||
</div>
|
||||
<div>
|
||||
<span v-if="item.intervene_type != 0"><el-tag
|
||||
:type="interveneTypeEnum[item.intervene_type]?.type" effect="plain">
|
||||
{{ interveneTypeEnum[item.intervene_type]?.text }}
|
||||
</el-tag></span>
|
||||
<span v-if="item.transition_"
|
||||
:style="{ color: item.transition_.attribute_type === 1 ? '#67C23A' : '#F56C6C' }">
|
||||
{{ item.transition_.name }}
|
||||
</span>
|
||||
<span v-if="item.participant_">-{{ item.participant_.name }}</span>
|
||||
</div>
|
||||
<div v-if="item.suggestion">
|
||||
<el-tooltip v-if="item.suggestion.length > 20" class="box-item" effect="dark"
|
||||
:content="item.suggestion" placement="top">
|
||||
<span>{{ item.suggestion.slice(0, 20) + "..." }}</span>
|
||||
</el-tooltip>
|
||||
<span v-else>
|
||||
{{ item.suggestion }}
|
||||
</span>
|
||||
</div>
|
||||
</el-timeline-item>
|
||||
</el-timeline></div>
|
||||
<div class="wf-side">
|
||||
<!-- 工单基本信息卡 -->
|
||||
<section class="wf-side__card">
|
||||
<header class="wf-side__card-header">
|
||||
<span class="wf-side__card-bar"></span>
|
||||
<h4 class="wf-side__card-title">基本信息</h4>
|
||||
<el-tag
|
||||
v-if="ticketDetail.act_state !== undefined"
|
||||
:type="actStateEnum[ticketDetail.act_state]?.type"
|
||||
effect="dark"
|
||||
size="small"
|
||||
round
|
||||
>{{ actStateEnum[ticketDetail.act_state]?.text }}</el-tag>
|
||||
</header>
|
||||
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
<el-dialog :title="dialogTitle" v-model="dialogVisible">
|
||||
<el-input v-model="suggestion" type="textarea" :rows="2"></el-input>
|
||||
<template #footer>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="dialogConfirm()">确 定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<div class="wf-side__sn-row" v-if="ticketDetail.sn">
|
||||
<span class="wf-side__sn-tag">{{ ticketDetail.sn }}</span>
|
||||
<span class="wf-side__sn-title" :title="ticketDetail.title">{{ ticketDetail.title }}</span>
|
||||
</div>
|
||||
|
||||
<dl class="wf-side__kv">
|
||||
<div class="wf-side__kv-row">
|
||||
<dt>提交人</dt>
|
||||
<dd>{{ ticketDetail.create_by_name || '—' }}</dd>
|
||||
</div>
|
||||
<div class="wf-side__kv-row">
|
||||
<dt>当前节点</dt>
|
||||
<dd>
|
||||
<el-tag type="info" effect="plain" size="small">{{ ticketDetail.state_?.name || '—' }}</el-tag>
|
||||
</dd>
|
||||
</div>
|
||||
<div
|
||||
class="wf-side__kv-row"
|
||||
v-if="ticketDetail.participant_type == 2 || ticketDetail.participant_type == 1"
|
||||
>
|
||||
<dt>可处理人</dt>
|
||||
<dd class="wf-side__participants">
|
||||
<span
|
||||
v-for="item in ticketDetail.participant_"
|
||||
:key="item.id"
|
||||
class="wf-side__chip"
|
||||
>{{ item.name }}</span>
|
||||
</dd>
|
||||
</div>
|
||||
</dl>
|
||||
|
||||
<div class="wf-side__actions" v-if="ticketDetail.state_?.enable_retreat && isOwn">
|
||||
<el-button type="danger" size="small" plain @click="handleRetreat">
|
||||
<el-icon><RefreshLeft /></el-icon><span style="margin-left:4px">撤回</span>
|
||||
</el-button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 审批历史卡 -->
|
||||
<section class="wf-side__card wf-side__card--history">
|
||||
<header class="wf-side__card-header">
|
||||
<span class="wf-side__card-bar"></span>
|
||||
<h4 class="wf-side__card-title">审批历史</h4>
|
||||
<span class="wf-side__count" v-if="ticketLog.length">{{ ticketLog.length }}</span>
|
||||
</header>
|
||||
|
||||
<div class="wf-side__timeline" v-if="ticketLog.length">
|
||||
<div
|
||||
v-for="(item, idx) in ticketLog"
|
||||
:key="item.id"
|
||||
class="wf-side__tl-item"
|
||||
:class="`is-${kindOf(item)}`"
|
||||
>
|
||||
<div class="wf-side__tl-rail">
|
||||
<span class="wf-side__tl-dot"></span>
|
||||
<span v-if="idx !== ticketLog.length - 1" class="wf-side__tl-line"></span>
|
||||
</div>
|
||||
<div class="wf-side__tl-body">
|
||||
<div class="wf-side__tl-head">
|
||||
<strong class="wf-side__tl-state">{{ item.state_?.name || '未知状态' }}</strong>
|
||||
<span class="wf-side__tl-time">{{ shortTime(item.create_time) }}</span>
|
||||
</div>
|
||||
<div class="wf-side__tl-meta">
|
||||
<el-tag
|
||||
v-if="item.intervene_type != 0"
|
||||
:type="interveneTypeEnum[item.intervene_type]?.type"
|
||||
effect="plain"
|
||||
size="small"
|
||||
>{{ interveneTypeEnum[item.intervene_type]?.text }}</el-tag>
|
||||
<span
|
||||
v-if="item.transition_"
|
||||
class="wf-side__tl-transition"
|
||||
:class="{
|
||||
'is-approve': item.transition_.attribute_type === 1,
|
||||
'is-reject': item.transition_.attribute_type === 2
|
||||
}"
|
||||
>{{ item.transition_.name }}</span>
|
||||
<span v-if="item.participant_" class="wf-side__tl-user">· {{ item.participant_.name }}</span>
|
||||
</div>
|
||||
<div class="wf-side__tl-suggestion" v-if="item.suggestion">
|
||||
<el-tooltip
|
||||
v-if="item.suggestion.length > 28"
|
||||
effect="dark"
|
||||
:content="item.suggestion"
|
||||
placement="top"
|
||||
>
|
||||
<span>{{ item.suggestion.slice(0, 28) + '…' }}</span>
|
||||
</el-tooltip>
|
||||
<span v-else>{{ item.suggestion }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-empty v-else description="暂无审批记录" :image-size="60" />
|
||||
</section>
|
||||
|
||||
<el-dialog :title="dialogTitle" v-model="dialogVisible" width="420px">
|
||||
<el-input v-model="suggestion" type="textarea" :rows="3" placeholder="请输入说明" />
|
||||
<template #footer>
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="dialogConfirm()">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, defineProps, onMounted, watch } from "vue";
|
||||
import { actStateEnum, interveneTypeEnum } from "@/utils/enum.js";
|
||||
import { RefreshLeft } from "@element-plus/icons-vue";
|
||||
import API from '@/api';
|
||||
import TOOL from "@/utils/tool.js";
|
||||
|
||||
const props = defineProps({
|
||||
ticket_data: { type: Object, default: null },
|
||||
ticket_: { type: Object, default: null, required: true },
|
||||
});
|
||||
const currentUser = ref(TOOL.data.get("USER_INFO").id)
|
||||
const currentUser = ref(TOOL.data.get("USER_INFO").id);
|
||||
const isOwn = ref(false);
|
||||
const activeNames = ref(['1', '2']);
|
||||
const ticketDetail = ref({
|
||||
state_: {}
|
||||
});
|
||||
const ticketDetail = ref({ state_: {} });
|
||||
const ticketLog = ref([]);
|
||||
const ticketId = ref(null);
|
||||
|
||||
onMounted(() => {
|
||||
// 立即处理初始值
|
||||
if (props.ticket_ && props.ticket_.id) {
|
||||
ticketId.value = props.ticket_.id
|
||||
getTicketDetail()
|
||||
getTicketLog()
|
||||
ticketId.value = props.ticket_.id;
|
||||
getTicketDetail();
|
||||
getTicketLog();
|
||||
}
|
||||
|
||||
// 同时监听后续变化
|
||||
watch(
|
||||
() => props.ticket_,
|
||||
async (newVal) => {
|
||||
if (newVal && Object.keys(newVal).length > 0) {
|
||||
ticketId.value = newVal.id
|
||||
getTicketDetail()
|
||||
getTicketLog()
|
||||
ticketId.value = newVal.id;
|
||||
getTicketDetail();
|
||||
getTicketLog();
|
||||
}
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
const emit = defineEmits(['success']);
|
||||
const refreshTicket = async () => {
|
||||
isOwn.value = false
|
||||
ticketLog.value = []
|
||||
activeNames.value = ['1', '2'] // 根据需要恢复初始展开项
|
||||
getTicketDetail()
|
||||
getTicketLog()
|
||||
emit('success')
|
||||
}
|
||||
isOwn.value = false;
|
||||
ticketLog.value = [];
|
||||
getTicketDetail();
|
||||
getTicketLog();
|
||||
emit('success');
|
||||
};
|
||||
|
||||
const getTicketDetail = () => {
|
||||
API.wf.ticket.ticketItem.req(ticketId.value).then(res => {
|
||||
ticketDetail.value = res;
|
||||
const isCreator = res.create_by === currentUser.value
|
||||
if (isCreator) {
|
||||
isOwn.value = true
|
||||
}
|
||||
if (res.create_by === currentUser.value) isOwn.value = true;
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
const getTicketLog = () => {
|
||||
API.wf.ticket.ticketFlowlogs.req(ticketId.value).then(res => {
|
||||
ticketLog.value = res;
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function getColor(item) {
|
||||
if (item.transition_?.attribute_type === 1) return "#67C23A"; // 同意 绿色
|
||||
if (item.transition_?.attribute_type === 2) return "#F56C6C"; // 拒绝 红色
|
||||
return "#909399"; // 默认灰色
|
||||
function kindOf(item) {
|
||||
if (item.transition_?.attribute_type === 1) return "approve";
|
||||
if (item.transition_?.attribute_type === 2) return "reject";
|
||||
return "neutral";
|
||||
}
|
||||
function shortTime(ts) {
|
||||
if (!ts) return "";
|
||||
return ts.length >= 16 ? ts.slice(5, 16) : ts;
|
||||
}
|
||||
|
||||
const dialogVisible = ref(false);
|
||||
|
|
@ -141,13 +193,243 @@ const dialogTitle = ref("意见/原因");
|
|||
const suggestion = ref("");
|
||||
const handleRetreat = () => {
|
||||
dialogTitle.value = "撤回原因";
|
||||
suggestion.value = "";
|
||||
dialogVisible.value = true;
|
||||
};
|
||||
const dialogConfirm = () => {
|
||||
API.wf.ticket.ticketRetreat
|
||||
.req(ticketId.value, {"suggestion": suggestion.value})
|
||||
.then((res) => {
|
||||
refreshTicket();
|
||||
});
|
||||
.req(ticketId.value, { "suggestion": suggestion.value })
|
||||
.then(() => {
|
||||
dialogVisible.value = false;
|
||||
refreshTicket();
|
||||
});
|
||||
};
|
||||
</script>
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.wf-side {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
padding: 6px 4px 12px;
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.wf-side__card {
|
||||
background: var(--el-bg-color);
|
||||
border: 1px solid var(--el-border-color-lighter);
|
||||
border-radius: 10px;
|
||||
padding: 14px 14px 12px;
|
||||
transition: box-shadow 0.2s ease;
|
||||
}
|
||||
.wf-side__card:hover {
|
||||
box-shadow: 0 2px 12px -8px rgba(0, 0, 0, 0.18);
|
||||
}
|
||||
.wf-side__card--history {
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
|
||||
.wf-side__card-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.wf-side__card-bar {
|
||||
width: 3px;
|
||||
height: 14px;
|
||||
border-radius: 2px;
|
||||
background: var(--el-color-primary);
|
||||
}
|
||||
.wf-side__card-title {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: var(--el-text-color-primary);
|
||||
letter-spacing: 0.3px;
|
||||
flex: 1;
|
||||
}
|
||||
.wf-side__count {
|
||||
font-size: 11px;
|
||||
color: var(--el-text-color-secondary);
|
||||
background: var(--el-fill-color);
|
||||
padding: 1px 7px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.wf-side__sn-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-bottom: 10px;
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 1px dashed var(--el-border-color-lighter);
|
||||
}
|
||||
.wf-side__sn-tag {
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
||||
font-size: 11.5px;
|
||||
padding: 2px 8px;
|
||||
background: var(--el-color-primary-light-9);
|
||||
color: var(--el-color-primary);
|
||||
border-radius: 4px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.wf-side__sn-title {
|
||||
font-size: 13px;
|
||||
color: var(--el-text-color-primary);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.wf-side__kv {
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
.wf-side__kv-row {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 10px;
|
||||
font-size: 13px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
.wf-side__kv-row dt {
|
||||
width: 64px;
|
||||
flex-shrink: 0;
|
||||
color: var(--el-text-color-secondary);
|
||||
font-weight: 400;
|
||||
}
|
||||
.wf-side__kv-row dd {
|
||||
margin: 0;
|
||||
color: var(--el-text-color-primary);
|
||||
flex: 1;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.wf-side__participants {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 4px;
|
||||
}
|
||||
.wf-side__chip {
|
||||
display: inline-block;
|
||||
padding: 1px 8px;
|
||||
font-size: 12px;
|
||||
background: var(--el-fill-color);
|
||||
color: var(--el-text-color-regular);
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.wf-side__actions {
|
||||
margin-top: 10px;
|
||||
padding-top: 10px;
|
||||
border-top: 1px dashed var(--el-border-color-lighter);
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
/* ===== 时间线 ===== */
|
||||
.wf-side__timeline {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.wf-side__tl-item {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
position: relative;
|
||||
}
|
||||
.wf-side__tl-rail {
|
||||
position: relative;
|
||||
width: 12px;
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding-top: 6px;
|
||||
}
|
||||
.wf-side__tl-dot {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 50%;
|
||||
background: var(--el-color-info);
|
||||
box-shadow: 0 0 0 3px var(--el-fill-color);
|
||||
z-index: 1;
|
||||
}
|
||||
.wf-side__tl-line {
|
||||
flex: 1;
|
||||
width: 2px;
|
||||
background: var(--el-border-color-lighter);
|
||||
margin-top: 2px;
|
||||
}
|
||||
.wf-side__tl-item.is-approve .wf-side__tl-dot {
|
||||
background: var(--el-color-success);
|
||||
box-shadow: 0 0 0 3px var(--el-color-success-light-9);
|
||||
}
|
||||
.wf-side__tl-item.is-reject .wf-side__tl-dot {
|
||||
background: var(--el-color-danger);
|
||||
box-shadow: 0 0 0 3px var(--el-color-danger-light-9);
|
||||
}
|
||||
|
||||
.wf-side__tl-body {
|
||||
flex: 1;
|
||||
padding-bottom: 14px;
|
||||
min-width: 0;
|
||||
}
|
||||
.wf-side__tl-head {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.wf-side__tl-state {
|
||||
font-size: 13px;
|
||||
color: var(--el-text-color-primary);
|
||||
font-weight: 600;
|
||||
}
|
||||
.wf-side__tl-time {
|
||||
font-size: 11.5px;
|
||||
color: var(--el-text-color-placeholder);
|
||||
font-variant-numeric: tabular-nums;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.wf-side__tl-meta {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
font-size: 12px;
|
||||
color: var(--el-text-color-regular);
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.wf-side__tl-transition {
|
||||
font-weight: 500;
|
||||
}
|
||||
.wf-side__tl-transition.is-approve { color: var(--el-color-success); }
|
||||
.wf-side__tl-transition.is-reject { color: var(--el-color-danger); }
|
||||
.wf-side__tl-user {
|
||||
color: var(--el-text-color-secondary);
|
||||
}
|
||||
.wf-side__tl-suggestion {
|
||||
background: var(--el-fill-color-light);
|
||||
border-left: 2px solid var(--el-border-color);
|
||||
padding: 5px 8px;
|
||||
border-radius: 0 6px 6px 0;
|
||||
font-size: 12px;
|
||||
color: var(--el-text-color-regular);
|
||||
line-height: 1.5;
|
||||
margin-top: 4px;
|
||||
}
|
||||
.wf-side__tl-item.is-approve .wf-side__tl-suggestion {
|
||||
border-left-color: var(--el-color-success);
|
||||
background: var(--el-color-success-light-9);
|
||||
}
|
||||
.wf-side__tl-item.is-reject .wf-side__tl-suggestion {
|
||||
border-left-color: var(--el-color-danger);
|
||||
background: var(--el-color-danger-light-9);
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
Loading…
Reference in New Issue