diff --git a/src/api/flow/index.js b/src/api/flow/index.js index 38accec..0695d50 100644 --- a/src/api/flow/index.js +++ b/src/api/flow/index.js @@ -263,3 +263,60 @@ export function getOvertimeHoliday(params,isLoading=false) { isLoading }) } + +// 获取预算年度选项 +export function getBudgetYearOptions(isLoading=false) { + return request({ + method: 'get', + url: '/api/budget/budget-data-year-options', + isLoading + }) +} + +// 获取预算数据树 +export function getBudgetDataTree(params, isLoading=false) { + return request({ + method: 'get', + url: '/api/budget/budget-data', + params, + isLoading + }) +} + +// 获取流程详情用于合同预填 +export function getFlowDetailForContract(flowId, isLoading = false) { + return request({ + method: 'get', + url: `/api/oa/flow/detail-for-contract/${flowId}`, + isLoading + }) +} + +// 获取合同设置 +export function getContractSettings(flowId = null, isLoading = false) { + return request({ + method: 'get', + url: '/api/oa/flow/contract-settings', + params: flowId ? { flow_id: flowId } : {}, + isLoading + }) +} + +// 根据flow_id获取合同详情 +export function getContractByFlowId(flowId, isLoading = false) { + return request({ + method: 'get', + url: `/api/oa/flow/contract-by-flow/${flowId}`, + isLoading + }) +} + +// 创建合同 +export function createContract(data, isLoading = false) { + return request({ + method: 'post', + url: '/api/oa/flow/create-contract', + data, + isLoading + }) +} diff --git a/src/components/BudgetSourcePickerField.vue b/src/components/BudgetSourcePickerField.vue new file mode 100644 index 0000000..8fb3195 --- /dev/null +++ b/src/components/BudgetSourcePickerField.vue @@ -0,0 +1,297 @@ + + + + + + + diff --git a/src/components/ContractSignField.vue b/src/components/ContractSignField.vue new file mode 100644 index 0000000..ffd6a9f --- /dev/null +++ b/src/components/ContractSignField.vue @@ -0,0 +1,470 @@ + + + + + + diff --git a/src/utils/formBuilder.js b/src/utils/formBuilder.js index 7499266..29b2e64 100644 --- a/src/utils/formBuilder.js +++ b/src/utils/formBuilder.js @@ -7,6 +7,8 @@ import axios from "axios"; import { flowList } from "@/api/flow"; import MobilePicker from '@/components/MobilePicker/index.vue'; import MobileMultipleSelect from "@/components/MobileMultipleSelect/index.vue"; +import BudgetSourcePickerField from "@/components/BudgetSourcePickerField.vue"; +import ContractSignField from "@/components/ContractSignField.vue"; import { Message } from 'element-ui' function isJSON(str) { if (typeof str !== 'string') return false; @@ -231,6 +233,45 @@ export default function formBuilder( ) ); break; + case "budget-source": + // 可写:hidden input + “选取”按钮 + 弹窗(在独立组件内实现) + formItem = h(BudgetSourcePickerField, { + props: { + fieldName: info.name, + value: target[info.name], + display: target[`${info.name}_display`], + }, + on: { + input: (val) => { + this.$set(target, info.name, val); + }, + "update:display": (txt) => { + // 用于回显(只读/展示) + this.$set(target, `${info.name}_display`, txt); + }, + }, + }); + break; + case "contract-sign": + // 合同签订字段:hidden input + "合同签订"按钮 + 弹窗(在独立组件内实现) + formItem = h(ContractSignField, { + props: { + fieldName: info.name, + value: target[info.name], + display: target[`${info.name}_display`], + flowId: this.$route?.query?.flow_id || "", + }, + on: { + input: (val) => { + this.$set(target, info.name, val); + }, + "update:display": (txt) => { + // 用于回显(只读/展示) + this.$set(target, `${info.name}_display`, txt); + }, + }, + }); + break; case "file": formItem = row ? h("vxe-upload", { @@ -1068,6 +1109,28 @@ export default function formBuilder( ] ); break; + case "budget-source": + // 只读模式下显示后端返回的 _display 值 + const displayFieldName = info.name + '_display'; + const displayValue = target[displayFieldName] || target[info.name] || ''; + console.log('[budget-source] 只读模式渲染', { + fieldName: info.name, + displayFieldName, + displayValue, + originalValue: target[info.name], + targetKeys: Object.keys(target).filter(k => k.includes(info.name)), + target: target + }); + formItem = h( + "span", + { + style: { + color: "#333", + }, + }, + displayValue + ); + break; default: formItem = h( "span", @@ -2056,6 +2119,25 @@ export default function formBuilder( }) ); break; + case "budget-source": + // 只读模式下显示后端返回的 _display 值 + const displayFieldNameMobile = info.name + '_display'; + const displayValueMobile = target[displayFieldNameMobile] || target[info.name] || ''; + console.log('[budget-source] 只读模式渲染(移动端)', { + fieldName: info.name, + displayFieldName: displayFieldNameMobile, + displayValue: displayValueMobile, + originalValue: target[info.name], + targetKeys: Object.keys(target).filter(k => k.includes(info.name)), + target: target + }); + formItem = h("van-field", { + props: { + value: displayValueMobile, + readonly: true, + }, + }); + break; default: formItem = h("van-field", { props: { diff --git a/src/views/MeetingMinutes/components/AddMeetingMinutes.vue b/src/views/MeetingMinutes/components/AddMeetingMinutes.vue index 4dcbc0c..a45cfb2 100644 --- a/src/views/MeetingMinutes/components/AddMeetingMinutes.vue +++ b/src/views/MeetingMinutes/components/AddMeetingMinutes.vue @@ -99,7 +99,7 @@ style="width: 100%;" :disabled="type === 'view'" > - + diff --git a/src/views/flow/create.vue b/src/views/flow/create.vue index 10b2cb5..3d200ff 100644 --- a/src/views/flow/create.vue +++ b/src/views/flow/create.vue @@ -720,7 +720,8 @@ export default { this.form[key] = jsonObj; } } catch (err) { - if (this.form.hasOwnProperty(key)) { + // 允许所有字段被赋值,包括 _display 字段 + if (this.form.hasOwnProperty(key) || key.endsWith('_display')) { if (data[key] instanceof Array) { if (data[key].length > 0 && data[key][0].hasOwnProperty('url')) { this.form[key] = data[key].map(i => ({ @@ -731,8 +732,9 @@ export default { } else { this.form[key] = '' } + } else { + this.form[key] = data[key]; } - this.form[key] = data[key]; } } } diff --git a/src/views/flow/detailCommon.vue b/src/views/flow/detailCommon.vue index b563608..3f94bef 100644 --- a/src/views/flow/detailCommon.vue +++ b/src/views/flow/detailCommon.vue @@ -521,6 +521,10 @@ export default { } else { if (/\/detail/.test(this.$route.path) && this.$route.query.flow_id) { object[field.name] = ""; + // 为 budget-source 类型字段初始化 _display 字段 + if (field.type === 'budget-source') { + object[field.name + '_display'] = ""; + } } else { if (this.writeableFields.indexOf(field.id) !== -1 || this.readableFields.indexOf(field.id) !== -1) { object[field.name] = (this.writeableFields.indexOf(field.id) !== -1 && field.default_value) ? field.default_value : (field.type === 'file' ? [] : ""); @@ -599,7 +603,8 @@ export default { this.form[key] = jsonObj; } } catch (err) { - if (this.form.hasOwnProperty(key)) { + // 允许所有字段被赋值,包括 _display 字段 + if (this.form.hasOwnProperty(key) || key.endsWith('_display')) { if (data[key] instanceof Array) { if (data[key].length > 0 && data[key][0].hasOwnProperty('url')) { this.form[key] = data[key].map(i => ({ @@ -610,8 +615,9 @@ export default { } else { this.form[key] = '' } + } else { + this.form[key] = data[key]; } - this.form[key] = data[key]; } } } @@ -707,7 +713,8 @@ export default { this.form[key] = jsonObj; } } catch (err) { - if (this.form.hasOwnProperty(key)) { + // 允许所有字段被赋值,包括 _display 字段 + if (this.form.hasOwnProperty(key) || key.endsWith('_display')) { if (data[key] instanceof Array) { if (data[key].length > 0) { this.form[key] = data[key];