lion 1 month ago
commit efe83f773a

@ -340,6 +340,15 @@ export function getRelationList(flowId, isLoading = false) {
})
}
export function getRelationMeetingMinuteOptions(params, isLoading = false) {
return request({
method: 'get',
url: '/api/oa/flow/relation-meeting-minute-options',
params,
isLoading
})
}
// 打捞流程至付款流程
export function salvageFlow(flowId, isLoading = true) {
return request({

@ -260,8 +260,49 @@
</el-tree>
</div>
<div v-if="tradeUnionTree.length" class="tree-block" style="margin-top: 16px">
<div class="tree-title">工会</div>
<el-tree
ref="tradeUnionTreeRef"
:data="tradeUnionTree"
node-key="id"
:props="treeProps"
highlight-current
default-expand-all
:expand-on-click-node="false"
show-checkbox
check-strictly
:check-on-click-node="false"
@check-change="onTreeCheckChange"
@node-click="onNodeClickToggle"
>
<span class="custom-tree-node" slot-scope="{ node, data }">
<span class="node-label" :class="{ 'node-label--clickable': data.is_leaf }" @click.stop="onLabelClick(data, node, $refs.tradeUnionTreeRef)">{{ node.label }}</span>
<span v-if="data.is_leaf" class="node-usage-info">
<span class="usage-item">
<span class="usage-label">预算:</span>
<span class="usage-value">{{ formatAmount(data.budget_amount) }}</span>
</span>
<span class="usage-item">
<span class="usage-label">已用:</span>
<span class="usage-value usage-value--used">{{ formatAmount(data.used_amount || 0) }}</span>
</span>
<span class="usage-item">
<span class="usage-label">执行率:</span>
<span
class="usage-value usage-value--rate"
:class="getExecutionRateClass(data.execution_rate || 0)"
>
{{ formatExecutionRate(data.execution_rate || 0) }}
</span>
</span>
</span>
</span>
</el-tree>
</div>
<div
v-if="!treeLoading && departmentTree.length === 0 && projectTree.length === 0 && specialFundTree.length === 0 && lastYearCarryoverTree.length === 0 && offsetPrepaidTree.length === 0"
v-if="!treeLoading && departmentTree.length === 0 && projectTree.length === 0 && specialFundTree.length === 0 && lastYearCarryoverTree.length === 0 && offsetPrepaidTree.length === 0 && tradeUnionTree.length === 0"
style="text-align: center; color: #909399; padding: 32px 0"
>
暂无数据
@ -506,6 +547,9 @@ export default {
offsetPrepaidTree() {
return (this.treeData || []).filter((n) => n?.budget_type === "offset_prepaid");
},
tradeUnionTree() {
return (this.treeData || []).filter((n) => n?.budget_type === "trade_union");
},
budgetTypeMap() {
return {
department: "部门预算",
@ -513,6 +557,7 @@ export default {
special_fund: "专项资金",
last_year_carryover: "上一年结转资金",
offset_prepaid: "抵消预付账款",
trade_union: "工会",
};
},
//
@ -670,6 +715,7 @@ export default {
this.$refs.specialFundTreeRef,
this.$refs.lastYearCarryoverTreeRef,
this.$refs.offsetPrepaidTreeRef,
this.$refs.tradeUnionTreeRef,
].filter(Boolean);
const nodes = [];
refs.forEach((tree) => {
@ -693,6 +739,7 @@ export default {
this.$refs.specialFundTreeRef,
this.$refs.lastYearCarryoverTreeRef,
this.$refs.offsetPrepaidTreeRef,
this.$refs.tradeUnionTreeRef,
].filter(Boolean);
refs.forEach((tree) => {
if (typeof tree.setCheckedKeys === "function") {

@ -503,8 +503,8 @@ export default {
//
initRules() {
//
const baseRules = {
contract_no_without_prefix: [{ required: true, message: "请填写合同编号", trigger: "blur" }],
//
const baseRulesCommon = {
title: [{ required: true, message: "请填写合同名称", trigger: "blur" }],
main_content: [{ required: true, message: "请填写合同主要内容", trigger: "blur" }],
party_a: [{ required: true, message: "请填写甲方", trigger: "blur" }],
@ -547,10 +547,18 @@ export default {
//
if (!this.isEditMode()) {
this.rules = baseRules;
this.rules = {
...baseRulesCommon,
};
return;
}
//
const baseRules = {
contract_no_without_prefix: [{ required: true, message: "请填写合同编号", trigger: "blur" }],
...baseRulesCommon,
};
//
this.rules = {
...baseRules,

@ -1,5 +1,13 @@
import store from '@/store'
import moment from 'moment'
function sanitizePrintFieldHtml(html) {
const wrapper = document.createElement('div')
wrapper.innerHTML = html || ''
wrapper.querySelectorAll('input[type="file"], .el-upload__input').forEach(el => el.remove())
return wrapper.innerHTML
}
/**
* @param{string} printJs 打印模版
* @param{boolean} isLog 是否带审批
@ -78,7 +86,7 @@ export async function print(printJs, isLog, form, logContent) {
printStr = printStr.replace(fieldMath,subFormBody)
// console.log(fieldMath, printStr)
} else {
printStr = printStr.replace(fieldMath,`<span>${value}</span>`)
printStr = printStr.replace(fieldMath,`<span>${sanitizePrintFieldHtml(value)}</span>`)
}
}
} else {

@ -99,15 +99,18 @@
<el-option
v-for="flow in availableFlows"
:key="flow.id"
:label="(flow.title || flow.no || ('流程' + flow.id)) + ' (' + (flow.no || '') + ')'"
:label="(flow.title || flow.no || ('流程' + flow.id)) + (flow.meeting_minutes_count > 0 ? ' 【已关联 ' + flow.meeting_minutes_count + ' 次】' : '') + ' (' + (flow.no || '') + ')'"
:value="flow.id"
>
<span style="float: left">{{ flow.title || flow.no || ('流程' + flow.id) }}</span>
<span style="float: left">
{{ flow.title || flow.no || ('流程' + flow.id) }}
<span v-if="flow.meeting_minutes_count > 0" style="margin-left: 4px; color: #333;"> {{ flow.meeting_minutes_count }} </span>
</span>
<span style="float: right; color: #8492a6; font-size: 13px">{{ flow.no || '' }}</span>
</el-option>
</el-select>
<div style="margin-top: 8px; color: #909399; font-size: 12px;">
提示可以关联多个上会审议审批流程
提示可以关联多个上会审议审批流程同一条流程可被多个会议纪要关联
</div>
</el-form-item>
<el-form-item label="附件上传" prop="files">
@ -140,7 +143,7 @@
placeholder="请选择类型"
style="width: 100%;"
>
<el-option label="""" value=""""></el-option>
<el-option label="“三重一大”事项" value="“三重一大”事项"></el-option>
<el-option label="资金申请" value="资金申请"></el-option>
<el-option label="资金支付" value="资金支付"></el-option>
<el-option label="其他" value="其他"></el-option>
@ -315,12 +318,7 @@ export default {
return //
}
try {
const params = {}
// ID
if (this.type === 'edit' && this.form.id) {
params.meeting_minute_id = this.form.id
}
const res = await getFlows(params)
const res = await getFlows({})
this.availableFlows = res || []
} catch (err) {
console.error('加载流程列表失败:', err)

@ -507,7 +507,8 @@ export default {
try {
await this.getFlows();
const res = await getInfo()
this.usualFlows = res.quick_enter?res.quick_enter:[]
const quickEnterIds = this.normalizeQuickEnter(res.quick_enter)
this.usualFlows = this.flows.filter(flow => quickEnterIds.includes(Number(flow.id)))
// const res = await configIndex({
// filter: [
// {
@ -533,16 +534,27 @@ export default {
console.error(err);
}
},
normalizeQuickEnter(quickEnter) {
if (!quickEnter) return []
if (!Array.isArray(quickEnter)) return []
return quickEnter.map(item => {
if (item && typeof item === 'object') {
return Number(item.id)
}
return Number(item)
}).filter(id => Number.isInteger(id) && id > 0)
},
openQucik(){
const quickEnterIds = this.normalizeQuickEnter(this.usualFlows)
this.flows.map(flow => {
const isChecked = this.usualFlows.some(usualFlow => usualFlow.id === flow.id);
const isChecked = quickEnterIds.includes(Number(flow.id));
flow.checked = isChecked
});
this.isShowQuick = true
},
updatequick(){
this.quickLoading = true
let arr = this.flows.filter((i)=> i.checked===true)
let arr = this.flows.filter((i)=> i.checked===true).map(i => Number(i.id))
saveMyself({
quick_enter:arr
}).then(res=>{

@ -23,8 +23,20 @@
<!-- 搜索区域 -->
<div class="search-area" v-show="!collapsed && !readonly" @click.stop>
<el-row :gutter="10">
<el-col :span="4">
<el-select
v-model="relationCategory"
placeholder="关联类别"
style="width: 100%"
@change="handleCategoryChange"
>
<el-option label="流程" value="flow"></el-option>
<el-option label="会议纪要" value="meetingMinute"></el-option>
</el-select>
</el-col>
<el-col :span="6">
<el-select
v-if="relationCategory === 'flow'"
v-model="searchForm.custom_model_id"
placeholder="流程类型"
clearable
@ -46,7 +58,7 @@
<el-col :span="10">
<el-input
v-model="searchForm.keyword"
placeholder="输入标题或编号搜索"
:placeholder="relationCategory === 'flow' ? '输入标题或编号搜索' : '输入会议纪要标题搜索'"
clearable
@keyup.enter.native="handleSearch"
>
@ -63,24 +75,53 @@
<div class="selected-flows" v-show="!collapsed && selectedFlows.length > 0">
<div class="selected-title">已关联的流程{{ selectedFlows.length }}</div>
<div class="selected-list">
<el-tag
v-for="flow in selectedFlows"
:key="flow.id"
:closable="!readonly"
@close="handleRemove(flow.id)"
@click="handleViewFlow(flow)"
class="flow-tag"
type="info"
effect="plain"
>
<span class="flow-title">{{ flow.title }}</span>
<span class="flow-meta">{{ flow.no }}</span>
</el-tag>
<div v-for="flow in selectedFlows" :key="flow.id" class="selected-flow-block">
<el-tag
:closable="!readonly"
@close="handleRemove(flow.id)"
@click="handleViewFlow(flow)"
class="flow-tag"
type="info"
effect="plain"
>
<span class="flow-title">{{ flow.title }}</span>
<span class="flow-meta">{{ flow.no }}</span>
</el-tag>
<div v-if="flow.meeting_minutes && flow.meeting_minutes.length" class="flow-meeting-minutes">
<span class="mm-label">会议纪要</span>
<span v-for="(mm, idx) in (flow.meeting_minutes || [])" :key="mm.id" class="mm-link-wrap">
<el-link type="primary" size="mini" @click.stop="$emit('open-meeting-minute', mm.id)">{{ mm.title }}</el-link>
<span v-if="idx < (flow.meeting_minutes.length - 1)" class="mm-sep"></span>
</span>
</div>
</div>
</div>
</div>
<div class="selected-flows" v-show="!collapsed && selectedMeetingMinutes.length > 0">
<div class="selected-title">已关联的会议纪要{{ selectedMeetingMinutes.length }}</div>
<div class="selected-list">
<div v-for="item in selectedMeetingMinutes" :key="`mm-${item.id}`" class="selected-flow-block">
<el-tag
:closable="!readonly"
@close="handleRemoveMeetingMinute(item.id)"
@click.native.stop="$emit('open-meeting-minute', item.id)"
class="flow-tag"
type="warning"
effect="plain"
>
<span class="flow-title">{{ item.title || ('会议纪要' + item.id) }}</span>
</el-tag>
<div class="flow-meeting-minutes">
<span class="mm-label">创建时间</span>
<span>{{ formatDate(item.created_at) }}</span>
</div>
</div>
</div>
</div>
<!-- 可选流程列表 -->
<div class="available-flows" v-show="!collapsed && !readonly">
<div class="available-flows" v-show="!collapsed && !readonly && relationCategory === 'flow'">
<div class="available-title">可选流程</div>
<div v-loading="loading" class="flow-list">
<el-empty v-if="!loading && availableFlows.length === 0" description="暂无可用流程"></el-empty>
@ -104,6 +145,13 @@
<span class="flow-creator">发起人{{ flow.creator_name }}</span>
<span class="flow-date">{{ formatDate(flow.created_at) }}</span>
</div>
<div v-if="flow.meeting_minutes && flow.meeting_minutes.length" class="flow-meeting-minutes">
<span class="mm-label">会议纪要</span>
<span v-for="(mm, idx) in (flow.meeting_minutes || [])" :key="mm.id" class="mm-link-wrap">
<el-link type="primary" size="mini" @click.stop="$emit('open-meeting-minute', mm.id)">{{ mm.title }}</el-link>
<span v-if="idx < (flow.meeting_minutes.length - 1)" class="mm-sep"></span>
</span>
</div>
</div>
<div class="flow-actions">
<el-button
@ -147,38 +195,123 @@
</div>
</div>
<div class="available-flows" v-show="!collapsed && !readonly && relationCategory === 'meetingMinute'">
<div class="available-title">可选会议纪要</div>
<div v-loading="loading" class="flow-list">
<el-empty v-if="!loading && availableMeetingMinutes.length === 0" description="暂无可用会议纪要"></el-empty>
<div
v-for="item in availableMeetingMinutes"
:key="`meeting-minute-${item.id}`"
class="flow-item"
:class="{ 'is-selected': isMeetingMinuteSelected(item.id) }"
@click="handleToggleMeetingMinute(item)"
>
<div class="flow-content">
<div class="flow-header">
<span class="flow-title-text">{{ item.title || ('会议纪要' + item.id) }}</span>
<el-tag size="mini" type="warning">会议纪要</el-tag>
</div>
<div class="flow-info">
<span class="flow-no">ID{{ item.id }}</span>
<span class="flow-date">{{ formatDate(item.created_at) }}</span>
</div>
</div>
<div class="flow-actions">
<el-button
size="mini"
type="text"
icon="el-icon-view"
@click.stop="$emit('open-meeting-minute', item.id)"
>
查看
</el-button>
<el-button
v-if="!isMeetingMinuteSelected(item.id)"
size="mini"
type="primary"
@click.stop="handleToggleMeetingMinute(item)"
>
关联
</el-button>
<el-button
v-else
size="mini"
type="danger"
@click.stop="handleToggleMeetingMinute(item)"
>
取消
</el-button>
</div>
</div>
</div>
<div class="pagination" v-if="meetingMinutePagination.total > 0">
<el-pagination
@current-change="handleMeetingMinutePageChange"
:current-page="meetingMinutePagination.page"
:page-size="meetingMinutePagination.page_size"
:total="meetingMinutePagination.total"
layout="total, prev, pager, next"
small
></el-pagination>
</div>
</div>
<!-- 只读模式显示关联流程 -->
<div class="readonly-flows" v-show="readonly">
<div v-if="relatedFlows.length > 0" class="related-section">
<div class="section-title">关联的流程{{ relatedFlows.length }}</div>
<div class="related-list">
<div
v-for="flow in relatedFlows"
:key="flow.id"
class="related-item"
@click="handleViewFlow(flow)"
>
<span class="flow-title-text">{{ flow.title }}</span>
<span class="flow-meta">{{ flow.no }} - {{ flow.custom_model_name }}</span>
<div v-for="flow in relatedFlows" :key="flow.id" class="related-item">
<div class="related-item-flow" @click="handleViewFlow(flow)">
<span class="flow-title-text">{{ flow.title }}</span>
<span class="flow-meta">{{ flow.no }} - {{ flow.custom_model_name }}</span>
</div>
<div v-if="flow.meeting_minutes && flow.meeting_minutes.length" class="related-item-meeting-minutes">
<span class="mm-label">会议纪要</span>
<span
v-for="mm in (flow.meeting_minutes || [])"
:key="mm.id"
class="mm-block"
@click="$emit('open-meeting-minute', mm.id)"
>{{ mm.title }}</span>
</div>
</div>
</div>
</div>
<div v-if="relatedByFlows.length > 0" class="related-section">
<div class="section-title">被关联的流程{{ relatedByFlows.length }}</div>
<div class="related-list">
<div
v-for="flow in relatedByFlows"
:key="flow.id"
class="related-item"
@click="handleViewFlow(flow)"
>
<span class="flow-title-text">{{ flow.title }}</span>
<span class="flow-meta">{{ flow.no }} - {{ flow.custom_model_name }}</span>
<div v-for="flow in relatedByFlows" :key="flow.id" class="related-item">
<div class="related-item-flow" @click="handleViewFlow(flow)">
<span class="flow-title-text">{{ flow.title }}</span>
<span class="flow-meta">{{ flow.no }} - {{ flow.custom_model_name }}</span>
</div>
<div v-if="flow.meeting_minutes && flow.meeting_minutes.length" class="related-item-meeting-minutes">
<span class="mm-label">会议纪要</span>
<span
v-for="mm in (flow.meeting_minutes || [])"
:key="mm.id"
class="mm-block"
@click="$emit('open-meeting-minute', mm.id)"
>{{ mm.title }}</span>
</div>
</div>
</div>
</div>
<div v-if="relatedMeetingMinutes.length > 0" class="related-section">
<div class="section-title">关联的会议纪要{{ relatedMeetingMinutes.length }}</div>
<div class="related-list">
<div v-for="item in relatedMeetingMinutes" :key="`readonly-mm-${item.id}`" class="related-item">
<div class="related-item-flow" @click="$emit('open-meeting-minute', item.id)">
<span class="flow-title-text">{{ item.title || ('会议纪要' + item.id) }}</span>
<span class="flow-meta">ID: {{ item.id }}</span>
</div>
</div>
</div>
</div>
<div v-if="readonly && relatedFlows.length === 0 && relatedByFlows.length === 0" class="empty-tip">
<span class="empty-text">暂无关联流程</span>
<div v-if="readonly && relatedFlows.length === 0 && relatedByFlows.length === 0 && relatedMeetingMinutes.length === 0" class="empty-tip">
<span class="empty-text">暂无关联</span>
</div>
</div>
</el-card>
@ -202,7 +335,7 @@
</template>
<script>
import { getRelationOptions, getRelationList, flowList, flow as flowIndex } from '@/api/flow'
import { getRelationMeetingMinuteOptions, getRelationOptions, getRelationList, flowList, flow as flowIndex } from '@/api/flow'
import { getToken } from '@/utils/auth'
import moment from 'moment'
@ -221,6 +354,10 @@ export default {
type: [Number, String],
default: null
},
meetingMinuteValue: {
type: [String, Array],
default: () => []
},
collapsible: {
type: Boolean,
default: true
@ -230,20 +367,29 @@ export default {
return {
collapsed: this.readonly ? false : true, // readonly
loading: false,
relationCategory: 'flow',
searchForm: {
keyword: '',
custom_model_id: ''
},
availableFlows: [],
availableMeetingMinutes: [],
selectedFlows: [],
selectedMeetingMinutes: [],
relatedFlows: [],
relatedByFlows: [],
relatedMeetingMinutes: [],
customModels: [],
pagination: {
page: 1,
page_size: 20,
total: 0
},
meetingMinutePagination: {
page: 1,
page_size: 20,
total: 0
},
showFlowDetail: false,
currentFlow: null,
flowDetailUrl: ''
@ -264,6 +410,19 @@ export default {
}
}
},
meetingMinuteValue: {
immediate: true,
handler(newVal) {
if (newVal) {
const ids = Array.isArray(newVal) ? newVal : newVal.toString().split(',').filter(Boolean).map(Number)
if (ids.length > 0 && this.selectedMeetingMinutes.length === 0) {
this.loadSelectedMeetingMinutes(ids)
}
} else {
this.selectedMeetingMinutes = []
}
}
},
readonly: {
immediate: true,
handler(newVal) {
@ -296,7 +455,17 @@ export default {
mounted() {
this.loadCustomModels()
},
methods: {
methods: {
handleCategoryChange() {
this.searchForm.keyword = ''
this.searchForm.custom_model_id = ''
this.pagination.page = 1
this.meetingMinutePagination.page = 1
if (this.collapsed) {
return
}
this.handleSearch()
},
handleToggleCollapse(e) {
if (e) {
e.stopPropagation()
@ -321,10 +490,10 @@ export default {
const res = await flowList('all', { page: 1, page_size: 1, is_simple: 1 })
// customModels res res.data
if (res.customModels && res.customModels.length > 0) {
this.customModels = res.customModels
this.customModels = (res.customModels || []).filter(model => !model.url)
return
} else if (res.data && res.data.customModels) {
this.customModels = res.data.customModels
this.customModels = (res.data.customModels || []).filter(model => !model.url)
return
}
} catch (err) {
@ -343,7 +512,7 @@ export default {
models.push(...cate.customerModels)
}
})
this.customModels = models.map(m => ({ id: m.id, name: m.name }))
this.customModels = models.filter(m => !m.url).map(m => ({ id: m.id, name: m.name, url: m.url }))
}
} catch (e) {
console.error('备用加载流程类型失败', e)
@ -351,6 +520,9 @@ export default {
}
},
async handleSearch() {
if (this.relationCategory === 'meetingMinute') {
return this.handleMeetingMinuteSearch()
}
this.loading = true
try {
const params = {
@ -397,13 +569,48 @@ export default {
status_text: this.getStatusText(flow.status),
created_by: flow.created_by,
creator_name: flow.creator ? flow.creator.name : (flow.creator_name || ''),
created_at: flow.created_at
created_at: flow.created_at,
meeting_minutes: flow.meeting_minutes || []
}))
}
} catch (err) {
console.error('加载已选流程失败', err)
}
},
async handleMeetingMinuteSearch() {
this.loading = true
try {
const res = await getRelationMeetingMinuteOptions({
page: this.meetingMinutePagination.page,
page_size: this.meetingMinutePagination.page_size,
keyword: this.searchForm.keyword
})
if (res) {
this.availableMeetingMinutes = res.data || []
this.meetingMinutePagination.total = res.total || 0
this.meetingMinutePagination.page = res.page || 1
this.meetingMinutePagination.page_size = res.page_size || 20
}
} catch (err) {
this.$message.error('搜索失败:' + (err.message || '未知错误'))
} finally {
this.loading = false
}
},
async loadSelectedMeetingMinutes(ids) {
if (!ids || ids.length === 0) {
this.selectedMeetingMinutes = []
return
}
try {
const res = await getRelationMeetingMinuteOptions({
ids: ids.join(',')
})
this.selectedMeetingMinutes = res.data || []
} catch (err) {
console.error('加载已选会议纪要失败', err)
}
},
async loadRelationList() {
if (!this.flowId) return
try {
@ -412,6 +619,7 @@ export default {
if (res) {
this.relatedFlows = res.related_flows || []
this.relatedByFlows = res.related_by_flows || []
this.relatedMeetingMinutes = res.related_meeting_minutes || []
}
} catch (err) {
console.error('加载关联列表失败', err)
@ -433,18 +641,42 @@ export default {
this.selectedFlows = this.selectedFlows.filter(f => f.id !== flowId)
this.updateValue()
},
handleToggleMeetingMinute(item) {
if (this.isMeetingMinuteSelected(item.id)) {
this.handleRemoveMeetingMinute(item.id)
} else {
this.selectedMeetingMinutes.push(item)
this.updateMeetingMinuteValue()
}
},
handleRemoveMeetingMinute(id) {
this.selectedMeetingMinutes = this.selectedMeetingMinutes.filter(item => item.id !== id)
this.updateMeetingMinuteValue()
},
isSelected(flowId) {
return this.selectedFlows.some(f => f.id === flowId)
},
isMeetingMinuteSelected(id) {
return this.selectedMeetingMinutes.some(item => item.id === id)
},
updateValue() {
const ids = this.selectedFlows.map(f => f.id)
this.$emit('input', ids.join(','))
this.$emit('change', ids)
},
updateMeetingMinuteValue() {
const ids = this.selectedMeetingMinutes.map(item => item.id)
this.$emit('update:meetingMinuteValue', ids.join(','))
this.$emit('meeting-minute-change', ids)
},
handlePageChange(page) {
this.pagination.page = page
this.handleSearch()
},
handleMeetingMinutePageChange(page) {
this.meetingMinutePagination.page = page
this.handleMeetingMinuteSearch()
},
handleViewFlow(flow) {
this.currentFlow = flow
const baseUrl = process.env.VUE_APP_BASE_API || ''
@ -536,6 +768,13 @@ export default {
flex-wrap: wrap;
gap: 8px;
.selected-flow-block {
display: inline-flex;
flex-direction: column;
align-items: flex-start;
gap: 4px;
}
.flow-tag {
cursor: pointer;
padding: 5px 10px;
@ -554,6 +793,36 @@ export default {
background-color: #ecf5ff;
}
}
.flow-meeting-minutes {
font-size: 12px;
color: #606266;
padding-left: 4px;
.mm-label {
color: #909399;
margin-right: 2px;
}
.mm-sep {
margin: 0 2px;
color: #909399;
}
}
}
}
.flow-meeting-minutes {
font-size: 12px;
color: #606266;
margin-top: 6px;
.mm-label {
color: #909399;
margin-right: 4px;
}
.mm-sep {
margin: 0 2px;
color: #909399;
}
}
@ -644,26 +913,63 @@ export default {
.related-list {
.related-item {
padding: 8px 12px;
padding: 10px 12px;
margin-bottom: 8px;
background: #f5f7fa;
border-radius: 4px;
cursor: pointer;
transition: all 0.3s;
&:hover {
background: #ecf5ff;
}
.related-item-flow {
display: block;
padding: 6px 10px;
margin: -4px -6px 8px -6px;
border-radius: 4px;
cursor: pointer;
transition: background 0.2s;
.flow-title-text {
color: #409eff;
font-weight: 500;
&:hover {
background: #ecf5ff;
}
.flow-title-text {
color: #409eff;
font-weight: 500;
}
.flow-meta {
color: #909399;
font-size: 12px;
margin-left: 8px;
}
}
.flow-meta {
color: #909399;
font-size: 12px;
margin-left: 8px;
.related-item-meeting-minutes {
margin-top: 4px;
.mm-label {
display: inline-block;
color: #909399;
font-size: 12px;
margin-right: 8px;
vertical-align: middle;
}
.mm-block {
display: inline-block;
padding: 4px 10px;
margin: 2px 6px 2px 0;
color: #409eff;
font-size: 13px;
background: #ecf5ff;
border-radius: 4px;
cursor: pointer;
transition: all 0.2s;
&:hover {
background: #d9ecff;
color: #66b1ff;
}
}
}
}
}
@ -698,4 +1004,3 @@ export default {
}
}
</style>

@ -19,10 +19,12 @@
<!-- 关联流程组件 -->
<RelatedFlows
v-model="form.related_flow_ids"
:meeting-minute-value.sync="form.related_meeting_minute_ids"
:readonly="/\/detail/.test($route.path) || (!!$route.query.flow_id && !isFirstNode)"
:flow-id="$route.query.flow_id"
:collapsible="(!/\/detail/.test($route.path)) && (!$route.query.flow_id || isFirstNode)"
style="margin-bottom: 20px;"
@open-meeting-minute="openMeetingMinutesDrawer"
></RelatedFlows>
<!-- 关联的支付信息查看/办理只要有 flow_id 就展示没数据时展示空态 -->
@ -136,16 +138,20 @@
</div>
</div>
<!-- 会议纪要点击抽屉查看 -->
<!-- 会议纪要点击抽屉查看一对多多条链接 -->
<div v-else-if="el.type === 'meeting_minutes'">
<el-link
v-if="extractMeetingMinuteId(getPaymentTemplateElementValue(el, payment))"
type="primary"
:underline="false"
@click="openMeetingMinutesDrawer(extractMeetingMinuteId(getPaymentTemplateElementValue(el, payment)))"
>
{{ (getPaymentTemplateElementValue(el, payment) && getPaymentTemplateElementValue(el, payment).title) ? getPaymentTemplateElementValue(el, payment).title : '查看会议纪要' }}
</el-link>
<template v-if="getPaymentMeetingMinutesList(el, payment).length">
<span v-for="(item, idx) in getPaymentMeetingMinutesList(el, payment)" :key="item.id">
<el-link
type="primary"
:underline="false"
@click="openMeetingMinutesDrawer(item.id)"
>
{{ item.title || '查看会议纪要' }}
</el-link>
<span v-if="idx < getPaymentMeetingMinutesList(el, payment).length - 1"></span>
</span>
</template>
<span v-else>-</span>
</div>
@ -305,16 +311,20 @@
<span v-if="getPlannedFileItems(expId, f).length === 0">-</span>
</template>
<!-- meeting_minutes点击抽屉查看 -->
<!-- meeting_minutes点击抽屉查看一对多多条链接 -->
<template v-else-if="f.element_type === 'meeting_minutes'">
<el-link
v-if="extractMeetingMinuteId(getIndirectFieldValue(expId, getTplFieldKey(f)))"
type="primary"
:underline="false"
@click="openMeetingMinutesDrawer(extractMeetingMinuteId(getIndirectFieldValue(expId, getTplFieldKey(f))))"
>
查看会议纪要
</el-link>
<template v-if="getIndirectMeetingMinutesList(expId, getTplFieldKey(f)).length">
<span v-for="(item, idx) in getIndirectMeetingMinutesList(expId, getTplFieldKey(f))" :key="item.id">
<el-link
type="primary"
:underline="false"
@click="openMeetingMinutesDrawer(item.id)"
>
{{ item.title || '查看会议纪要' }}
</el-link>
<span v-if="idx < getIndirectMeetingMinutesList(expId, getTplFieldKey(f)).length - 1"></span>
</span>
</template>
<span v-else>-</span>
</template>
@ -392,7 +402,24 @@
<!-- 合同基本信息 -->
<el-descriptions v-if="contractDetail" :column="2" border size="small" style="margin-bottom: 12px;">
<el-descriptions-item label="合同编号">
{{ contractDetail.contract_no || '-' }}
<template v-if="contractDetail.id">
<el-link
type="primary"
:underline="false"
@click="openContractDrawer(contractDetail.id, contractDetail.title || contractDetail.contract_no)"
>
{{ contractDetail.contract_no || '-' }}
</el-link>
<el-link
type="primary"
:underline="false"
style="margin-left: 8px;"
@click="openContractDrawer(contractDetail.id, contractDetail.title || contractDetail.contract_no)"
>
查看详情
</el-link>
</template>
<span v-else>{{ contractDetail.contract_no || '-' }}</span>
</el-descriptions-item>
<el-descriptions-item label="合同名称">
{{ contractDetail.title || '-' }}
@ -770,8 +797,9 @@
:visible.sync="rightDrawerVisible"
:title="rightDrawerTitle"
direction="rtl"
size="60%"
:size="$store.getters.device === 'mobile' ? '100%' : (rightDrawerType === 'contract' ? '78%' : '60%')"
:with-header="true"
custom-class="flow-detail-drawer"
>
<!-- 流程详情iframe -->
<div v-if="rightDrawerType === 'flow'" style="width: 100%; height: 100%;">
@ -782,33 +810,196 @@
/>
</div>
<!-- 会议纪要请求数据展示 -->
<!-- 会议纪要请求数据展示与会议纪要管理查看模式字段顺序一致 -->
<div v-else-if="rightDrawerType === 'meetingMinutes'" v-loading="loadingMeetingMinutes">
<div v-if="meetingMinutesDetail">
<el-descriptions :column="1" border>
<el-descriptions-item label="标题">
{{ meetingMinutesDetail.title || '-' }}
<el-descriptions-item label="会议纪要标题">
<span style="font-weight: 500;">{{ meetingMinutesDetail.title || '-' }}</span>
</el-descriptions-item>
<el-descriptions-item label="内容清单">
<div v-if="meetingMinutesDetail.items && meetingMinutesDetail.items.length">
<div v-for="(it, idx) in meetingMinutesDetail.items" :key="idx" style="margin-bottom: 8px;">
<span style="color:#409EFF;">{{ it.type || '类型' }}</span>
<span>{{ it.content || '-' }}</span>
<el-descriptions-item label="关联上会审议流程">
<div v-if="meetingMinutesDetail.flows && meetingMinutesDetail.flows.length">
<el-tag
v-for="flow in meetingMinutesDetail.flows"
:key="flow.id"
type="info"
style="margin-right: 8px; margin-bottom: 4px;"
>
{{ flow.title || flow.no || ('流程' + flow.id) }}
<span v-if="flow.no" style="color: #909399; margin-left: 4px;">({{ flow.no }})</span>
</el-tag>
</div>
<span v-else style="color: #909399;">未关联</span>
</el-descriptions-item>
<el-descriptions-item label="附件">
<div v-if="meetingMinutesDetail.files_details && meetingMinutesDetail.files_details.length">
<div v-for="(f, idx) in meetingMinutesDetail.files_details" :key="idx" style="margin-bottom: 8px;">
<el-link type="primary" :underline="false" :href="f.url" target="_blank" style="margin-right: 10px;">
<i class="el-icon-view"></i> {{ f.original_name || f.name || '附件' }}
</el-link>
<el-link type="primary" :underline="false" :href="f.url" target="_blank" download>
<i class="el-icon-download"></i> 下载
</el-link>
</div>
</div>
<span v-else></span>
<span v-else style="color: #909399;">无附件</span>
</el-descriptions-item>
<el-descriptions-item label="附件" v-if="meetingMinutesDetail.files_details && meetingMinutesDetail.files_details.length">
<div v-for="(f, idx) in meetingMinutesDetail.files_details" :key="idx" style="margin-bottom: 6px;">
<el-link type="primary" :underline="false" :href="f.url" target="_blank">
{{ f.original_name || f.name || '附件' }}
</el-link>
<el-descriptions-item label="内容清单">
<div v-if="meetingMinutesDetail.items && meetingMinutesDetail.items.length">
<div
v-for="(it, idx) in meetingMinutesDetail.items"
:key="idx"
style="margin-bottom: 12px; padding: 12px; background-color: #f5f7fa; border-radius: 4px;"
>
<div style="margin-bottom: 4px;">
<el-tag size="small" type="primary">{{ it.type || '未分类' }}</el-tag>
</div>
<div style="color: #606266; line-height: 1.6;">{{ it.content || '-' }}</div>
</div>
</div>
<span v-else style="color: #909399;">无内容清单</span>
</el-descriptions-item>
</el-descriptions>
</div>
<div v-else style="color:#909399;">未获取到会议纪要数据</div>
</div>
<!-- 合同详情请求数据展示 -->
<div v-else-if="rightDrawerType === 'contract'" v-loading="loadingContractDrawer">
<div v-if="contractDrawerDetail">
<div class="contract-drawer">
<el-descriptions :column="2" border class="contract-drawer-descriptions">
<el-descriptions-item label="合同编号">
{{ contractDrawerDetail.contract_no || '-' }}
</el-descriptions-item>
<el-descriptions-item label="合同名称">
{{ contractDrawerDetail.title || '-' }}
</el-descriptions-item>
<el-descriptions-item label="合同主要内容" :span="2">
{{ contractDrawerDetail.main_content || '-' }}
</el-descriptions-item>
<el-descriptions-item label="甲方">
{{ contractDrawerDetail.party_a || '-' }}
</el-descriptions-item>
<el-descriptions-item label="乙方">
{{ contractDrawerDetail.party_b || '-' }}
</el-descriptions-item>
<el-descriptions-item label="合同金额(元)">
{{ formatAmount(contractDrawerDetail.amount_total) }}
</el-descriptions-item>
<el-descriptions-item label="项目预算金额(元)">
{{ formatAmount(contractDrawerDetail.budget_amount) }}
</el-descriptions-item>
<el-descriptions-item label="金额类型">
<el-tag v-if="contractDrawerDetail.amount_type === 'fixed'" type="success" size="small"></el-tag>
<el-tag v-else-if="contractDrawerDetail.amount_type === 'open'" type="warning" size="small">开口合同</el-tag>
<span v-else>-</span>
</el-descriptions-item>
<el-descriptions-item label="金额说明" v-if="contractDrawerDetail.amount_type === 'open'">
{{ contractDrawerDetail.amount_description || '-' }}
</el-descriptions-item>
<el-descriptions-item label="签订日期">
{{ formatDate(contractDrawerDetail.sign_date) || '-' }}
</el-descriptions-item>
<el-descriptions-item label="申请日期">
{{ formatDate(contractDrawerDetail.apply_date) || '-' }}
</el-descriptions-item>
<el-descriptions-item label="合同履行期">
{{ contractDrawerDetail.perform_period || '-' }}
</el-descriptions-item>
<el-descriptions-item label="付款方式">
{{ contractDrawerDetail.pay_method || '-' }}
</el-descriptions-item>
<el-descriptions-item label="预算年度">
{{ getContractBudgetYear(contractDrawerDetail) }}
</el-descriptions-item>
<el-descriptions-item label="计划资金来源" :span="2">
{{ getContractPlanFundSource(contractDrawerDetail) }}
</el-descriptions-item>
<el-descriptions-item label="实际资金来源" :span="2">
{{ formatArrayText(contractDrawerDetail.actual_fund_sources) }}
</el-descriptions-item>
<el-descriptions-item label="合同类型">
{{ (contractDrawerDetail.contractType && contractDrawerDetail.contractType.name) || '-' }}
</el-descriptions-item>
<el-descriptions-item label="采购类别">
{{ (contractDrawerDetail.purchaseCategory && contractDrawerDetail.purchaseCategory.name) || '-' }}
</el-descriptions-item>
<el-descriptions-item label="采购方式">
{{ getContractPurchaseMethod(contractDrawerDetail) }}
</el-descriptions-item>
<el-descriptions-item label="是否政府采购">
<el-tag v-if="contractDrawerDetail.is_government_purchase" type="success" size="small"></el-tag>
<el-tag v-else type="info" size="small"></el-tag>
</el-descriptions-item>
<el-descriptions-item label="招标代理">
{{ contractDrawerDetail.tender_agent || '-' }}
</el-descriptions-item>
<el-descriptions-item label="合同履行情况">
{{ contractDrawerDetail.perform_status || '-' }}
</el-descriptions-item>
<el-descriptions-item label="是否验收">
<el-tag v-if="contractDrawerDetail.is_accepted" type="success" size="small"></el-tag>
<el-tag v-else type="info" size="small"></el-tag>
</el-descriptions-item>
<el-descriptions-item label="科室">
{{ formatDepartmentNames(contractDrawerDetail.owner_department_ids || contractDrawerDetail.owner_department_id) }}
</el-descriptions-item>
<el-descriptions-item label="合同签订/变更经办人">
{{ formatUserNames(contractDrawerDetail.handler_admin_ids) }}
</el-descriptions-item>
<el-descriptions-item label="申请科室经办人">
{{ formatUserNames(contractDrawerDetail.apply_handler_id) }}
</el-descriptions-item>
<el-descriptions-item label="采购科室经办人">
{{ formatUserNames(contractDrawerDetail.purchase_handler_id) }}
</el-descriptions-item>
<el-descriptions-item label="已发起付款">
<span style="font-weight: 600;">
<span style="color: #409eff;">{{ (contractDrawerDetail.payment_stats && contractDrawerDetail.payment_stats.payment_count) || 0 }} </span>
<span style="color: #67c23a; margin-left: 8px;">{{ formatAmount((contractDrawerDetail.payment_stats && contractDrawerDetail.payment_stats.paid_amount) || 0) }}</span>
</span>
</el-descriptions-item>
<el-descriptions-item label="备注" :span="2">
{{ contractDrawerDetail.remark || '-' }}
</el-descriptions-item>
<el-descriptions-item label="附件" :span="2">
<template v-if="getContractAttachmentUrl(contractDrawerDetail)">
<el-link
type="primary"
:underline="false"
:href="getContractAttachmentUrl(contractDrawerDetail)"
target="_blank"
>
{{ (contractDrawerDetail.attachment && contractDrawerDetail.attachment.original_name) || (contractDrawerDetail.attachment && contractDrawerDetail.attachment.name) || '查看附件' }}
</el-link>
</template>
<span v-else>-</span>
</el-descriptions-item>
</el-descriptions>
<el-divider content-position="left">付款计划</el-divider>
<el-table :data="contractDrawerDetail.pay_plans || []" border size="small" style="width: 100%;">
<el-table-column prop="phase_no" label="期次" width="100" />
<el-table-column label="计划付款日" width="150">
<template slot-scope="scope">
{{ formatDate(scope.row.due_date) || '-' }}
</template>
</el-table-column>
<el-table-column label="计划金额" min-width="160" align="right">
<template slot-scope="scope">
<span style="color: #F56C6C; font-weight: bold;">¥{{ formatAmount(scope.row.amount_plan) }}</span>
</template>
</el-table-column>
</el-table>
<div v-if="!(contractDrawerDetail.pay_plans && contractDrawerDetail.pay_plans.length)" class="contract-empty-tip">
暂无付款计划
</div>
</div>
</div>
<div v-else style="color:#909399;">未获取到合同详情</div>
</div>
</el-drawer>
</div>
</template>
@ -928,6 +1119,8 @@ export default {
rightDrawerUrl: '',
meetingMinutesDetail: null,
loadingMeetingMinutes: false,
contractDrawerDetail: null,
loadingContractDrawer: false,
// fill_flow_title watcher deep watcher oldVal/newVal
_unwatchFillFlowTitle: null,
};
@ -962,12 +1155,9 @@ export default {
return this.getOaCustomModelBindings(expenditureId, field).length > 0;
}
// meeting_minutes ID
// meeting_minutes
if (field.element_type === 'meeting_minutes') {
const meetingMinuteId = this.extractMeetingMinuteId(
this.getIndirectFieldValue(expenditureId, this.getTplFieldKey(field))
);
return meetingMinuteId !== null && meetingMinuteId !== undefined;
return this.getIndirectMeetingMinutesList(expenditureId, this.getTplFieldKey(field)).length > 0;
}
// attachment/file
@ -1049,6 +1239,9 @@ export default {
if (el.type === 'form_element' && el.field_type === 'attachment') {
return Array.isArray(val) && val.length > 0;
}
if (el.type === 'meeting_minutes') {
return this.normalizeMeetingMinutesValue(val).length > 0;
}
return !this.isEmptyValue(val);
});
},
@ -1434,6 +1627,9 @@ export default {
if (!object.hasOwnProperty('related_flow_ids')) {
object['related_flow_ids'] = '';
}
if (!object.hasOwnProperty('related_meeting_minute_ids')) {
object['related_meeting_minute_ids'] = '';
}
// fill_flow_title=1
const fillFlowTitleField = (fields || []).find(f =>
@ -1487,6 +1683,80 @@ export default {
if (!date) return '';
return this.$moment(date).format('YYYY-MM-DD');
},
formatArrayText(val) {
if (!val) return '-';
if (Array.isArray(val)) {
const arr = val.map(item => (item === null || item === undefined ? '' : String(item).trim())).filter(Boolean);
return arr.length ? arr.join(' | ') : '-';
}
if (typeof val === 'string') {
const s = val.trim();
return s || '-';
}
return String(val);
},
parseIdList(val) {
if (val === null || val === undefined || val === '') return [];
if (Array.isArray(val)) {
return val
.map(item => {
if (item && typeof item === 'object') return item.id || item.value || item.user_id || item.department_id || null;
return item;
})
.filter(item => item !== null && item !== undefined && item !== '');
}
if (typeof val === 'number') return [val];
if (typeof val === 'string') {
return val
.split(',')
.map(item => item.trim())
.filter(Boolean);
}
if (typeof val === 'object') {
const id = val.id || val.value || val.user_id || val.department_id;
return id ? [id] : [];
}
return [];
},
formatDepartmentNames(val) {
const ids = this.parseIdList(val);
if (!ids.length) return '-';
return ids
.map(id => this.simpleDepartmentMap?.[id] || this.simpleDepartmentMap?.[Number(id)] || `部门ID: ${id}`)
.join('、');
},
formatUserNames(val) {
const ids = this.parseIdList(val);
if (!ids.length) return '-';
return ids
.map(id => this.simpleUserMap?.[id] || this.simpleUserMap?.[Number(id)] || `用户ID: ${id}`)
.join('、');
},
getContractBudgetYear(detail) {
const year = detail?.fund_source_year?.year || detail?.fundSourceYear?.year || detail?.fund_source_budget_data?.budget_year?.year || detail?.fundSourceBudgetData?.budget_year?.year;
return year ? `${year}` : '-';
},
getContractPlanFundSource(detail) {
return detail?.fund_source_budget_data?.name || detail?.fundSourceBudgetData?.name || detail?.fund_source || '-';
},
getContractPurchaseMethod(detail) {
const relationValue = detail && detail.purchaseMethod;
if (relationValue && typeof relationValue === 'object') {
return relationValue.name || relationValue.label || relationValue.title || '-';
}
const rawValue = detail && detail.purchase_method;
if (!rawValue) return '-';
if (typeof rawValue === 'string') return rawValue;
if (typeof rawValue === 'object') {
return rawValue.name || rawValue.label || rawValue.title || rawValue.text || '-';
}
return String(rawValue);
},
getContractAttachmentUrl(detail) {
const att = detail?.attachment;
return att?.url || att?.path || att?.file_url || att?.download_url || att?.preview_url || '';
},
//
formatDateTime(dateTime) {
if (!dateTime) return '';
@ -1894,6 +2164,33 @@ export default {
return null;
},
/** 将会议纪要值归一化为 [{ id, title }, ...],兼容单条与多条 */
normalizeMeetingMinutesValue(val) {
if (val === null || val === undefined) return [];
if (Array.isArray(val)) {
return val
.map((item) => {
const id = this.extractMeetingMinuteId(item);
if (!id) return null;
const title = (item && typeof item === 'object' && item.title) ? item.title : '';
return { id, title };
})
.filter(Boolean);
}
const id = this.extractMeetingMinuteId(val);
if (!id) return [];
const title = (val && typeof val === 'object' && val.title) ? val.title : '';
return [{ id, title }];
},
getPaymentMeetingMinutesList(el, payment) {
return this.normalizeMeetingMinutesValue(this.getPaymentTemplateElementValue(el, payment));
},
getIndirectMeetingMinutesList(expenditureId, fieldKey) {
return this.normalizeMeetingMinutesValue(this.getIndirectFieldValue(expenditureId, fieldKey));
},
async openFlowDrawer({ flowId, customModelId, title }) {
const fid = Number(flowId);
if (!fid || Number.isNaN(fid)) return;
@ -1930,11 +2227,12 @@ export default {
this.rightDrawerTitle = '查看会议纪要';
this.rightDrawerUrl = '';
this.meetingMinutesDetail = null;
this.contractDrawerDetail = null;
this.rightDrawerVisible = true;
this.loadingMeetingMinutes = true;
try {
// meetingMinutesShow res.data
const detail = await meetingMinutesShow({ id: meetingMinuteId });
const detail = await meetingMinutesShow({ id: meetingMinuteId, show_relation: ['flows', 'items'] });
this.meetingMinutesDetail = detail || null;
this.rightDrawerTitle = detail?.title || '查看会议纪要';
} catch (e) {
@ -1945,6 +2243,33 @@ export default {
}
},
async openContractDrawer(contractId, title = '') {
const cid = Number(contractId);
if (!cid || Number.isNaN(cid)) return;
this.rightDrawerType = 'contract';
this.rightDrawerTitle = title || '查看合同详情';
this.rightDrawerUrl = '';
this.meetingMinutesDetail = null;
this.contractDrawerDetail = null;
this.rightDrawerVisible = true;
this.loadingContractDrawer = true;
try {
const [detail] = await Promise.all([
getBudgetContractDetail(cid),
this.loadSimpleDepartmentMap(),
this.loadSimpleUserMap(),
]);
this.contractDrawerDetail = detail || null;
this.rightDrawerTitle = detail?.title || detail?.contract_no || title || '查看合同详情';
} catch (e) {
console.error('加载合同详情失败:', e);
this.contractDrawerDetail = null;
} finally {
this.loadingContractDrawer = false;
}
},
//
formatReadonlyValue(val) {
if (val === undefined || val === null || val === '') return '-';
@ -1956,25 +2281,30 @@ export default {
//
async loadRelatedPayments() {
if (!this.$route.query.flow_id) {
return;
return
}
this.loadingPayments = true;
try {
// request.js res.data payment null
const payment = await getPaymentsByFlowId(this.$route.query.flow_id, { all: true });
// (null)
if (payment) {
// request.js res.data
const result = await getPaymentsByFlowId(this.$route.query.flow_id, { all: true })
const payments = Array.isArray(result) ? result : (result ? [result] : [])
if (payments.length > 0) {
// breadcrumb
if (payment.payment_type_info && payment.payment_type_info.breadcrumb) {
const bc = payment.payment_type_info.breadcrumb;
payments.forEach((payment) => {
if (!payment.payment_type_info || !payment.payment_type_info.breadcrumb) {
return
}
const bc = payment.payment_type_info.breadcrumb
if (Array.isArray(bc)) {
payment.payment_type_info.breadcrumb = bc;
payment.payment_type_info.breadcrumb = bc
} else if (typeof bc === 'string') {
payment.payment_type_info.breadcrumb = bc.split(/\s*>\s*|\s*\/\s*/).filter(Boolean);
payment.payment_type_info.breadcrumb = bc.split(/\s*>\s*|\s*\/\s*/).filter(Boolean)
}
}
this.relatedPayments = [payment];
})
this.relatedPayments = payments
const payment = payments[0]
// fields
await this.loadPaymentTemplateElements(payment);
@ -2124,6 +2454,10 @@ export default {
const relatedIds = res.flow.related_flows.map(f => f.id).join(',');
this.form.related_flow_ids = relatedIds;
}
if (res?.flow?.related_meeting_minutes && res.flow.related_meeting_minutes.length > 0) {
const relatedMeetingMinuteIds = res.flow.related_meeting_minutes.map(item => item.id).join(',');
this.form.related_meeting_minute_ids = relatedMeetingMinuteIds;
}
// form
const { data } = res?.flow;
for (let key in data) {
@ -2246,6 +2580,10 @@ export default {
const relatedIds = res.flow.related_flows.map(f => f.id).join(',');
this.form.related_flow_ids = relatedIds;
}
if (res?.flow?.related_meeting_minutes && res.flow.related_meeting_minutes.length > 0) {
const relatedMeetingMinuteIds = res.flow.related_meeting_minutes.map(item => item.id).join(',');
this.form.related_meeting_minute_ids = relatedMeetingMinuteIds;
}
this.handleDefaultJSON();
const { data } = res?.flow;
for (let key in data) {
@ -2353,7 +2691,7 @@ export default {
let myField = this.fields.find(i => i.name === key)
// ID使writeableFields
if (key === 'related_flow_ids') {
if (key === 'related_flow_ids' || key === 'related_meeting_minute_ids') {
continue;
}
@ -2382,8 +2720,10 @@ export default {
// related_flow_ids
// 便
copyForm.related_flow_ids = this.form.related_flow_ids || ''
copyForm.related_meeting_minute_ids = this.form.related_meeting_minute_ids || ''
console.log("copyForm",copyForm,this.$refs["desktopForm"].form)
console.log("related_flow_ids:", copyForm.related_flow_ids, "form.related_flow_ids:", this.form.related_flow_ids)
console.log("related_meeting_minute_ids:", copyForm.related_meeting_minute_ids, "form.related_meeting_minute_ids:", this.form.related_meeting_minute_ids)
// return
if (this.$route.query.flow_id) {
copyForm.id = this.$route.query.flow_id;
@ -2750,6 +3090,38 @@ export default {
word-break: break-word;
}
}
.contract-drawer {
padding: 20px 24px 28px;
}
.contract-drawer-descriptions {
::v-deep .el-descriptions__table {
width: 100%;
table-layout: fixed;
}
::v-deep .el-descriptions-item__label {
width: 160px;
white-space: nowrap;
}
::v-deep .el-descriptions-item__content {
word-break: break-word;
line-height: 1.7;
}
}
.contract-empty-tip {
padding: 18px 4px 8px;
color: #909399;
}
::v-deep .flow-detail-drawer > .el-drawer__header {
margin-bottom: 0;
padding: 20px 24px 16px;
border-bottom: 1px solid #ebeef5;
}
::v-deep .flow-detail-drawer > .el-drawer__body {
overflow-y: auto;
}
</style>
<style lang="scss">
.log-table-scroll {

@ -573,18 +573,6 @@
@click="destroy(row)"
>删除</el-button
>
<el-button
v-if="
$route.params.type === 'handled' &&
row.custom_model_id === 99 &&
row.status === 1 &&
row.fund_log_is_end === 0
"
type="primary"
size="mini"
@click="toOutPay(row)"
>支付</el-button
>
</template>
<template v-else>
<el-button
@ -891,12 +879,6 @@ export default {
console.error(err);
}
},
//
async toOutPay(row) {
// this.$refs.payMx.payId = row.id;
this.$refs.payMx.payList = [row];
this.isShowPay = true;
},
//
multiPay() {
const records = this.$refs["table"]?.getCheckboxRecords(true) || [];
@ -1281,4 +1263,4 @@ export default {
}
}
}
</style>
</style>
Loading…
Cancel
Save