发票+数据权限

szh-new
sunzehua 2 months ago
parent 961dee56bd
commit 67f2c02188

@ -1259,7 +1259,7 @@ function handleAdd() {
}
function filterOption(input, option) {
return (
option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
option.value.toLowerCase().indexOf(input.toLowerCase()) >= 0
);
}

@ -0,0 +1,18 @@
import { request } from '/@/utils/request'
// 获取列表 (Auth)
export function GetList(parameter) {
return request({
url: '/feeApi/InvoiceApplicationAudit/GetList',
method: 'post',
data: parameter,
})
}
export function InvoiceApplicationGet(parameter) {
return request({
url: '/feeApi/InvoiceApplication/Get',
method: 'get',
params: parameter,
})
}

@ -0,0 +1,193 @@
import { ref } from 'vue'
import { BasicColumn, FormSchema } from '/@/components/Table'
import { getOptions } from '/@/hooks/dict'
export const billTypeData = [
{ value: 0, label: '未提交' },
{ value: 1, label: '提交审核' },
{ value: 2, label: '审核通过' },
{ value: 3, label: '审核驳回' },
{ value: 4, label: '已开出' },
{ value: 5, label: '部分开出' },
]
export const searchFormSchema: FormSchema[] = [
{
field: 'applicationNO',
label: '申请单号',
component: 'Input',
colProps: { span: 4 },
},
{
field: 'applicationNO',
label: '开票金额',
component: 'Input',
colProps: { span: 4 },
},
{
field: 'applyDate',
label: '申请日期',
component: 'RangePicker',
required: false,
dynamicDisabled: false,
colProps: { span: 4 },
componentProps: {
allowClear: true,
},
},
{
field: 'createByName',
label: '申请人',
component: 'Input',
colProps: { span: 4 },
},
{
field: 'status',
label: '审核状态',
component: 'Select',
colProps: { span: 4 },
componentProps: {
options: billTypeData,
},
},
]
//列表
export const columns: BasicColumn[] = [
{
title: '申请单号',
dataIndex: 'applicationNO',
width: 120,
align: 'left',
},
{
title: '状态',
dataIndex: 'statusText',
width: 70,
align: 'left',
},
{
title: '委托单位',
dataIndex: 'customerName',
width: 100,
align: 'left',
},
{
title: '发票抬头',
dataIndex: 'invoiceHeader',
width: 100,
align: 'left',
},
{
title: '发票币别',
dataIndex: 'currency',
width: 100,
align: 'left',
},
{
title: '申请方式',
dataIndex: 'currency',
width: 100,
align: 'left',
},
{
title: '原币金额',
dataIndex: 'originalAmount',
width: 100,
align: 'left',
},
{
title: '申请人',
dataIndex: 'createByName',
width: 100,
align: 'left',
},
{
title: '申请开票日期',
dataIndex: 'applyDate',
width: 100,
align: 'left',
},
{
title: '申请类型',
dataIndex: 'orgName',
width: 100,
align: 'left',
},
{
title: '申请时间',
dataIndex: 'orgName',
width: 100,
align: 'left',
},
{
title: '开票税率',
dataIndex: 'taxRate',
width: 100,
align: 'left',
},
{
title: '发票号',
dataIndex: 'invoiceNO',
width: 100,
align: 'left',
},
]
//列表
export const detailColumns: BasicColumn[] = [
{
title: '货物或业务应税劳动名称',
dataIndex: 'name',
width: 120,
align: 'left',
},
{
title: '规格型号',
dataIndex: 'specification',
width: 70,
align: 'left',
},
{
title: '单位',
dataIndex: 'unit',
width: 100,
align: 'left',
},
{
title: '数量',
dataIndex: 'quantity',
width: 100,
align: 'left',
},
{
title: '含税单价',
dataIndex: 'taxUnitPrice',
width: 100,
align: 'left',
},
{
title: '单价',
dataIndex: 'unitPrice',
width: 100,
align: 'left',
},
{
title: '金额',
dataIndex: 'amount',
width: 100,
align: 'left',
},
{
title: '税率',
dataIndex: 'taxRate',
width: 100,
align: 'left',
},
{
title: '税额',
dataIndex: 'taxAmount',
width: 100,
align: 'left',
}
]

