数据引入

szh-new
lijingjia 6 months ago
parent eb30778ccf
commit 04d5f146e1

@ -49,9 +49,19 @@
<a-dropdown>
<template #overlay>
<a-menu>
<a-menu-item key="1">1st item</a-menu-item>
<a-menu-item key="2">2nd item</a-menu-item>
<a-menu-item key="3">3rd item</a-menu-item>
<a-menu-item @click="submit"></a-menu-item>
<a-menu-item>{{ tbType == 'receive' ? '应收提交' : '应付提交' }}</a-menu-item>
<a-menu-item>整票提交</a-menu-item>
<a-menu-item @click="revokeSubmit"></a-menu-item>
<a-menu-item>撤销整票提交</a-menu-item>
<a-menu-item>申请开票</a-menu-item>
<a-menu-item>收费申请</a-menu-item>
<a-menu-item>费用拆分</a-menu-item>
<a-menu-item>查看工作流</a-menu-item>
<a-menu-item>批量更改费用对象</a-menu-item>
<a-menu-item>批量修改核算单位</a-menu-item>
<a-menu-item>禁开发票</a-menu-item>
<a-menu-item>费用信息排序</a-menu-item>
</a-menu>
</template>
<a-button type="link">
@ -59,6 +69,15 @@
<span class="iconfont icon-xia" :style="{ fontSize: '12px' }"></span>
</a-button>
</a-dropdown>
<a-button type="link">
申请修改
</a-button>
<a-button type="link">
申请删除
</a-button>
<a-button type="link">
取消申请
</a-button>
<a-dropdown>
<template #overlay>
<a-menu>
@ -91,7 +110,7 @@
import FeeTemDrawer from './components/feeTemDrawer.vue'
import ToFeeTemDrawer from './components/ToFeeTemDrawer.vue'
const { createMessage } = useMessage()
const emits = defineEmits(['save', 'delete', 'cancel', 'refresh', 'history', 'selectInsert'])
const emits = defineEmits(['revoke', 'save', 'delete', 'cancel', 'refresh', 'history', 'selectInsert', 'submit'])
const props = defineProps({
//
data: {
@ -127,11 +146,13 @@
const needCopy = props.data.filter(item => {
return item.selected
})
if (needCopy.length == 0) return createMessage.warning('请勾选要复制的费用!')
needCopy.forEach(item => {
item.selected = false
const deepCopyRow = JSON.parse(JSON.stringify(item))
deepCopyRow.id = ''
deepCopyRow.feeStatus = 1
deepCopyRow.feeStatusText = '录入状态'
props.data.push(deepCopyRow)
})
}
@ -164,6 +185,17 @@
}
//
const save = () => {
let flag = false
const arr = []
for (let i = 0; i < props.data.length; i++) {
if (!props.data[i].feeName && props.data[i].feeStatus == 1) {
createMessage.warning(`费用名称不能为空!`)
return false
}
if (!props.data[i].amount && props.data[i].feeStatus == 1) {
return createMessage.warning(`金额不能为空!`)
}
}
emits('save')
}
//
@ -200,6 +232,45 @@
const saveToTem = () => {
toFeeTemDrawer.value.init()
}
//
const submit = () => {
let flag = false
const arr = []
props.data.forEach(item => {
if (item?.selected) {
flag = true
arr.push(item)
}
})
if (!flag) return createMessage.warning('请勾选要提交审核的费用!')
for (let i = 0; i < arr.length; i++) {
if (!arr[i].feeName) {
createMessage.warning(`费用名称不能为空!`)
return false
}
if (!arr[i].amount) {
return createMessage.warning(`金额不能为空!`)
}
}
emits('submit', arr)
}
//
const revokeSubmit = () => {
let flag = false
const ids = []
props.data.forEach(item => {
if (item?.selected) {
if (item.feeStatus != 2) {
return createMessage.warning('只能撤销状态为提交审核的费用!')
} else {
ids.push(item?.id)
}
flag = true
}
})
if (!flag) return createMessage.warning('请勾选要撤销提交的费用!')
emits('revoke', ids)
}
</script>
<style lang="scss">

@ -11,7 +11,9 @@ enum Api {
edit = '/feeApi/FeeRecord/Submit',
delete = '/feeApi/FeeRecord/Delete',
statistic = '/feeApi/FeeRecord/FeeStatistics',
ReadAsTemplate = '/feeApi/FeeRecord/ReadAsTemplate'
ReadAsTemplate = '/feeApi/FeeRecord/ReadAsTemplate',
submit = '/feeApi/FeeRecord/ApplyAudit',
Withdraw = '/feeApi/FeeRecord/Withdraw'
}
// 列表 (Auth)
export function GetList(data: PageRequest) {
@ -55,3 +57,21 @@ export function ReadAsTemplate(query) {
params: query
})
}
// 提交
export function ApplyAudit(data: PageRequest) {
return request<DataResult>({
url: Api.submit,
method: 'post',
data
})
}
// 撤销提交
export function Withdraw(data: PageRequest) {
return request<DataResult>({
url: Api.Withdraw,
method: 'post',
data
})
}

