This commit is contained in:
2025-12-29 16:51:44 +08:00
20 changed files with 429 additions and 157 deletions

View File

@ -3,8 +3,8 @@ import { defHttp } from '/@/utils/http/axios';
import { ErrorMessageMode } from '/#/axios';
enum Api {
// Page = '/approve/appro/page',
Page = '/magic-api/sales//lngApproPage',
Page = '/approve/appro/page',
// Page = '/magic-api/sales/lngApproPage',
List = '/approve/appro/list',
Info = '/approve/appro/info',
LngAppro = '/approve/appro',

View File

@ -4,15 +4,38 @@ import { ErrorMessageMode } from '/#/axios';
enum Api {
Page = '/contract/contractFact/page',
// Page = '/magic-api/contract/lngContractFact/page',
List = '/contract/contractFact/list',
Info = '/contract/contractFact/info',
LngContractFact = '/contract/contractFact',
queryAllCurrency ='/magic-api/mdm//queryAllCurrency'
queryAllCurrency ='/magic-api/mdm/queryAllCurrency',
queryAllUser ='/magic-api/mdm/queryAllUser',
queryBankByCode ='/magic-api/sales/queryBankByCode'
}
export async function getBankBList(code:String, type:String, mode: ErrorMessageMode = 'modal') {
return defHttp.get<LngContractFactPageResult>(
{
url: Api.queryBankByCode,
params: { code, type},
},
{
errorMessageMode: mode,
},
);
}
export async function getAllUser( mode: ErrorMessageMode = 'modal') {
return defHttp.get<LngContractFactPageResult>(
{
url: Api.queryAllUser,
params: { },
},
{
errorMessageMode: mode,
},
);
}
export async function getAllCurrency( mode: ErrorMessageMode = 'modal') {
return defHttp.get<LngContractFactPageResult>(
{

View File

@ -3,8 +3,8 @@ import { defHttp } from '/@/utils/http/axios';
import { ErrorMessageMode } from '/#/axios';
enum Api {
// Page = '/sales/scoreCustomer/page',
Page = '/magic-api/sales/scoreCustomerPage',
Page = '/sales/scoreCustomer/page',
// Page = '/magic-api/sales/scoreCustomerPage',
List = '/sales/scoreCustomer/list',
Info = '/sales/scoreCustomer/info',
LngScore = '/sales/scoreCustomer',

View File

@ -3,8 +3,8 @@ import { defHttp } from '/@/utils/http/axios';
import { ErrorMessageMode } from '/#/axios';
enum Api {
// Page = '/supplier/scoreSupplier/page',
Page = '/magic-api/supplier/scoreSupplierPage',
Page = '/supplier/scoreSupplier/page',
// Page = '/magic-api/supplier/scoreSupplierPage',
List = '/supplier/scoreSupplier/list',
Info = '/supplier/scoreSupplier/info',
LngScore = '/supplier/scoreSupplier',

View File

@ -1,5 +1,5 @@
<template>
<BasicModal v-bind="$attrs" destroyOnClose @register="registerModal" showFooter :title="getTitle" width="40%" @ok="handleSubmit" @cancel="handleCancel" :showOkBtn="!isDisable">
<BasicModal v-bind="$attrs" destroyOnClose @register="registerModal" showFooter :title="getTitle" width="60%" @ok="handleSubmit" @cancel="handleCancel" :showOkBtn="!isDisable">
<a-form ref="formRef" class="formViewStyle" :model="formState" :rules="rules" v-bind="{labelCol: { span: 8 },wrapperCol: { span: 16 },}">
<a-row>
<a-col :span="12">
@ -13,10 +13,10 @@
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="对方银行名称" name="cpBankName" :label-col="{ span: 8 }" :wrapper-col="{ span: 24 }">
<a-select v-model:value="formState.cpBankName" placeholder="请选择银行名称" :disabled="isDisable" style="width: 100%" allow-clear>
<a-select-option v-for="item in optionList" :key="item.code" :value="item.code">
{{ item.fullName }}
<a-form-item label="对方银行名称" name="cpBankCode" :label-col="{ span: 8 }" :wrapper-col="{ span: 24 }">
<a-select v-model:value="formState.cpBankCode" placeholder="请选择银行名称" :disabled="isDisable" style="width: 100%" allow-clear @change="bankChange">
<a-select-option v-for="item in optionList" :key="item.bankCode" :value="item.bankCode">
{{ item.bankName }}
</a-select-option>
</a-select>
</a-form-item>
@ -33,27 +33,27 @@
</a-col>
<a-col :span="12">
<a-form-item label="对方联系人姓名" name="contactName" :label-col="{ span: 8 }" :wrapper-col="{ span: 24 }">
<a-input v-model:value="formState.contactName" placeholder="请输入资质证书编号" />
<a-input v-model:value="formState.contactName" placeholder="请输入对方联系人姓名" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="对方联系人电话" name="contactTel" :label-col="{ span: 8 }" :wrapper-col="{ span: 24 }">
<a-input v-model:value="formState.contactTel" placeholder="请输入资质证书编号" />
<a-input v-model:value="formState.contactTel" placeholder="请输入对方联系人电话" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="对方联系人邮箱" name="contactEmail" :label-col="{ span: 8 }" :wrapper-col="{ span: 24 }">
<a-input v-model:value="formState.contactEmail" placeholder="请输入资质证书编号" />
<a-input v-model:value="formState.contactEmail" placeholder="请输入对方联系人邮箱" />
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="对方通讯地址" name="contactAddress" :label-col="{ span: 4 }" :wrapper-col="{ span: 24 }">
<a-input v-model:value="formState.contactAddress" placeholder="请输入资质证书编号" />
<a-input v-model:value="formState.contactAddress" placeholder="请输入对方通讯地址" />
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="备注" name="note" :label-col="{ span: 4 }" :wrapper-col="{ span: 24 }">
<a-textarea v-model:value="formState.note" placeholder="请输入备注最多50字" :disabled="isDisable" :maxlength="50" :auto-size="{ minRows: 2, maxRows: 5 }"/>
<a-textarea v-model:value="formState.note" placeholder="请输入备注" :disabled="isDisable" :auto-size="{ minRows: 2, maxRows: 5 }"/>
</a-form-item>
</a-col>
</a-row>
@ -64,86 +64,83 @@
<script setup lang="ts">
import { ref, onMounted, computed, unref,reactive } from 'vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicModal, useModalInner, useModal } from '/@/components/Modal';
import { Form, message } from 'ant-design-vue';
import { useI18n } from '/@/hooks/web/useI18n';
import type { Rule } from 'ant-design-vue/es/form';
import { useMessage } from '/@/hooks/web/useMessage';
import { getDocCpList } from '/@/api/sales/Customer';
import type { FormInstance } from 'ant-design-vue';
import customerSupplierListModal from '/@/components/common/customerSupplierListModal.vue';
import { getLngCustomer } from '/@/api/sales/Customer';
import { getLngSupplier } from '/@/api/supplier/Supplier';
import { getBankBList } from '/@/api/contract/ContractFact';
const { t } = useI18n();
const isUpdate = ref(true);
const isDisable = ref(false);
let optionList = reactive([])
let optionList = ref([])
const formRef = ref()
const { notification } = useMessage();
const emit = defineEmits(['success','register']);
const getTitle = computed(() => (!unref(isUpdate) ? t('新增证书') : t('编辑证书')));
const getTitle = computed(() => (!unref(isUpdate) ? t('新增相对方') : t('编辑相对方')));
let formState = reactive({
docTypeCode: '',
fileList: [],
filePath: ''
});
const list = ref()
const rules = {
docTypeCode: [{ required: true, message: "该项为必填项", trigger: 'change' }],
cpName: [{ required: true, message: "该项为必填项", trigger: 'change' }],
cpBankCode: [{ required: true, message: "该项为必填项", trigger: 'change' }],
contactEmail: [{ required: false, message: "该项为必填项", trigger: 'change' }, {type: 'email', message: '邮箱格式错误\n'} ],
};
const props = defineProps({
type: String
})
const [register, { openModal:openModal}] = useModal();
const onSearchUser = (val)=> {
openModal(true,{isUpdate: false})
}
const handleSuccess = (val) => {
formState.cpTableName = val[0].cpTableName
formState.cpCode = val[0].cpTableName == '客户' ? val[0].cuCode : val[0].suCode
formState.cpName = val[0].cpTableName == '客户' ? val[0].cuName : val[0].suName
// getLngCustomer(val[0].id)
getBankInfo(formState.cpCode, val[0].cpTableName)
}
const getBankInfo = async (code, type) => {
const res = await getBankBList(code, type=='客户'? 'C' : 'S')
optionList.value = res|| []
formState.cpBankCode = (optionList.value.find(v => v.defaultSign == 'Y') || {}).bankCode
formState.cpBankName = (optionList.value.find(v => v.defaultSign == 'Y') || {}).bankName
formState.cpBankAccountName = (optionList.value.find(v => v.defaultSign == 'Y') || {}).accountName
formState.cpBankAccount = (optionList.value.find(v => v.defaultSign == 'Y') || {}).account
}
const bankChange = (val) => {
formState.cpBankName = (optionList.value.find(v => v.bankCode == val) || {}).bankName
formState.cpBankAccountName = (optionList.value.find(v => v.bankCode == val) || {}).accountName
formState.cpBankAccount = (optionList.value.find(v => v.bankCode == val) || {}).account
}
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
curData.value = ''
formState.filePath = ''
getOption()
setModalProps({ confirmLoading: false });
isUpdate.value = !!data?.isUpdate;
isDisable.value = data?.btnType == 'view' ? true : false
list.value = data.list
if (unref(isUpdate)) {
Object.assign(formState, {...data.record})
getBankInfo(formState.cpCode, formState.cpTableName, 'code')
}
});
onMounted(() => {
getOption()
});
async function getOption() {
let obj = {}
if (props.type == 'cuSign') {
obj = {'cuSign': 'Y'}
} else {
obj = {'suSign': 'Y'}
tableName = 'supplier'
}
optionList = await getDocCpList({'valid': 'Y',...obj })
}
const handleCancel = () => {
formRef.value.resetFields();
}
const handleSubmit = async () => {
try {
await formRef.value.validate();
// 验证通过,提交表单
let obj = {
...formState,
}
let idx =list.value.findIndex(v => v.docTypeCode == obj.docTypeCode)
if (idx > -1 && formState.docTypeCode !=curData.value) {
message.warn('证书已存在')
formRef.value.resetFields();
closeModal();
return
}
emit('success', obj);
emit('success', formState);
notification.success({
message: t('操作'),
description:!unref(isUpdate)? t('新增成功') : t('编辑成功')

View File

@ -1,13 +1,13 @@
<template>
<div class="customerSupplierList">
<BasicModal v-bind="$attrs" :zIndex="1001 @register="registerModal" width="60%" :title="getTitle" @ok="handleSubmit"
<BasicModal v-bind="$attrs" :zIndex="1001" @register="registerModal" width="60%" :title="getTitle" @ok="handleSubmit"
@visible-change="handleVisibleChange" >
<a-tabs v-model:activeKey="activeKey" @change="handleTabChange" :class="{ 'h-full': ['1', '2'].includes(activeKey) }">
<a-tab-pane key="1" tab="客户">
<BasicTable @register="registerTable" class="customerSupplierListModal"></BasicTable>
<BasicTable @register="registerTable" class="customerListModal"></BasicTable>
</a-tab-pane>
<a-tab-pane key="2" tab="供应商" force-render>
<BasicTable @register="registerTableSupplier" class="customerSupplierListModal"></BasicTable>
<BasicTable @register="registerTableSupplier" class="supplierListModal"></BasicTable>
</a-tab-pane>
</a-tabs>
</BasicModal>
@ -38,7 +38,7 @@
];
const codeFormSchemaSupplier: FormSchema[] = [
{ field: 'suName', label: '供应商名称', component: 'Input' },
{ field: 'suName', label: '供应商名称', component: 'Input' }
];
const columnsSupplier: BasicColumn[] = [
@ -56,7 +56,7 @@
const selectedKeys = ref<string[]>([]);
const selectedValues = ref([]);
const props = defineProps({
selectType: { type: String, default: 'checkbox' },
selectType: { type: String, default: 'radio' },
});
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
@ -75,7 +75,7 @@
pagination: true,
canResize: false,
formConfig: {
labelCol:{span: 9, offSet:10},
labelCol:{span: 9},
schemas: codeFormSchema,
showResetButton: true,
},
@ -88,7 +88,7 @@
onChange: onSelectChange
},
});
const [registerTableSupplier, { getDataSource, setTableData, updateTableDataRecord, reload:reloadSupplier }] = useTable({
const [registerTableSupplier, { reload:reloadSupplier }] = useTable({
title: t('供应商列表'),
api: getLngSupplierPage,
columns:columnsSupplier,
@ -97,9 +97,10 @@
pagination: true,
canResize: false,
formConfig: {
labelCol:{span: 9, offSet:10},
labelCol:{span: 9},
schemas: codeFormSchemaSupplier,
showResetButton: true,
showAdvancedButton: false
},
immediate: false, // 设置为不立即调用
beforeFetch: (params) => {
@ -119,10 +120,11 @@
}
};
const handleTabChange = (key) => {
activeKey.value = key
};
function onSelectChange(rowKeys: string[], e) {
selectedKeys.value = rowKeys;
selectedValues.value = e
selectedValues.value = [{...e[0], cpTableName: activeKey.value=='1' ? '客户': '供应商'}]
}
const getTitle = computed(() => (!unref(isUpdate) ? t('客户列表') : t('')));
@ -130,7 +132,7 @@
if (!selectedValues.value.length) {
notification.warning({
message: t('提示'),
description: t('请选择数据')
description: t('请选择' + activeKey.value=='1' ? '客户': '供应商')
});
return
}
@ -146,7 +148,7 @@
</script>
<style >
.customerSupplierListModal .basicCol{
.customerListModal .basicCol, .supplierListModal .basicCol{
position: inherit !important;
top: 0;
}

View File

@ -5,7 +5,7 @@
<div style="display: flex;">
<div class="w-1/3 xl:w-1/3 overflow-hidden bg-white" :style="{ 'border-right': '1px solid #e5e7eb' }">
<BasicTree :title="t('组织列表')" ref="asyncTreeRef" search toolbar :clickRowToExpand="true" expandOnSearch :treeData="treeData" :fieldNames="{ key: 'id', title: 'name' }" @select="handleSelect" />
<BasicTree :title="t('组织列表')" style="height: 250px" ref="asyncTreeRef" search toolbar :clickRowToExpand="true" expandOnSearch :treeData="treeData" :fieldNames="{ key: 'id', title: 'name' }" @select="handleSelect" />
</div>
<BasicTable @register="registerTable" class="deptUserModal w-2/3 xl:w-2/3"></BasicTable>
</div>

View File

@ -0,0 +1,110 @@
// utils/amountToChinese.js
export function amountToChinese(money) {
// 1. 参数处理
if (money === '' || money === null || money === undefined || isNaN(money)) {
return '';
}
// 2. 金额验证
if (Math.abs(money) > 9999999999999.99) {
throw new Error('金额超出范围 (最大: 9999999999999.99)');
}
// 3. 定义常量
const CN_NUMBERS = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'];
const CN_INTEGER_UNIT = ['', '拾', '佰', '仟'];
const CN_GROUP_UNIT = ['', '万', '亿', '兆'];
const CN_DECIMAL_UNIT = ['角', '分'];
const CN_FULL = '整';
const CN_NEGATIVE = '负';
const CN_YUAN = '元';
// 4. 处理符号
let isNegative = false;
if (money < 0) {
isNegative = true;
money = Math.abs(money);
}
// 5. 格式化为两位小数
let moneyStr = parseFloat(money).toFixed(2);
// 6. 分离整数和小数
const [integerPart, decimalPart] = moneyStr.split('.');
// 7. 转换整数部分
let chineseStr = '';
if (parseInt(integerPart, 10) > 0) {
// 按4位一组分割
const groups = [];
for (let i = integerPart.length; i > 0; i -= 4) {
groups.push(integerPart.substring(Math.max(0, i - 4), i));
}
// 处理每一组
for (let i = 0; i < groups.length; i++) {
let groupStr = '';
const group = groups[i].split('').reverse().join('');
let hasZero = false;
for (let j = 0; j < group.length; j++) {
const digit = parseInt(group[j], 10);
const unit = CN_INTEGER_UNIT[j];
if (digit === 0) {
if (!hasZero && j !== 0) {
groupStr = CN_NUMBERS[0] + groupStr;
hasZero = true;
}
} else {
groupStr = CN_NUMBERS[digit] + unit + groupStr;
hasZero = false;
}
}
// 去除尾部的零
groupStr = groupStr.replace(/零+$/, '');
// 添加组单位(万、亿、兆)
if (groupStr) {
groupStr += CN_GROUP_UNIT[i];
}
chineseStr = groupStr + chineseStr;
}
chineseStr += CN_YUAN;
}
// 8. 转换小数部分
if (decimalPart) {
const decInt = parseInt(decimalPart, 10);
if (decInt > 0) {
for (let i = 0; i < decimalPart.length; i++) {
const digit = parseInt(decimalPart[i], 10);
if (digit > 0) {
chineseStr += CN_NUMBERS[digit] + CN_DECIMAL_UNIT[i];
}
}
}
}
// 9. 清理多余的零
chineseStr = chineseStr
.replace(/零+/g, '零')
.replace(/零([万亿兆])/g, '$1')
.replace(/零元/g, '元')
.replace(/元零?$/, '元');
// 10. 添加"整"或处理负数
if (!chineseStr.includes('角') && !chineseStr.includes('分')) {
chineseStr += CN_FULL;
}
if (isNegative) {
chineseStr = CN_NEGATIVE + chineseStr;
}
return chineseStr;
}

View File

@ -125,7 +125,7 @@
showResetButton: true,
},
beforeFetch: (params) => {
return { ...params, FormId: formIdComputedRef.value, PK: 'id',page: params.limit};
return { ...params, FormId: formIdComputedRef.value, PK: 'id'};
},
afterFetch: (res) => {
tableRef.value.setToolBarWidth();

View File

@ -17,7 +17,7 @@ export const searchFormSchema: FormSchema[] = [
component: 'XjrSelect',
componentProps: {
datasourceType: 'dic',
params: { itemId: '1990669393069129729' },
params: { itemId: '2003815292742479874' },
labelField: 'name',
valueField: 'value',
@ -45,7 +45,7 @@ export const columns: BasicColumn[] = [
sorter: true,
},
{
dataIndex: 'relTypeCode',
dataIndex: 'relTypeName',
title: '关联类别',
componentType: 'input',
align: 'left',
@ -53,7 +53,7 @@ export const columns: BasicColumn[] = [
sorter: true,
},
{
dataIndex: 'kTypeCode1',
dataIndex: 'kTypeName1',
title: '合同类别',
componentType: 'input',
align: 'left',
@ -62,7 +62,7 @@ export const columns: BasicColumn[] = [
},
{
dataIndex: 'kTypeCode2',
dataIndex: 'kTypeName2',
title: '二级类别',
componentType: 'input',
align: 'left',
@ -89,16 +89,7 @@ export const columns: BasicColumn[] = [
},
{
dataIndex: 'periodTypeCode',
title: '合同期限',
componentType: 'input',
align: 'left',
sorter: true,
},
{
dataIndex: 'periodTypeCode',
dataIndex: 'periodTypeName',
title: '合同期限',
componentType: 'input',
align: 'left',
@ -125,7 +116,7 @@ export const columns: BasicColumn[] = [
},
{
dataIndex: 'curCode',
dataIndex: 'curName',
title: '币种',
componentType: 'select',
align: 'left',
@ -133,7 +124,7 @@ export const columns: BasicColumn[] = [
sorter: true,
},
{
dataIndex: 'amountTypeCode',
dataIndex: 'amountTypeName',
title: '合同金额类型',
componentType: 'select',
align: 'left',
@ -151,7 +142,7 @@ export const columns: BasicColumn[] = [
},
{
dataIndex: 'empId',
dataIndex: 'empName',
title: '业务联系人',
componentType: 'input',
align: 'left',
@ -160,7 +151,7 @@ export const columns: BasicColumn[] = [
},
{
dataIndex: 'bDeptId',
dataIndex: 'bDeptName',
title: '业务部门',
componentType: 'input',
align: 'left',
@ -169,7 +160,7 @@ export const columns: BasicColumn[] = [
},
{
dataIndex: 'approCode',
dataIndex: 'approName',
title: '状态',
componentType: 'input',
align: 'left',

View File

@ -6,7 +6,7 @@
<a-row>
<a-col :span="8">
<a-form-item label="合同号" name="kNo">
<a-input v-model:value="formState.kNo" :disabled="isDisable" style="width: 65%" /><a-button type="primary" @click="onAppro">关联签报</a-button>
<a-input v-model:value="formState.kNo" :disabled="isDisable" style="width: 65%" /><a-button v-if="!isDisable" type="primary" @click="onAppro">关联签报</a-button>
</a-form-item>
</a-col>
<a-col :span="16">
@ -43,7 +43,7 @@
</a-col>
<a-col :span="8">
<a-form-item label="合同期限" name="periodTypeCode">
<a-select v-model:value="formState.periodTypeCode" :disabled="isDisable" placeholder="请选择合同期限" style="width: 100%" allow-clear>
<a-select v-model:value="formState.periodTypeCode" :disabled="isDisable" placeholder="请选择合同期限" @change="periodTypeCodeChange" style="width: 100%" allow-clear>
<a-select-option v-for="item in optionSelect.periodTypeCodeList" :key="item.code" :value="item.code">
{{ item.name }}
</a-select-option>
@ -52,17 +52,17 @@
</a-col>
<a-col :span="8">
<a-form-item label="有效期开始" name="dateFrom">
<a-date-picker v-model:value="formState.dateFrom" style="width: 100%" :disabled-date="disabledDateStart" placeholder="请选择开始日期" />
<a-date-picker v-model:value="formState.dateFrom" style="width: 100%" :disabled="isDisable" :disabled-date="disabledDateStart" placeholder="请选择开始日期" />
</a-form-item>
</a-col>
<a-col :span="8">
<a-form-item label="有效期结束" name="dateTo">
<a-date-picker v-model:value="formState.dateTo" style="width: 100%" :disabled-date="disabledDateEnd" placeholder="请选择结束日期" />
<a-date-picker v-model:value="formState.dateTo" style="width: 100%" :disabled="isDisable" :disabled-date="disabledDateEnd" placeholder="请选择结束日期" />
</a-form-item>
</a-col>
<a-col :span="8">
<a-form-item label="起草日期" name="dateDraft">
<a-date-picker v-model:value="formState.dateDraft" style="width: 100%" placeholder="请选择起草日期" />
<a-date-picker v-model:value="formState.dateDraft" style="width: 100%" :disabled="isDisable" placeholder="请选择起草日期" />
</a-form-item>
</a-col>
<a-col :span="8">
@ -76,21 +76,21 @@
</a-col>
<a-col :span="8">
<a-form-item label="相对方数量" name="cpCount">
<a-input-number v-model:value="formState.cpCount" style="width: 100%" :precision="0" :min="0" :step="1" :max="20"/>
<a-input-number v-model:value="formState.cpCount" style="width: 100%" :disabled="isDisable" :precision="0" :min="0" :step="1" :max="20"/>
</a-form-item>
</a-col>
<a-col :span="8">
<a-form-item label="合同金额类型" name="amountTypeCode">
<a-select v-model:value="formState.amountTypeCode" :disabled="isDisable" placeholder="请选择合同金额类型" style="width: 100%" allow-clear>
<a-select v-model:value="formState.amountTypeCode" :disabled="isDisable" placeholder="请选择合同金额类型" @change="amountTypeCodeChange" style="width: 100%" allow-clear>
<a-select-option v-for="item in optionSelect.amountTypeCodeList" :key="item.code" :value="item.code">
{{ item.fullName }}
{{ item.name }}
</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :span="8">
<a-form-item label="合同金额(万元)" name="amount">
<a-input-number v-model:value="formState.amount" style="width: 100%" :min="0" :disabled="isDisable" />
<a-input-number v-model:value="formState.amount" style="width: 100%" @blur="amountBlur(formState.amount)" :min="0" :disabled="isDisable" />
</a-form-item>
</a-col>
<a-col :span="8">
@ -107,7 +107,7 @@
<a-form-item label="结算类型" name="settleTypeCode">
<a-select v-model:value="formState.settleTypeCode" :disabled="isDisable" placeholder="请选择结算类型" style="width: 100%" allow-clear>
<a-select-option v-for="item in optionSelect.settleTypeCodeList" :key="item.code" :value="item.code">
{{ item.fullName }}
{{ item.name }}
</a-select-option>
</a-select>
</a-form-item>
@ -164,7 +164,7 @@
</a-col>
<a-col :span="8">
<a-form-item label="联系电话" name="tel">
<a-input v-model:value="formState.tel" />
<a-input-search v-model:value="formState.tel" :disabled="isDisable" placeholder="请输入电话" />
</a-form-item>
</a-col>
<a-col :span="8">
@ -200,11 +200,12 @@
</a-card>
<a-card title="相对方信息" :bordered="false" >
<div style="width: 100%">
<a-button type="primary" style="margin-bottom: 10px" @click="onAppro">新增行</a-button>
<a-table style="width: 100%" :columns="columns" :data-source="dataList" :pagination="false" :scroll="{x: 2000}">
<a-button type="primary" style="margin-bottom: 10px" @click="addUser" v-if="!isDisable">新增行</a-button>
<a-table style="width: 100%" :columns="columns" :data-source="dataList" :pagination="false" :scroll="{x: 1000}">
<template #bodyCell="{ column, record, index }">
<template v-if="column.dataIndex === 'operation'">
<!-- <a @click="btnCheck(record, index)">删除</a> -->
<a v-if="!isDisable" style="margin-right: 10px" @click="btnCheck('cp', 'edit', record, index)">编辑</a>
<a v-if="!isDisable" style="margin-right: 10px" @click="btnCheck('cp', 'delete', record, index)">删除</a>
</template>
</template>
</a-table>
@ -214,11 +215,17 @@
<UploadList :disabled="isDisable" :list="dataFile" :value="formState.filePath" :tableName="tableName" :columnName="columnName" @change="uploadListChange"/>
</a-card>
<a-card title="签报列表" :bordered="false" >
<a-button type="primary" style="margin-bottom: 10px" @click="onAppro">关联签报</a-button>
<a-button type="primary" style="margin-bottom: 10px" v-if="!isDisable" @click="onAppro">关联签报</a-button>
<a-table :columns="columnsAppro" :data-source="dataListAppro" :pagination="false">
<template #bodyCell="{ column, record, index }">
<template v-if="column.dataIndex === 'file'">
<div v-for="item in (record.lngFileUploadList )">
<a @click="handleDownload(item)">{{item.fileOrg}}</a>
</div>
</template>
<template v-if="column.dataIndex === 'operation'">
<!-- <a @click="btnCheck(record, index)">删除</a> -->
<a style="margin-right: 10px" @click="btnCheck('appro', 'view', record, index)">查看</a>
<a v-if="!isDisable" style="margin-right: 10px" @click="btnCheck('appro', 'delete', record, index)">删除</a>
</template>
</template>
</a-table>
@ -228,6 +235,7 @@
<deptUserModal @register="register" @success="handleSuccess"/>
<deptListModal @register="registerDept" @success="handleSuccessDept" />
<approListModal @register="registerAppro" @success="handleSuccessAppro" />
<contractFactUserModal @register="registerUser" @success="handleSuccessUser" />
</a-spin>
</template>
@ -242,7 +250,7 @@
import type { Rule } from 'ant-design-vue/es/form';
import { getDictionary } from '/@/api/sales/Customer';
import { useModal } from '/@/components/Modal';
import { addLngContractFact,updateLngContractFact,getAllCurrency, getLngContractFact } from '/@/api/contract/ContractFact';
import { addLngContractFact,updateLngContractFact,getAllCurrency,getAllUser, getLngContractFact } from '/@/api/contract/ContractFact';
import { getLngAppro,getCompDept } from '/@/api/approve/Appro';
import dayjs from 'dayjs';
import { getAppEnvConfig } from '/@/utils/env';
@ -251,6 +259,10 @@
import deptUserModal from '/@/components/common/deptUserModal.vue';
import deptListModal from '/@/components/common/deptListModal.vue';
import approListModal from '/@/components/common/approListModal.vue';
import contractFactUserModal from '/@/components/common/contractFactUserModal.vue';
import { amountToChinese } from '/@/utils/amountToChinese';
import { parseDownloadUrl} from '/@/api/system/file';
import { downloadByUrl } from '/@/utils/file/download';
import { Modal } from 'ant-design-vue';
import { useUserStore } from '/@/store/modules/user';
@ -292,7 +304,8 @@
const [register, { openModal:openModal}] = useModal();
const [registerDept, { openModal:openModalDept}] = useModal();
const [registerAppro, { openModal:openModalAppro}] = useModal();
const rules: Record<string, Rule[]> = {
const [registerUser, { openModal:openModalUser}] = useModal();
const rules= reactive({
kNo: [{ required: true, message: "该项为必填项", trigger: 'change' }],
kName: [{ required: true, message: "该项为必填项", trigger: 'change' }],
relTypeCode: [{ required: true, message: "该项为必填项", trigger: 'change' }],
@ -310,7 +323,7 @@
tel: [{ required: true, message: "该项为必填项", trigger: 'change' }],
bDeptName: [{ required: true, message: "该项为必填项", trigger: 'change' }],
};
});
const layout = {
labelCol: { span: 8 },
wrapperCol: { span: 16 },
@ -318,13 +331,13 @@
const columns= ref([
{ title: t('序号'), dataIndex: 'index', key: 'index', sorter: true, customRender: (column) => `${column.index + 1}` ,width: 100},
{ title: t('相对方名称'), dataIndex: 'cpName', sorter: true, width:200},
{ title: t('相对方顺序'), dataIndex: 'sort', sorter: true, width: 180},
{ title: t('相对方顺序'), dataIndex: 'sort', sorter: true, width: 130},
{ title: t('相对方银行名称'), dataIndex: 'cpBankName', sorter: true, width: 200},
{ title: t('对方银行开户名'), dataIndex: 'cpBankAccountName', sorter: true, width: 300},
{ title: t('对方银行账号'), dataIndex: 'cpBankAccount', sorter: true, width: 300},
{ title: t('对方联系人姓名'), dataIndex: 'contactName', sorter: true, width: 300},
{ title: t('对方银行账号'), dataIndex: 'cpBankAccount', sorter: true, width: 200},
{ title: t('对方联系人姓名'), dataIndex: 'contactName', sorter: true, width: 200},
{ title: t('对方联系人电话'), dataIndex: 'contactTel', sorter: true, width: 200},
{ title: t('对方联系人邮箱'), dataIndex: 'contactEmail', sorter: true, width: 300},
{ title: t('对方联系人邮箱'), dataIndex: 'contactEmail', sorter: true, width: 200},
{ title: t('对方通讯地址'), dataIndex: 'contactAddress', sorter: true, width: 200},
{ title: t('备注'), dataIndex: 'note', sorter: true, width: 200},
{ title: t('操作'), dataIndex: 'operation', width: 120, fixed: 'right',align: 'center'},
@ -337,10 +350,10 @@
{ title: t('拟稿人'), dataIndex: 'empName', sorter: true, width: 140},
{ title: t('拟稿人所属部门'), dataIndex: 'bDeptName', sorter: true, width: 140},
{ title: t('拟稿时间'), dataIndex: 'dateAppro', sorter: true, width: 140},
{ title: t('附件'), dataIndex: 'contactTel', sorter: true, width: 140},
{ title: t('附件'), dataIndex: 'file', sorter: true, width: 140},
{ title: t('操作'), dataIndex: 'operation', width: 120, fixed: 'right',align: 'center'},
]);
const dataList = ref([{cpName: 88}])
const dataList = ref([])
const dataFile = ref([]);
const dataListAppro = ref([])
let optionSelect= reactive({
@ -365,6 +378,10 @@
() => props.disabled,
(val) => {
isDisable.value = val
if (val) {
let idx = columns.value.findIndex(v =>v.dataIndex == 'operation')
idx>-1 && columns.value.splice(idx, 1)
}
},
{
immediate: true
@ -378,8 +395,6 @@
formState.empName = userInfo.name
formState.empId = userInfo.id
formState.tel = userInfo.mobile
console.log(userInfo, 'userInfo')
}
});
@ -389,13 +404,17 @@
async function getInfo(id) {
spinning.value = true
try {
let data = await getLngAppro(id)
let data = await getLngContractFact(id)
spinning.value = false
Object.assign(formState, {...data})
Object.assign(dataFile.value, formState.lngFileUploadList || [])
Object.assign(dataList.value, formState.lngContractFactCpList || [])
Object.assign(dataListAppro.value, formState.lngApproVoList || [])
formState.dateDraft = formState.dateDraft ? dayjs(formState.dateDraft) : null
formState.dateFrom = formState.dateFrom ? dayjs(formState.dateFrom) : null
formState.dateTo = formState.dateTo ? dayjs(formState.dateTo) : null
periodTypeCodeChange(formState.periodTypeCode)
amountTypeCodeChange(formState.amountTypeCode)
} catch (error) {
spinning.value = false
}
@ -413,6 +432,7 @@
optionSelect.approCodeList = await getDictionary('LNG_APPRO')
optionSelect.curCodeList = await getAllCurrency()
// optionSelect.telList = await getAllUser()
if (!pageId.value) {
const res = await getCompDept(userInfo.id)
@ -424,6 +444,33 @@
}
}
const handleDownload = (info) => {
const url = parseDownloadUrl(info.response ? info.response.data.fileUrl : info.fileUrl);
const fileName = info.response ? info.response.data.fileOrg : info.fileOrg;
downloadByUrl({ url, fileName: fileName});
};
const periodTypeCodeChange = (val) => {
if (val === 'Y') {
rules.dateTo = [{ required: true, message: "该项为必填项", trigger: 'change' }]
rules.dateFrom = [{ required: true, message: "该项为必填项", trigger: 'change' }]
} else {
rules.dateTo = [{ required: false, message: "该项为必填项", trigger: 'change' }]
rules.dateFrom = [{ required: false, message: "该项为必填项", trigger: 'change' }]
}
}
const amountTypeCodeChange = (val) => {
if (val === 'Y') {
rules.curCode = [{ required: true, message: "该项为必填项", trigger: 'change' }]
rules.amount = [{ required: true, message: "该项为必填项", trigger: 'change' }]
} else {
rules.curCode = [{ required: false, message: "该项为必填项", trigger: 'change' }]
rules.amount = [{ required: false, message: "该项为必填项", trigger: 'change' }]
}
}
const amountBlur = (val) => {
if (!val) return
formState.amountCn = amountToChinese(Number(val)*10000)
}
const disabledDateStart = (startValue) => {
const endValue = formState?.dateTo;
if (!startValue || !endValue) {
@ -447,6 +494,10 @@
const onAppro = (val)=> {
openModalAppro(true,{isUpdate: false})
}
const addUser = (val)=> {
openModalUser(true,{isUpdate: false})
}
const handleSuccess = (val) => {
formState.empName = val[0].name
formState.empId = val[0].id
@ -460,6 +511,10 @@
formState.comId = info.id
}
const handleSuccessAppro = (val) =>{
val.forEach(v => {
v.approId = v.id
v.id = null
})
if (!dataListAppro.value.length) {
dataListAppro.value = val
return
@ -468,7 +523,7 @@
val.forEach(v => {
dataListAppro.value.forEach(i => {
if (v.code == i.code){
message.warning(v.code + '已重复')
message.warning(v.code + '已重复, 签报不需要重复选择')
} else {
arr.push(v)
}
@ -476,6 +531,45 @@
})
dataListAppro.value = unique([...dataListAppro.value, ...arr], 'code')
}
const handleSuccessUser = (val) => {
if (curIdx.value != null) {
dataList.value[curIdx.value] = {...val}
return
}
dataList.value.push({...val})
}
const btnCheck = (type, btn, record, index) => {
curIdx.value = null
if (type == 'cp') {
if (btn == 'delete') {
dataList.value.splice(index, 1)
}
if (btn == 'edit') {
openModalUser(true, {record: record,isUpdate: true});
}
}
// 签报
if (type == 'appro') {
if (btn == 'delete') {
Modal.confirm({
title: '提示信息',
content: '是否取消关联?',
okText: '确认',
cancelText: '取消',
onOk() {
dataListAppro.value.splice(index, 1);
},
onCancel() {}
});
}
if (btn == 'view') {
}
}
}
function unique(arr, u_key) {
const map = new Map()
arr.forEach((item, index) => {
@ -494,9 +588,19 @@
async function handleSubmit(type) {
try {
await formRef.value.validateFields();
if (Number(formState.cpCount) !== dataList.value.length) {
notification.warning({
message: 'Tip',
description: '相对数量需与相对方信息个数一致'
});
return
}
let obj = {
...formState,
lngFileUploadList: dataFile.value
lngFileUploadList: dataFile.value,
lngContractFactCpList: dataList.value,
lngContractApproRelList: dataListAppro.value
}
spinning.value = true;

View File

@ -76,7 +76,7 @@
//所有按钮
const buttons = ref([{"name":"新增","code":"add","icon":"ant-design:plus-outlined","isDefault":true,"isUse":true,"type":"primary"},{"name":"编辑","code":"edit","icon":"ant-design:form-outlined","isDefault":true,"isUse":true},{"name":"刷新","code":"refresh","icon":"ant-design:reload-outlined","isDefault":true,"isUse":true},{"name":"查看","code":"view","icon":"ant-design:eye-outlined","isDefault":true,"isUse":true},{"name":"发起审批","code":"startwork","icon":"ant-design:form-outlined","isDefault":true,"isUse":true},{"name":"查看流转记录","code":"flowRecord","icon":"ant-design:form-outlined","isDefault":true,"isUse":true},{"name":"变更","code":"update","icon":"ant-design:edit-filled","isDefault":false,"isUse":true},{"name":"删除","code":"delete","icon":"ant-design:delete-outlined","isDefault":true,"isUse":true}]);
//展示在列表内的按钮
const actionButtons = ref<string[]>(['view', 'edit','datalog', 'copyData', 'delete', 'startwork','flowRecord']);
const actionButtons = ref<string[]>(['view', 'edit','datalog', 'copyData', 'delete','update', 'startwork','flowRecord']);
const buttonConfigs = computed(()=>{
return filterButtonAuth(buttons.value);
})
@ -89,7 +89,7 @@
return buttonConfigs.value?.filter((x) => actionButtons.value.includes(x.code));
});
const btnEvent = {add : handleAdd,edit : handleEdit,refresh : handleRefresh,view : handleView,startwork : handleStartwork,flowRecord : handleFlowRecord,delete : handleDelete,}
const btnEvent = {add : handleAdd,edit : handleEdit,refresh : handleRefresh,view : handleView,startwork : handleStartwork,flowRecord : handleFlowRecord,delete : handleDelete,update: handleUpdate}
const { currentRoute } = useRouter();
const router = useRouter();
@ -121,10 +121,8 @@
gutter: 16,
},
schemas: customSearchFormSchema,
fieldMapToTime: [['dateDraft', ['dateDraftStart', 'dateDraftEnd'], 'YYYY-MM-DD ', true],
['dateFrom', ['dateFromStart', 'dateFromEnd'], 'YYYY-MM-DD HH:mm:ss ', true],
['dateTo', ['dateToStart', 'dateToEnd'], 'YYYY-MM-DD HH:mm:ss ', true],],
showResetButton: false,
fieldMapToTime: [],
showResetButton: true,
},
beforeFetch: (params) => {
return { ...params, FormId: formIdComputedRef.value, PK: 'id' };
@ -161,7 +159,8 @@
query: {
taskId: taskIds[0],
formName: formName,
formId:currentRoute.value.meta.formId
formId:currentRoute.value.meta.formId,
id: record.id
}
});
} else if (schemaId && !taskIds && processId) {
@ -171,18 +170,32 @@
readonly: 1,
taskId: '',
formName: formName,
formId:currentRoute.value.meta.formId
formId:currentRoute.value.meta.formId,
id: record.id
}
});
} else {
router.push({
path: '/form/ContractFact/' + record.id + '/viewForm',
query: {
formPath: 'contract/ContractFact',
formName: formName,
formId:currentRoute.value.meta.formId
}
});
if (schemaIdComputedRef.value) {
router.push({
path: '/flow/' + schemaIdComputedRef.value + '/0/createFlow',
query: {
formPath: 'contract/ContractFact',
formName: formName,
formId:currentRoute.value.meta.formId,
type:'edit',
id: record.id,
disabled: 1,
}
});
}
// router.push({
// path: '/form/ContractFact/' + record.id + '/viewForm',
// query: {
// formPath: 'contract/ContractFact',
// formName: formName,
// formId:currentRoute.value.meta.formId
// }
// });
}
}
@ -213,15 +226,42 @@
}
function handleEdit(record: Recordable) {
router.push({
path: '/form/ContractFact/' + record.id + '/updateForm',
query: {
if (schemaIdComputedRef.value) {
router.push({
path: '/flow/' + schemaIdComputedRef.value + '/0/createFlow',
query: {
formPath: 'contract/ContractFact',
formName: formName,
formId:currentRoute.value.meta.formId
formId:currentRoute.value.meta.formId,
type:'edit',
id: record.id
}
});
} else {
router.push({
path: '/form/ContractFact/' + record.id + '/updateForm',
query: {
formPath: 'contract/ContractFact',
formName: formName,
formId:currentRoute.value.meta.formId
}
});
}
}
function handleUpdate(record: Recordable) {
const { processId, taskIds, schemaId, status } = record.workflowData || {};
router.push({
path: '/flow/' + schemaId + '/' + processId + '/approveFlow',
query: {
readonly: 1,
taskId: '',
formName: formName,
formId:currentRoute.value.meta.formId,
id: record.id,
status
}
});
}
function handleDelete(record: Recordable) {
deleteList([record.id]);
@ -314,6 +354,10 @@
actionsList = actionsList.concat(editAndDelBtn);
}
}
if (record.approCode !== 'YSP') {
let idx = actionsList.findIndex(v =>v.tooltip == '变更')
idx>-1 && actionsList.splice(idx, 1)
}
return actionsList;
}
function handleStartwork(record: Recordable) {

View File

@ -390,7 +390,7 @@
]);
const columnsBank = ref([
{ title: t('序号'), dataIndex: 'index', sorter: true, customRender: (column) => `${column.index + 1}`},
{ title: t('银行名称'), dataIndex: 'bankCode', sorter: true},
{ title: t('银行名称'), dataIndex: 'bankName', sorter: true},
{ title: t('联行号'), dataIndex: 'code', sorter: true},
{ title: t('账号名称'), dataIndex: 'accountName', sorter: true},
{ title: t('银行账号'), dataIndex: 'account', sorter: true},

View File

@ -125,7 +125,7 @@ const loadData: CascaderProps['loadData'] = async (selectedOptions) => {
let list = selectedOptions.map(v=> {
return v.name
})
formState.eDeptName = list.join('/')
formState.eDeptName = list[list.length -1]
}
onMounted(() => {

View File

@ -247,9 +247,9 @@
formState.score = null
dataList.value.forEach(v => {
v.aTime = dayjs(new Date()).format('YYYY-MM-DD HH:mm:ss')
v.aEmpCode = userInfo.id
v.aEmpCode = userInfo.code
v.aEmpName = userInfo.name
v.aDeptCode = compDep.value?.dept?.id
v.aDeptCode = compDep.value?.dept?.code
v.aDeptName = compDep.value?.dept?.name
v.gsiId = v.id

View File

@ -125,7 +125,7 @@
showResetButton: true,
},
beforeFetch: (params) => {
return { ...params, FormId: formIdComputedRef.value, PK: 'id',page:params.limit };
return { ...params, FormId: formIdComputedRef.value, PK: 'id' };
},
afterFetch: (res) => {
clearSelectedRowKeys()

View File

@ -248,9 +248,9 @@
formState.score = null
dataList.value.forEach(v => {
v.aTime = dayjs(new Date()).format('YYYY-MM-DD HH:mm:ss')
v.aEmpCode = userInfo.id
v.aEmpCode = userInfo.code
v.aEmpName = userInfo.name
v.aDeptCode = compDep.value?.dept?.id
v.aDeptCode = compDep.value?.dept?.code
v.aDeptName = compDep.value?.dept?.name
v.gsiId = v.id

View File

@ -125,7 +125,7 @@
showResetButton: true,
},
beforeFetch: (params) => {
return { ...params, FormId: formIdComputedRef.value, PK: 'id',page:params.limit };
return { ...params, FormId: formIdComputedRef.value, PK: 'id'};
},
afterFetch: (res) => {
clearSelectedRowKeys()

View File

@ -308,7 +308,7 @@
]);
const columnsBank = ref([
{ title: t('序号'), dataIndex: 'index', sorter: true, customRender: (column) => `${column.index + 1}`},
{ title: t('银行名称'), dataIndex: 'bankCode', sorter: true},
{ title: t('银行名称'), dataIndex: 'bankName', sorter: true},
{ title: t('联行号'), dataIndex: 'code', sorter: true},
{ title: t('账号名称'), dataIndex: 'accountName', sorter: true},
{ title: t('银行账号'), dataIndex: 'account', sorter: true},

View File

@ -197,13 +197,14 @@ const UserProperties = {
index: 2
},
// 现在没有拒绝选项
// {
// buttonType: ButtonType.DEFAULT, //按钮类型
// buttonName: t('不同意'), //按钮名称
// buttonCode: ApproveCode.DISAGREE, //按钮编码
// approveType: ApproveType.DISAGREE, //
// checked: false, //选中
// },
{
buttonType: ButtonType.DEFAULT, //按钮类型
buttonName: t('拒绝'), //按钮名称
buttonCode: ApproveCode.DISAGREE, //按钮编码
approveType: ApproveType.DISAGREE, //
checked: true, //选中
index: 3
},
{
buttonType: ButtonType.DEFAULT, //按钮类型
buttonName: t('驳回'), //按钮名称