@ -0,0 +1,204 @@
<template>
<div class="main">
<div class="top">
<BasicTable height="600px" @row-click="handleClick" class="examine-table" @register="registerTable">
<template #tableTitle>
<a-button type="link"><i class="icon-yiwancheng2-copy iconfont"></i>审核通过</a-button>
<a-button type="link"><i class="icon-piliangshenhe iconfont"></i>全部审核通过</a-button>
<a-button type="link"><i class="icon-bohui-01 iconfont"></i>驳回提交</a-button>
</template>
<template v-slot:bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
<TableAction :actions="[
{
icon: 'clarity:note-edit-line',
tooltip: '编辑',
onClick: () => {
GoDetailed(true, record)
},
},
]" />
</template>
</template>
</BasicTable>
</div>
<div style="padding-left: 20px;" >
<a-spin :spinning="loading">
<a-tabs v-model:activeKey="activeKey">
<a-tab-pane :key="0" tab="发票明细"></a-tab-pane>
<a-tab-pane :key="1" tab="费用明细"></a-tab-pane>
<a-tab-pane :key="2" tab="附件"></a-tab-pane>
</a-tabs>
<div style="display: flex;" v-if="activeKey == 0" >
<div class="left">
<BasicTable @register="registerTableDetail">
<template v-slot:bodyCell="{ column, record }">
</template>
</BasicTable>
</div>
<div class="right">
<div style="font-size: 12px;color: black;font-weight: bold;margin-bottom: 10px">票面信息</div>
<div class="row">
<span class="text">发票抬头</span>
<span class="bold">{{ feeData.invoiceHeader }}</span>
</div>
<div class="row">
<span class="text">纳税人识别号</span>
<span class="bold">{{ feeData.taxID }}</span>
</div>
<div class="row">
<span class="text">地址电话</span>
<span class="bold">{{ feeData.customerAddTel }}</span>
</div>
<div class="row">
<span class="text">RMB开户行/账号</span>
<span class="bold">{{ feeData.customerBankName }}</span>
</div>
<div class="row" style="border-bottom: 1px solid #ebebeb;padding-bottom: 10px;">
<span class="text">USD开户行/账号</span>
<span class="bold">{{ feeData.usdCustomerBankName }}</span>
</div>
<div class="row">
<div style="margin-right: 30px">
<span class="text">申请人</span>
<span class="bold">{{ feeData.createByName }}</span>
</div>
<div>
<span class="text">申请开票日期</span>
<span class="bold">{{ feeData.invoiceDate }}</span>
</div>
</div>
<div class="row">
<div style="margin-right: 30px">
<span class="text">所属分部</span>
<span class="bold">{{ feeData.saleDeptName }}</span>
</div>
<div>
<span class="text">代开客户</span>
<span class="bold">{{ feeData.autualCustomerName }}</span>
</div>
</div>
<div class="row">
<div>
<span class="text">客户名称</span>
<span class="bold">{{ feeData.customerName }}</span>
</div>
</div>
</div>
</div>
</a-spin>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted, defineExpose, computed } from 'vue'
import { GetList, InvoiceApplicationGet } from './api.js'
import { BasicTable, useTable, TableAction } from '/@/components/Table'
import { formatParams } from '/@/hooks/web/common'
import { columns, searchFormSchema, detailColumns } from './columns'
const [registerTable, { reload, getPaginationRef, getSelectRows, getRawDataSource }] = useTable({
maxHeight: 300,
api: async (p) => {
const res: API.DataResult = await GetList(p)
return new Promise((resolve) => {
resolve({ data: [...res.data], total: res.count })
})
},
//
beforeFetch: (p) => {
return formatParams(p)
},
columns,
formConfig: {
labelWidth: 120,
schemas: searchFormSchema,
useAdvancedSearch: true,
},
isTreeTable: false,
pagination: true,
striped: true,
useSearchForm: true,
showTableSetting: true,
bordered: true,
showIndexColumn: true,
indexColumnProps: {
width: 60,
},
canResize: true,
immediate: true,
actionColumn: {
width: 80,
title: '操作',
dataIndex: 'action',
fixed: 'right',
},
})
const [registerTableDetail, { setTableData, setLoading }] = useTable({
columns: detailColumns,
isTreeTable: false,
pagination: false,
striped: true,
useSearchForm: false,
showTableSetting: false,
bordered: true,
showIndexColumn: false,
indexColumnProps: {
width: 60,
},
canResize: true,
immediate: true,
})
const activeKey = ref(0)
const feeData = ref({}) as any
const loading = ref(false)
function handleClick(row) {
loading.value = true
InvoiceApplicationGet({ id: row.id }).then(res => {
if (res.succeeded) {
feeData.value = res.data
setTableData(res.data.invoiceDetails)
}
loading.value = false
})
}
</script>
<style lang="less" scoped>
/deep/ .ant-table-pagination.ant-pagination {
border-bottom: 1px solid #ebebeb;
margin-bottom: 0px;
padding-bottom: 10px;
}
.left {
width: 58%;
margin-right: 1%;
padding-right: 10px;
border-right: 1px solid #ebebeb;
}
.right {
width: 40%;
padding-top: 5px;
font-size: 12px;
}
.row {
margin-bottom: 10px;
display: flex;
.text {
color: #7a8798;
width: 105px;
display: inline-block;
}
.bold {
color: black;
display: inline-block;
width: 200px;
}
}
</style>

