szh-new
sunzehua 2 months ago
parent 2d9b92b92a
commit ba1e60c486

@ -139,32 +139,7 @@ const [registerTable, { setTableData, setProps, getSelectRows, setLoading }] = u
immediate: false, immediate: false,
}) })
const props = defineProps({ const props = defineProps({
//
tbType: {
type: String,
default: '',
},
//
broData: {
type: Array,
default: () => {
return []
},
},
// ID
id: {
type: String,
default: '',
},
//
details: { type: [Object, Array] }, details: { type: [Object, Array] },
//
type: { type: [String, Number] },
//
height: {
type: [String, Number],
default: '300'
}
}) })
const feeFlag = ref(false) const feeFlag = ref(false)
function openFee() { function openFee() {

@ -25,3 +25,10 @@ export function Audit(parameter) {
} }
export function GetInvoiceCodeList() {
return request({
url: '/mainApi/ClientCommon/GetInvoiceCodeList',
method: 'get',
})
}

@ -1,13 +1,13 @@
<template> <template>
<div @mouseover="showTooltip = true" @mouseleave="showTooltip = false" class="invoiceNo"> <div @mouseover="showTooltip = true" @mouseleave="showTooltip = false" class="invoiceNo">
<span>{{ label }}</span> <span class="label" >{{ label }}</span>
<span v-show="invoiceEditFlag"> <span v-show="invoiceEditFlag">
<slot name="text"></slot> <slot name="text"></slot>
</span> </span>
<span v-show="!invoiceEditFlag"> <span v-show="!invoiceEditFlag" style="flex-grow: 1" >
<slot name="content"></slot> <slot name="content"></slot>
</span> </span>
<span class="iconfont icon-bianji1" style="cursor: pointer" @click="CilckEdit" v-show="showTooltip"></span> <span class="iconfont icon-bianji1" style="cursor: pointer" @click="CilckEdit" v-show="showTooltip && showEdit"></span>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
@ -25,6 +25,10 @@ const props = defineProps({
type: String, type: String,
default: '', default: '',
}, },
showEdit: {
type: Boolean,
default: true,
},
}) })
</script> </script>
<style lang="less" scoped > <style lang="less" scoped >
@ -32,5 +36,12 @@ const props = defineProps({
font-size: 12px; font-size: 12px;
display: flex; display: flex;
width: 100%; width: 100%;
align-items: center;
margin-bottom: 10px;
}
.label{
margin-right: 5px;
font-weight: 400;
color: rgba(158, 83, 9, 1);
} }
</style> </style>