@ -2,18 +2,18 @@ export const feeColumns = [
{
title: '费用状态',
dataIndex: 'feeStatusText',
width: 120
width: '150px'
}, {
title: '费用名称',
width: 130,
width: 150,
dataIndex: 'feeName'
}, {
title: '客户类别',
width: 130,
width: 150,
dataIndex: 'customerTypeText'
}, {
title: '结算对象',
width: 130,
width: 150,
dataIndex: 'customerName'
}, {
title: '单价',
@ -29,11 +29,11 @@ export const feeColumns = [
dataIndex: 'taxRate'
}, {
title: '不含税金额',
width: 130,
width: 180,
dataIndex: 'noTaxAmount'
}, {
title: '金额',
width: 130,
width: 100,
dataIndex: 'amount'
}, {
title: '币别',
@ -45,11 +45,11 @@ export const feeColumns = [
dataIndex: 'exchangeRate'
}, {
title: '销项税额',
width: 130,
width: 150,
dataIndex: 'accTaxAmount'
}, {
title: '财务税率',
width: 130,
width: 150,
dataIndex: 'accTaxRate'
}, {
title: '备注',
@ -57,7 +57,7 @@ export const feeColumns = [
dataIndex: 'note'
}, {
title: '费用英文名称',
width: 130,
width: 230,
dataIndex: 'feeEnName'
}
]

@ -4,10 +4,11 @@
* @Date: 2024-05-07 15:19:07
-->
<template>
<div class="ds-introduce">
<div class="ds-fee-table">
<a-table
:row-selection="{ selectedRowKeys: state.infoRowKeys, onChange: infoChange }"
rowKey="id"
:scroll="{ x: '100%', y: 300 }"
:columns="feeColumns"
:data-source="feeData"
:pagination="false"
@ -168,48 +169,16 @@
}
defineExpose({
list,
feeData,
init
})
</script>
<style lang="scss">
.full-modal {
.ant-modal {
max-width: 100%;
top: 0;
padding-bottom: 0;
margin: 0;
}
.ant-modal-content {
display: flex;
flex-direction: column;
height: calc(100vh);
}
.ant-modal-body {
flex: 1;
}
.vben-basic-table {
padding-top: 0;
height: auto;
padding-bottom: 0;
form {
margin-bottom: 0;
padding: 10px 0 0 0;
}
}
.ant-form-item-control-input-content {
.ant-btn {
margin-top: 22px;
}
}
.ds-fee-table {
padding: 0 20px;
.ant-table-cell {
padding: 4px 8px!important;
}
.ant-table-wrapper {
padding: 0;
padding: 5px 12px;
}
.info {
padding: 0 15px;
}
}
</style>

@ -10,13 +10,12 @@
v-model:visible="visible"
v-if="visible"
title="费用模版"
width="100%"
wrap-class-name="full-modal"
width="80%"
@ok="handleOk"
>
<BasicTable @register="registerTable" :row-selection="{ selectedRowKeys: state.historyRowKeys, onChange: historyChange }" rowKey="id"></BasicTable>
<BasicTable @register="registerTable" :canRowSelect="true" :row-selection="{ selectedRowKeys: state.historyRowKeys, onChange: historyChange }" rowKey="id" @row-click="onRowClick"></BasicTable>
<div class="info">
<h2>费用明细</h2>
<h2 style="margin-left: 20px; font-weight: 600">费用明细</h2>
<feeTable
ref="feeTabel"
></feeTable>
@ -120,6 +119,12 @@
const feeTabel = ref(null)
//
const handleOk = () => {
let data = []
if (feeTabel.value.list.length) {
data = feeTabel.value.list
} else {
data = feeTabel.value.feeData
}
emits('submit', feeTabel.value.list)
}
const historyChange = (v) => {
@ -129,8 +134,19 @@
state.historyRowKeys = [v[v.length - 1]]
}
}
//
const onRowClick = (record, index) => {
//
const newSelectedRowKeys = [...state.historyRowKeys];
if (newSelectedRowKeys.includes(record.id)) {
newSelectedRowKeys.splice(newSelectedRowKeys.indexOf(record.id), 1);
} else {
newSelectedRowKeys.push(record.id);
}
state.historyRowKeys = newSelectedRowKeys
}
watch(() => state.historyRowKeys, (v) => {
feeTabel.value.init(v, 'tem')
if (v.length == 1) feeTabel.value.init(v, 'tem')
})
defineExpose({
init,
@ -174,9 +190,6 @@
.ant-table-wrapper {
padding: 0;
}
.info {
padding: 0 15px;
}
.h2 {
font-weight: 600;
}

@ -4,19 +4,26 @@
* @Date: 2024-05-07 15:19:07
-->
<template>
<div class="ds-introduce">
<div class="ds-history-drawer">
<!-- 引入弹窗 -->
<a-modal
v-model:visible="visible"
v-if="visible"
title="历史引入"
width="100%"
wrap-class-name="full-modal"
width="80%"
@ok="handleOk"
>
<BasicTable @register="registerTable" :row-selection="{ selectedRowKeys: state.historyRowKeys, onChange: historyChange }" rowKey="id"></BasicTable>
<BasicTable
class="ds-history-drawer"
:canRowSelect="true"
:scroll="{ x: '100%', y: 300 }"
:row-selection="{ selectedRowKeys: state.historyRowKeys, onChange: historyChange }"
rowKey="id"
@register="registerTable"
@row-click="onRowClick"
></BasicTable>
<div class="info">
<h2>费用明细</h2>
<h2 style="padding-left: 20px; font-weight: 600;">费用明细</h2>
<feeTable
ref="feeTabel"
></feeTable>
@ -111,13 +118,10 @@
const visible = ref(false)
//
const state = reactive({
historyRowKeys: ['1780891904372772864']
historyRowKeys: []
})
//
const feeData = ref([])
const afterOpenChange = () => {
}
const init = () => {
visible.value = true
}
@ -127,7 +131,13 @@
const feeTabel = ref(null)
//
const handleOk = () => {
emits('submit', feeTabel.value.list)
let data = []
if (feeTabel.value.list.length) {
data = feeTabel.value.list
} else {
data = feeTabel.value.feeData
}
emits('submit', data)
}
const historyChange = (v) => {
if (v.length == 1) {
@ -136,8 +146,19 @@
state.historyRowKeys = [v[v.length - 1]]
}
}
//
const onRowClick = (record, index) => {
//
const newSelectedRowKeys = [...state.historyRowKeys];
if (newSelectedRowKeys.includes(record.id)) {
newSelectedRowKeys.splice(newSelectedRowKeys.indexOf(record.id), 1);
} else {
newSelectedRowKeys.push(record.id);
}
state.historyRowKeys = newSelectedRowKeys
}
watch(() => state.historyRowKeys, (v) => {
feeTabel.value.init(v, 'history')
if (v.length == 1) feeTabel.value.init(v, 'history')
})
defineExpose({
init,
@ -146,7 +167,7 @@
</script>
<style lang="scss">
.full-modal {
.ds-history-drawer {
.ant-modal {
max-width: 100%;
top: 0;
@ -165,11 +186,12 @@
padding-top: 0;
height: auto;
padding-bottom: 0;
}
form {
margin-bottom: 0;
margin-bottom: 0!important;
padding: 10px 0 0 0;
}
}
.ant-form-item-control-input-content {
.ant-btn {
margin-top: 22px;
@ -184,8 +206,5 @@
.info {
padding: 0 15px;
}
.h2 {
font-weight: 600;
}
}
</style>

@ -18,6 +18,8 @@
@refresh="init"
@history="history"
@selectInsert="selectInsert"
@revoke="revoke"
@submit="submit"
></ActionBar>
</div>
<div>
@ -31,15 +33,15 @@
import { defineProps, defineEmits, ref, watch, watchEffect, computed, unref, defineComponent, onMounted, reactive, nextTick, provide } from 'vue'
//
import { GetFeeCurrencySelectList, GetFeeCodeSelectList } from '/@/api/common'
import { HotTable } from '@handsontable/vue3';
import { registerAllModules } from 'handsontable/registry';
import 'handsontable/dist/handsontable.full.min.css';
import { HotTable } from '@handsontable/vue3'
import { registerAllModules } from 'handsontable/registry'
import 'handsontable/dist/handsontable.full.min.css'
//
import ActionBar from './actionBar.vue'
import { feeStatusList } from './columns'
//
import { feeUnitDict } from '/@/hooks/dict/index'
import { GetList, SubmitFee, DeleteFee } from './api'
import { GetList, SubmitFee, DeleteFee, ApplyAudit, Withdraw } from './api'
import { useMessage } from '/@/hooks/web/useMessage'
const { createMessage } = useMessage()
defineComponent({
@ -83,6 +85,7 @@
feeCode: '',
feeName: '',
feeEnName: '',
quantity: 1,
feeType: props.tbType == 'receive' ? 1 : 2
}
//
@ -274,7 +277,7 @@
}, {
title: '录入人',
width: 100,
data: 'submitBy',
data: 'createByName',
readOnly: true
}, {
title: '录入日期',
@ -299,12 +302,12 @@
}, {
title: '修改人',
width: 100,
data: 'submitBy',
data: 'updateByName',
readOnly: true
}, {
title: '修改日期',
width: 100,
data: 'createTime',
data: 'updateTime',
readOnly: true
}, {
title: '发票申请金额',
@ -339,7 +342,7 @@
fixedColumnsLeft: 1,
//
hiddenColumns: {
columns: [1],
columns: [1, 2],
indicators: true
},
//
@ -468,8 +471,55 @@
}
loading.value = true
SubmitFee(postData).then(res => {
loading.value = false
init()
createMessage.success(res.message)
}).catch(() => {
loading.value = false
})
}
//
const submit = (arr) => {
loading.value = true
const ids = []
arr.forEach(res => {
if (res.id) ids.push(res.id)
})
if (ids.length == arr.length) {
ApplyAudit({ id: '', ids }).then(res => {
loading.value = false
createMessage.success(res.message)
init()
}).catch(() => {
loading.value = false
})
} else {
const postData = {
BusinessId: '1780891904372772864',
items: arr
}
SubmitFee(postData).then(res => {
const { data } = res
const ids = data.map(item => {
return item.id
})
ApplyAudit({ ids }).then(res => {
loading.value = false
createMessage.success(res.message)
init()
}).catch(() => {
loading.value = false
})
})
}
}
//
const revoke = (ids) => {
loading.value = true
Withdraw(ids).then(res => {
loading.value = false
createMessage.success(res.message)
init()
}).catch(() => {
loading.value = false
})
@ -554,6 +604,7 @@
item['feeStatusText'] = feeStatusList[item.feeStatus]
if (item.createTime) item.createTime = item.createTime.split(' ')[0]
if (item.auditDate) item.auditDate = item.auditDate.split(' ')[0]
if (item.updateTime) item.updateTime = item.updateTime.split(' ')[0]
})
list.value = data
// 使
@ -563,11 +614,24 @@
cells: function(row, col) {
//
const props = { readOnly: true }
// STATUS=0
// STATUS=1
// STATUS=2
// (STATUS=3)
// (STATUS=4)
// (STATUS=5)
// STATUS=6
// STATUS=7
// STATUS=8
// STATUS=9
if (data[row]?.feeStatus != 1 && col != 0) {
//
if (data[row]?.feeStatus == 0) {
props['className'] = 'hot-green'
}
if (data[row]?.feeStatus == 2) {
props['className'] = 'hot-yellow'
}
return props
} else {
return
@ -586,7 +650,7 @@
hot.addHook('beforeKeyDown', function(event) {
// 'Enter'
if (event.key === 'ArrowDown') {
if (hot.getSelected()[0][0] == list.value.length - 1) {
if (hot.getSelected()[0][0] == list.value.length - 1 && !hot.getActiveEditor()?._opened) {
list.value.push(JSON.parse(JSON.stringify(row)))
nextTick(() => {
hot.selectCell(list.value.length - 1, 3)
@ -653,6 +717,14 @@
.hot-green {
background: #9ACD32;
}
.hot-yellow {
background: #FFE37E;
}
.hot-green, .hot-yellow {
.htAutocompleteArrow {
display: none;
}
}
}
.handsontableInput {
line-height: 30px;

@ -386,7 +386,7 @@
hot.addHook('beforeKeyDown', function(event) {
// 'Enter'
if (event.key === 'ArrowDown') {
if (hot.getSelected()[0][0] == list.value.length - 1) {
if (hot.getSelected()[0][0] == list.value.length - 1 && !hot.getActiveEditor()?._opened) {
list.value.push(JSON.parse(JSON.stringify(row)))
nextTick(() => {
hot.selectCell(list.value.length - 1, 3)

Loading…
Cancel
Save