@ -41,7 +41,8 @@
<div class="bold">申请开票明细</div>
<div style="display: flex;">
<div class="apply" :class="{ active: form.isYB }">
<a-checkbox :disabled="route.query.id ? true : false" v-model:checked="form.isYB" @change="handleChangeApply">
<a-checkbox :disabled="route.query.id ? true : false"
v-model:checked="form.isYB" @change="handleChangeApply">
原币申请
<span :class="{ rmb: item.currency == 'RMB', yb: item.currency != 'RMB' }"
v-for="(item, index) in amountArr" :key="index">{{ item.applyAmount }}
@ -50,8 +51,9 @@
</a-checkbox>
</div>
<div class="apply" :class="{ active: form.isRMB }">
<a-checkbox :disabled="route.query.id ? true : false" v-model:checked="form.isRMB"
@change="handleChangeApply1">折算人民币申请</a-checkbox>
<a-checkbox @change="handleChangeApply1"
:disabled="route.query.id ? true : false"
v-model:checked="form.isRMB">折算人民币申请</a-checkbox>
<span class="rmb" v-if="totalRmb != 0">{{ totalRmb }} RMB</span>
<span></span>
</div>
@ -208,7 +210,6 @@ const [registerTable, { getForm, setSelectedRowKeys, getSelectRows, setProps, ge
maxHeight: '600',
pagination: true,
striped: true,
rowKey: 'id',
bordered: true,
indexColumnProps: {
width: 60,
@ -237,7 +238,7 @@ const exchangeFlag = ref(false)
const loading = ref(false)
const form = ref({
isYB: true,
isRMB:false
isRMB: false
}) as any
function handleChangeApply(e) {
form.value.isRMB = !e.target.checked
@ -248,6 +249,8 @@ const exchangeData = ref({}) as any
//
function handleChangeApply1(e) {
form.value.isYB = !e.target.checked
}
function changeApply() {
const arr = getSelectRowsFee()
const exchangeArr = [] as any
if (arr.length > 0) {
@ -284,9 +287,6 @@ function handleChangeApply1(e) {
totalRmb.value = total
}
}
}
const totalRmb = ref(0)
@ -308,13 +308,25 @@ function handleSureExhange() {
}
})
totalRmb.value = total
setTimeout(() => {
arr.forEach(item => {
item.originalCurrency = item.currency
item.currency = 'RMB'
item.originalAmount = item.applyAmount
item.applyAmount = Number((Number(item.applyAmount) * Number(item.exchangeRate)).toFixed(2))
})
emits('updateList', arr, 'isRMB')
open.value = false
exchangeFlag.value = false
}, 100)
}
function handleClick(record, index) {
setSelectedRowKeys([record.id])
const data = {
id: record.id,
businessType: record.businessType
businessType: record.businessType,
customerId:record.customerId
}
loading.value = true
InvoiceApplicationGetFees([data]).then(res => {
@ -347,11 +359,11 @@ function init(data) {
customerId: customerIdP.value
})
}
if(data.isRMB){
if (data.isRMB) {
form.value.isRMB = true
form.value.isYB = false
}
if(data.isYB){
if (data.isYB) {
form.value.isYB = true
form.value.isRMB = false
}
@ -395,19 +407,11 @@ function handleAddDetial() {
})
}
if (form.value.isRMB) {
arr.forEach(item => {
item.originalCurrency = item.currency
item.currency = 'RMB'
item.originalAmount = item.applyAmount
item.applyAmount = Number((Number(item.applyAmount) * Number(item.exchangeRate)).toFixed(2))
})
}
open.value = false
if (form.value.isRMB) {
emits('updateList', arr, 'isRMB')
changeApply()
}
if (form.value.isYB) {
emits('updateList', arr, 'isYB')
open.value = false
}
}
const amountArr = ref([]) as any
@ -506,12 +510,12 @@ function addDetailed() {
});
});
return Promise.all(promises).then(() => {
emits('addLeft', arrRight, queryDataStr, exchangarr,'isRMB')
emits('addLeft', arrRight, queryDataStr, exchangarr, 'isRMB')
open.value = false
setLoading(false)
});
} else {
emits('addLeft', arrRight, queryDataStr, [],'isRMB')
emits('addLeft', arrRight, queryDataStr, [], 'isRMB')
open.value = false
setLoading(false)
}
@ -520,7 +524,7 @@ function addDetailed() {
}
if (arrRight.length > 0 && form.value.isYB) {
emits('addLeft', arrRight, queryDataStr, [],'isYB')
emits('addLeft', arrRight, queryDataStr, [], 'isYB')
open.value = false
setLoading(false)
}
@ -596,6 +600,7 @@ defineExpose({ init, changeCustIn })
font-weight: bold;
margin: 0 10px;
}
/deep/ .ant-checkbox-wrapper-checked .ant-checkbox-inner {
background-color: #257afa;
border-color: #257afa;

@ -989,7 +989,8 @@ function addLeftSave(arr, query, exchang, type) {
arr.forEach(item => {
itemList.push({
id: item.id,
businessType: item.businessType
businessType: item.businessType,
customerId:item.customerId
})
})
const data = {

@ -486,7 +486,7 @@
},
filterOption(input, option) {
return (
option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
option.value.toLowerCase().indexOf(input.toLowerCase()) >= 0
)
},
handleYardChange(index) {

@ -30,17 +30,21 @@
<a-button type="link" @click="setLook(2)"><i class="icon-shichuang-duoge iconfont"></i>应用操作范围到当前页</a-button>
</template>
<template v-slot:bodyCell="{ column, record }">
<template v-if="column.key === 'permissioName'">
<span>{{ record.templateName ? record.templateName : record.permissioName }}</span>
</template>
<template v-if="column.key === 'visibleRuleScopeName'">
<a-select @change="handleChangeLook($event, record)" v-model:value="record.visibleTemplateId" size="small"
style="width: 100%">
<a-select-option v-for="(item, index) in lookSelect" :key="index" :value="item.id">{{ item.ruleScopeName
<a-select @change="handleChangeLook($event, record, 'look')" v-model:value="record.visibleTemplateId"
size="small" style="width: 100%">
<a-select-option v-for="(item, index) in record.visibleTemplates" :key="index" :value="item.id">{{
item.ruleScopeName
}}</a-select-option>
</a-select>
</template>
<template v-if="column.key === 'operateRuleScopeName'">
<a-select @change="handleChangeLook($event, record)" v-model:value="record.operateTemplateId" size="small"
style="width: 100%">
<a-select-option v-for="(item, index) in actionSelect" :key="index" :value="item.id">{{
<a-select @change="handleChangeLook($event, record, 'opera')" v-model:value="record.operateTemplateId"
size="small" style="width: 100%">
<a-select-option v-for="(item, index) in record.operateTemplates" :key="index" :value="item.id">{{
item.ruleScopeName }}</a-select-option>
</a-select>
</template>
@ -49,7 +53,7 @@
</div>
</div>
<a-modal @ok="handleCopy" width="800px" @cancel="openFlag = false" :visible="openFlag" title="选择用户复制">
<a-spin :spinning="copyLoad" >
<a-spin :spinning="copyLoad">
<BasicTree key="value" v-model:checkedKeys="checkedKeys" checkable check-strictly :treeData="treeDataCopy">
<template #title="custom">
<span>{{ custom.node.title }}</span>
@ -75,7 +79,7 @@ const { createMessage } = useMessage()
// import { columns, searchFormSchema } from './columns'
const treeData = ref([])
const treeDataCopy = ref([])
const menuTree = ref([])
const menuTree = ref([]) as any
const openFlag = ref(false)
onMounted(() => {
GetOrgUserTree().then(res => {
@ -117,7 +121,7 @@ function handleCopy() {
}
copyLoad.value = true
CopyDataRuleScope(data).then(res => {
if(res.succeeded){
if (res.succeeded) {
createMessage.success('复制成功')
}
copyLoad.value = false
@ -170,6 +174,11 @@ function handleSelect(selectedKeys: any, info: any) {
menuLoad.value = true
GetClientUserPermissions({ id: info.node.value }).then(res => {
menuTree.value = res.data
menuTree.value.unshift({
"id": "0",
"parentId": "0",
"name": "全部",
})
menuLoad.value = false
}).catch(err => {
menuLoad.value = false
@ -179,7 +188,7 @@ function handleSelect(selectedKeys: any, info: any) {
const lookSelect = ref([]) as any
const actionSelect = ref([]) as any
function handleSelectMenu(selectedKeys: any, info: any) {
if (info.node.children == null || info.node.children.length == 0) {
if ((info.node.children == null || info.node.children.length == 0) && info.node.parentId != 0) {
const data = {
permissionId: info.node.parentId,
userId: userId.value
@ -193,20 +202,35 @@ function handleSelectMenu(selectedKeys: any, info: any) {
}).catch(err => {
setLoading(false)
})
GetDataRuleTemplateSelectList({ id: info.node.parentId, ruleType: 'visible' }).then(res => {
lookSelect.value = res.data
})
GetDataRuleTemplateSelectList({ id: info.node.parentId, ruleType: 'operate' }).then(res => {
actionSelect.value = res.data
})
// GetDataRuleTemplateSelectList({ id: info.node.parentId, ruleType: 'visible' }).then(res => {
// lookSelect.value = res.data
// })
// GetDataRuleTemplateSelectList({ id: info.node.parentId, ruleType: 'operate' }).then(res => {
// actionSelect.value = res.data
// })
}
if (info.node.parentId == 0) {
const data = {
permissionId: 0,
userId: userId.value
}
setLoading(true)
GetCodeDataRuleList(data).then(res => {
if (res.succeeded) {
setTableData(res.data)
}
setLoading(false)
}).catch(err => {
setLoading(false)
})
}
}
function openRule() {
openFlag.value = true
}
const columns = [
{ dataIndex: 'templateName', width: 100, title: '权限模板类型' },
{ dataIndex: 'permissioName', width: 100, title: '权限模板类型' },
{ dataIndex: 'description', width: 100, title: '权限描述' },
{ dataIndex: 'note', width: 100, title: '备注' },
{ dataIndex: 'visibleRuleScopeName', width: 100, title: '可视范围' },
@ -225,9 +249,10 @@ const [registerTable, { reload, setLoading, setTableData, getSelectRows, setProp
canResize: true,
resizeHeightOffset: 35,
})
function handleChangeLook(val, row) {
function handleChangeLook(val, row, type) {
const data = {} as any
lookSelect.value.forEach(item => {
if (type == 'look') {
row.visibleTemplates.forEach(item => {
if (item.id == val) {
data.templateId = item.id
data.ruleType = item.ruleType
@ -235,7 +260,17 @@ function handleChangeLook(val, row) {
data.ruleScopeName = item.ruleScopeName
}
})
data.id = row.id
} else {
row.operateTemplates.forEach(item => {
if (item.id == val) {
data.templateId = item.id
data.ruleType = item.ruleType
data.ruleScope = item.ruleScope
data.ruleScopeName = item.ruleScopeName
}
})
}
data.id = row.id ? row.id : 0
setLoading(true)
AssignDataRuleScope(data).then(res => {
if (res.succeeded) {

@ -371,7 +371,7 @@
:filter-option="filterOption"
v-model:value="UserId"
>
<a-select-option v-for="item in UserList" :key="item.value" :value="item.value">
<a-select-option v-for="item in UserList" :label="item.label" :key="item.value" :value="item.value">
{{ item.label }}
</a-select-option>
</a-select>
@ -762,7 +762,7 @@
}
function filterOption(input, option) {
return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
}
//
function changeTopLevel() {

Loading…
Cancel
Save