feat:财税管理 进项发票&报销单相关展示及逻辑优化

zth
yujinlong 3 weeks ago
parent a97bf805e1
commit 4d4247196f

@ -13,6 +13,7 @@ VITE_PUBLIC_PATH = /
# Cross-domain proxy, you can configure multiple
# Please note that no line breaks
# VITE_PROXY = [["/basic-api","http://60.209.125.238"],["/upload","http://localhost:3300/upload"]]
# VITE_PROXY=[["/api","http://60.209.125.238:3008"],["/stage-api","https://www.666cxf.com/stage-api"]] # 开发 测试环境
VITE_PROXY=[["/api","http://118.190.144.189:3008"],["/stage-api","https://www.666cxf.com/stage-api"]] # 开发 测试环境
# Delete console

@ -12,7 +12,7 @@
<slot name="formHeader"></slot>
<template v-for="schema in getSchema" :key="schema.field">
<FormItem
v-if="schema.isEdit != 1 || schema.component == 'Divider' || schema.component == 'InputTextArea'"
v-if="getFormItemVisible(schema)"
:is-advanced="fieldsIsAdvancedMap[schema.field]"
:table-action="tableAction"
:form-action-type="formActionType"
@ -28,10 +28,14 @@
</template>
</FormItem>
<!-- 只读 -->
<a-col :span="schema?.colProps?.span || 24" v-if="schema.show !== false && schema.isEdit == 1 && schema.component != 'Divider' && schema.component != 'InputTextArea'">
<a-col :span="schema?.colProps?.span || 24" v-if="getReadonlyColItemVisible(schema)">
<div class="ds-form-onlyread">
<span class="label">{{ schema.label }}</span> {{ formModel[schema.field] || '-' }}
<span v-if="!schema.dynamicDisabled" class="iconfont icon-bianji1" @click="editFormItem(schema)"></span>
<span
v-if="!schema.dynamicDisabled"
class="iconfont icon-bianji1"
@click="editFormItem(schema)"
></span>
</div>
</a-col>
</template>
@ -131,6 +135,18 @@
() => ({ ...attrs, ...props, ...unref(getProps) } as Recordable),
)
const getFormItemVisible = (schema: FormSchema) => {
const visibleFlag = schema.isEdit != 1 || schema.component == 'Divider'
if (unref(getBindValue).textAreaReadOnly) return visibleFlag
return visibleFlag || schema.component == 'InputTextArea'
}
const getReadonlyColItemVisible = (schema: FormSchema) => {
const visibleFlag =
schema.show !== false && schema.isEdit == 1 && schema.component != 'Divider'
if (unref(getBindValue).textAreaReadOnly) return visibleFlag
return visibleFlag && schema.component != 'InputTextArea'
}
const getSchema = computed((): FormSchema[] => {
const schemas: FormSchema[] = unref(schemaRef) || (unref(getProps).schemas as any)
const isReadonly = unref(propsRef).readonly
@ -174,7 +190,7 @@
schema.isEdit = 2
formActionType.updateSchema({
field: schema.field,
isEdit: 2
isEdit: 2,
})
}
@ -339,6 +355,8 @@
),
fieldsIsAdvancedMap,
...formActionType,
getFormItemVisible,
getReadonlyColItemVisible,
}
},
})
@ -351,7 +369,7 @@
font-size: 12px;
margin: 6px 0;
.label {
color: #7A8798;
color: #7a8798;
}
.icon-bianji1 {
display: none;

@ -69,6 +69,8 @@ export const basicProps = {
showActionButtonGroup: propTypes.bool.def(true),
// 默认条件下表单为可编辑
readonly: propTypes.bool.def(false),
// 文本域组件是否需要只读状态
textAreaReadOnly: propTypes.bool.def(false),
// 操作列Col配置
actionColOptions: Object as PropType<Partial<ColEx>>,
// 显示重置按钮

@ -130,6 +130,8 @@ export interface FormProps {
colon?: boolean,
// 表单是否初始状态是只读属性
readonly: boolean
// 文本域组件是否需要只读状态
textAreaReadOnly: boolean
}
export interface FormSchema {
// Field name

@ -66,23 +66,25 @@
}
// 定义所有表单组件高度为26
input::placeholder {
font-size: 12px!important;
font-size: 12px !important;
}
input, button, textarea {
font-size: 12px!important;
input,
button,
textarea {
font-size: 12px !important;
}
.iconfont {
font-size: 12px;
margin-right: 4px;
}
.ant-btn-link {
padding: 5px 10px!important;
padding: 5px 10px !important;
span:nth-child(2) {
color: @main-color!important;
}
}
.vben-basic-table-header__toolbar > * {
margin-right: 0!important;
margin-right: 0 !important;
}
h1,
@ -102,7 +104,7 @@ h1 {
h2 {
font-size: 14px;
font-weight: 600!important;
font-weight: 600 !important;
}
h3 {
font-size: 14px;
@ -114,11 +116,11 @@ h3 {
}
h4 {
font-size: 12px;
font-weight: 600!important;
font-weight: 600 !important;
}
h5 {
font-size: 12px;
color: #33383D;
color: #33383d;
font-weight: 400;
}
@ -173,7 +175,7 @@ h5 {
.ds-card {
padding: 8px 20px 11px;
background-color: #ffffff;
border: 0.7px solid #E8EBED;
border: 0.7px solid #e8ebed;
}
.mr15 {
@ -189,7 +191,7 @@ h5 {
margin-left: 15px;
}
.pl0 {
padding-left: 0!important;
padding-left: 0 !important;
}
// 表格状态使用
.ds-green-tag,
@ -278,7 +280,7 @@ h5 {
position: relative;
left: 3px;
top: -1px;
color: #7A8798;
color: #7a8798;
}
.ds-view-box {
@ -291,4 +293,36 @@ h5 {
.anticon-exclamation-circle {
// display: none!important;
}
}
.flex_arrange(@direction: row, @justify: center, @align: center) {
display: flex;
flex-direction: @direction;
justify-content: @justify;
align-items: @align;
}
.line-feed() {
word-break: break-all;
word-wrap: break-word;
white-space: break-spaces;
hyphens: auto;
}
.ellipses() {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
-o-text-overflow: hidden;
-webkit-box-orient: vertical;
}
.text_ellipsis_rowX(@lineNum: 2) {
text-overflow: -o-ellipsis-lastline;
overflow: hidden; //溢出内容隐藏
text-overflow: ellipsis; //文本溢出部分用省略号表示
display: -webkit-box; //特别显示模式
-webkit-line-clamp: @lineNum; //行数
line-clamp: @lineNum;
-webkit-box-orient: vertical;
}

@ -343,3 +343,57 @@ export function numberThousandFormat(num: number | string, fixedDigit = 2, needT
return '0.00'
}
}
// 向右移位
function shiftRight(number, digit) {
digit = parseInt(digit, 10);
var value = number.toString().split('e');
return +(value[0] + 'e' + (value[1] ? +value[1] + digit : digit));
}
// 向左移位
function shiftLeft(number, digit) {
digit = parseInt(digit, 10);
var value = number.toString().split('e');
return +(value[0] + 'e' + (value[1] ? +value[1] - digit : -digit));
}
/**
*
* @param n
* @return {string}
*/
export const digitUppercase = (n) => {
const fraction = ['角', '分'];
const digit = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'];
const unit = [
['元', '万', '亿'],
['', '拾', '佰', '仟'],
];
let head = n < 0 ? '欠' : '';
n = Math.abs(n);
let s = '';
for (let i = 0; i < fraction.length; i++) {
s += (digit[Math.floor(shiftRight(n, 1 + i)) % 10] + fraction[i]).replace(
/零./,
''
);
}
s = s || '整';
n = Math.floor(n);
for (let i = 0; i < unit[0].length && n > 0; i++) {
let p = '';
for (let j = 0; j < unit[1].length && n > 0; j++) {
p = digit[n % 10] + unit[1][j] + p;
n = Math.floor(shiftLeft(n, 1));
}
s = p.replace(/(零.)*零$/, '').replace(/^$/, '零') + unit[0][i] + s;
}
return (
head +
s
.replace(/(零.)*零元/, '元')
.replace(/(零.)+/g, '零')
.replace(/^整$/, '零元整')
);
};

@ -91,7 +91,7 @@
width: 60,
},
canResize: true,
resizeHeightOffset: 35,
resizeHeightOffset: 15,
actionColumn: {
width: 80,
title: '操作',
@ -176,9 +176,7 @@
padding: 18px 12px;
border: 1px solid #e8ebed;
.bank-item {
display: flex;
justify-content: flex-start;
align-items: center;
.flex_arrange(row, flex-start);
color: #33383d;
font-size: 12px;
font-weight: 400;

@ -1,8 +1,9 @@
import { BasicColumn, FormSchema } from '/@/components/Table'
import moment from 'moment'
import { numberThousandFormat } from '/@/utils/commonUtil'
import { numberThousandFormat, digitUppercase } from '/@/utils/commonUtil'
import { BillItem } from '../columns'
import { GetClientBankList } from '../api'
import { h, nextTick } from 'vue'
export type PageType = '' | 'ADD' | 'EDIT' | 'VIEW' | 'AUDIT'
@ -39,7 +40,26 @@ export const columns: BasicColumn[] = [
width: 200,
},
{
title: '发票类型代码',
title: '销方开票名称',
dataIndex: 'sellerInvoiceName',
width: 200,
// sorter: true,
},
{
title: '销方开票税号',
dataIndex: 'sellerInvoiceTaxNumber',
width: 200,
ellipsis: true,
// sorter: true,
},
{
title: '销方识别号',
dataIndex: 'sellerIdentificationNumber',
width: 200,
// sorter: true,
},
{
title: '发票类型',
dataIndex: 'invoiceTypeCode',
width: 200,
customRender({ text }) {
@ -57,7 +77,15 @@ export const columns: BasicColumn[] = [
// sorter: true,
width: 100,
customRender({ text }) {
return numberThousandFormat(text)
return h(
'b',
{
style: {
fontWeight: 900,
},
},
numberThousandFormat(text),
)
},
},
{
@ -75,7 +103,15 @@ export const columns: BasicColumn[] = [
width: 100,
// sorter: true,
customRender({ text }) {
return numberThousandFormat(text)
return h(
'b',
{
style: {
fontWeight: 900,
},
},
numberThousandFormat(text),
)
},
},
{
@ -93,12 +129,6 @@ export const columns: BasicColumn[] = [
width: 80,
// sorter: true,
},
{
title: '原发票号码',
dataIndex: 'originalInvoiceNumber',
width: 200,
// sorter: true,
},
{
title: '购方开票名称',
dataIndex: 'buyerInvoiceName',
@ -112,32 +142,6 @@ export const columns: BasicColumn[] = [
width: 200,
// sorter: true,
},
{
title: '销方开票名称',
dataIndex: 'sellerInvoiceName',
width: 150,
// sorter: true,
},
{
title: '销方开票税号',
dataIndex: 'sellerInvoiceTaxNumber',
width: 200,
ellipsis: true,
// sorter: true,
},
{
title: '是否已获取详情',
dataIndex: 'isDetailObtained',
width: 120,
align: 'center',
// sorter: true,
},
{
title: '销方识别号',
dataIndex: 'sellerIdentificationNumber',
width: 200,
// sorter: true,
},
]
export const getDetailForm = (type: PageType): FormSchema[] => {
@ -149,7 +153,7 @@ export const getDetailForm = (type: PageType): FormSchema[] => {
rules: [{ required: true }],
dynamicDisabled: ['VIEW', 'AUDIT'].includes(type),
component: 'ApiSelect',
isEdit: ['VIEW', 'AUDIT'].includes(type) ? 1 : 0,
isEdit: 1,
componentProps: ({ formModel }) => {
return {
immediate: true,
@ -221,6 +225,23 @@ export const getDetailForm = (type: PageType): FormSchema[] => {
label: '金额',
colProps: { span: 4 },
isEdit: 1,
dynamicDisabled: ['VIEW', 'AUDIT'].includes(type),
component: 'InputNumber',
componentProps: ({ formModel }) => {
return {
onChange: (e) => {
nextTick(() => {
formModel.amountUppercase = digitUppercase(formModel?.amount || 0)
})
},
}
},
},
{
field: 'amountUppercase',
label: '金额大写',
colProps: { span: 4 },
isEdit: 1,
dynamicDisabled: true,
component: 'Input',
},
@ -244,10 +265,11 @@ export const getDetailForm = (type: PageType): FormSchema[] => {
component: 'Input',
},
{
// show: type === 'VIEW',
isEdit: 1,
dynamicDisabled: ['VIEW', 'AUDIT'].includes(type),
field: 'reason',
label: '事由',
colProps: { span: 4 },
colProps: { span: 8 },
component: 'InputTextArea',
componentProps: {
disTrans: true,

@ -64,8 +64,6 @@
})
const rejectRowId = ref('')
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
console.log('data', data)
resetFields()
rejectRowId.value = data.id
})

@ -13,10 +13,10 @@
<div class="table-title-box">
<div class="module-title">发票列表</div>
<div class="bill-import-opt-box">
<div class="bill-import-opt-btn" @click="addBillHandle">
<i class="iconfont icon-icon_tianjia" style="color: #257afa; font-size: 16px"></i>
<span>添加</span>
</div>
<el-button class="bill-import-opt-btn" type="primary" @click="addBillHandle">
<i class="iconfont icon-icon_tianjia" style="font-size: 20px"></i>
<span>添加到报销单</span>
</el-button>
</div>
</div>
</template>
@ -178,30 +178,22 @@
color: #33383d;
}
.table-title-box {
display: flex;
align-items: center;
justify-content: flex-start;
.flex_arrange(row, flex-start);
padding: 16px 0 6px 0;
.bill-import-opt {
display: flex;
align-items: center;
justify-content: flex-start;
.flex_arrange(row, flex-start);
cursor: pointer;
&-box {
display: flex;
align-items: center;
justify-content: flex-start;
.flex_arrange(row, flex-start);
margin-left: 40px;
}
&-btn {
margin-left: 16px;
display: flex;
align-items: center;
justify-content: flex-start;
.flex_arrange(row, flex-start);
cursor: pointer;
& > span {
margin-left: 2px;
font-size: 12px;
font-size: 14px;
color: #33383d;
font-weight: 400;
letter-spacing: 0px;
@ -216,7 +208,7 @@
.calc-sum-box {
display: flex;
align-items: center;
font-size: 12px;
font-size: 14px;
font-weight: 700;
padding-top: 16px;
.calc-sum-label {

@ -1,6 +1,7 @@
import { BasicColumn, FormSchema } from '/@/components/Table'
import moment from 'moment'
import { numberThousandFormat } from '/@/utils/commonUtil'
import { h } from 'vue'
export const invoiceCodeList: LabelValueOptions = [
{ label: '全电发票(铁路电子客票)', value: '51' },
@ -26,6 +27,12 @@ export const columns: BasicColumn[] = [
dataIndex: 'invoiceNumber',
width: 200,
},
{
title: '销方开票名称',
dataIndex: 'sellerInvoiceName',
width: 200,
// sorter: true,
},
{
title: '发票类型代码',
dataIndex: 'invoiceTypeCode',
@ -45,7 +52,15 @@ export const columns: BasicColumn[] = [
sorter: true,
width: 100,
customRender({ text }) {
return numberThousandFormat(text)
return h(
'b',
{
style: {
fontWeight: 900,
},
},
numberThousandFormat(text),
)
},
},
{
@ -63,7 +78,15 @@ export const columns: BasicColumn[] = [
width: 100,
sorter: true,
customRender({ text }) {
return numberThousandFormat(text)
return h(
'b',
{
style: {
fontWeight: 900,
},
},
numberThousandFormat(text),
)
},
},
{
@ -81,12 +104,6 @@ export const columns: BasicColumn[] = [
width: 80,
sorter: true,
},
{
title: '原发票号码',
dataIndex: 'originalInvoiceNumber',
width: 200,
// sorter: true,
},
{
title: '购方开票名称',
dataIndex: 'buyerInvoiceName',
@ -100,12 +117,6 @@ export const columns: BasicColumn[] = [
width: 200,
// sorter: true,
},
{
title: '销方开票名称',
dataIndex: 'sellerInvoiceName',
width: 130,
// sorter: true,
},
{
title: '销方开票税号',
dataIndex: 'sellerInvoiceTaxNumber',
@ -129,18 +140,6 @@ export const columns: BasicColumn[] = [
]
export const searchFormSchema: FormSchema[] = [
{
field: 'invoiceNumber',
label: '发票号码',
colProps: { span: 4 },
component: 'Input',
},
{
field: 'buyerInvoiceTaxNumber',
label: '购方开票税号',
colProps: { span: 4 },
component: 'Input',
},
{
field: 'buyerInvoiceName',
label: '购方开票名称',
@ -156,4 +155,16 @@ export const searchFormSchema: FormSchema[] = [
allowClear: true,
},
},
{
field: 'invoiceNumber',
label: '发票号码',
colProps: { span: 4 },
component: 'Input',
},
{
field: 'buyerInvoiceTaxNumber',
label: '购方开票税号',
colProps: { span: 4 },
component: 'Input',
},
]

@ -60,18 +60,6 @@
></i>
<span>{{ record.invoiceNumber || '' }}</span>
</template>
<template v-if="column.dataIndex == 'isDetailObtained'">
<CheckCircleFilled
style="color: #257afa; font-size: 14px"
v-if="record.isDetailObtained"
/>
</template>
<template v-if="column.dataIndex == 'isPaperInvoice'">
<CheckCircleFilled
style="color: #257afa; font-size: 14px"
v-if="record.isPaperInvoice" />
<CloseCircleFilled v-else style="color: #adadad; font-size: 14px"
/></template>
<template v-if="column.key === 'action'">
<TableAction :actions="getActionOptList(record)" />
</template>
@ -116,9 +104,8 @@
import { columns, PageType, getDetailForm, BillRowMap, BillDetail } from './columns'
import { statusList } from '../columns'
import { useMessage } from '/@/hooks/web/useMessage'
import { CheckCircleFilled, CloseCircleFilled } from '@ant-design/icons-vue'
import { plus } from 'number-precision'
import { numberThousandFormat } from '/@/utils/commonUtil'
import { numberThousandFormat, digitUppercase } from '/@/utils/commonUtil'
import { useAppStore } from '/@/store/modules/app'
import { useUserStore } from '/@/store/modules/user'
import { useModal } from '/@/components/Modal'
@ -161,7 +148,11 @@
const calcSumAmountFormat = computed(() => {
const totalAmountStr = numberThousandFormat(calcSumAmount.value)
BasicFormRef.value && setFieldsValue({ amount: totalAmountStr })
BasicFormRef.value &&
setFieldsValue({
amount: calcSumAmount.value,
amountUppercase: digitUppercase(calcSumAmount.value),
})
return totalAmountStr
})
@ -185,6 +176,7 @@
labelWidth: 100,
schemas: getDetailForm(pageType.value),
showActionButtonGroup: false,
textAreaReadOnly: true,
})
const [registerTable, { setTableData, getSelectRows }] = useTable({
@ -204,7 +196,7 @@
width: 60,
},
canResize: true,
resizeHeightOffset: 15,
resizeHeightOffset: 80,
immediate: true,
})
@ -269,7 +261,7 @@
const getStatusInfo = (key) => {
const item = statusList?.find(
(el) => el.value === expenseAccountDetail.value?.reimbursementType,
(el) => el.value === (expenseAccountDetail.value?.reimbursementType || 0),
)
return (item?.[key] as string) || ''
}
@ -456,17 +448,13 @@
padding: 0;
}
.top-opt-wrapper {
display: flex;
justify-content: flex-start;
align-items: center;
.flex_arrange(row, flex-start);
padding: 8px 16px;
background: #f5f9fc;
position: relative;
.status-box {
margin: 15px;
display: flex;
justify-content: center;
align-items: center;
.flex_arrange;
& > span {
margin-left: 4px;
font-size: 12px;
@ -496,26 +484,18 @@
margin-top: 14px;
}
.table-title-box {
display: flex;
align-items: center;
justify-content: flex-start;
.flex_arrange(row, flex-start);
padding: 16px 0 6px 0;
.bill-import-opt {
display: flex;
align-items: center;
justify-content: flex-start;
.flex_arrange(row, flex-start);
cursor: pointer;
&-box {
display: flex;
align-items: center;
justify-content: flex-start;
.flex_arrange(row, flex-start);
margin-left: 40px;
}
&-btn {
margin-left: 16px;
display: flex;
align-items: center;
justify-content: flex-start;
.flex_arrange(row, flex-start);
cursor: pointer;
& > span {
margin-left: 2px;
@ -532,12 +512,9 @@
}
}
.calc-sum-box {
// position: fixed;
// bottom: 10px;
display: flex;
align-items: center;
// margin-left: 20px;
font-size: 12px;
font-size: 14px;
font-weight: 700;
padding-top: 16px;
.calc-sum-label {
@ -558,9 +535,7 @@
box-shadow: 0px -3px 6px #d6d6d6;
padding-right: 40px;
margin-top: auto;
display: flex;
align-items: center;
justify-content: flex-end;
.flex_arrange(row, flex-end);
.ant-btn + .ant-btn {
margin-left: 10px;
}

@ -105,6 +105,7 @@
},
canResize: true,
immediate: true,
resizeHeightOffset: 15,
actionColumn: {
width: 80,
title: '操作',
@ -212,9 +213,7 @@
}
}
.status-box {
display: flex;
justify-content: center;
align-items: center;
.flex_arrange;
& > span {
margin-left: 4px;
font-size: 12px;

@ -1,5 +1,7 @@
import moment from 'moment'
import { BasicColumn, FormSchema } from '/@/components/Table'
import { numberThousandFormat } from '/@/utils/commonUtil'
import { h } from 'vue'
export const invoiceCodeList: LabelValueOptions = [
{ label: '全电发票(铁路电子客票)', value: '51' },
@ -19,6 +21,14 @@ export const invoiceStatusList: LabelValueOptions = [
{ label: '红票', value: '01' },
]
export const reimbursementStatusList: LabelValueOptions = [
{ label: '未提交', value: 0, class: 'icon-jichu_yuanquan', color: '#7A8798' },
{ label: '已提交', value: 1, class: 'icon-yiwancheng2-copy', color: '#257AFA' },
{ label: '审核通过', value: 2, class: 'icon-yiwancheng2', color: '#17A6A3' },
{ label: '审核驳回', value: 3, class: 'icon-weiwancheng-copy', color: '#BA3849' },
{ label: '已撤销', value: 4, class: 'icon-yichexiao', color: '#7A8798' },
]
export const columns: BasicColumn[] = [
{
title: '发票号码',
@ -27,12 +37,12 @@ export const columns: BasicColumn[] = [
sorter: true,
},
{
title: '发票类型代码',
title: '发票类型',
dataIndex: 'invoiceTypeCode',
width: 180,
sorter: true,
customRender({ text }) {
return invoiceCodeList.find((el) => el.value === text)?.label || ''
return invoiceCodeList.find((el) => el.value === text)?.label || '未知'
},
},
{
@ -47,7 +57,15 @@ export const columns: BasicColumn[] = [
sorter: true,
width: 100,
customRender({ text }) {
return numberThousandFormat(text)
return h(
'b',
{
style: {
fontWeight: 900,
},
},
numberThousandFormat(text),
)
},
},
{
@ -65,7 +83,15 @@ export const columns: BasicColumn[] = [
width: 100,
sorter: true,
customRender({ text }) {
return numberThousandFormat(text)
return h(
'b',
{
style: {
fontWeight: 900,
},
},
numberThousandFormat(text),
)
},
},
{
@ -105,7 +131,7 @@ export const columns: BasicColumn[] = [
{
title: '销方开票名称',
dataIndex: 'sellerInvoiceName',
width: 130,
width: 200,
sorter: true,
},
{
@ -116,15 +142,14 @@ export const columns: BasicColumn[] = [
sorter: true,
},
{
title: '是否已获取详情',
dataIndex: 'isDetailObtained',
width: 120,
align: 'center',
title: '销方地址电话',
dataIndex: 'sellerAddressPhone',
width: 200,
sorter: true,
},
{
title: '销方识别号',
dataIndex: 'sellerIdentificationNumber',
title: '销方银行账户',
dataIndex: 'sellerBankAccount',
width: 200,
sorter: true,
},
@ -135,16 +160,18 @@ export const columns: BasicColumn[] = [
sorter: true,
},
{
title: '购方名称',
dataIndex: 'buyerName',
title: '购方银行账户',
dataIndex: 'buyerBankAccount',
width: 200,
ellipsis: true,
sorter: true,
},
{
title: '当前时间',
dataIndex: 'currentTime',
title: '购方地址电话',
dataIndex: 'buyerAddressPhone',
width: 200,
ellipsis: true,
sorter: true,
width: 150,
},
{
title: '扣除额',
@ -155,12 +182,6 @@ export const columns: BasicColumn[] = [
return numberThousandFormat(text)
},
},
{
title: '机动车发票类型代码',
dataIndex: 'vehicleInvoiceTypeCode',
width: 200,
sorter: true,
},
{
title: '税控码',
dataIndex: 'taxControlCode',
@ -168,12 +189,6 @@ export const columns: BasicColumn[] = [
ellipsis: true,
sorter: true,
},
{
title: '购方税号',
dataIndex: 'buyerTaxNumber',
width: 200,
sorter: true,
},
{
title: '纸质发票号码',
dataIndex: 'paperInvoiceNumber',
@ -192,41 +207,6 @@ export const columns: BasicColumn[] = [
width: 120,
sorter: true,
},
{
title: '开票单位代码',
dataIndex: 'invoiceUnitCode',
width: 200,
sorter: true,
},
{
title: '购方银行账户',
dataIndex: 'buyerBankAccount',
width: 200,
ellipsis: true,
sorter: true,
},
{
title: '购方银行账号',
dataIndex: 'buyerBankAccountNumber',
width: 200,
sorter: true,
},
{
title: '金额',
dataIndex: 'amount',
width: 100,
sorter: true,
customRender({ text }) {
return numberThousandFormat(text)
},
},
{
title: '销方名称',
dataIndex: 'sellerName',
width: 200,
ellipsis: true,
sorter: true,
},
{
title: '特定要素',
dataIndex: 'specialElements',
@ -241,69 +221,79 @@ export const columns: BasicColumn[] = [
},
{
title: '报销状态',
dataIndex: 'reimbursementStatus',
dataIndex: 'reimbursementType',
width: 100,
sorter: true,
},
{
title: '操作员代码',
dataIndex: 'operatorCode',
width: 200,
title: '报销单编号',
dataIndex: 'reimbursementId',
width: 180,
sorter: true,
},
{
title: '购方地址电话',
dataIndex: 'buyerAddressPhone',
width: 200,
ellipsis: true,
title: '报销人',
dataIndex: 'reimburser',
width: 100,
sorter: true,
},
{
title: '是否为纸质发票',
dataIndex: 'isPaperInvoice',
width: 120,
align: 'center',
title: '科目名称',
dataIndex: 'ledgerAccount',
width: 160,
sorter: true,
},
{
title: '发票请求流水号',
dataIndex: 'invoiceRequestNumber',
width: 200,
title: '报销事由',
dataIndex: 'reason',
width: 180,
sorter: true,
},
{
title: '税额',
dataIndex: 'taxAmount',
width: 100,
title: '报销申请时间',
dataIndex: 'reimbTime',
width: 180,
sorter: true,
customRender({ text }) {
return numberThousandFormat(text)
},
},
{
title: '备注',
dataIndex: 'remarks',
width: 200,
title: '使用情况',
dataIndex: 'reimbursementDesc',
width: 500,
// sorter: true,
ellipsis: true,
customRender({ record }) {
return record.reimbursementId
? `报销单号${record.reimbursementId}使用,报销人:${record.reimburser},报销时间:${moment(
record.createTime,
).format('YYYY-MM-DD')} ${record.reason ?? '-'}`
: '-'
},
},
{
title: '审核通过/驳回时间',
dataIndex: 'approvalTime',
width: 180,
sorter: true,
},
{
title: '购方识别号',
dataIndex: 'buyerIdentificationNumber',
title: '操作员代码',
dataIndex: 'operatorCode',
width: 200,
sorter: true,
},
{
title: '购方名称',
dataIndex: 'buyerFullName',
width: 200,
title: '是否为纸质发票',
dataIndex: 'isPaperInvoice',
width: 120,
align: 'center',
sorter: true,
},
{
title: '销方税号',
dataIndex: 'sellerTaxNumber',
title: '备注',
dataIndex: 'remarks',
width: 200,
sorter: true,
ellipsis: true,
// sorter: true,
},
{
title: '发票代码',
@ -311,18 +301,6 @@ export const columns: BasicColumn[] = [
width: 160,
sorter: true,
},
{
title: '销方地址电话',
dataIndex: 'sellerAddressPhone',
width: 200,
sorter: true,
},
{
title: '销方银行账号',
dataIndex: 'sellerBankAccountNumber',
width: 200,
sorter: true,
},
{
title: '复核人',
dataIndex: 'reviewer',
@ -341,12 +319,6 @@ export const columns: BasicColumn[] = [
width: 200,
sorter: true,
},
{
title: '销方银行账户',
dataIndex: 'sellerBankAccount',
width: 200,
sorter: true,
},
]
export const searchFormSchema: FormSchema[] = [
@ -378,3 +350,9 @@ export const searchFormSchema: FormSchema[] = [
},
},
]
export const getStatusInfo = (row, key) => {
const item = reimbursementStatusList?.find((el) => el.value === row?.reimbursementType)
return (item?.[key] as string) || ''
}

@ -1,6 +1,8 @@
import { invoiceCodeList, invoiceStatusList } from '../columns'
import { BasicColumn } from '/@/components/Table'
import moment from 'moment'
import { h } from 'vue'
import { numberThousandFormat } from '/@/utils/commonUtil'
type DisplayCardList = Array<
Array<{
@ -9,6 +11,8 @@ type DisplayCardList = Array<
isSearch?: boolean
isDate?: boolean
isCustomRender?: boolean
isBold?: boolean
needNumberFormat?: boolean
list?: LabelValueOptions
}>
>
@ -17,45 +21,34 @@ export const displayCardList: DisplayCardList = [
[
{ label: '发票号码:', key: 'invoiceNumber' },
{ label: '发票代码:', key: 'invoiceCode' },
{ label: '发票类型代码', key: 'invoiceTypeCode', isSearch: true, list: invoiceCodeList },
{ label: '发票类型', key: 'invoiceTypeCode', isSearch: true, list: invoiceCodeList },
{ label: '发票状态:', key: 'invoiceStatus', isSearch: true, list: invoiceStatusList },
{ label: '发票请求流水号:', key: 'invoiceRequestNumber' },
{ label: '商品或服务名称:', key: 'itemOrServiceName' },
{ label: '开票日期:', key: 'invoicingDate', isDate: true },
{ label: '当前时间:', key: 'currentTime' },
{ label: '税控码:', key: 'taxControlCode' },
{ label: '开票单位代码:', key: 'invoiceUnitCode' },
{ label: '是否为纸质发票:', key: 'isPaperInvoice', isCustomRender: true },
{ label: '纸质发票号码:', key: 'paperInvoiceNumber' },
{ label: '特定要素:', key: 'specialElements' },
{ label: '特定要素类型代码:', key: 'specialElementTypeCode' },
{ label: '报销状态:', key: 'reimbursementStatus' },
{ label: '最终校验码:', key: 'finalCheckCode' },
{ label: '清单标志:', key: 'itemFlag' },
{ label: '机器编号:', key: 'machineCode' },
{ label: '机动车发票类型代码:', key: 'vehicleInvoiceTypeCode' },
{ label: '原发票号码:', key: 'originalInvoiceNumber' },
{ label: '是否已获取详情:', key: 'isDetailObtained', isCustomRender: true },
{ label: '备注:', key: 'remarks' },
],
[
{ label: '购方名称:', key: 'buyerName' },
{ label: '购方开票名称:', key: 'buyerInvoiceName' },
{ label: '购方税号:', key: 'buyerTaxNumber' },
{ label: '购方开票税号:', key: 'buyerInvoiceTaxNumber' },
{ label: '购方识别号:', key: 'buyerIdentificationNumber' },
{ label: '购方银行账户:', key: 'buyerBankAccount' },
{ label: '购方银行账号:', key: 'buyerBankAccountNumber' },
{ label: '购方地址电话:', key: 'buyerAddressPhone' },
],
[
{ label: '销方名称:', key: 'sellerName' },
{ label: '销方开票名称:', key: 'sellerInvoiceName' },
{ label: '销方税号:', key: 'sellerTaxNumber' },
{ label: '销方开票税号:', key: 'sellerInvoiceTaxNumber' },
{ label: '销方识别号:', key: 'sellerIdentificationNumber' },
{ label: '销方银行账户:', key: 'sellerBankAccount' },
{ label: '销方银行账号:', key: 'sellerBankAccountNumber' },
{ label: '销方地址电话:', key: 'sellerAddressPhone' },
],
[
@ -65,10 +58,20 @@ export const displayCardList: DisplayCardList = [
{ label: '操作员代码:', key: 'operatorCode' },
],
[
{ label: '合计金额:', key: 'totalAmount' },
{ label: '合计税额:', key: 'totalTax' },
{ label: '扣除额:', key: 'deductionAmount' },
{ label: '价税合计:', key: 'totalWithTax' },
{ label: '报销状态:', key: 'reimbursementType' },
{ label: '报销单编号:', key: 'reimbursementId' },
{ label: '报销人:', key: 'reimburser' },
{ label: '科目名称:', key: 'ledgerAccount' },
{ label: '报销事由:', key: 'reason' },
{ label: '报销申请时间:', key: 'reimbTime' },
{ label: '使用情况:', key: 'reimbursementDesc' },
{ label: '审核通过/驳回时间:', key: 'approvalTime' },
],
[
{ label: '合计金额:', key: 'totalAmount', isBold: true, needNumberFormat: true },
{ label: '合计税额:', key: 'totalTax', needNumberFormat: true },
{ label: '扣除额:', key: 'deductionAmount', needNumberFormat: true },
{ label: '价税合计:', key: 'totalWithTax', isBold: true, needNumberFormat: true },
],
]
@ -94,11 +97,11 @@ export const columns: BasicColumn[] = [
width: 200,
},
{
title: '发票类型代码',
title: '发票类型',
dataIndex: 'invoiceTypeCode',
width: 200,
customRender({ text }) {
return invoiceCodeList.find((el) => el.value === text)?.label || ''
return invoiceCodeList.find((el) => el.value === text)?.label || '未知'
},
},
{
@ -120,17 +123,31 @@ export const columns: BasicColumn[] = [
{
title: '金额',
dataIndex: 'amount',
width: 100,
width: 130,
customRender({ text }) {
return h(
'b',
{
style: {
fontWeight: 900,
},
},
numberThousandFormat(text),
)
},
},
{
title: '税率',
dataIndex: 'taxRate',
width: 100,
width: 130,
},
{
title: '税额',
dataIndex: 'taxAmount',
width: 100,
width: 130,
customRender({ text }) {
return numberThousandFormat(text)
},
},
{
title: '商品名称',
@ -159,6 +176,9 @@ export const columns: BasicColumn[] = [
title: '商品单价',
dataIndex: 'unitPrice',
width: 100,
customRender({ text }) {
return numberThousandFormat(text)
},
},
{
title: '商品编码',
@ -191,14 +211,26 @@ export const columns: BasicColumn[] = [
]
export const getDisplayValLabel = (displayItem, detailInfo): string => {
if (displayItem['isSearch']) {
return (
displayItem?.['list'].find((el) => el.value === detailInfo?.[displayItem?.['key']])?.label ||
'未知'
)
} else if (displayItem['isDate']) {
return moment(detailInfo?.[displayItem?.['key']]).format('YYYY-MM-DD HH:mm:ss')
if (displayItem['key'] === 'reimbursementDesc') {
return detailInfo.reimbursementId
? `报销单号${detailInfo.reimbursementId}使用,报销人:${
detailInfo.reimburser
}${moment(detailInfo.createTime).format('YYYY-MM-DD')} ${
detailInfo.reason ?? '-'
}`
: '-'
} else {
return detailInfo?.[displayItem?.['key']] || ''
if (displayItem['isSearch']) {
return (
displayItem?.['list'].find((el) => el.value === detailInfo?.[displayItem?.['key']])
?.label || '未知'
)
} else if (displayItem['isDate']) {
return moment(detailInfo?.[displayItem?.['key']]).format('YYYY-MM-DD HH:mm:ss')
} else if (displayItem['needNumberFormat']) {
return numberThousandFormat(detailInfo?.[displayItem?.['key']])
} else {
return detailInfo?.[displayItem?.['key']] || ''
}
}
}

@ -29,13 +29,27 @@
<template v-if="item.isCustomRender && incomeInvoiceDetail">
<CheckCircleFilled
style="color: #257afa; font-size: 14px"
v-if="incomeInvoiceDetail[item['key']]"
v-if="incomeInvoiceDetail[item['key']] == '1'"
/>
<CloseCircleFilled v-else style="color: #adadad; font-size: 14px" />
</template>
<span v-else>
{{ getDisplayValLabel(item, incomeInvoiceDetail) }}
</span>
<template v-else>
<span
v-if="item.key === 'reimbursementType'"
:class="['status-box', 'iconfont', getStatusInfo(incomeInvoiceDetail, 'class')]"
:style="{
color: getStatusInfo(incomeInvoiceDetail, 'color'),
fontSize: '16px',
}"
>
<span :style="{ color: getStatusInfo(incomeInvoiceDetail, 'color') }">
{{ getStatusInfo(incomeInvoiceDetail, 'label') }}
</span>
</span>
<span :style="{ fontWeight: item.isBold ? 900 : '' }" v-else>
{{ getDisplayValLabel(item, incomeInvoiceDetail) }}
</span>
</template>
</div>
</div>
<div class="info-item-line"></div>
@ -68,6 +82,7 @@
import { GetInfo } from '../api'
import { useCopyToClipboard } from '/@/hooks/web/useCopyToClipboard'
import { columns, displayCardList, getDisplayValLabel } from './columns'
import { getStatusInfo } from '../columns'
import { CheckCircleFilled, CloseCircleFilled } from '@ant-design/icons-vue'
import { useMessage } from '/@/hooks/web/useMessage'
import { useGo } from '/@/hooks/web/usePage'
@ -176,18 +191,14 @@
padding: 0;
}
.top-opt-wrapper {
display: flex;
justify-content: flex-start;
align-items: center;
.flex_arrange(row, flex-start);
padding: 8px 16px;
background: #f5f9fc;
.ds-action-svg-btn {
display: inline-block;
width: 32px;
height: 32px;
display: flex;
justify-content: center;
align-items: center;
.flex_arrange;
border-radius: 2px;
margin-right: 8px;
cursor: pointer;
@ -209,9 +220,7 @@
padding: 14px 0 4px 0;
}
.info-wrapper {
display: flex;
justify-content: flex-start;
align-items: flex-start;
.flex_arrange(row, flex-start, flex-start);
flex-wrap: wrap;
.info-item {
display: flex;
@ -227,10 +236,7 @@
&-value {
flex: 1;
color: #33383d;
word-break: break-all;
word-wrap: break-word;
white-space: break-spaces;
hyphens: auto;
.line-feed();
}
}
.info-item-line {
@ -241,5 +247,12 @@
}
}
}
.status-box {
.flex_arrange(row, flex-start);
& > span {
margin-left: 4px;
font-size: 12px;
}
}
}
</style>

@ -11,16 +11,23 @@
@click="copyHandle(record)"
></i>
</template>
<template v-if="column.dataIndex == 'isDetailObtained'">
<template v-if="column.dataIndex == 'isPaperInvoice'">
<CheckCircleFilled
style="color: #257afa; font-size: 14px"
v-if="record.isDetailObtained"
v-if="record.isPaperInvoice == '1'"
/>
<CloseCircleFilled v-else style="color: #adadad; font-size: 14px" />
</template>
<template v-if="column.dataIndex == 'reimbursementType'">
<span
:class="['status-box', 'iconfont', getStatusInfo(record, 'class')]"
:style="{ color: getStatusInfo(record, 'color'), fontSize: '16px' }"
>
<span :style="{ color: getStatusInfo(record, 'color') }">
{{ getStatusInfo(record, 'label') }}
</span>
</span>
</template>
<template v-if="column.dataIndex == 'isPaperInvoice'">
<CheckCircleFilled style="color: #257afa; font-size: 14px" v-if="record.isPaperInvoice" />
<CloseCircleFilled v-else style="color: #adadad; font-size: 14px"
/></template>
<template v-if="column.key === 'action'">
<TableAction :actions="getActionOptList(record)" />
</template>
@ -34,7 +41,7 @@
import { GetList } from './api'
import { formatParams } from '/@/hooks/web/common'
import { useGo } from '/@/hooks/web/usePage'
import { columns, searchFormSchema } from './columns'
import { columns, searchFormSchema, getStatusInfo } from './columns'
import { useMessage } from '/@/hooks/web/useMessage'
import { CheckCircleFilled, CloseCircleFilled } from '@ant-design/icons-vue'
import { useCopyToClipboard } from '/@/hooks/web/useCopyToClipboard'
@ -139,5 +146,12 @@
<style lang="less" scoped>
.ds-fee-settle-main-table {
.status-box {
.flex_arrange;
& > span {
margin-left: 4px;
font-size: 12px;
}
}
}
</style>

@ -60,7 +60,7 @@ export default ({ command, mode }: ConfigEnv): UserConfig => {
proxy: createProxy(VITE_PROXY),
},
esbuild: {
pure: VITE_DROP_CONSOLE ? ['console.log', 'debugger'] : [],
pure: VITE_DROP_CONSOLE ? ['console.log', 'debugger'] : [],
},
build: {
target: 'es2015',
@ -92,6 +92,7 @@ export default ({ command, mode }: ConfigEnv): UserConfig => {
preprocessorOptions: {
less: {
modifyVars: generateModifyVars(),
additionalData: `@import "${pathResolve('src/design/public.less')}";`,
javascriptEnabled: true,
},
},

Loading…
Cancel
Save