Files
supervision-test-frontend-repo/src/views/gh/improvementProposal/components/ImprovementProposalForm.vue
T

488 lines
19 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<a-spin :spinning="loading">
<JFormContainer :disabled="disabled">
<template #detail>
<a-form v-bind="formItemLayout" name="ImprovementProposalForm" ref="formRef" :class="{ 'detail-disabled': disabled }">
<a-row>
<a-col :span="12">
<a-form-item label="提案编号" :required="false" id="ImprovementProposalForm-proposalNo" name="proposalNo">
<a-input v-model:value="formData.proposalNo" :disabled="true" allow-clear></a-input>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="提出日期" id="ImprovementProposalForm-proposalDate" name="proposalDate">
<a-input v-model:value="formData.proposalDate" :disabled="true" allow-clear></a-input>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="提案名称" v-bind="validateInfos.proposalName" id="ImprovementProposalForm-proposalName" name="proposalName">
<a-input v-model:value="formData.proposalName" placeholder="请输入提案名称" allow-clear ></a-input>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="提案类别" v-bind="validateInfos.proposalCategory" id="ImprovementProposalForm-proposalCategory" name="proposalCategory">
<j-dict-select-tag v-model:value="formData.proposalCategory" dictCode="proposal_category" placeholder="请选择提案类别" allow-clear />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="提案部门" :required="false" id="ImprovementProposalForm-proposalDeptId" name="proposalDeptId">
<a-input v-model:value="formData.proposalDeptName" :disabled="true" allow-clear></a-input>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="提案人" v-bind="validateInfos.applicantName" id="ImprovementProposalForm-applicantName" name="applicantName">
<a-input v-model:value="formData.applicantName" placeholder="请输入申请人姓名" allow-clear ></a-input>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="团队名称" v-bind="validateInfos.teamName" id="ImprovementProposalForm-teamName" name="teamName">
<a-input v-model:value="formData.teamName" placeholder="请输入团队名称" allow-clear ></a-input>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="问题描述" v-bind="validateInfos.problemDesc" id="ImprovementProposalForm-problemDesc" name="problemDesc" :labelCol="longLabelCol" :wrapperCol="longWrapperCol">
<a-textarea v-model:value="formData.problemDesc" :rows="4" placeholder="请输入问题描述" />
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="改善方法及措施" v-bind="validateInfos.improvementMethod" id="ImprovementProposalForm-improvementMethod" name="improvementMethod" :labelCol="longLabelCol" :wrapperCol="longWrapperCol">
<a-textarea v-model:value="formData.improvementMethod" :rows="4" placeholder="请输入改善方法及措施" />
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="改善前情况描述" v-bind="validateInfos.beforeDesc" id="ImprovementProposalForm-beforeDesc" name="beforeDesc" :labelCol="longLabelCol" :wrapperCol="longWrapperCol">
<a-textarea v-model:value="formData.beforeDesc" :rows="4" placeholder="请输入改善前情况描述" />
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="改善前图片" :labelCol="longLabelCol" :wrapperCol="longWrapperCol">
<SUploadFile ref="beforeFileRef" :bussiness-id="formData.proposalNo ? `${formData.proposalNo}:before` : ''" :multiple="true" :disabled="disabled" />
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="改善后情况描述" v-bind="validateInfos.afterDesc" id="ImprovementProposalForm-afterDesc" name="afterDesc" :labelCol="longLabelCol" :wrapperCol="longWrapperCol">
<a-textarea v-model:value="formData.afterDesc" :rows="4" placeholder="请输入改善后情况描述" />
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="改善后图片" :labelCol="longLabelCol" :wrapperCol="longWrapperCol">
<SUploadFile ref="afterFileRef" :bussiness-id="formData.proposalNo ? `${formData.proposalNo}:after` : ''" :multiple="true" :disabled="disabled" />
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="改善效果" v-bind="validateInfos.improvementEffect" id="ImprovementProposalForm-improvementEffect" name="improvementEffect" :labelCol="longLabelCol" :wrapperCol="longWrapperCol">
<a-textarea v-model:value="formData.improvementEffect" :rows="4" placeholder="请输入改善效果" />
</a-form-item>
</a-col>
<a-col v-if="disabled" :span="24">
<a-form-item label="部门评定结果" :labelCol="longLabelCol" :wrapperCol="longWrapperCol">
<j-dict-select-tag v-model:value="formData.finalAward" dictCode="proposal_prize" placeholder="请等待评定" disabled />
</a-form-item>
</a-col>
</a-row>
</a-form>
</template>
</JFormContainer>
<!-- 新增申请只填写主表子表由后续评分和投票流程维护 -->
<a-tabs v-if="showSubTables" v-model:activeKey="activeKey" animated style="overflow:hidden;">
<a-tab-pane tab="部门评议评分表" key="improvementDeptScore" :forceRender="true">
<j-vxe-table
:keep-source="true"
resizable
ref="improvementDeptScoreTableRef"
:loading="improvementDeptScoreTable.loading"
:columns="improvementDeptScoreTable.columns"
:dataSource="improvementDeptScoreTable.dataSource"
:height="340"
:disabled="disabled"
:rowNumber="true"
:rowSelection="true"
:toolbar="true"/>
</a-tab-pane>
<a-tab-pane tab="所级评议投票表" key="improvementInstituteVote" :forceRender="true">
<j-vxe-table
:keep-source="true"
resizable
ref="improvementInstituteVoteTableRef"
:loading="improvementInstituteVoteTable.loading"
:columns="improvementInstituteVoteTable.columns"
:dataSource="improvementInstituteVoteTable.dataSource"
:height="340"
:disabled="disabled"
:rowNumber="true"
:rowSelection="true"
:toolbar="true"/>
</a-tab-pane>
</a-tabs>
<div v-if="showFlowSubmitButton" :span="24" style="width: 100%;text-align: center;margin-top: 10px">
<a-button preIcon="ant-design:check-outlined" style="width: 126px" type="primary" @click="submitForm"> </a-button>
</div>
</a-spin>
</template>
<script lang="ts">
import { defineComponent, ref, reactive, computed, toRaw, onMounted, nextTick } from 'vue';
import { defHttp } from '/@/utils/http/axios';
import { useValidateAntFormAndTable } from '/@/hooks/system/useJvxeMethods';
import { queryImprovementDeptScoreListByMainId, queryImprovementInstituteVoteListByMainId, queryDataById, saveOrUpdate, getLatestProposalSequence } from '../ImprovementProposal.api';
import { JVxeTable } from '/@/components/jeecg/JVxeTable';
import {improvementDeptScoreColumns, improvementInstituteVoteColumns} from '../ImprovementProposal.data';
import JFormContainer from '/@/components/Form/src/container/JFormContainer.vue';
import { Form } from 'ant-design-vue';
import JDictSelectTag from '/@/components/Form/src/jeecg/components/JDictSelectTag.vue';
import SUploadFile from '/@/components/semri/fileComponent/SUploadFile.vue';
import { useUserStore } from '/@/store/modules/user';
const useForm = Form.useForm;
export default defineComponent({
name: "ImprovementProposalForm",
components:{
JVxeTable,
JFormContainer,
JDictSelectTag,
SUploadFile,
},
props:{
formDisabled:{
type: Boolean,
default: false
},
formData: { type: Object, default: ()=>{} },
formBpm: { type: Boolean, default: true }
},
emits:['success'],
setup(props, {emit}) {
const loading = ref(false);
const formRef = ref();
const beforeFileRef = ref();
const afterFileRef = ref();
const improvementDeptScoreTableRef = ref();
const improvementDeptScoreTable = reactive<Record<string, any>>({
loading: false,
columns: improvementDeptScoreColumns,
dataSource: []
});
const improvementInstituteVoteTableRef = ref();
const improvementInstituteVoteTable = reactive<Record<string, any>>({
loading: false,
columns: improvementInstituteVoteColumns,
dataSource: []
});
const activeKey = ref('improvementDeptScore');
const userStore = useUserStore();
const formData = reactive<Record<string, any>>({
id: '',
proposalNo: '',
proposalName: '',
proposalDate: '',
proposalDeptId: '',
proposalDeptName: '',
proposalDeptCode: '',
applicantId: '',
applicantName: '',
teamName: '',
proposalCategory: '',
problemDesc: '',
improvementMethod: '',
beforeDesc: '',
afterDesc: '',
improvementEffect: '',
finalAward: '',
});
//表单验证
const validatorRules = reactive({
proposalName: [{ required: true, message: '请输入提案名称!'},],
applicantName: [{ required: true, message: '请输入申请人姓名!'},],
proposalCategory: [{ required: true, message: '请选择提案类别!'},],
problemDesc: [{ required: true, message: '请输入问题描述!'},],
improvementMethod: [{ required: true, message: '请输入改善方法及措施!'},],
});
const {resetFields, validate, validateInfos} = useForm(formData, validatorRules, {immediate: false});
const dbData = {};
const formItemLayout = {
labelCol: {xs: {span: 24}, sm: {span: 5}},
wrapperCol: {xs: {span: 24}, sm: {span: 16}},
};
const longLabelCol = {
xs: {span: 24},
sm: {span: 5},
};
const longWrapperCol = {
xs: {span: 24},
sm: {span: 16},
};
const halfLabelCol = {
xs: {span: 24},
sm: {span: 5},
};
const halfWrapperCol = {
xs: {span: 24},
sm: {span: 18},
};
const disabled = computed(()=>{
if(props.formBpm === true){
if(props.formData.disabled === false){
return false;
}else{
return true;
}
}
return props.formDisabled;
});
// 子表由流程节点维护,普通新增、编辑和详情弹窗均不展示,避免误改评分或投票数据。
const showSubTables = computed(() => props.formBpm === true && Boolean(formData.id || props.formData?.dataId));
function getCurrentDate() {
const now = new Date();
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
const day = String(now.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
}
function getCurrentLoginDepart() {
const userInfo = (userStore.getUserInfo || {}) as Record<string, any>;
const loginInfo = (userStore.getLoginInfo || {}) as Record<string, any>;
let departs: any[] = [];
if (Array.isArray(loginInfo.departs)) {
departs = loginInfo.departs;
} else if (Array.isArray(userInfo.departs)) {
departs = userInfo.departs;
} else if (loginInfo.userInfo && Array.isArray(loginInfo.userInfo.departs)) {
departs = loginInfo.userInfo.departs;
}
if (userInfo.orgCode) {
const found = departs.find((item) => item && item.orgCode === userInfo.orgCode);
if (found) return found;
}
if (departs.length === 1) {
return departs[0];
}
if (departs.length > 0) {
return departs[0];
}
return undefined;
}
async function getCurrentDepartInfo() {
const userInfo = (userStore.getUserInfo || {}) as Record<string, any>;
const loginDepart = getCurrentLoginDepart();
if (loginDepart) {
return {
id: loginDepart.id || '',
departName: loginDepart.departName || loginDepart.name || '',
orgCode: loginDepart.orgCode || '',
};
}
if (userInfo.orgCode) {
try {
const depart = await defHttp.get({ url: '/sys/sysDepart/getDepartName', params: { orgCode: userInfo.orgCode } }, { successMessageMode: 'none' });
if (depart && (depart.id || depart.departName)) {
return {
id: depart.id || '',
departName: depart.departName || depart.depart_name || '',
orgCode: userInfo.orgCode,
};
}
} catch (e) {
// ignore
}
}
const deptId = userInfo.departIds || userInfo.deptId || userInfo.deptid || '';
const deptName = userInfo.departIds_dictText || userInfo.orgCodeTxt || userInfo.deptName || '';
return { id: deptId, departName: deptName, orgCode: userInfo.orgCode || '' };
}
async function applyCurrentUserDeptInfo() {
const departInfo = await getCurrentDepartInfo();
formData.proposalDeptId = departInfo.id;
formData.proposalDeptName = departInfo.departName;
formData.proposalDeptCode = departInfo.orgCode;
}
async function getProposalSequence() {
const year = new Date().getFullYear();
const latestSequence = await getLatestProposalSequence(year);
// return Number(latestSequence) + 1;
return String(Number(latestSequence) + 1).padStart(4, '0');
}
async function generateProposalNo() {
const deptCode = formData.proposalDeptName || '';
const year = new Date().getFullYear();
const proposalSequence = await getProposalSequence();
return `${deptCode}-${year}年-${proposalSequence}`;
}
onMounted(()=>{
initFormData();
});
const queryByIdUrl = '/improvementproposal/improvementProposal/queryById';
async function initFormData(){
if(props.formBpm === true){
let params = {id: props.formData.dataId};
const row = await defHttp.get({url: queryByIdUrl, params});
Object.keys(row).map(k => {
formData[k] = row[k];
});
const improvementDeptScoreDataList = await queryImprovementDeptScoreListByMainId(row['id']);
improvementDeptScoreTable.dataSource = [...improvementDeptScoreDataList];
const improvementInstituteVoteDataList = await queryImprovementInstituteVoteListByMainId(row['id']);
improvementInstituteVoteTable.dataSource = [...improvementInstituteVoteDataList];
}
}
const showFlowSubmitButton = computed(()=>{
if(props.formBpm === true){
if(props.formData.disabled === false){
return true
}
}
return false
});
async function add() {
resetFields();
improvementDeptScoreTable.dataSource = [];
improvementInstituteVoteTable.dataSource = [];
formData.proposalDate = getCurrentDate();
await applyCurrentUserDeptInfo();
formData.proposalNo = await generateProposalNo();
}
async function edit(row) {
//主表数据
await queryMainData(row.id);
// 普通编辑不加载子表,并清理弹窗复用时可能残留的表格数据。
improvementDeptScoreTable.dataSource = [];
improvementInstituteVoteTable.dataSource = [];
// 加载改善前/后图片文件列表
await nextTick();
if (formData.id) {
beforeFileRef.value?.loadFileList();
afterFileRef.value?.loadFileList();
}
}
async function queryMainData(id) {
const row = await queryDataById(id);
resetFields();
const tmpData = {};
Object.keys(formData).forEach((key) => {
if(row.hasOwnProperty(key)){
tmpData[key] = row[key]
}
})
//赋值
Object.assign(formData,tmpData);
}
const {getSubFormAndTableData, transformData} = useValidateAntFormAndTable(activeKey, {
'improvementDeptScore': improvementDeptScoreTableRef,
'improvementInstituteVote': improvementInstituteVoteTableRef,
});
async function getFormData() {
try {
// 触发表单验证
await validate();
} catch ({ errorFields }) {
if (errorFields) {
const firstField = errorFields[0];
if (firstField) {
formRef.value.scrollToField(firstField.name, { behavior: 'smooth', block: 'center' });
}
}
return Promise.reject(errorFields);
}
return transformData(toRaw(formData))
}
async function submitForm() {
const mainData = await getFormData();
const isUpdate = Boolean(mainData.id);
const values = Object.assign({}, dbData, mainData);
// 仅流程表单提交子表,普通编辑不能覆盖后续流程维护的评分和投票记录。
if (isUpdate && showSubTables.value) {
const subData = await getSubFormAndTableData();
Object.assign(values, subData);
}
console.log('表单提交数据', values)
const result = await saveOrUpdate(values, isUpdate);
// 新增时,保存成功后绑定附件的 bussinessId
if (!isUpdate) {
const newId = typeof result === 'string' ? result : (result?.id || result);
if (newId) {
formData.id = newId;
await beforeFileRef.value?.bindBussinessId(`${formData.proposalNo}:before`);
await afterFileRef.value?.bindBussinessId(`${formData.proposalNo}:after`);
}
}
emit('success');
}
function setFieldsValue(values) {
if(values){
Object.keys(values).map(k=>{
formData[k] = values[k];
});
}
}
function handleFormChange(key, value) {
formData[key] = value;
}
return {
improvementDeptScoreTableRef,
improvementDeptScoreTable,
improvementInstituteVoteTableRef,
improvementInstituteVoteTable,
validatorRules,
validateInfos,
activeKey,
loading,
formData,
setFieldsValue,
handleFormChange,
formItemLayout,
longLabelCol,
longWrapperCol,
halfLabelCol,
halfWrapperCol,
disabled,
showSubTables,
showFlowSubmitButton,
getFormData,
submitForm,
add,
edit,
formRef,
beforeFileRef,
afterFileRef,
}
}
});
</script>
<style lang="less" scoped>
.ant-tabs-tabpane.sub-one-form {
max-height: 340px;
overflow: auto;
}
.detail-disabled :deep(.ant-input-clear-icon) {
display: none !important;
}
.detail-disabled :deep(.ant-select-clear) {
display: none !important;
}
.detail-disabled :deep(.ant-input-password-icon) {
display: none !important;
}
</style>