主单 详情下来修改 以及 订舱 截单 VGM 运踪

szh-new
张同海 6 months ago
commit bfd4a4573d

@ -49,9 +49,19 @@
<a-dropdown> <a-dropdown>
<template #overlay> <template #overlay>
<a-menu> <a-menu>
<a-menu-item key="1">1st item</a-menu-item> <a-menu-item @click="submit"></a-menu-item>
<a-menu-item key="2">2nd item</a-menu-item> <a-menu-item>{{ tbType == 'receive' ? '应收提交' : '应付提交' }}</a-menu-item>
<a-menu-item key="3">3rd item</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> </a-menu>
</template> </template>
<a-button type="link"> <a-button type="link">
@ -59,6 +69,15 @@
<span class="iconfont icon-xia" :style="{ fontSize: '12px' }"></span> <span class="iconfont icon-xia" :style="{ fontSize: '12px' }"></span>
</a-button> </a-button>
</a-dropdown> </a-dropdown>
<a-button type="link">
申请修改
</a-button>
<a-button type="link">
申请删除
</a-button>
<a-button type="link">
取消申请
</a-button>
<a-dropdown> <a-dropdown>
<template #overlay> <template #overlay>
<a-menu> <a-menu>
@ -91,7 +110,7 @@
import FeeTemDrawer from './components/feeTemDrawer.vue' import FeeTemDrawer from './components/feeTemDrawer.vue'
import ToFeeTemDrawer from './components/ToFeeTemDrawer.vue' import ToFeeTemDrawer from './components/ToFeeTemDrawer.vue'
const { createMessage } = useMessage() 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({ const props = defineProps({
// //
data: { data: {
@ -127,11 +146,13 @@
const needCopy = props.data.filter(item => { const needCopy = props.data.filter(item => {
return item.selected return item.selected
}) })
if (needCopy.length == 0) return createMessage.warning('请勾选要复制的费用!')
needCopy.forEach(item => { needCopy.forEach(item => {
item.selected = false item.selected = false
const deepCopyRow = JSON.parse(JSON.stringify(item)) const deepCopyRow = JSON.parse(JSON.stringify(item))
deepCopyRow.id = '' deepCopyRow.id = ''
deepCopyRow.feeStatus = 1 deepCopyRow.feeStatus = 1
deepCopyRow.feeStatusText = '录入状态'
props.data.push(deepCopyRow) props.data.push(deepCopyRow)
}) })
} }
@ -164,6 +185,17 @@
} }
// //
const save = () => { 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') emits('save')
} }
// //
@ -200,6 +232,45 @@
const saveToTem = () => { const saveToTem = () => {
toFeeTemDrawer.value.init() 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> </script>
<style lang="scss"> <style lang="scss">

@ -11,7 +11,9 @@ enum Api {
edit = '/feeApi/FeeRecord/Submit', edit = '/feeApi/FeeRecord/Submit',
delete = '/feeApi/FeeRecord/Delete', delete = '/feeApi/FeeRecord/Delete',
statistic = '/feeApi/FeeRecord/FeeStatistics', statistic = '/feeApi/FeeRecord/FeeStatistics',
ReadAsTemplate = '/feeApi/FeeRecord/ReadAsTemplate' ReadAsTemplate = '/feeApi/FeeRecord/ReadAsTemplate',
submit = '/feeApi/FeeRecord/ApplyAudit',
Withdraw = '/feeApi/FeeRecord/Withdraw'
} }
// 列表 (Auth) // 列表 (Auth)
export function GetList(data: PageRequest) { export function GetList(data: PageRequest) {
@ -54,4 +56,22 @@ export function ReadAsTemplate(query) {
method: 'get', method: 'get',
params: 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: '费用状态', title: '费用状态',
dataIndex: 'feeStatusText', dataIndex: 'feeStatusText',
width: 120 width: '150px'
}, { }, {
title: '费用名称', title: '费用名称',
width: 130, width: 150,
dataIndex: 'feeName' dataIndex: 'feeName'
}, { }, {
title: '客户类别', title: '客户类别',
width: 130, width: 150,
dataIndex: 'customerTypeText' dataIndex: 'customerTypeText'
}, { }, {
title: '结算对象', title: '结算对象',
width: 130, width: 150,
dataIndex: 'customerName' dataIndex: 'customerName'
}, { }, {
title: '单价', title: '单价',
@ -29,11 +29,11 @@ export const feeColumns = [
dataIndex: 'taxRate' dataIndex: 'taxRate'
}, { }, {
title: '不含税金额', title: '不含税金额',
width: 130, width: 180,
dataIndex: 'noTaxAmount' dataIndex: 'noTaxAmount'
}, { }, {
title: '金额', title: '金额',
width: 130, width: 100,
dataIndex: 'amount' dataIndex: 'amount'
}, { }, {
title: '币别', title: '币别',
@ -45,11 +45,11 @@ export const feeColumns = [
dataIndex: 'exchangeRate' dataIndex: 'exchangeRate'
}, { }, {
title: '销项税额', title: '销项税额',
width: 130, width: 150,
dataIndex: 'accTaxAmount' dataIndex: 'accTaxAmount'
}, { }, {
title: '财务税率', title: '财务税率',
width: 130, width: 150,
dataIndex: 'accTaxRate' dataIndex: 'accTaxRate'
}, { }, {
title: '备注', title: '备注',
@ -57,7 +57,7 @@ export const feeColumns = [
dataIndex: 'note' dataIndex: 'note'
}, { }, {
title: '费用英文名称', title: '费用英文名称',
width: 130, width: 230,
dataIndex: 'feeEnName' dataIndex: 'feeEnName'
} }
] ]

@ -4,10 +4,11 @@
* @Date: 2024-05-07 15:19:07 * @Date: 2024-05-07 15:19:07
--> -->
<template> <template>
<div class="ds-introduce"> <div class="ds-fee-table">
<a-table <a-table
:row-selection="{ selectedRowKeys: state.infoRowKeys, onChange: infoChange }" :row-selection="{ selectedRowKeys: state.infoRowKeys, onChange: infoChange }"
rowKey="id" rowKey="id"
:scroll="{ x: '100%', y: 300 }"
:columns="feeColumns" :columns="feeColumns"
:data-source="feeData" :data-source="feeData"
:pagination="false" :pagination="false"
@ -168,48 +169,16 @@
} }
defineExpose({ defineExpose({
list, list,
feeData,
init init
}) })
</script> </script>
<style lang="scss"> <style lang="scss">
.full-modal { .ds-fee-table {
.ant-modal { padding: 0 20px;
max-width: 100%; .ant-table-cell {
top: 0; padding: 5px 12px;
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;
} }
} }
.ant-table-cell {
padding: 4px 8px!important;
}
.ant-table-wrapper {
padding: 0;
}
.info {
padding: 0 15px;
}
}
</style> </style>

@ -10,13 +10,12 @@
v-model:visible="visible" v-model:visible="visible"
v-if="visible" v-if="visible"
title="费用模版" title="费用模版"
width="100%" width="80%"
wrap-class-name="full-modal"
@ok="handleOk" @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"> <div class="info">
<h2>费用明细</h2> <h2 style="margin-left: 20px; font-weight: 600">费用明细</h2>
<feeTable <feeTable
ref="feeTabel" ref="feeTabel"
></feeTable> ></feeTable>
@ -120,6 +119,12 @@
const feeTabel = ref(null) const feeTabel = ref(null)
// //
const handleOk = () => { const handleOk = () => {
let data = []
if (feeTabel.value.list.length) {
data = feeTabel.value.list
} else {
data = feeTabel.value.feeData
}
emits('submit', feeTabel.value.list) emits('submit', feeTabel.value.list)
} }
const historyChange = (v) => { const historyChange = (v) => {
@ -129,8 +134,19 @@
state.historyRowKeys = [v[v.length - 1]] 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) => { watch(() => state.historyRowKeys, (v) => {
feeTabel.value.init(v, 'tem') if (v.length == 1) feeTabel.value.init(v, 'tem')
}) })
defineExpose({ defineExpose({
init, init,
@ -174,9 +190,6 @@
.ant-table-wrapper { .ant-table-wrapper {
padding: 0; padding: 0;
} }
.info {
padding: 0 15px;
}
.h2 { .h2 {
font-weight: 600; font-weight: 600;
} }

@ -4,19 +4,26 @@
* @Date: 2024-05-07 15:19:07 * @Date: 2024-05-07 15:19:07
--> -->
<template> <template>
<div class="ds-introduce"> <div class="ds-history-drawer">
<!-- 引入弹窗 --> <!-- 引入弹窗 -->
<a-modal <a-modal
v-model:visible="visible" v-model:visible="visible"
v-if="visible" v-if="visible"
title="历史引入" title="历史引入"
width="100%" width="80%"
wrap-class-name="full-modal"
@ok="handleOk" @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"> <div class="info">
<h2>费用明细</h2> <h2 style="padding-left: 20px; font-weight: 600;">费用明细</h2>
<feeTable <feeTable
ref="feeTabel" ref="feeTabel"
></feeTable> ></feeTable>
@ -111,13 +118,10 @@
const visible = ref(false) const visible = ref(false)
// //
const state = reactive({ const state = reactive({
historyRowKeys: ['1780891904372772864'] historyRowKeys: []
}) })
// //
const feeData = ref([]) const feeData = ref([])
const afterOpenChange = () => {
}
const init = () => { const init = () => {
visible.value = true visible.value = true
} }
@ -127,7 +131,13 @@
const feeTabel = ref(null) const feeTabel = ref(null)
// //
const handleOk = () => { 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) => { const historyChange = (v) => {
if (v.length == 1) { if (v.length == 1) {
@ -136,8 +146,19 @@
state.historyRowKeys = [v[v.length - 1]] 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) => { watch(() => state.historyRowKeys, (v) => {
feeTabel.value.init(v, 'history') if (v.length == 1) feeTabel.value.init(v, 'history')
}) })
defineExpose({ defineExpose({
init, init,
@ -146,7 +167,7 @@
</script> </script>
<style lang="scss"> <style lang="scss">
.full-modal { .ds-history-drawer {
.ant-modal { .ant-modal {
max-width: 100%; max-width: 100%;
top: 0; top: 0;
@ -165,10 +186,11 @@
padding-top: 0; padding-top: 0;
height: auto; height: auto;
padding-bottom: 0; padding-bottom: 0;
form {
margin-bottom: 0; }
padding: 10px 0 0 0; form {
} margin-bottom: 0!important;
padding: 10px 0 0 0;
} }
.ant-form-item-control-input-content { .ant-form-item-control-input-content {
.ant-btn { .ant-btn {
@ -184,8 +206,5 @@
.info { .info {
padding: 0 15px; padding: 0 15px;
} }
.h2 {
font-weight: 600;
}
} }
</style> </style>

@ -18,6 +18,8 @@
@refresh="init" @refresh="init"
@history="history" @history="history"
@selectInsert="selectInsert" @selectInsert="selectInsert"
@revoke="revoke"
@submit="submit"
></ActionBar> ></ActionBar>
</div> </div>
<div> <div>
@ -52,7 +54,7 @@
import { feeStatusList } from './columns' import { feeStatusList } from './columns'
// //
import { feeUnitDict } from '/@/hooks/dict/index' 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' import { useMessage } from '/@/hooks/web/useMessage'
const { createMessage } = useMessage() const { createMessage } = useMessage()
defineComponent({ defineComponent({
@ -96,7 +98,8 @@
feeCode: '', feeCode: '',
feeName: '', feeName: '',
feeEnName: '', feeEnName: '',
feeType: props.tbType == 'receive' ? 1 : 2, quantity: 1,
feeType: props.tbType == 'receive' ? 1 : 2
} }
// //
const list = ref([]) const list = ref([])
@ -311,10 +314,9 @@
{ {
title: '录入人', title: '录入人',
width: 100, width: 100,
data: 'submitBy', data: 'createByName',
readOnly: true, readOnly: true
}, }, {
{
title: '录入日期', title: '录入日期',
width: 100, width: 100,
data: 'createTime', data: 'createTime',
@ -341,16 +343,14 @@
{ {
title: '修改人', title: '修改人',
width: 100, width: 100,
data: 'submitBy', data: 'updateByName',
readOnly: true, readOnly: true
}, }, {
{
title: '修改日期', title: '修改日期',
width: 100, width: 100,
data: 'createTime', data: 'updateTime',
readOnly: true, readOnly: true
}, }, {
{
title: '发票申请金额', title: '发票申请金额',
width: 100, width: 100,
data: 'orderInvoiceAmount', data: 'orderInvoiceAmount',
@ -385,9 +385,9 @@
rowHeights: 32, rowHeights: 32,
fixedColumnsLeft: 1, fixedColumnsLeft: 1,
// //
hiddenColumns: { hiddenColumns: {
columns: [1], columns: [1, 2],
indicators: true, indicators: true
}, },
// //
enterMoves: 'row', enterMoves: 'row',
@ -519,14 +519,59 @@
}), }),
} }
loading.value = true loading.value = true
SubmitFee(postData) SubmitFee(postData).then(res => {
.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 loading.value = false
createMessage.success(res.message) createMessage.success(res.message)
}) init()
.catch(() => { }).catch(() => {
loading.value = false 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
})
} }
// //
const cancelEdit = () => { const cancelEdit = () => {
@ -601,40 +646,53 @@
{ FieldName: 'FeeType', FieldValue: props.tbType == 'receive' ? 1 : 2, ConditionalType: 1 }, { FieldName: 'FeeType', FieldValue: props.tbType == 'receive' ? 1 : 2, ConditionalType: 1 },
]), ]),
} }
GetList(postData) GetList(postData).then(res => {
.then((res) => { loading.value = false
loading.value = false const { data } = res
const { data } = res data.forEach((item, index) => {
data.forEach((item, index) => { item['feeStatusText'] = feeStatusList[item.feeStatus]
item['feeStatusText'] = feeStatusList[item.feeStatus] if (item.createTime) item.createTime = item.createTime.split(' ')[0]
if (item.createTime) item.createTime = item.createTime.split(' ')[0] if (item.auditDate) item.auditDate = item.auditDate.split(' ')[0]
if (item.auditDate) item.auditDate = item.auditDate.split(' ')[0] if (item.updateTime) item.updateTime = item.updateTime.split(' ')[0]
})
list.value = data
// 使
oldData = JSON.parse(JSON.stringify(data))
if (data.length != 0) {
hotTb.value.hotInstance.updateSettings({
cells: function (row, col) {
//
const props = { readOnly: true }
if (data[row]?.feeStatus != 1 && col != 0) {
//
if (data[row]?.feeStatus == 0) {
props['className'] = 'hot-green'
}
return props
} else {
return
}
},
})
}
hotTb.value.hotInstance.loadData(data)
})
.catch(() => {
loading.value = false
}) })
list.value = data
// 使
oldData = JSON.parse(JSON.stringify(data))
if (data.length != 0) {
hotTb.value.hotInstance.updateSettings({
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
}
}
})
}
hotTb.value.hotInstance.loadData(data)
})
.catch(() => {
loading.value = false
})
} }
onMounted(() => { onMounted(() => {
const hot = hotTb.value.hotInstance const hot = hotTb.value.hotInstance
@ -642,7 +700,7 @@
hot.addHook('beforeKeyDown', function (event) { hot.addHook('beforeKeyDown', function (event) {
// 'Enter' // 'Enter'
if (event.key === 'ArrowDown') { 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))) list.value.push(JSON.parse(JSON.stringify(row)))
nextTick(() => { nextTick(() => {
hot.selectCell(list.value.length - 1, 3) hot.selectCell(list.value.length - 1, 3)
@ -715,4 +773,15 @@
.handsontableInput { .handsontableInput {
line-height: 30px; line-height: 30px;
} }
.hot-yellow {
background: #FFE37E;
}
.hot-green, .hot-yellow {
.htAutocompleteArrow {
display: none;
}
}
.handsontableInput {
line-height: 30px;
}
</style> </style>

@ -386,7 +386,7 @@
hot.addHook('beforeKeyDown', function(event) { hot.addHook('beforeKeyDown', function(event) {
// 'Enter' // 'Enter'
if (event.key === 'ArrowDown') { 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))) list.value.push(JSON.parse(JSON.stringify(row)))
nextTick(() => { nextTick(() => {
hot.selectCell(list.value.length - 1, 3) hot.selectCell(list.value.length - 1, 3)

Loading…
Cancel
Save