@ -75,44 +75,142 @@
</div> </div>
</div> </div>
<div class="content"> <div class="content">
<div class="left"> <div class="left">
<div class="left-top"> <div class="left-top">
<div class="left-top-item"> <div class="left-top-item" style="padding-right: 100px">
<editCompent ref="editCompentRef" label="发票币别:"> <editCompent ref="editCompentRef" label="发票币别:">
<template #text> <template #text>
<span> {{ form.currency }}</span> <span> {{ form.currency }}</span>
</template> </template>
<template #content> <template #content>
<a-select size="small" v-model:value="form.currency" style="width: 100%" > <a-select size="small" v-model:value="form.currency" style="width: 100%">
<a-select-option :key="index" v-for="(item,index) in currencyList" :value="item.codeName">{{item.description}}</a-select-option> <a-select-option :key="index" v-for="(item, index) in currencyList"
:value="item.codeName">{{ item.description }}</a-select-option>
</a-select> </a-select>
</template> </template>
</editCompent> </editCompent>
<editCompent :showEdit="false" ref="editCompentRef" label="开票类型:">
<template #text>
<span>正票</span>
</template>
</editCompent>
<editCompent ref="editCompentRef" label="开票日期:">
<template #text>
<span> {{ form.invoiceDate }}</span>
</template>
<template #content>
<a-date-picker size="small" style="width: 100%" valueFormat="YYYY-MM-DD"
v-model:value="form.invoiceDate" />
</template>
</editCompent>
</div> </div>
<div class="left-top-item"> <div class="left-top-item middle" style="padding-left: 9%;">
<editCompent ref="editCompentRef" label="发票币别:"> <a-dropdown>
<a style="color: rgba(158, 83, 9, 1);">
{{ getCategory() }}
<DownOutlined />
</a>
<template #overlay>
<a-menu @click="onClick">
<a-menu-item key="bs">
<a href="javascript:;">全电专票(电子)</a>
</a-menu-item>
<a-menu-item key="pc">
<a href="javascript:;">全电普票(电子)</a>
</a-menu-item>
</a-menu>
</template>
</a-dropdown>
</div>
<div class="left-top-item" style="padding-left: 120px">
<editCompent :showEdit="false" ref="editCompentRef" label="发票号:">
<template #text> <template #text>
<span> {{ form.currency }}</span> <span>{{ form.invoiceNO }}</span>
</template>
</editCompent>
<editCompent :showEdit="false" ref="editCompentRef" label="发票代码:">
<template #text>
<span>{{ form.invoiceNO }}</span>
</template>
</editCompent>
<editCompent :showEdit="false" ref="editCompentRef" label="发票流水号:">
<template #text>
<span>{{ form.invoiceNO }}</span>
</template>
</editCompent>
</div>
</div>
<div class="box">
<div class="box-top">
<div class="box-top-item" style="border-right: 1px solid rgba(158, 83, 9, 1)">
<editCompent ref="editCompentRef" label="购买方名称:">
<template #text>
<span> {{ form.customerName }}</span>
</template> </template>
<template #content> <template #content>
<a-select size="small" v-model:value="form.invoiceNO" style="width: 100%" > <a-select size="small" v-model:value="form.customerId" style="width: 90%">
<a-select-option :key="index" v-for="(item,index) in currencyList" :value="item.codeName">{{item.description}}</a-select-option> <a-select-option :key="index" v-for="(item, index) in customerList"
:value="item.id">{{ item.pinYinCode }}</a-select-option>
</a-select> </a-select>
</template> </template>
</editCompent> </editCompent>
<editCompent ref="editCompentRef" label="纳税人识别号/统一社会信用代码:">
<template #text>
<span> {{ form.taxID }}</span>
</template>
<template #content>
<a-input v-model:value="form.taxID" size="small"></a-input>
</template>
</editCompent>
</div> </div>
<div class="left-top-item"> <div class="box-top-item">
<editCompent ref="editCompentRef" label="发票币别:"> <editCompent ref="editCompentRef" label="销售方名称:">
<template #text> <template #text>
<span> {{ form.currency }}</span> <span> {{ form.customerName }}</span>
</template> </template>
<template #content> <template #content>
<a-select size="small" v-model:value="form.invoiceNO" style="width: 100%" > <a-select size="small" v-model:value="form.customerId" style="width: 90%">
<a-select-option :key="index" v-for="(item,index) in currencyList" :value="item.codeName">{{item.description}}</a-select-option> <a-select-option :key="index" v-for="(item, index) in customerList"
:value="item.id">{{ item.pinYinCode }}</a-select-option>
</a-select> </a-select>
</template> </template>
</editCompent> </editCompent>
<editCompent ref="editCompentRef" label="纳税人识别号/统一社会信用代码:">
<template #text>
<span> {{ form.taxID }}</span>
</template>
<template #content>
<a-input v-model:value="form.taxID" size="small"></a-input>
</template>
</editCompent>
</div>
</div>
<div class="box-row">
<span style="font-weight: bold;color:rgba(158, 83, 9, 1) ">发票明细</span>
<a-button v-repeat type="link" @click="add">
<span class="iconfont icon-jia"></span>添加
</a-button>
<a-button v-repeat type="link">
<span class="iconfont icon-shanchu1"></span>删除
</a-button>
<a-button v-repeat type="link">
<span class="iconfont icon-peizhitubiaosvg-"></span>费用明细
</a-button>
<a-button v-repeat type="link">
<span class="iconfont icon-fujian1"></span>附件
</a-button>
</div>
<div class="invoiceIssue-table" >
<input class="ds-tb-check" type="checkbox" v-model="allCheck" :indeterminate="someCheck" />
<hot-table ref="hotTb" :data="list" :settings="settings">
<img v-show="!list.length" class="hot-tb-no-data"
src="../../../../assets/images/nodata.png" alt="" />
</hot-table>
</div>
<div>
<span>合计</span>
<span>金额:</span>
<span>税额:</span>
</div> </div>
</div> </div>
</div> </div>
@ -121,14 +219,14 @@
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, onMounted, watch } from 'vue' import { ref, onMounted, defineComponent, nextTick } from 'vue'
import editCompent from './editCompent.vue' import editCompent from './editCompent.vue'
import { BasicForm, useForm } from '/@/components/Form/index' import { BasicForm, useForm } from '/@/components/Form/index'
import { AutoComplete } from 'ant-design-vue' import { AutoComplete } from 'ant-design-vue'
import feeTable from './feeTable.vue' import feeTable from './feeTable.vue'
import { DownOutlined } from '@ant-design/icons-vue' import { DownOutlined } from '@ant-design/icons-vue'
import { import {
GetInvoiceCodeList
} from '../api' } from '../api'
import { useMessage } from '/@/hooks/web/useMessage' import { useMessage } from '/@/hooks/web/useMessage'
import { useRoute, useRouter } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
@ -140,11 +238,16 @@ import { GetFeeCurrencySelectList, GetClientListByCode } from '/@/api/common'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { useGo } from '/@/hooks/web/usePage' import { useGo } from '/@/hooks/web/usePage'
import { useUserStore } from '/@/store/modules/user' import { useUserStore } from '/@/store/modules/user'
import { set } from 'nprogress'
import { isNamedTupleMember } from 'typescript' import { isNamedTupleMember } from 'typescript'
import { detailColumns } from '../columns' import { detailColumns } from '../columns'
import { get } from 'sortablejs' import { HotTable } from '@handsontable/vue3'
import { useMultipleTabStore } from '/@/store/modules/multipleTab' import { useMultipleTabStore } from '/@/store/modules/multipleTab'
import { registerAllModules } from 'handsontable/registry'
import 'handsontable/dist/handsontable.full.min.css'
defineComponent({
HotTable,
})
registerAllModules()
const tabStore = useMultipleTabStore() const tabStore = useMultipleTabStore()
const userStore = useUserStore() const userStore = useUserStore()
const go = useGo() const go = useGo()
@ -154,18 +257,286 @@ const id = ref(route.query.id)
const loading = ref(false) const loading = ref(false)
const invoiceNO = ref('') const invoiceNO = ref('')
const editCompentRef = ref() const editCompentRef = ref()
const form = ref({}) as any const form = ref({
category: '全电普票(电子)',
categoryCode: 'pc'
}) as any
const currencyList = ref([]) as any const currencyList = ref([]) as any
const customerList = ref([]) as any
onMounted(() => { onMounted(() => {
GetFeeCurrencySelectList().then(res => { GetFeeCurrencySelectList().then(res => {
currencyList.value = res.data currencyList.value = res.data
}) })
GetClientListByCode().then(res => {
customerList.value = res.data
})
//
}) })
function handleBlur() { function handleBlur() {
editCompentRef.value.invoiceEditFlag = true editCompentRef.value.invoiceEditFlag = true
} }
const row = {
selected: false,
name: '',
taxAmount: '',
taxRate: '',
amount: '',
unitPrice: '',
taxUnitPrice: '',
quantity: 1,
unit: '',
specification: '',
}
//
const add = () => {
const deepCopyRow = JSON.parse(JSON.stringify(row))
list.value.push(deepCopyRow)
const hot = hotTb.value.hotInstance
hotTb.value.hotInstance.loadData(list)
nextTick(() => {
hot.selectCell(list.value.length - 1, 1)
})
}
function onClick({ key }) {
form.value.categoryCode = key
CategoryData.forEach((item) => {
if (item.value == key) {
form.value.category = item.label
}
})
}
const CategoryData = [
{
value: 'bs',
label: '全电专票(电子)'
},
{
value: 'pc',
label: '全电普票(电子)'
},
]
function getCategory() {
let str = ''
CategoryData.forEach((item) => {
if (item.value == form.value.categoryCode) {
str = item.label
}
})
return str
}
//
const feeDict = ref([])
//
const list = ref([]) as any
const hotTb = ref(null) as any
const activeKey = ref('1')
//
const allCheck = ref(false)
//
const someCheck = ref(false)
import { feeUnitDict } from '/@/hooks/dict/index'
const unitDict = ref([]) as any
//
const columns = [
{
data: 'selected',
type: 'checkbox',
title: ' ',
width: 32,
className: 'htCenter',
readOnly: false,
},
{
title: '项目名称',
width: 120,
data: 'name',
type: 'dropdown',
// (process)
source: async (query, process) => {
const res = feeDict.value.length ? feeDict.value : (await GetInvoiceCodeList())?.data
if (!feeDict.value.length) feeDict.value = res
const dict = res.map((res) => {
return res.displayName
})
process(dict)
},
},
{
title: '规格型号',
width: 120,
data: 'specification',
},
{
title: '单位',
width: 120,
data: 'unit',
type: 'dropdown',
source: async (query, process) => {
if (unitDict.value && unitDict.value.length) {
const dict = unitDict.value.map((item) => {
return item.value + '-' + item.name
})
process(dict)
} else {
const results = await feeUnitDict()
unitDict.value = results
const dict = results.map((item) => {
return item.value + '-' + item.name
})
process(dict)
}
},
},
{
title: '数量',
width: 60,
data: 'quantity',
type: 'numeric',
format: '0',
},
{
title: '单价',
width: 80,
data: 'taxUnitPrice',
type: 'numeric',
format: '0.00',
},
{
title: '不含税单价',
width: 100,
data: 'unitPrice',
type: 'numeric',
readOnly: true,
},
{
title: '金额',
width: 80,
data: 'amount',
type: 'numeric',
},
{
title: '不含税金额',
width: 100,
data: 'noTaxAmount',
type: 'numeric',
},
{
title: '税率',
width: 80,
data: 'taxRate',
type: 'numeric',
},
{
title: '税额',
width: 80,
data: 'taxAmount',
type: 'numeric',
readOnly: true,
},
{
title: '是否享受优惠政策',
width: 100,
data: 'taxAmount',
type: 'numeric',
readOnly: true,
},
{
title: '增值税特殊管理',
width: 100,
data: 'taxAmount',
type: 'numeric',
readOnly: true,
},
{
title: '零税率标识',
width: 100,
data: 'taxAmount',
type: 'numeric',
readOnly: true,
},
]
//
const settings = {
height: '350',
autoWrapRow: true,
autoWrapCol: true,
//
rowHeights: 32,
fixedColumnsLeft: 1,
//
enterMoves: 'row',
columnSorting: true,
//
afterValidate: function (isValid, value, row, prop, source) {
if (!isValid) {
hotTb.value.hotInstance.setDataAtRowProp(row, prop, '')
}
},
columns: columns,
// ()
licenseKey: 'non-commercial-and-evaluation',
//
afterChange(changes, source) {
//
if (source === 'edit' || source === 'Autofill.fill' || source === 'CopyPaste.paste') {
let dict = {} as any
//
const index = changes[0][0]
//
if (changes[0][1] === 'taxUnitPrice') {
//
list.value[index].unitPrice = Number(
(changes[0][3] || 0) / ((list.value[index].taxRate || 0) / 100 + 1),
).toFixed(2)
//
list.value[index].amount = Number(
(changes[0][3] || 0) * (list.value[index].quantity || 0),
).toFixed(2)
//
list.value[index].noTaxAmount = Number(
(list.value[index].unitPrice || 0) * (list.value[index].quantity || 0),
).toFixed(2)
//
list.value[index].taxAmount = Number(
(list.value[index].amount || 0) - (list.value[index].noTaxAmount || 0),
).toFixed(2)
}
//
if (changes[0][1] === 'quantity') {
//
list.value[index].amount = Number(
(changes[0][3] || 0) * (list.value[index].taxUnitPrice || 0),
).toFixed(2)
//
list.value[index].noTaxAmount = Number(
(changes[0][3] || 0) * (list.value[index].unitPrice || 0),
).toFixed(2)
//
list.value[index].taxAmount = Number(
(list.value[index].amount || 0) - (list.value[index].noTaxAmount || 0),
).toFixed(2)
}
//
if (changes[0][1] === 'taxRate') {
//
list.value[index].unitPrice = Number(
(list.value[index].taxUnitPrice || 0) / ((changes[0][3] || 0) / 100 + 1),
).toFixed(2)
//
list.value[index].noTaxAmount = Number(
(list.value[index].unitPrice || 0) * (list.value[index].quantity || 0),
).toFixed(2)
//
list.value[index].taxAmount = Number(
(list.value[index].amount || 0) - (list.value[index].noTaxAmount || 0),
).toFixed(2)
}
}
},
}
</script> </script>
@ -205,18 +576,81 @@ function handleBlur() {
} }
.content { .content {
padding-left: 15px;
.left { .left {
background-color: #fffbf7; background-color: #fffbf7;
padding: 15px 20px; padding: 15px 10px;
width: 60%; width: 60%;
.left-top{
.left-top {
padding: 0 20px;
display: flex; display: flex;
width: 100%; width: 100%;
.left-top-item{
.left-top-item {
width: 20%; width: 20%;
flex-grow: 1;
}
}
}
}
.middle {
font-weight: bold;
font-size: 22px;
padding-top: 24px;
}
.box {
border: 1px solid rgba(158, 83, 9, 1);
// margin-left: 15px;
.box-top {
display: flex;
border-bottom: 1px solid rgba(158, 83, 9, 1);
.box-top-item {
padding-left: 15px;
padding-top: 5px;
width: 50%;
} }
} }
.box-row {
background: #f7f2ed;
padding-left: 15px;
font-size: 12px;
} }
}
.ds-tb-check {
left: 35px;
}
</style>
<style lang="less">
.invoiceIssue-table {
.handsontable {
.wtHider {
max-height: 240px!important;
min-height: 160px;
}
.htCheckboxRendererInput {
position: relative;
z-index: 999;
}
}
.handsontable .htCore tbody tr td{
background: #fffbf7;
border-color: #fffbf7;
border-bottom: 1px solid #ebeaea;
}
.handsontable .htCore thead tr th {
background: #fffbf7;
border-color: #fffbf7;
color: rgba(158, 83, 9, 1);
}
} }
</style> </style>
Loading…
Cancel
Save