供应商选择

This commit is contained in:
z9130 2024-10-18 15:45:42 +08:00
parent 51c170acf8
commit 22fc4c413f
16 changed files with 641 additions and 311 deletions

View File

@ -121,27 +121,27 @@ function handleMenuClick(e) {
}
onMounted(async () => {
const data = await Apis.home.get_todo({
params: { pageNum: 1, pageSize: 20 },
});
// const data = await Apis.home.get_todo({
// params: { pageNum: 1, pageSize: 20 },
// });
notifications.value = data.rows.map((item) => {
let module =
getDictObj(DICT_TYPE.contract_todo_type, item.module)?.label || '';
module = module.slice(-4);
let moduleTextArr = [...module];
moduleTextArr =
moduleTextArr.length <= 3 ? moduleTextArr : moduleTextArr.slice(-4);
return {
moduleTextArr,
avatar: '',
date: item.createTime,
isRead: true,
message: item.contractName,
title: item.taskName,
};
});
console.log(notifications);
// notifications.value = data.rows.map((item) => {
// let module =
// getDictObj(DICT_TYPE.contract_todo_type, item.module)?.label || '';
// module = module.slice(-4);
// let moduleTextArr = [...module];
// moduleTextArr =
// moduleTextArr.length <= 3 ? moduleTextArr : moduleTextArr.slice(-4);
// return {
// moduleTextArr,
// avatar: '',
// date: item.createTime,
// isRead: true,
// message: item.contractName,
// title: item.taskName,
// };
// });
// console.log(notifications);
// resetAllStores();
});
</script>
@ -172,13 +172,13 @@ onMounted(async () => {
<a-button> {{ value ? `代理${value}` : '代理切换' }} </a-button>
</a-dropdown>
<Notification
<!-- <Notification
:dot="showDot"
:notifications="notifications"
@clear="handleNoticeClear"
@make-all="handleMakeAll"
@view-all="handleViewAll"
/>
/> -->
</template>
<template #extra>
<AuthenticationLoginExpiredModal

View File

@ -57,5 +57,5 @@ export enum DICT_TYPE {
/** 合同授权期限 */
contract_authorization_period = 'contract_authorization_period',
/** 合同待办类型 */
contract_todo_type = 'contract_todo_type',
contract_todo_type = 'contract_todo_type'
}

View File

@ -73,7 +73,15 @@ export default {
{ label: '开始节点', value: 'paStart' },
{ label: '待编制', value: 'paEdit' },
{ label: '待部门自审', value: 'paDepartmentAudit' },
{ label: '选商编制', value: 'smEdit' },
{ label: '待部门自审', value: 'smDepartmentAudit' },
{ label: '待计划规划部审查', value: 'smPlanningDepartment' },
{ label: '待财务资产部审查', value: 'smFinancialDepartment' },
{ label: '待合规审查(企管法规部)', value: 'smRegulationDepartment' },
{ label: '待主管领导审批', value: 'smManager' },
{ label: '待公司领导审核', value: 'smLeaders' },
{ label: '选商结果填报', value: 'smrEdit' },
]),
contract_business_flow_node: createEntry('合同选商节点流程', [

View File

@ -443,6 +443,12 @@ async function handleSave() {
}
async function handleSubmit() {
// flowinstanceid ,退
if (currData.value.flowInstanceId) {
auditType.value = 'access';
handleAudit('confirm');
return;
}
userModalOpenType.value = 'audit';
// isLoading.value = true
chooseUserModalApi.setData({
@ -642,7 +648,11 @@ onMounted(async () => {
<template>
<Page ref="pageRef" content-class="h-full flex flex-col">
<ChooseUserModal class="w-[950px]" multiple @confirm="handleChooseUserConfirm" />
<ChooseUserModal
class="w-[950px]"
multiple
@confirm="handleChooseUserConfirm"
/>
<ChooseSigningBasisModal class="w-[950px]" @confirm="handleChooseConfirm" />
@ -653,7 +663,11 @@ onMounted(async () => {
/>
<!-- {{ currData.step }} -->
<a-affix :offset-top="0" :style="{ zIndex: 50 }" :target="() => pageRef.bodyRef">
<a-affix
:offset-top="0"
:style="{ zIndex: 50 }"
:target="() => pageRef.bodyRef"
>
<div class="flex w-full flex-row bg-white pl-1 pt-1">
<a-space class="flex-1">
<vben-button
@ -671,6 +685,7 @@ onMounted(async () => {
>
提交
</vben-button>
<vben-button
v-if="['paDepartmentAudit'].includes(currData.step) && taskId"
:disabled="!auditId"
@ -732,11 +747,13 @@ onMounted(async () => {
>
通过
</vben-button> -->
<vben-button variant="secondary" @click="handleBack()"> 返回 </vben-button>
<vben-button variant="secondary" @click="handleBack()">
返回
</vben-button>
</a-space>
<vben-button variant="secondary" @click="handleFold()">
一键{{ isFold ? "展开" : "收起" }}
一键{{ isFold ? '展开' : '收起' }}
</vben-button>
</div>
</a-affix>

View File

@ -1,23 +1,24 @@
<script setup lang="tsx">
import {
ref,
reactive,
watch,
onMounted,
computed,
defineEmits,
defineExpose,
withDefaults,
defineProps,
computed,
onMounted,
reactive,
ref,
watch,
withDefaults,
} from 'vue';
import Apis from '#/api'; // Apis
import { filterContractTypes } from '#/views/contract/utils'; // utils
import type { UploadChangeParam } from 'ant-design-vue';
import { DICT_TYPE, getDictDatasAsync } from '#/utils/dict';
import { MdiUpload } from '@vben/icons';
import { FileUploader } from '#/utils/file';
const emit = defineEmits(['update:form', 'field-change']);
import { MdiUpload } from '@vben/icons';
import { DICT_TYPE, getDictDatasAsync } from '#/utils/dict';
import { FileUploader } from '#/utils/file';
const props = withDefaults(
defineProps<{
@ -28,6 +29,8 @@ const props = withDefaults(
},
);
const emit = defineEmits(['update:form', 'field-change']);
const fileUploader = new FileUploader({});
const formRef = ref();
@ -41,16 +44,16 @@ watch(
{ deep: true, immediate: true },
);
// const readOnly = computed(() => {
// return [
// 'smDepartmentAudit',
// 'smPlanningDepartment',
// 'smFinancialDepartment',
// 'smRegulationDepartment',
// 'smManager',
// 'smLeaders',
// ].includes(form.step);
// });
const readOnly = computed(() => {
return [
'smDepartmentAudit',
'smFinancialDepartment',
'smLeaders',
'smManager',
'smPlanningDepartment',
'smRegulationDepartment',
].includes(form.businessStep);
});
watch(
() => props.form.fileUuid,
@ -132,21 +135,21 @@ defineExpose({ validate, submit });
<template>
<a-form
:model="form"
:rules="rules"
ref="formRef"
:label-col="{ style: { width: '120px' } }"
:model="form"
:rules="rules"
>
<a-row :gutter="16">
<a-col :span="16">
<a-form-item label="合同名称" name="contractName">
<a-input v-model:value="form.contractName" />
<a-input v-model:value="form.contractName" :disabled="readOnly" />
</a-form-item>
</a-col>
<a-col :span="8">
<a-form-item label="报审序号" name="reportNo">
<a-input v-model:value="form.reportNo" disabled />
<a-input v-model:value="form.reportNo" :disabled="readOnly" />
</a-form-item>
</a-col>
@ -154,8 +157,9 @@ defineExpose({ validate, submit });
<a-form-item label="合同类别" name="ctrType">
<a-select
v-model:value="form.ctrType"
class="min-w-[200px]"
:disabled="readOnly"
:options="filteredContractTypes('-1')"
class="min-w-[200px]"
/>
</a-form-item>
</a-col>
@ -164,8 +168,9 @@ defineExpose({ validate, submit });
<a-form-item label="二级类别" name="ctrTwoType">
<a-select
v-model:value="form.ctrTwoType"
class="min-w-[200px]"
:disabled="readOnly"
:options="filteredContractTypes(form.ctrType)"
class="min-w-[200px]"
/>
</a-form-item>
</a-col>
@ -181,18 +186,20 @@ defineExpose({ validate, submit });
<a-form-item label="预算金额" name="budgetSum">
<a-input-number
v-model:value="form.budgetSum"
class="min-w-[200px]"
:disabled="readOnly"
:min="0"
class="min-w-[200px]"
/>
</a-form-item>
<a-col :span="3">
<a-form-item label="" :colon="false" name="priceType">
<a-form-item :colon="false" label="" name="priceType">
<a-select
class="w-full min-w-[120px]"
v-model:value="form.priceType"
:disabled="readOnly"
:min="0"
:options="dictMap[DICT_TYPE.contract_currency_unit]"
class="w-full min-w-[120px]"
/>
</a-form-item>
</a-col>
@ -203,8 +210,9 @@ defineExpose({ validate, submit });
<a-form-item label="资金流向" name="fundAllocation">
<a-select
v-model:value="form.fundAllocation"
class="min-w-[200px]"
:disabled="readOnly"
:options="dictMap[DICT_TYPE.contract_fund_flow]"
class="min-w-[200px]"
/>
</a-form-item>
</a-col>
@ -213,8 +221,9 @@ defineExpose({ validate, submit });
<a-form-item label="资金渠道" name="fundDitch">
<a-select
v-model:value="form.fundDitch"
class="min-w-[200px]"
:disabled="readOnly"
:options="dictMap[DICT_TYPE.contract_funding_source]"
class="min-w-[200px]"
/>
</a-form-item>
</a-col>
@ -223,6 +232,7 @@ defineExpose({ validate, submit });
<a-form-item label="框架协议" name="frameProtocol">
<a-radio-group
v-model:value="form.frameProtocol"
:disabled="readOnly"
:options="dictMap[DICT_TYPE.common_whether]"
/>
</a-form-item>
@ -232,6 +242,7 @@ defineExpose({ validate, submit });
<a-form-item label="框架协议下的合同" name="frameProtocolCtr">
<a-radio-group
v-model:value="form.frameProtocolCtr"
:disabled="readOnly"
:options="dictMap[DICT_TYPE.common_whether]"
/>
</a-form-item>
@ -241,8 +252,9 @@ defineExpose({ validate, submit });
<a-form-item label="组织方式" name="organiza">
<a-radio-group
v-model:value="form.organiza"
class="min-w-[200px]"
:disabled="readOnly"
:options="dictMap[DICT_TYPE.contract_organization_form]"
class="min-w-[200px]"
/>
</a-form-item>
</a-col>
@ -252,15 +264,22 @@ defineExpose({ validate, submit });
<a-upload
v-model:file-list="form.fileList"
:before-upload="() => false"
:disabled="readOnly"
:max-count="3"
accept=".pdf,.ppt,.pptx"
name="file"
@change="handleChange"
>
<a-button>
<a-button v-if="!readOnly">
<MdiUpload />
点击上传
</a-button>
<div
v-if="readOnly && form.fileList.length === 0"
class="text-gray-700"
>
无附件
</div>
</a-upload>
</a-form-item>
</a-col>

View File

@ -1,33 +1,28 @@
<script setup lang="ts">
import {
ref,
reactive,
watch,
computed,
defineEmits,
defineProps,
withDefaults,
onMounted,
nextTick,
computed,
onMounted,
reactive,
ref,
watch,
withDefaults,
} from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { DICT_TYPE, getDictDatasAsync, getDictObj } from '#/utils/dict';
import { getBidColumns, getProviderColumns } from './bid-columns';
import chooseCompanyModal from '../../company/list/choose-company-modal.vue';
import Apis from '#/api';
import { logger } from 'common-utils';
import { message } from 'ant-design-vue';
import { logger } from 'common-utils';
import { cloneDeep } from 'lodash-es';
import Apis from '#/api';
import { DICT_TYPE, getDictDatasAsync, getDictObj } from '#/utils/dict';
import { FileUploader } from '#/utils/file';
const [ChooseCompanyModal, chooseCompanyModalApi] = useVbenModal({
connectedComponent: chooseCompanyModal,
});
const fileUploader = new FileUploader({});
const emit = defineEmits(['update:form', 'field-change']);
import chooseCompanyModal from '../../company/list/choose-company-modal.vue';
import { getBidColumns, getProviderColumns } from './bid-columns';
const props = withDefaults(
defineProps<{
@ -38,20 +33,28 @@ const props = withDefaults(
},
);
const readOnly = computed(() => {
return [
'smDepartmentAudit',
'smPlanningDepartment',
'smFinancialDepartment',
'smRegulationDepartment',
'smManager',
'smLeaders',
].includes(form.step);
const emit = defineEmits(['update:form', 'field-change']);
const [ChooseCompanyModal, chooseCompanyModalApi] = useVbenModal({
connectedComponent: chooseCompanyModal,
});
const fileUploader = new FileUploader({});
const formRef = ref();
const form = reactive({ ...props.form });
const readOnly = computed(() => {
return [
'smDepartmentAudit',
'smFinancialDepartment',
'smLeaders',
'smManager',
'smPlanningDepartment',
'smRegulationDepartment',
].includes(form.step);
});
const rules = {
projectNum: [{ required: true, message: '请输入项目' }],
projectProp: [{ required: true, message: '请选择项目类别' }],
@ -157,20 +160,29 @@ const currBid = ref();
function handleChooseCompanyConfirm(e) {
console.log(currBid.value);
if (currBid.value.phaseSeq === 99999) {
console.log(providerGridRefs.value);
if (currBid.value.phaseSeq === 99_999) {
const gridRef = providerGridRefs2.value;
e.map((item) => (item.guid = undefined));
e.map((item) => {
item.phaseSeq = `${currBid.value.phaseSeq}`;
item._guid = item.guid;
item.guid = undefined;
});
gridRef.insertAt(e, -1);
return;
}
const gridRef = providerGridRefs.value.get(currBid.value.phaseSeq); // Assuming you have a main grid ref
const gridRef = providerGridRefs.value.get(`${currBid.value.phaseSeq}`); // Assuming you have a main grid ref
//
const bidRef = bidGridRefs.value.get(currBid.value.phaseSeq);
const bidRef = bidGridRefs.value.get(`${currBid.value.phaseSeq}`);
const bidFullData = bidRef.getTableData().fullData;
for (const item of bidFullData) {
if (item.phaseSeq === currBid.value.phaseSeq) {
item.providerList = item.providerList || [];
e.map((item) => (item.guid = undefined));
e.map((item) => {
item.phaseSeq = `${currBid.value.phaseSeq}`;
item._guid = item.guid;
item.guid = undefined;
});
item.providerList.push(...e);
bidRef.loadData(bidFullData);
break;
@ -183,13 +195,14 @@ function handleChooseCompanyConfirm(e) {
function onChooseProvider(row) {
currBid.value = row;
if (row.phaseSeq === 99999) {
if (row.phaseSeq === 99_999) {
const tableFullData =
providerGridRefs2.value?.getTableData()?.fullData || [];
console.log(tableFullData);
chooseCompanyModalApi.setData({
title: '选择推荐供应商',
limitMultipleNum: 5,
guids: tableFullData.map((item) => item.guid) || [],
guids: tableFullData.map((item) => item._guid) || [],
});
chooseCompanyModalApi.open();
@ -197,15 +210,19 @@ function onChooseProvider(row) {
}
const gridRef = providerGridRefs.value.get(currBid.value.phaseSeq); // Assuming you have a main grid ref
const tableFullData = gridRef?.getTableData()?.fullData || [];
console.log(tableFullData);
chooseCompanyModalApi.setData({
title: '选择供应商',
limitMultipleNum: 5,
guids: tableFullData.map((item) => item.guid) || [],
guids: tableFullData.map((item) => item._guid) || [],
});
chooseCompanyModalApi.open();
}
async function removeProvider(row) {
const gridRef = providerGridRefs.value.get(`${row.phaseSeq}`);
console.log(providerGridRefs.value, row);
if (row.guid) {
try {
await Apis.contractRecommendProvider.post_deletes({
@ -219,7 +236,6 @@ async function removeProvider(row) {
return;
}
}
const gridRef = providerGridRefs.value.get(`${row.phaseSeq}`);
gridRef.remove(row);
}
@ -306,15 +322,15 @@ onMounted(async () => {
});
function validate() {
let a = getExtraForm();
if (!a) {
throw new Error('请完成必填项的填写');
const a = getExtraForm();
if (typeof a === 'string') {
throw new TypeError(a);
}
return formRef.value?.validate();
}
function getForm() {
let tempForm = cloneDeep(form);
const tempForm = cloneDeep(form);
tempForm.priceStyleName = getDictObj(
DICT_TYPE.contract_price_style,
@ -325,40 +341,40 @@ function getForm() {
tempForm.choiceType,
)?.label;
let extraForm = getExtraForm();
const extraForm = getExtraForm();
return { form: tempForm, ...extraForm };
return form;
}
function getExtraForm() {
console.log(form);
if (form.frameProtocol === '0') {
let fullData = providerGridRefs2.value.getTableData().fullData || [];
const fullData = providerGridRefs2.value.getTableData().fullData || [];
return {
biddingList: [],
contractRecommendProviderList: fullData.map((item) => ({
...item,
phaseSeq: 99999,
phaseSeq: 99_999,
})),
};
}
if (form.frameProtocol === '1') {
const tempBidList: any = [];
debugger;
const tempProviderList: any = [];
for (const item of bidList.value) {
const gridRef = bidGridRefs.value.get(item.phaseSeq);
const gridRef = bidGridRefs.value.get(`${item.phaseSeq}`);
const fullData = gridRef.getTableData().fullData;
console.log(fullData);
if (fullData.length > 0) {
const bidInfo = fullData[0];
if (!bidInfo.phaseName) {
message.error(`【标段${item.phaseSeq}】中的标段名称不能为空`);
return;
return `【标段${item.phaseSeq}】中的标段名称不能为空`;
}
if (!bidInfo.phaseMoney) {
message.error(`${item.phaseName}】中的预算金额不能为空`);
return;
return `${item.phaseName}】中的预算金额不能为空`;
}
bidInfo.id = undefined;
bidInfo.priceType = form.priceType;
@ -366,23 +382,20 @@ function getExtraForm() {
tempBidList.push(bidInfo);
const providerGrid = providerGridRefs.value.get(item.phaseSeq);
const providerGrid = providerGridRefs.value.get(`${item.phaseSeq}`);
const providerFullData = providerGrid.getTableData().fullData;
console.log(providerFullData);
for (const item2 of providerFullData || []) {
item2.phaseSeq = item.phaseSeq;
if (!item2.aptitudeName) {
message.error(`【标段${item.phaseSeq}】中供应商资质名称不能为空`);
return;
return `【标段${item.phaseSeq}】中供应商资质名称不能为空`;
}
if (!item2.contactPerson) {
message.error(`【标段${item.phaseSeq}】中供应商联系人不能为空`);
return;
return `【标段${item.phaseSeq}】中供应商联系人不能为空`;
}
if (!item2.contactPhone) {
message.error(`【标段${item.phaseSeq}】中供应商联系人电话不能为空`);
return;
return `【标段${item.phaseSeq}】中供应商联系人电话不能为空`;
}
item2.contractId = form.contractId;
tempProviderList.push(item2);
@ -402,10 +415,10 @@ defineExpose({ validate, getForm });
<template>
<ChooseCompanyModal class="w-[950px]" @confirm="handleChooseCompanyConfirm" />
<a-form
:model="form"
:rules="rules"
ref="formRef"
:label-col="{ style: { width: '120px' } }"
:model="form"
:rules="rules"
label-wrap
>
<a-row :gutter="16">
@ -433,8 +446,8 @@ defineExpose({ validate, getForm });
<a-form-item label="项目名称" name="projectName">
<a-select
v-model:value="form.projectName"
:options="dictMap[DICT_TYPE.comprehensive_project_name]"
:disabled="readOnly"
:options="dictMap[DICT_TYPE.comprehensive_project_name]"
/>
</a-form-item>
</a-col>
@ -575,9 +588,9 @@ defineExpose({ validate, getForm });
<span class="ml-2 mr-4 w-full">标段数量</span>
<a-select
v-model:value="form.bidNum"
:disabled="readOnly"
:options="dictMap[DICT_TYPE.section_num]"
class="min-w-[180px]"
:disabled="readOnly"
@change="onBidNumChange"
/>
</div>
@ -608,8 +621,8 @@ defineExpose({ validate, getForm });
<template #phasemoney-slot="{ row }">
<a-input-number
v-model:value="row.phaseMoney"
addon-after="元"
:disabled="readOnly"
addon-after="元"
/>
</template>
@ -622,10 +635,10 @@ defineExpose({ validate, getForm });
<!-- 操作的插槽 -->
<template #operate-slot="{ row }">
<a-button
:disabled="readOnly"
size="small"
type="primary"
@click="onChooseProvider(row)"
:disabled="readOnly"
>
选择供应商
</a-button>

View File

@ -28,6 +28,9 @@ import { getFormSchema } from './curd';
import BasicInfoCard from './basic-info-card.vue';
import { cloneDeep } from 'lodash-es';
import BusinessCard from './business-card.vue';
import AuditNodeTable from '#/views/contract/components/audit-node-table/audit-node-table.vue';
const [ChooseCompanyModal, chooseCompanyModalApi] = useVbenModal({
connectedComponent: chooseCompanyModal,
});
@ -67,6 +70,17 @@ const isLoading = ref(true);
const bidGridRefs = ref<Map<string, any>>(new Map());
const providerGridRefs = ref<Map<string, any>>(new Map());
const readOnly = computed(() => {
return [
'smDepartmentAudit',
'smPlanningDepartment',
'smFinancialDepartment',
'smRegulationDepartment',
'smManager',
'smLeaders',
].includes(businessData.value.step);
});
watch(
() => contractData.value.frameProtocol,
(newValue) => {
@ -152,7 +166,7 @@ function handleBack() {
* 页面返回并关闭tab
*/
function back() {
router.replace('/contract/business/list');
router.replace('/contract/business/todo');
}
const handleChange = (info: UploadChangeParam) => {
@ -174,7 +188,7 @@ function handleDelete() {
});
}
const collapses = ['1', '2', '3', '4'];
const collapses = ['1', '2', '3', '4', '5'];
// const collapses = ['3', '4'];
const collapseActiveKey = ref(collapses);
function areArraysEqualUnordered(arr1, arr2) {
@ -381,7 +395,8 @@ async function handleSave() {
try {
await contractCardRef.value.validate();
await businessCardRef.value.validate();
} catch {
} catch (e) {
console.log(e);
message.error('请完成必填项的填写');
return;
}
@ -509,7 +524,6 @@ async function handleSubmit(type: 'openModal' | 'submit') {
}
if (type === 'submit') {
isLoading.value = true;
try {
await Apis.selectMerchantsBasicInfo.post_flowStart({
data: {
@ -556,6 +570,9 @@ onMounted(async () => {
const business: any = await Apis.selectMerchantsBasicInfo.get_getOne({
params: { contractId: contract.contractId },
});
contractData.value.businessStep = business.step;
business.priceType = contract.priceType;
business.priceTypeName = contract.priceTypeName;
business.frameProtocol = contract.frameProtocol;
@ -563,7 +580,8 @@ onMounted(async () => {
selectMerchantsBasicInfoId.value = business.guid;
if (business.fileUuid) {
const files = await fileUploader.select(business.fileUuid);
business.fileList = files;
// business.fileList = files;
fileList.value = files;
}
businessData.value = business;
@ -738,15 +756,30 @@ onMounted(async () => {
accept=".pdf,.ppt,.pptx"
name="file"
@change="handleChange"
:disabled="readOnly"
>
<a-button>
<a-button v-if="!readOnly">
<MdiUpload />
点击上传
</a-button>
<div
v-if="readOnly && fileList.length === 0"
class="text-gray-700"
>
无附件
</div>
</a-upload>
</a-form-item>
</a-form>
</a-collapse-panel>
<a-collapse-panel
v-if="businessData.flowInstanceId"
key="5"
class="w-full"
header="审批信息"
>
<AuditNodeTable :flow-instance-id="businessData.flowInstanceId" />
</a-collapse-panel>
</a-collapse>
</div>
</a-spin>

View File

@ -1,23 +1,28 @@
<script setup lang="ts">
import { computed, onMounted, reactive, ref } from "vue";
import { useRouter } from "vue-router";
import { computed, onMounted, reactive, ref } from 'vue';
import { useRouter } from 'vue-router';
import { Page } from "@vben/common-ui";
import { MdiExport, MdiRadioChecked, MdiRadioUnchecked, MdiUpdate } from "@vben/icons";
import { Page } from '@vben/common-ui';
import {
MdiExport,
MdiRadioChecked,
MdiRadioUnchecked,
MdiUpdate,
} from '@vben/icons';
import { message } from "ant-design-vue";
import { message } from 'ant-design-vue';
import Apis from "#/api";
import { useVxeTable } from "#/hooks/vxeTable";
import { toDetailPage } from "#/views/contract/utils.ts";
import Apis from '#/api';
import { useVxeTable } from '#/hooks/vxeTable';
import { toDetailPage } from '#/views/contract/utils.ts';
import { getColumns, getFormSchema, PrimaryKey } from "./crud.tsx";
import { getColumns, getFormSchema, PrimaryKey } from './crud.tsx';
const router = useRouter();
const searchRef = ref();
const { xGridRef, triggerProxy, gridProps } = useVxeTable({ ref: "xGridRef" });
const { xGridRef, triggerProxy, gridProps } = useVxeTable({ ref: 'xGridRef' });
/** Hooks - 表格 */
const gridOptions = reactive(
@ -44,35 +49,37 @@ const gridOptions = reactive(
toolbarConfig: {
enabled: true,
},
})
}),
);
function handleEdit(record?: any) {
// if (["end"].includes(record.step)) {
// router.push(
// `/contract/business/result/${record[PrimaryKey]}?flowInstanceId=${record.flowInstanceId}`
// );
// } else {
router.push(`/contract/business/edit/${record["contractId"]}`);
// }
if (false) {
router.push(
`/contract/business/result/${record[PrimaryKey]}?flowInstanceId=${record.flowInstanceId}`,
);
} else {
router.push(
`/contract/business/edit/${record['contractId']}?flowInstanceId=${record.flowInstanceId}`,
);
}
}
function handleExport() {
const $grid = xGridRef.value;
if ($grid) {
$grid.exportData({
type: "xlsx",
type: 'xlsx',
columnFilterMethod: ({ column }) => {
if (["operate", "step"].includes(column.field)) {
if (['operate', 'step'].includes(column.field)) {
return false;
}
if (column.type === "radio") {
if (column.type === 'radio') {
return false;
}
return true;
},
});
message.success("导出成功");
message.success('导出成功');
}
}
@ -96,13 +103,13 @@ function handleCellClick({ row }) {
}
onMounted(() => {
triggerProxy("reload");
triggerProxy('reload');
});
const searchForm = ref({
...getFormSchema(),
onSearch(_context: any) {
triggerProxy("reload");
triggerProxy('reload');
},
});
</script>
@ -133,7 +140,11 @@ const searchForm = ref({
</fs-search>
<div class="min-h-300px flex-1">
<vxe-grid ref="xGridRef" v-bind="gridOptions" @cell-click="handleCellClick">
<vxe-grid
ref="xGridRef"
v-bind="gridOptions"
@cell-click="handleCellClick"
>
<template #toolbar_buttons>
<a-space>
<vben-button

View File

@ -1,23 +1,28 @@
<script setup lang="ts">
import { computed, onMounted, reactive, ref } from "vue";
import { useRouter } from "vue-router";
import { computed, onMounted, reactive, ref } from 'vue';
import { useRouter } from 'vue-router';
import { Page } from "@vben/common-ui";
import { MdiExport, MdiRadioChecked, MdiRadioUnchecked, MdiUpdate } from "@vben/icons";
import { Page } from '@vben/common-ui';
import {
MdiExport,
MdiRadioChecked,
MdiRadioUnchecked,
MdiUpdate,
} from '@vben/icons';
import { message } from "ant-design-vue";
import { message } from 'ant-design-vue';
import Apis from "#/api";
import { useVxeTable } from "#/hooks/vxeTable";
import { toDetailPage } from "#/views/contract/utils.ts";
import Apis from '#/api';
import { useVxeTable } from '#/hooks/vxeTable';
import { toDetailPage } from '#/views/contract/utils.ts';
import { getColumns, getFormSchema, PrimaryKey } from "./crud.tsx";
import { getColumns, getFormSchema, PrimaryKey } from './crud.tsx';
const router = useRouter();
const searchRef = ref();
const { xGridRef, triggerProxy, gridProps } = useVxeTable({ ref: "xGridRef" });
const { xGridRef, triggerProxy, gridProps } = useVxeTable({ ref: 'xGridRef' });
/** Hooks - 表格 */
const gridOptions = reactive(
@ -44,35 +49,31 @@ const gridOptions = reactive(
toolbarConfig: {
enabled: true,
},
})
}),
);
function handleEdit(record?: any) {
if (["end"].includes(record.step)) {
router.push(
`/contract/business/result/${record[PrimaryKey]}?flowInstanceId=${record.flowInstanceId}`
);
} else {
router.push(`/contract/business/edit/${record[PrimaryKey]}`);
}
router.push(
`/contract/business/result/${record.contractId}?flowInstanceId=${record.flowInstanceId}`,
);
}
function handleExport() {
const $grid = xGridRef.value;
if ($grid) {
$grid.exportData({
type: "xlsx",
type: 'xlsx',
columnFilterMethod: ({ column }) => {
if (["operate", "step"].includes(column.field)) {
if (['operate', 'step'].includes(column.field)) {
return false;
}
if (column.type === "radio") {
if (column.type === 'radio') {
return false;
}
return true;
},
});
message.success("导出成功");
message.success('导出成功');
}
}
@ -96,13 +97,13 @@ function handleCellClick({ row }) {
}
onMounted(() => {
triggerProxy("reload");
triggerProxy('reload');
});
const searchForm = ref({
...getFormSchema(),
onSearch(_context: any) {
triggerProxy("reload");
triggerProxy('reload');
},
});
</script>
@ -133,7 +134,11 @@ const searchForm = ref({
</fs-search>
<div class="min-h-300px flex-1">
<vxe-grid ref="xGridRef" v-bind="gridOptions" @cell-click="handleCellClick">
<vxe-grid
ref="xGridRef"
v-bind="gridOptions"
@cell-click="handleCellClick"
>
<template #toolbar_buttons>
<a-space>
<vben-button

View File

@ -1,12 +1,14 @@
<script setup lang="ts">
import { onMounted, ref } from "vue";
import { onMounted, ref } from 'vue';
import { useVbenModal } from "@vben/common-ui";
import { useVbenModal } from '@vben/common-ui';
import chooseCompanyModal from "../../company/list/choose-company-modal.vue";
import { message } from "ant-design-vue";
import Apis from "#/api";
import { logger } from "common-utils";
import { message } from 'ant-design-vue';
import { logger } from 'common-utils';
import Apis from '#/api';
import chooseCompanyModal from '../../company/list/choose-company-modal.vue';
const props = withDefaults(
defineProps<{
@ -14,20 +16,20 @@ const props = withDefaults(
projectId: string;
}>(),
{
contractId: "",
projectId: "",
}
contractId: '',
projectId: '',
},
);
const emit = defineEmits<{
(e: "submit", data: any): void;
(e: 'submit', data: any): void;
}>();
const [ChooseCompanyModal, chooseCompanyModalApi] = useVbenModal({
connectedComponent: chooseCompanyModal,
});
const companyChooseType = ref<"providerPt" | "biddingProvider">("providerPt");
const companyChooseType = ref<'biddingProvider' | 'providerPt'>('providerPt');
/** 必填字段校验 */
const requiredFieldRules: any = {
@ -41,11 +43,11 @@ const requiredFieldRules: any = {
/** 必填字段校验,如果是必填字段则返回对应message */
function isRequired(field: string): string {
let rule = requiredFieldRules[field];
const rule = requiredFieldRules[field];
if (rule && rule.required) {
return rule.message || `${field}不可为空`;
}
return "";
return '';
}
const biddingExpertRef = ref();
@ -62,19 +64,19 @@ const biddingPtInfo = ref<any>({});
const biddingProviderRef = ref();
const biddingProviderList = ref([{}]);
function onAddProviderPt(type: string, data?: any) {
companyChooseType.value = "providerPt";
companyChooseType.value = 'providerPt';
const tableFullData = providerPtRef1.value.getTableData()?.fullData || [];
if (type === "openModal") {
if (type === 'openModal') {
chooseCompanyModalApi.setData({
title: "选择单位",
title: '选择单位',
limitMultipleNum: 5,
guids: tableFullData.map((item) => item.guid) || [],
});
chooseCompanyModalApi.open();
}
if (type === "confirm") {
if (type === 'confirm') {
console.log(data);
data.map((item) => (item.guid = undefined));
providerPtRef1.value.insert(data);
@ -83,19 +85,19 @@ function onAddProviderPt(type: string, data?: any) {
}
function onAddBiddingProvider(type: string, data?: any) {
companyChooseType.value = "biddingProvider";
companyChooseType.value = 'biddingProvider';
const tableFullData = biddingProviderRef.value.getTableData()?.fullData || [];
if (type === "openModal") {
if (type === 'openModal') {
chooseCompanyModalApi.setData({
title: "选择单位",
title: '选择单位',
limitMultipleNum: 1,
guids: tableFullData.map((item) => item.guid) || [],
});
chooseCompanyModalApi.open();
}
if (type === "confirm") {
if (type === 'confirm') {
console.log(data);
data.map((item) => (item.guid = undefined));
biddingProviderRef.value.loadData(data);
@ -114,7 +116,7 @@ function onRemoveBiddingExpertRow(row) {
function onRemoveProviderPtRow(row) {
providerPtRef1.value.remove(row);
let fullData = providerPtRef2.value.getTableData().fullData;
const fullData = providerPtRef2.value.getTableData().fullData;
for (const item of fullData) {
if (item.providerId === row.providerId) {
providerPtRef2.value.remove(item);
@ -123,11 +125,11 @@ function onRemoveProviderPtRow(row) {
}
function handleChooseCompanyConfirm(e) {
if (companyChooseType.value == "providerPt") {
onAddProviderPt("confirm", e);
if (companyChooseType.value == 'providerPt') {
onAddProviderPt('confirm', e);
}
if (companyChooseType.value == "biddingProvider") {
onAddBiddingProvider("confirm", e);
if (companyChooseType.value == 'biddingProvider') {
onAddBiddingProvider('confirm', e);
}
}
@ -143,14 +145,14 @@ async function verify() {
}
function getFormData() {
let _fullData1 = providerPtRef1.value.getTableData().fullData;
let _fullData2 = providerPtRef2.value.getTableData().fullData;
let _fullData3 = biddingExpertRef.value.getTableData().fullData;
let _fullData4 = biddingProviderRef.value.getTableData().fullData;
const _fullData1 = providerPtRef1.value.getTableData().fullData;
const _fullData2 = providerPtRef2.value.getTableData().fullData;
const _fullData3 = biddingExpertRef.value.getTableData().fullData;
const _fullData4 = biddingProviderRef.value.getTableData().fullData;
console.log(_fullData1, _fullData2, _fullData3, _fullData4);
let data1: any[] = [];
const data1: any[] = [];
for (const item1 of _fullData1) {
for (const item2 of _fullData2) {
@ -166,13 +168,13 @@ function getFormData() {
}
}
let tempBiddingResult = JSON.parse(JSON.stringify(biddingResult.value));
const tempBiddingResult = JSON.parse(JSON.stringify(biddingResult.value));
tempBiddingResult.projectId = props.projectId;
let tempBiddingPtInfo = JSON.parse(JSON.stringify(biddingPtInfo.value));
const tempBiddingPtInfo = JSON.parse(JSON.stringify(biddingPtInfo.value));
tempBiddingPtInfo.projectId = props.projectId;
_fullData3.map((item) => (item.projectId = props.projectId));
let form = {
const form = {
biddingResult: tempBiddingResult,
biddingExpertList: _fullData3,
providerPtList: data1,
@ -185,28 +187,28 @@ function getFormData() {
onMounted(async () => {
try {
//
let data = await Apis.biddingResult.get_page({
const data = await Apis.biddingResult.get_page({
params: {
pageNum: 1,
pageSize: 1,
projectId: props.projectId,
},
});
if (data.rows.length) {
if (data.rows.length > 0) {
biddingResult.value = data.rows[0];
}
console.log("选商结果信息", biddingResult.value);
console.log('选商结果信息', biddingResult.value);
//
let experData = await Apis.biddingExpert.get_list({
const experData = await Apis.biddingExpert.get_list({
params: {
contractId: props.contractId,
projectId: props.projectId,
},
});
console.log("招标专家信息", experData);
console.log('招标专家信息', experData);
} catch (error) {
logger.error("获取选商结果填报数据出错", error);
logger.error('获取选商结果填报数据出错', error);
}
// biddingResult.value = currData.value;
});
@ -220,7 +222,12 @@ defineExpose({
<template>
<ChooseCompanyModal class="w-[950px]" @confirm="handleChooseCompanyConfirm" />
<a-descriptions :label-style="{ width: '150px' }" bordered size="small" title="">
<a-descriptions
:label-style="{ width: '150px' }"
bordered
size="small"
title=""
>
<a-descriptions-item :span="3" label="标段信息">
<vxe-table ref="providerPtRef1" :data="providerPtList" size="mini">
<vxe-column field="providerName" title="单位名称">
@ -240,7 +247,11 @@ defineExpose({
</vxe-column>
<vxe-column field="operate" title="" width="100">
<template #header>
<a-button size="small" type="primary" @click="onAddProviderPt('openModal')">
<a-button
size="small"
type="primary"
@click="onAddProviderPt('openModal')"
>
添加
</a-button>
</template>
@ -371,7 +382,10 @@ defineExpose({
</vxe-column>
<vxe-column field="offerMoney" title="报价(人民币元)">
<template #default="{ row }">
<a-input-number v-model:value="row.offerMoney" addon-after="" />
<a-input-number
v-model:value="row.offerMoney"
addon-after="元"
/>
</template>
</vxe-column>
<vxe-column field="bidScore" title="综合得分(综合评价)">
@ -395,10 +409,14 @@ defineExpose({
</a-descriptions-item>
<a-descriptions-item :span="3" label="招标结果">
<vxe-table ref="biddingProviderRef" :data="biddingProviderList" size="mini">
<vxe-table
ref="biddingProviderRef"
:data="biddingProviderList"
size="mini"
>
<vxe-column field="providerName" title="单位名称">
<template #default="{ row }">
{{ row.providerName || "" }}
{{ row.providerName || '' }}
<a-button
size="small"
type="primary"

View File

@ -1,20 +1,20 @@
<script setup lang="ts">
import { computed, onMounted, ref } from "vue";
import { useRoute, useRouter } from "vue-router";
import { computed, onMounted, ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { Page, useVbenModal } from "@vben/common-ui";
import { Page, useVbenModal } from '@vben/common-ui';
import { message, Modal } from "ant-design-vue";
import { logger } from "common-utils";
import { message, Modal } from 'ant-design-vue';
import { logger } from 'common-utils';
import Apis from "#/api";
import AuditNodeTable from "#/views/contract/components/audit-node-table/audit-node-table.vue";
import FileCard from "#/views/contract/components/file-card/file-card.vue";
import ApprovalCard from "#/views/contract/iframe-info/components/info-approval/approval-card.vue";
import BusinessCard from "#/views/contract/iframe-info/components/info-business/business-card.vue";
import chooseUserModal from "#/views/system/user/choose-user-modal.vue";
import Apis from '#/api';
import AuditNodeTable from '#/views/contract/components/audit-node-table/audit-node-table.vue';
import FileCard from '#/views/contract/components/file-card/file-card.vue';
import ApprovalCard from '#/views/contract/iframe-info/components/info-approval/approval-card.vue';
import BusinessCard from '#/views/contract/iframe-info/components/info-business/business-card.vue';
import chooseUserModal from '#/views/system/user/choose-user-modal.vue';
import FillResultCard from "./fill-result-card.vue";
import FillResultCard from './fill-result-card.vue';
const [ChooseUserModal, chooseUserModalApi] = useVbenModal({
connectedComponent: chooseUserModal,
@ -35,10 +35,12 @@ const isLoading = ref(false);
const contractTypeData = ref([]);
const bidList = ref<any[]>([]);
const submitGuid = ref();
// const collapses = ['1', '2', '3', '4','5'];
const collapses = ["5"];
const collapses = ['1', '2', '3', '4', '5'];
// const collapses = ['5'];
const collapseActiveKey = ref(collapses);
function areArraysEqualUnordered(arr1, arr2) {
if (arr1.length !== arr2.length) return false;
@ -57,19 +59,19 @@ function handleFold() {
* 页面返回并关闭tab
*/
function back() {
router.replace("/contract/business/list");
router.replace('/contract/business/list');
}
const selectUsers = ref([]);
async function handleChooseUserConfirm(e) {
selectUsers.value = e;
chooseUserModalApi.close();
handleSubmit("submit");
handleSubmit('submit');
}
function handleBack() {
Modal.confirm({
title: "提示",
title: '提示',
content: `是否确认返回上一页面?`,
onOk: async () => {
back();
@ -80,43 +82,43 @@ function handleBack() {
async function handleSave() {
try {
await fillResultCardRef.value.verify();
} catch (error) {
message.error("请完成必填项的填写");
} catch {
message.error('请完成必填项的填写');
return;
}
try {
let form = fillResultCardRef.value.getFormData();
const form = fillResultCardRef.value.getFormData();
console.log(form);
let data = await Apis.biddingResult.post_save({
const data = await Apis.biddingResult.post_save({
data: form,
});
submitGuid.value = data.guid;
message.success("保存成功");
message.success('保存成功');
Modal.confirm({
title: "提示",
content: "保存成功!是否进行提交?提交后数据将不可变更",
title: '提示',
content: '保存成功!是否进行提交?提交后数据将不可变更',
onOk: () => {
handleSubmit("openModal");
handleSubmit('openModal');
},
onCancel: () => {
back();
},
});
} catch (error) {
logger.error("选商结果填报保存失败", error);
logger.error('选商结果填报保存失败', error);
}
}
async function handleSubmit(type: "openModal" | "submit") {
if (type === "openModal") {
async function handleSubmit(type: 'openModal' | 'submit') {
if (type === 'openModal') {
chooseUserModalApi.setData({
title: "选择审批人",
title: '选择审批人',
});
chooseUserModalApi.open();
}
if (type === "submit") {
if (type === 'submit') {
isLoading.value = true;
try {
@ -126,11 +128,11 @@ async function handleSubmit(type: "openModal" | "submit") {
// assigneeList: selectUsers.value.map((item) => item.ACCOUNT_ID),
// },
// });
message.success("提交成功");
message.success('提交成功');
back();
} catch (error) {
message.error("提交失败,请稍候再试");
logger.error("合同选商结果提交", error);
message.error('提交失败,请稍候再试');
logger.error('合同选商结果提交', error);
} finally {
isLoading.value = false;
}
@ -147,7 +149,7 @@ onMounted(async () => {
if (id.value) {
const contract: any = await Apis.contractBaseInfo.get_getOne({
params: { guid: id.value },
params: { contractId: id.value },
});
currData.value = contract;
@ -155,13 +157,23 @@ onMounted(async () => {
params: { contractId: contract.contractId },
});
businseeData.value = business;
//
const providerData = await Apis.contractRecommendProvider.get_list({
params: {
contractId: business.contractId,
},
});
providerList = providerData.rows || [];
// xGridRef.value!.reloadColumn(getColumns());
}
} catch (error) {
logger.error("获取合同信息出错", error);
logger.error('获取合同信息出错', error);
Modal.error({
title: "提示",
content: "当前合同信息不存在",
title: '提示',
content: '当前合同信息不存在',
onOk() {},
});
} finally {
@ -172,21 +184,37 @@ onMounted(async () => {
<template>
<Page ref="pageRef" content-class="h-full flex flex-col">
<ChooseUserModal class="w-[950px]" multiple @confirm="handleChooseUserConfirm" />
<ChooseUserModal
class="w-[950px]"
multiple
@confirm="handleChooseUserConfirm"
/>
<a-affix :offset-top="0" :style="{ zIndex: 50 }" :target="() => pageRef.bodyRef">
<a-affix
:offset-top="0"
:style="{ zIndex: 50 }"
:target="() => pageRef.bodyRef"
>
<div class="flex w-full flex-row bg-white pl-1 pt-1">
<a-space class="flex-1">
<template v-if="!isLoading">
<vben-button variant="primary" @click="handleSave()"> 保存 </vben-button>
<vben-button :disabled="!submitGuid" variant="primary" @click="handleSave()">
<vben-button variant="primary" @click="handleSave()">
保存
</vben-button>
<vben-button
:disabled="!submitGuid"
variant="primary"
@click="handleSave()"
>
提交
</vben-button>
</template>
<vben-button variant="secondary" @click="handleBack()"> 返回 </vben-button>
<vben-button variant="secondary" @click="handleBack()">
返回
</vben-button>
</a-space>
<vben-button variant="secondary" @click="handleFold()">
一键{{ isFold ? "展开" : "收起" }}
一键{{ isFold ? '展开' : '收起' }}
</vben-button>
</div>
</a-affix>

View File

@ -37,6 +37,8 @@ const data = ref({
});
const checkRecords = ref([]);
const checkRecordIds = ref([]);
const limitMultipleNum = ref(1);
const searchBinding = ref({
@ -63,8 +65,13 @@ const gridOptions = reactive(
...searchRef.value.formData,
},
});
for (const row of checkRecords.value) {
xGridRef.value!.setCheckboxRow(row, true);
for (const row of checkRecordIds.value) {
for (const item of result.rows || []) {
if (item.guid === row) {
xGridRef.value!.setCheckboxRow(item, true);
checkRecords.value.push(item);
}
}
}
return result;
},
@ -82,11 +89,10 @@ const gridOptions = reactive(
//
reserve: true,
checkMethod: ({ row }) => {
const checkRecordIds =
checkRecords.value.map((item) => item.guid) || [];
const tempCheckRecordIds = checkRecordIds.value || [];
if (
checkRecords.value.length < limitMultipleNum.value ||
checkRecordIds.includes(row.guid)
checkRecordIds.value.length < limitMultipleNum.value ||
tempCheckRecordIds.includes(row.guid)
) {
return true;
}
@ -115,6 +121,7 @@ function handleCheckboxChange(e) {
if (e.checked) {
const existingIds = new Set(checkRecords.value.map((item) => item.guid));
checkRecordIds.value = [...checkRecordIds.value, e.row.guid];
if (!existingIds.has(e.row.guid)) {
checkRecords.value = [...checkRecords.value, e.row];
@ -138,6 +145,8 @@ function handleCloseTag(row) {
const title = ref('选择合同相对人');
// id
const existIds = ref([]);
const [BaseModal, baseModalApi] = useVbenModal({
onOpenChange(isOpen: boolean) {
if (isOpen) {
@ -150,6 +159,8 @@ const [BaseModal, baseModalApi] = useVbenModal({
limitMultipleNum.value = data.value.limitMultipleNum;
}
console.log(data.value.guids);
checkRecordIds.value = data.value.guids || [];
existIds.value = data.value.guids || [];
const rows: any = [];
for (const element of checkRecords.value) {
if (data.value.guids.includes(element.guid)) {
@ -160,8 +171,12 @@ const [BaseModal, baseModalApi] = useVbenModal({
}
},
onConfirm() {
console.info('onConfirm');
emit('confirm', checkRecords.value);
console.info('onConfirm', checkRecords.value);
// id
const result = checkRecords.value.filter(
(item) => !existIds.value.includes(item.guid),
);
emit('confirm', result);
baseModalApi.close();
},
onCancel() {

View File

@ -1,68 +1,205 @@
<script setup lang="ts">
import { DICT_TYPE, getDictObj, getDictOptions } from "#/utils/dict";
import FileCard from "#/views/contract/components/file-card/file-card.vue";
import { onMounted, ref } from 'vue';
withDefaults(
import Apis from '#/api';
import { DICT_TYPE, getDictObj } from '#/utils/dict';
const props = withDefaults(
defineProps<{
info: any;
}>(),
{
info: () => {},
}
},
);
const bidList = ref<any[]>([]);
const providerPtList = ref<any[]>([]);
onMounted(async () => {
// console.log(info.value);
const info = props.info;
//
//
if (info.frameProtocol === '1') {
const bidData = await Apis.bidding.get_list({
params: {
projectId: info.projectId,
contractId: info.contractId,
},
});
bidData.rows.forEach((bid) => {
bid.providerList = [];
});
bidList.value = bidData.rows;
}
//
const providerData = await Apis.contractRecommendProvider.get_list({
params: {
contractId: info.contractId,
},
});
if (info.frameProtocol === '0') {
providerPtList.value = providerData.rows;
}
if (info.frameProtocol === '1') {
bidList.value.forEach((bid) => {
bid.providerList = providerData.rows;
});
}
});
</script>
<template>
<a-descriptions title="" size="small" :labelStyle="{ width: '150px' }" bordered>
<a-descriptions-item label="项目" :span="3">
<a-descriptions
:label-style="{ width: '150px' }"
bordered
size="small"
title=""
>
<a-descriptions-item :span="3" label="项目">
{{ info.projectNum }}
</a-descriptions-item>
<a-descriptions-item label="项目类别" :span="1">
<a-descriptions-item :span="1" label="项目类别">
{{ getDictObj(DICT_TYPE.contract_project_type, info.projectProp)?.label }}
</a-descriptions-item>
<a-descriptions-item label="项目名称" :span="1">
<a-descriptions-item :span="1" label="项目名称">
{{ info.projectName }}
</a-descriptions-item>
<a-descriptions-item label="商务计价方式" :span="1">
<a-descriptions-item :span="1" label="商务计价方式">
{{ getDictObj(DICT_TYPE.contract_price_style, info.priceStyleId)?.label }}
</a-descriptions-item>
<a-descriptions-item label="备注" :span="3">
{{ info.remark || "无" }}
<a-descriptions-item :span="3" label="备注">
{{ info.remark || '无' }}
</a-descriptions-item>
<a-descriptions-item label="选商方式" :span="1">
{{ getDictObj(DICT_TYPE.contract_selection_method, info.choiceType)?.label }}
<a-descriptions-item :span="3" label="选商方式">
{{
getDictObj(DICT_TYPE.contract_selection_method, info.choiceType)?.label
}}
</a-descriptions-item>
<a-descriptions-item label="选商方式说明" :span="3">
{{ info.choiceReason || "无" }}
<a-descriptions-item :span="3" label="选商方式说明">
{{ info.choiceReason || '无' }}
</a-descriptions-item>
<a-descriptions-item label="资质要求" :span="3">
{{ info.qualificReq || "无" }}
<a-descriptions-item :span="3" label="资质要求">
{{ info.qualificReq || '无' }}
</a-descriptions-item>
<a-descriptions-item label="受托招标代理">
{{ (info.budgetSum || "") + " " + (info.priceTypeName || "") }}
<a-descriptions-item :span="3" label="受托招标代理">
{{ `${info.budgetSum || ''} ${info.priceTypeName || ''}` }}
</a-descriptions-item>
<a-descriptions-item label="推荐供应商" :span="3">
{{ info.stockPlanMx || "无" }}
<a-descriptions-item
v-show="info.frameProtocol === '0'"
:span="3"
label="推荐供应商"
>
<div class="w-full">
<vxe-table :data="providerPtList" size="mini">
<vxe-column field="providerName" title="供应商名称">
<template #default="{ row }">
{{ row.providerName }}
</template>
</vxe-column>
<vxe-column field="qualification" title="资质情况">
<template #default="{ row }">
{{ row.qualification }}
</template>
</vxe-column>
<vxe-column field="contactPerson" title="联系人">
<template #default="{ row }">
{{ row.contactPerson }}
</template>
</vxe-column>
<vxe-column field="contactPhone" title="联系电话">
<template #default="{ row }">
{{ row.contactPhone }}
</template>
</vxe-column>
<vxe-column field="remarks" title="备注">
<template #default="{ row }">
{{ row.remarks }}
</template>
</vxe-column>
</vxe-table>
</div>
</a-descriptions-item>
<a-descriptions-item label="项目范围" :span="3">
{{ info.projectRange || "无" }}
<a-descriptions-item
v-show="info.frameProtocol === '1'"
:span="3"
label="标段信息"
>
<template v-for="bid in bidList" :key="bid.id">
<vxe-table :data="[bid]" size="mini">
<vxe-column field="bidName" title="标段名称">
<template #default="{ row }">
{{ row.bidName }}
</template>
</vxe-column>
<vxe-column field="phaseMoney" title="预算金额">
<template #default="{ row }">
{{ row.phaseMoney }}
</template>
</vxe-column>
<vxe-column field="phaseDesc" title="标段范围说明">
<template #default="{ row }">
{{ row.phaseDesc }}
</template>
</vxe-column>
<vxe-column field="phaseDesc" title="标段范围说明">
<template #default="{ row }">
{{ row.phaseDesc }}
</template>
</vxe-column>
</vxe-table>
<vxe-table :data="bid.providerList" size="mini">
<vxe-column field="providerName" title="供应商名称">
<template #default="{ row }">
{{ row.providerName }}
</template>
</vxe-column>
<vxe-column field="qualification" title="资质情况">
<template #default="{ row }">
{{ row.qualification }}
</template>
</vxe-column>
<vxe-column field="contactPerson" title="联系人">
<template #default="{ row }">
{{ row.contactPerson }}
</template>
</vxe-column>
<vxe-column field="contactPhone" title="联系电话">
<template #default="{ row }">
{{ row.contactPhone }}
</template>
</vxe-column>
<vxe-column field="remarks" title="备注">
<template #default="{ row }">
{{ row.remarks }}
</template>
</vxe-column>
</vxe-table>
</template>
</a-descriptions-item>
<a-descriptions-item label="项目内容" :span="3">
{{ info.projectContent || "无" }}
<a-descriptions-item :span="3" label="项目范围">
{{ info.projectRange || '无' }}
</a-descriptions-item>
<a-descriptions-item label="工期/质量要求" :span="3">
{{ info.quality || "无" }}
<a-descriptions-item :span="3" label="项目内容">
{{ info.projectContent || '无' }}
</a-descriptions-item>
<a-descriptions-item label="工程量(采购量)" :span="3">
{{ info.stockNums || "无" }}
<a-descriptions-item :span="3" label="工期/质量要求">
{{ info.quality || '无' }}
</a-descriptions-item>
<a-descriptions-item label="计划投资明细" :span="3">
{{ info.stockPlanMx || "无" }}
<a-descriptions-item :span="3" label="工程量(采购量)">
{{ info.stockNums || '无' }}
</a-descriptions-item>
<a-descriptions-item :span="3" label="计划投资明细">
{{ info.stockPlanMx || '无' }}
</a-descriptions-item>
</a-descriptions>
</template>

View File

@ -10,6 +10,7 @@ import {
CardTitle,
VbenButton,
} from '@vben-core/shadcn-ui';
import { logger } from 'common-utils';
defineOptions({
name: 'WorkbenchTodo',
@ -29,6 +30,29 @@ interface Props {
function handleViewAll() {
router.push('/user/todo');
}
function toDetail(type: string, id: string, row?: any) {
console.log(type, row);
if (['contractSetup', 'contractSetupAbolish'].includes(type)) {
router.push(`/contract/approval/edit/${id}?taskId=${row.taskId}`);
return;
}
if (['selectMerchant'].includes(type)) {
router.push(
`/contract/business/edit/${row.contractId}?taskId=${row.taskId}&flowInstanceId=${row.flowInstanceId}`,
);
return;
}
if (['contractDeclare'].includes(type)) {
router.push(
`/contract/declaration/edit/${row.contractId}?taskId=${row.taskId}&flowInstanceId=${row.flowInstanceId}`,
);
return;
}
logger.error(`toDetail not support type:${type}`, row);
}
</script>
<template>
@ -49,11 +73,12 @@ function handleViewAll() {
'select-none line-through opacity-60': item.completed,
}"
class="flex cursor-pointer justify-between gap-x-6 px-4 py-2"
@click="toDetail(item.module, item.businessId, item)"
>
<div class="flex min-w-0 items-center gap-x-4">
<div class="min-w-0 flex-auto">
<p class="text-foreground text-sm font-semibold leading-6">
{{ item.module }} {{ item.title }}
{{ item.moduleName }} {{ item.title }}
</p>
<!-- eslint-disable vue/no-v-html -->
<p

View File

@ -67,15 +67,16 @@ onMounted(async () => {
});
todoItems.value = data.rows.map((item) => {
let module =
let moduleName =
getDictObj(DICT_TYPE.contract_todo_type, item.module)?.label || '';
if (module) {
module = `[${module}]`;
if (moduleName) {
moduleName = `[${moduleName}]`;
}
return {
module,
...item,
moduleName,
avatar: '',
date: item.createTime,
isRead: true,

View File

@ -150,13 +150,13 @@ function handleMenuClick(e) {
<a-button> {{ value ? `代理${value}` : '代理切换' }} </a-button>
</a-dropdown>
<Notification
<!-- <Notification
:dot="showDot"
:notifications="notifications"
@clear="handleNoticeClear"
@make-all="handleMakeAll"
@view-all="handleViewAll"
/>
/> -->
</template>
<template #extra>
<AuthenticationLoginExpiredModal