Toggle navigation
Toggle navigation
This project
Loading...
Sign in
zhouhui.jiang
/
test_cursor
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Snippets
Network
Create a new issue
Builds
Commits
Issue Boards
Authored by
zhouhui.jiang
2025-09-28 13:14:24 +0800
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
fadab012e43676013bd33fb84d02e8f345971298
fadab012
1 parent
f8362114
update 单据管理
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
696 additions
and
113 deletions
backend/src/main/java/com/apple/erp/dto/DeliveryAddReq.java
backend/src/main/java/com/apple/erp/entity/DeliveryMain.java
backend/src/main/java/com/apple/erp/service/impl/DeliveryMainServiceImpl.java
database/scripts/07_insert_order_delivery_invoice_permissions.sql
database/scripts/08_fix_delivery_add_permission.sql
frontend/src/api/delivery.ts
frontend/src/api/invoice.ts
frontend/src/api/order.ts
frontend/src/views/delivery/index.vue
frontend/src/views/invoice/index.vue
frontend/src/views/order/index.vue
backend/src/main/java/com/apple/erp/dto/DeliveryAddReq.java
View file @
fadab01
...
...
@@ -40,7 +40,7 @@ public class DeliveryAddReq {
@NotNull
(
message
=
"出库日期不能为空"
)
@JsonFormat
(
pattern
=
"yyyy-MM-dd HH:mm:ss"
)
@Schema
(
description
=
"出库日期"
,
required
=
true
)
private
LocalDateTime
deliveryDate
;
private
String
deliveryDate
;
@Schema
(
description
=
"出库状态(0-未出库/1-已出库)"
)
private
Integer
deliveryStatus
;
...
...
backend/src/main/java/com/apple/erp/entity/DeliveryMain.java
View file @
fadab01
...
...
@@ -44,15 +44,9 @@ public class DeliveryMain {
@Schema
(
description
=
"出库状态(0-未出库/1-已出库)"
)
private
Integer
deliveryStatus
;
@Schema
(
description
=
"出库总金额"
)
private
BigDecimal
totalAmount
;
@Schema
(
description
=
"仓库编码"
)
private
String
warehouseCode
;
@Schema
(
description
=
"仓库名称"
)
private
String
warehouseName
;
@Schema
(
description
=
"数据来源"
)
private
String
dataSource
;
...
...
backend/src/main/java/com/apple/erp/service/impl/DeliveryMainServiceImpl.java
View file @
fadab01
...
...
@@ -111,6 +111,9 @@ public class DeliveryMainServiceImpl extends ServiceImpl<DeliveryMainMapper, Del
BeanUtils
.
copyProperties
(
addReq
,
deliveryMain
);
deliveryMain
.
setCreateTime
(
LocalDateTime
.
now
());
deliveryMain
.
setUpdateTime
(
LocalDateTime
.
now
());
if
(
StringUtils
.
hasText
(
addReq
.
getDeliveryDate
()))
{
deliveryMain
.
setDeliveryDate
(
parseDateTime
(
addReq
.
getDeliveryDate
()));
}
deliveryMain
.
setDelFlag
(
"0"
);
int
insert
=
baseMapper
.
insert
(
deliveryMain
);
if
(
insert
>
0
)
{
...
...
database/scripts/07_insert_order_delivery_invoice_permissions.sql
View file @
fadab01
...
...
@@ -35,12 +35,15 @@ VALUES
INSERT
INTO
t_sys_menu
(
menu_id
,
parent_id
,
menu_name
,
menu_type
,
path
,
icon
,
sort
,
status
,
perms
,
create_by
,
create_time
,
update_by
,
update_time
,
del_flag
)
VALUES
(
301
,
3
,
'出库查询'
,
'2'
,
''
,
''
,
1
,
'1'
,
'delivery:list'
,
'admin'
,
NOW
(),
'admin'
,
NOW
(),
'0'
),
(
302
,
3
,
'出库详情'
,
'2'
,
''
,
''
,
2
,
'1'
,
'delivery:query'
,
'admin'
,
NOW
(),
'admin'
,
NOW
(),
'0'
),
(
303
,
3
,
'出库导出'
,
'2'
,
''
,
''
,
3
,
'1'
,
'delivery:export'
,
'admin'
,
NOW
(),
'admin'
,
NOW
(),
'0'
),
(
304
,
3
,
'出库统计'
,
'2'
,
''
,
''
,
4
,
'1'
,
'delivery:statistics'
,
'admin'
,
NOW
(),
'admin'
,
NOW
(),
'0'
),
(
305
,
3
,
'出库打印'
,
'2'
,
''
,
''
,
5
,
'1'
,
'delivery:print'
,
'admin'
,
NOW
(),
'admin'
,
NOW
(),
'0'
),
(
306
,
3
,
'出库确认'
,
'2'
,
''
,
''
,
6
,
'1'
,
'delivery:confirm'
,
'admin'
,
NOW
(),
'admin'
,
NOW
(),
'0'
),
(
307
,
3
,
'出库撤销'
,
'2'
,
''
,
''
,
7
,
'1'
,
'delivery:cancel'
,
'admin'
,
NOW
(),
'admin'
,
NOW
(),
'0'
);
(
302
,
3
,
'出库新增'
,
'2'
,
''
,
''
,
2
,
'1'
,
'delivery:add'
,
'admin'
,
NOW
(),
'admin'
,
NOW
(),
'0'
),
(
303
,
3
,
'出库修改'
,
'2'
,
''
,
''
,
3
,
'1'
,
'delivery:edit'
,
'admin'
,
NOW
(),
'admin'
,
NOW
(),
'0'
),
(
304
,
3
,
'出库删除'
,
'2'
,
''
,
''
,
4
,
'1'
,
'delivery:delete'
,
'admin'
,
NOW
(),
'admin'
,
NOW
(),
'0'
),
(
305
,
3
,
'出库详情'
,
'2'
,
''
,
''
,
5
,
'1'
,
'delivery:detail'
,
'admin'
,
NOW
(),
'admin'
,
NOW
(),
'0'
),
(
306
,
3
,
'出库导出'
,
'2'
,
''
,
''
,
6
,
'1'
,
'delivery:export'
,
'admin'
,
NOW
(),
'admin'
,
NOW
(),
'0'
),
(
307
,
3
,
'出库统计'
,
'2'
,
''
,
''
,
7
,
'1'
,
'delivery:statistics'
,
'admin'
,
NOW
(),
'admin'
,
NOW
(),
'0'
),
(
308
,
3
,
'出库打印'
,
'2'
,
''
,
''
,
8
,
'1'
,
'delivery:print'
,
'admin'
,
NOW
(),
'admin'
,
NOW
(),
'0'
),
(
309
,
3
,
'出库确认'
,
'2'
,
''
,
''
,
9
,
'1'
,
'delivery:confirm'
,
'admin'
,
NOW
(),
'admin'
,
NOW
(),
'0'
),
(
310
,
3
,
'出库撤销'
,
'2'
,
''
,
''
,
10
,
'1'
,
'delivery:cancel'
,
'admin'
,
NOW
(),
'admin'
,
NOW
(),
'0'
);
-- =========================================
-- 3. 插入发票管理相关按钮权限
...
...
@@ -78,7 +81,7 @@ AND del_flag = '0';
INSERT
INTO
t_sys_role_menu
(
role_id
,
menu_id
,
create_by
,
create_time
,
update_by
,
update_time
,
del_flag
)
SELECT
@
admin_role_id
,
menu_id
,
'admin'
,
NOW
(),
'admin'
,
NOW
(),
'0'
FROM
t_sys_menu
WHERE
menu_id
IN
(
301
,
302
,
303
,
304
,
305
,
306
,
307
)
WHERE
menu_id
IN
(
301
,
302
,
303
,
304
,
305
,
306
,
307
,
308
,
309
,
310
)
AND
del_flag
=
'0'
;
-- 为ADMIN角色分配发票管理按钮权限
...
...
@@ -102,11 +105,11 @@ FROM t_sys_menu
WHERE
menu_id
IN
(
201
,
202
,
203
,
205
,
206
,
207
,
208
,
209
,
210
)
AND
del_flag
=
'0'
;
-- 为OPERATOR角色分配出库查询按钮权限
-- 为OPERATOR角色分配出库查询按钮权限
(除删除外)
INSERT
INTO
t_sys_role_menu
(
role_id
,
menu_id
,
create_by
,
create_time
,
update_by
,
update_time
,
del_flag
)
SELECT
@
operator_role_id
,
menu_id
,
'admin'
,
NOW
(),
'admin'
,
NOW
(),
'0'
FROM
t_sys_menu
WHERE
menu_id
IN
(
301
,
302
,
303
,
30
4
,
305
,
306
,
307
)
WHERE
menu_id
IN
(
301
,
302
,
303
,
30
5
,
306
,
307
,
308
,
309
,
310
)
AND
del_flag
=
'0'
;
-- 为OPERATOR角色分配发票管理按钮权限(除删除外)
...
...
@@ -130,11 +133,11 @@ FROM t_sys_menu
WHERE
menu_id
IN
(
201
,
205
,
206
)
AND
del_flag
=
'0'
;
-- 为DEALER_MANAGER角色分配出库查询按钮权限
-- 为DEALER_MANAGER角色分配出库查询按钮权限
(只读权限)
INSERT
INTO
t_sys_role_menu
(
role_id
,
menu_id
,
create_by
,
create_time
,
update_by
,
update_time
,
del_flag
)
SELECT
@
dealer_manager_role_id
,
menu_id
,
'admin'
,
NOW
(),
'admin'
,
NOW
(),
'0'
FROM
t_sys_menu
WHERE
menu_id
IN
(
301
,
30
2
,
303
,
304
,
305
)
WHERE
menu_id
IN
(
301
,
30
5
,
306
,
307
,
308
)
AND
del_flag
=
'0'
;
-- 为DEALER_MANAGER角色分配发票管理按钮权限(只读权限)
...
...
database/scripts/08_fix_delivery_add_permission.sql
0 → 100644
View file @
fadab01
-- Apple经销商ERP系统 - 修复出库新增权限
-- 创建时间: 2025-01-27
-- 版本: v1.0
-- 设置数据库和字符集
SET
NAMES
utf8mb4
;
SET
FOREIGN_KEY_CHECKS
=
0
;
-- 使用数据库
USE
apple_erp
;
-- =========================================
-- 1. 添加缺失的出库新增权限
-- =========================================
-- 检查是否已存在出库新增权限
SET
@
delivery_add_exists
=
(
SELECT
COUNT
(
*
)
FROM
t_sys_menu
WHERE
perms
=
'delivery:add'
AND
del_flag
=
'0'
);
-- 如果不存在,则添加出库新增权限
INSERT
INTO
t_sys_menu
(
menu_id
,
parent_id
,
menu_name
,
menu_type
,
path
,
icon
,
sort
,
status
,
perms
,
create_by
,
create_time
,
update_by
,
update_time
,
del_flag
)
SELECT
302
,
3
,
'出库新增'
,
'2'
,
''
,
''
,
2
,
'1'
,
'delivery:add'
,
'admin'
,
NOW
(),
'admin'
,
NOW
(),
'0'
WHERE
@
delivery_add_exists
=
0
;
-- =========================================
-- 2. 为所有角色分配出库新增权限
-- =========================================
-- 获取ADMIN角色ID
SET
@
admin_role_id
=
(
SELECT
role_id
FROM
t_sys_role
WHERE
role_code
=
'ADMIN'
AND
del_flag
=
'0'
LIMIT
1
);
-- 为ADMIN角色分配出库新增权限
INSERT
IGNORE
INTO
t_sys_role_menu
(
role_id
,
menu_id
,
create_by
,
create_time
,
update_by
,
update_time
,
del_flag
)
SELECT
@
admin_role_id
,
menu_id
,
'admin'
,
NOW
(),
'admin'
,
NOW
(),
'0'
FROM
t_sys_menu
WHERE
perms
=
'delivery:add'
AND
del_flag
=
'0'
;
-- 获取OPERATOR角色ID
SET
@
operator_role_id
=
(
SELECT
role_id
FROM
t_sys_role
WHERE
role_code
=
'OPERATOR'
AND
del_flag
=
'0'
LIMIT
1
);
-- 为OPERATOR角色分配出库新增权限
INSERT
IGNORE
INTO
t_sys_role_menu
(
role_id
,
menu_id
,
create_by
,
create_time
,
update_by
,
update_time
,
del_flag
)
SELECT
@
operator_role_id
,
menu_id
,
'admin'
,
NOW
(),
'admin'
,
NOW
(),
'0'
FROM
t_sys_menu
WHERE
perms
=
'delivery:add'
AND
del_flag
=
'0'
;
-- 获取DEALER_MANAGER角色ID
SET
@
dealer_manager_role_id
=
(
SELECT
role_id
FROM
t_sys_role
WHERE
role_code
=
'DEALER_MANAGER'
AND
del_flag
=
'0'
LIMIT
1
);
-- 为DEALER_MANAGER角色分配出库新增权限
INSERT
IGNORE
INTO
t_sys_role_menu
(
role_id
,
menu_id
,
create_by
,
create_time
,
update_by
,
update_time
,
del_flag
)
SELECT
@
dealer_manager_role_id
,
menu_id
,
'admin'
,
NOW
(),
'admin'
,
NOW
(),
'0'
FROM
t_sys_menu
WHERE
perms
=
'delivery:add'
AND
del_flag
=
'0'
;
-- 重置外键检查
SET
FOREIGN_KEY_CHECKS
=
1
;
-- 输出完成信息
SELECT
'出库新增权限修复完成!'
AS
message
;
frontend/src/api/delivery.ts
0 → 100644
View file @
fadab01
import
{
request
}
from
'../utils/request'
// 出库相关类型定义
export
interface
DeliveryInfo
{
deliveryId
:
number
deliveryNo
:
string
dealerCode
:
string
dealerName
:
string
orderNo
:
string
deliveryDate
:
string
deliveryStatus
:
number
warehouseCode
:
string
dataSource
:
string
uploadTime
?:
string
createBy
?:
string
createTime
?:
string
updateBy
?:
string
updateTime
?:
string
deliveryItems
?:
DeliveryItemInfo
[]
}
export
interface
DeliveryItemInfo
{
itemId
?:
number
deliveryId
?:
number
productCode
:
string
productName
:
string
deliveryQty
:
number
deliveryPrice
:
number
deliveryAmount
:
number
}
export
interface
DeliveryQueryReq
{
deliveryNo
?:
string
dealerCode
?:
string
dealerName
?:
string
deliveryStatus
?:
number
warehouseCode
?:
string
dataSource
?:
string
deliveryStartDate
?:
string
deliveryEndDate
?:
string
minAmount
?:
number
maxAmount
?:
number
pageNum
?:
number
pageSize
?:
number
}
export
interface
DeliveryAddReq
{
deliveryNo
:
string
dealerCode
:
string
dealerName
:
string
orderNo
:
string
deliveryDate
:
string
deliveryStatus
?:
number
warehouseCode
:
string
dataSource
?:
string
deliveryItems
:
DeliveryItemAddReq
[]
}
export
interface
DeliveryItemAddReq
{
productCode
:
string
productName
:
string
deliveryQty
:
number
deliveryPrice
:
number
deliveryAmount
:
number
}
export
interface
DeliveryUpdateReq
{
deliveryId
:
number
deliveryNo
:
string
dealerCode
:
string
dealerName
:
string
orderNo
:
string
deliveryDate
:
string
deliveryStatus
?:
number
warehouseCode
:
string
dataSource
?:
string
deliveryItems
:
DeliveryItemUpdateReq
[]
}
export
interface
DeliveryItemUpdateReq
{
itemId
?:
number
productCode
:
string
productName
:
string
deliveryQty
:
number
deliveryPrice
:
number
deliveryAmount
:
number
}
// 出库API接口
export
const
deliveryApi
=
{
// 分页查询出库列表
getDeliveryList
:
(
params
:
DeliveryQueryReq
)
=>
{
return
request
.
get
(
'/api/delivery/list'
,
params
)
},
// 获取出库详情
getDeliveryDetail
:
(
deliveryId
:
number
)
=>
{
return
request
.
get
(
`/api/delivery/
${
deliveryId
}
`
)
},
// 新增出库
addDelivery
:
(
data
:
DeliveryAddReq
)
=>
{
return
request
.
post
(
'/api/delivery'
,
data
)
},
// 修改出库
updateDelivery
:
(
data
:
DeliveryUpdateReq
)
=>
{
return
request
.
post
(
'/api/delivery/update'
,
data
)
},
// 删除出库
deleteDelivery
:
(
deliveryId
:
number
)
=>
{
return
request
.
delete
(
`/api/delivery/
${
deliveryId
}
`
)
},
// 批量删除出库
batchDeleteDeliveries
:
(
deliveryIds
:
number
[])
=>
{
return
request
.
post
(
'/api/delivery/batchDelete'
,
deliveryIds
)
},
// 修改出库状态
updateDeliveryStatus
:
(
deliveryId
:
number
,
deliveryStatus
:
number
)
=>
{
return
request
.
post
(
`/api/delivery/
${
deliveryId
}
/deliveryStatus`
,
null
,
{
params
:
{
deliveryStatus
}
})
}
}
frontend/src/api/invoice.ts
0 → 100644
View file @
fadab01
import
{
request
}
from
'../utils/request'
export
interface
InvoiceInfo
{
invoiceId
:
number
invoiceNo
:
string
orderNo
:
string
deliveryNo
:
string
dealerCode
:
string
dealerName
:
string
totalAmount
:
number
invoiceDate
:
string
invoiceStatus
:
number
taxRate
:
number
dataSource
:
string
uploadTime
?:
string
createBy
?:
string
createTime
?:
string
updateBy
?:
string
updateTime
?:
string
invoiceItems
?:
InvoiceItemInfo
[]
}
export
interface
InvoiceItemInfo
{
itemId
:
number
invoiceId
:
number
invoiceNo
:
string
productCode
:
string
productName
:
string
productQty
:
number
unitPrice
:
number
itemAmount
:
number
taxRate
:
number
taxAmount
:
number
createBy
?:
string
createTime
?:
string
updateBy
?:
string
updateTime
?:
string
}
export
interface
InvoiceQueryReq
{
invoiceNo
?:
string
orderNo
?:
string
deliveryNo
?:
string
dealerCode
?:
string
dealerName
?:
string
invoiceStatus
?:
number
dataSource
?:
string
invoiceStartDate
?:
string
invoiceEndDate
?:
string
pageNum
:
number
pageSize
:
number
}
export
interface
InvoiceAddReq
{
invoiceNo
:
string
orderNo
:
string
deliveryNo
:
string
dealerCode
:
string
dealerName
:
string
totalAmount
:
number
invoiceDate
:
string
invoiceStatus
?:
number
taxRate
:
number
dataSource
?:
string
invoiceItems
:
InvoiceItemAddReq
[]
}
export
interface
InvoiceUpdateReq
{
invoiceId
:
number
invoiceNo
:
string
orderNo
:
string
deliveryNo
:
string
dealerCode
:
string
dealerName
:
string
totalAmount
:
number
invoiceDate
:
string
invoiceStatus
?:
number
taxRate
:
number
dataSource
?:
string
invoiceItems
:
InvoiceItemUpdateReq
[]
}
export
interface
InvoiceItemAddReq
{
productCode
:
string
productName
:
string
productQty
:
number
unitPrice
:
number
itemAmount
:
number
taxRate
:
number
taxAmount
:
number
}
export
interface
InvoiceItemUpdateReq
{
itemId
?:
number
productCode
:
string
productName
:
string
productQty
:
number
unitPrice
:
number
itemAmount
:
number
taxRate
:
number
taxAmount
:
number
}
export
const
invoiceApi
=
{
getInvoiceList
:
(
params
:
InvoiceQueryReq
)
=>
{
return
request
.
get
(
'/api/invoice/list'
,
params
)
},
getInvoiceDetail
:
(
invoiceId
:
number
)
=>
{
return
request
.
get
(
`/api/invoice/
${
invoiceId
}
`
)
},
addInvoice
:
(
data
:
InvoiceAddReq
)
=>
{
return
request
.
post
(
'/api/invoice'
,
data
)
},
updateInvoice
:
(
data
:
InvoiceUpdateReq
)
=>
{
return
request
.
post
(
'/api/invoice/update'
,
data
)
},
deleteInvoice
:
(
invoiceId
:
number
)
=>
{
return
request
.
delete
(
`/api/invoice/
${
invoiceId
}
`
)
},
batchDeleteInvoices
:
(
invoiceIds
:
number
[])
=>
{
return
request
.
post
(
'/api/invoice/batchDelete'
,
invoiceIds
)
},
updateInvoiceStatus
:
(
invoiceId
:
number
,
invoiceStatus
:
number
)
=>
{
return
request
.
post
(
`/api/invoice/
${
invoiceId
}
/invoiceStatus`
,
null
,
{
params
:
{
invoiceStatus
}
})
}
}
frontend/src/api/order.ts
View file @
fadab01
...
...
@@ -103,7 +103,7 @@ export interface OrderItemUpdateReq {
export
const
orderApi
=
{
// 分页查询订单列表
getOrderList
:
(
params
:
OrderQueryReq
)
=>
{
return
request
.
get
(
'/order/list'
,
{
params
}
)
return
request
.
get
(
'/order/list'
,
params
)
},
// 获取订单详情
...
...
frontend/src/views/delivery/index.vue
View file @
fadab01
...
...
@@ -86,25 +86,25 @@
<table class="data-table">
<thead>
<tr>
<th>
订
单ID</th>
<th class="sortable">
订
单编号 ↕️</th>
<th>
出库
单ID</th>
<th class="sortable">
出库
单编号 ↕️</th>
<th>经销商编码</th>
<th>经销商名称</th>
<th>
订单
日期</th>
<th>
订单金额
</th>
<th>
出库
日期</th>
<th>
关联订单编号
</th>
<th>出库状态</th>
<th>出库时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="order in orderList" :key="order.
order
Id">
<td>{{ order.
order
Id }}</td>
<td>{{ order.
order
No }}</td>
<tr v-for="order in orderList" :key="order.
delivery
Id">
<td>{{ order.
delivery
Id }}</td>
<td>{{ order.
delivery
No }}</td>
<td>{{ order.dealerCode }}</td>
<td>{{ order.dealerName }}</td>
<td>{{ formatDate(order.
order
Date) }}</td>
<td>{{
formatCurrency(order.totalAmount)
}}</td>
<td>{{ formatDate(order.
delivery
Date) }}</td>
<td>{{
order.orderNo
}}</td>
<td>
<span :class="getDeliveryStatusClass(order.deliveryStatus)">
{{ getDeliveryStatusText(order.deliveryStatus) }}
...
...
@@ -113,6 +113,7 @@
<td>{{ formatTime(order.uploadTime || '') }}</td>
<td class="action-col">
<button @click="handleView(order)" class="view-btn">👁️ 查看</button>
<button @click="handleDelete(order)" class="delete-btn">🗑️ 删除</button>
</td>
</tr>
</tbody>
...
...
@@ -298,6 +299,7 @@
v-model="addFormData.deliveryDate"
class="form-input"
type="datetime-local"
step="1"
required
/>
</div>
...
...
@@ -409,13 +411,13 @@
<script setup lang="ts">
import { ref, reactive, computed, onMounted } from 'vue'
import {
orderApi, type OrderInfo, type OrderQueryReq } from '../../api/order
'
import {
deliveryApi, type DeliveryAddReq, type DeliveryInfo, type DeliveryQueryReq } from '../../api/delivery
'
// 响应式数据
const loading = ref(false)
const orderList = ref<
Order
Info[]>([])
const orderList = ref<
Delivery
Info[]>([])
const showDetailDialog = ref(false)
const orderDetail = ref<
Order
Info | null>(null)
const orderDetail = ref<
Delivery
Info | null>(null)
// 新增出库相关数据
const showAddDialog = ref(false)
...
...
@@ -433,12 +435,14 @@ const addFormData = reactive({
// 搜索参数
const searchParams = reactive({
order
No: '',
delivery
No: '',
dealerCode: '',
dealerName: '',
deliveryStatus: undefined,
startDate: '',
endDate: '',
warehouseCode: '',
dataSource: '',
deliveryStartDate: '',
deliveryEndDate: '',
pageNum: 1,
pageSize: 10
})
...
...
@@ -511,7 +515,7 @@ const fetchOrders = async () => {
try {
loading.value = true
const params = { ...searchParams, pageNum: pagination.pageNum, pageSize: pagination.pageSize }
const response = await
orderApi.getOrder
List(params) as any
const response = await
deliveryApi.getDelivery
List(params) as any
console.log('出库查询API响应:', response)
// 由于request.ts的响应拦截器已经处理了code=200的情况,直接返回data
...
...
@@ -551,13 +555,13 @@ const handleReset = () => {
fetchOrders()
}
const handleView = async (order:
Order
Info) => {
const handleView = async (order:
Delivery
Info) => {
try {
const response = await
orderApi.getOrderDetail(order.order
Id) as any
const response = await
deliveryApi.getDeliveryDetail(order.delivery
Id) as any
console.log('出库查询详情API响应:', response)
// 由于request.ts的响应拦截器已经处理了code=200的情况,直接返回data
if (response && response.
order
Id) {
if (response && response.
delivery
Id) {
orderDetail.value = response
showDetailDialog.value = true
} else {
...
...
@@ -569,6 +573,19 @@ const handleView = async (order: OrderInfo) => {
}
}
const handleDelete = async (order: DeliveryInfo) => {
if (confirm(`确定要删除出库单"${order.deliveryNo}"吗?`)) {
try {
await deliveryApi.deleteDelivery(order.deliveryId)
showMessage('删除出库单成功', 'success')
fetchOrders() // 刷新列表
} catch (error) {
console.error('删除出库单失败:', error)
showMessage('删除出库单失败, 请重试', 'error')
}
}
}
const handleExport = () => {
showMessage('导出功能开发中...', 'warning')
...
...
@@ -618,11 +635,36 @@ const calculateDeliveryItemTotal = (index: number) => {
const handleSubmitAdd = async () => {
try {
// 这里应该调用新增出库的API
// await deliveryApi.addDelivery(addFormData)
showMessage('新增出库功能开发中...', 'warning')
// 处理日期时间格式,将datetime-local格式转换为后端需要的格式
let formattedDeliveryDate = addFormData.deliveryDate
if (formattedDeliveryDate && formattedDeliveryDate.includes('T')) {
// 将 YYYY-MM-DDTHH:MM:SS 格式转换为 YYYY-MM-DD HH:MM:SS 格式
formattedDeliveryDate = formattedDeliveryDate.replace('T', ' ')
}
// 构造新增出库的请求数据
const deliveryData: DeliveryAddReq = {
deliveryNo: addFormData.deliveryNo,
dealerCode: addFormData.dealerCode,
dealerName: addFormData.dealerName,
orderNo: addFormData.orderNo,
deliveryDate: formattedDeliveryDate,
deliveryStatus: 1, // 默认已出库
warehouseCode: addFormData.warehouseCode,
dataSource: addFormData.dataSource || '系统录入',
deliveryItems: addFormData.deliveryItems.map(item => ({
productCode: item.productCode,
productName: item.productName,
deliveryQty: item.deliveryQty,
deliveryPrice: item.deliveryPrice,
deliveryAmount: item.deliveryAmount
}))
}
await deliveryApi.addDelivery(deliveryData)
showMessage('新增出库成功', 'success')
closeAddDialog()
//
fetchOrders() // 刷新列表
fetchOrders() // 刷新列表
} catch (error) {
console.error('新增出库失败:', error)
showMessage('新增出库失败, 请重试', 'error')
...
...
@@ -891,6 +933,11 @@ onMounted(() => {
color: white;
}
.delete-btn {
background: #dc3545;
color: white;
}
.status-btn {
background: #28a745;
color: white;
...
...
frontend/src/views/invoice/index.vue
View file @
fadab01
...
...
@@ -4,6 +4,14 @@
<div class="search-section">
<div class="search-row">
<div class="search-item">
<label>发票编号:</label>
<input
v-model="searchParams.invoiceNo"
class="search-input"
placeholder="请输入发票编号"
/>
</div>
<div class="search-item">
<label>订单编号:</label>
<input
v-model="searchParams.orderNo"
...
...
@@ -38,17 +46,17 @@
</div>
<div class="search-row">
<div class="search-item">
<label>开始日期:</label>
<label>开
票开
始日期:</label>
<input
v-model="searchParams.
s
tartDate"
v-model="searchParams.
invoiceS
tartDate"
class="search-input"
type="date"
/>
</div>
<div class="search-item">
<label>结束日期:</label>
<label>
开票
结束日期:</label>
<input
v-model="searchParams.
e
ndDate"
v-model="searchParams.
invoiceE
ndDate"
class="search-input"
type="date"
/>
...
...
@@ -65,8 +73,6 @@
<div class="action-buttons">
<button @click="handleAdd" class="action-btn primary">✨ 新增发票</button>
<button @click="handleExport" class="action-btn secondary">📋 导出</button>
<button @click="handlePrint" class="action-btn secondary">🖨️ 打印</button>
<button @click="handleStatistics" class="action-btn secondary">📊 统计</button>
</div>
</div>
...
...
@@ -88,40 +94,36 @@
<table class="data-table">
<thead>
<tr>
<th>
订单
ID</th>
<th class="sortable">
订单
编号 ↕️</th>
<th>
发票
ID</th>
<th class="sortable">
发票
编号 ↕️</th>
<th>经销商编码</th>
<th>经销商名称</th>
<th>
订单
日期</th>
<th>
订单
金额</th>
<th>
开票
日期</th>
<th>
发票
金额</th>
<th>开票状态</th>
<th>开票时间</th>
<th>
发票号码
</th>
<th>
关联订单编号
</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="order in orderList" :key="order.
order
Id">
<td>{{ order.
order
Id }}</td>
<td>{{ order.
order
No }}</td>
<tr v-for="order in orderList" :key="order.
invoice
Id">
<td>{{ order.
invoice
Id }}</td>
<td>{{ order.
invoice
No }}</td>
<td>{{ order.dealerCode }}</td>
<td>{{ order.dealerName }}</td>
<td>{{ formatDate(order.
order
Date) }}</td>
<td>{{ formatDate(order.
invoice
Date) }}</td>
<td>{{ formatCurrency(order.totalAmount) }}</td>
<td>
<span :class="getInvoiceStatusClass(order.invoiceStatus)">
{{ getInvoiceStatusText(order.invoiceStatus) }}
</span>
</td>
<td>{{ formatTime('') }}</td>
<td>{{
'-'
}}</td>
<td>{{ formatTime(
order.uploadTime ||
'') }}</td>
<td>{{
order.orderNo
}}</td>
<td class="action-col">
<button @click="handleView(order)" class="view-btn">👁️ 查看</button>
<button @click="handleEdit(order)" class="edit-btn">✏️ 编辑</button>
<button @click="handleInvoiceStatus(order)" class="status-btn">
{{ order.invoiceStatus === 0 ? '开票' : '撤销开票' }}
</button>
<button @click="handlePrintInvoice(order)" class="print-btn">🖨️ 打印</button>
</td>
</tr>
</tbody>
...
...
@@ -275,24 +277,47 @@
</div>
<div class="dialog-body">
<div v-if="invoiceDetail" class="detail-content">
<!-- 发票基本信息 -->
<div class="detail-section">
<h4>发票基本信息</h4>
<div class="detail-grid">
<div class="detail-item">
<label>
订单编号
:</label>
<span>{{ invoiceDetail.
orderNo
}}</span>
<label>
发票ID
:</label>
<span>{{ invoiceDetail.
invoiceId
}}</span>
</div>
<div class="detail-item">
<label>发票
号码
:</label>
<label>发票
编号
:</label>
<span>{{ invoiceDetail.invoiceNo }}</span>
</div>
<div class="detail-item">
<label>关联订单编号:</label>
<span>{{ invoiceDetail.orderNo }}</span>
</div>
<div class="detail-item">
<label>关联出库单编号:</label>
<span>{{ invoiceDetail.deliveryNo || '-' }}</span>
</div>
<div class="detail-item">
<label>经销商编码:</label>
<span>{{ invoiceDetail.dealerCode }}</span>
</div>
<div class="detail-item">
<label>经销商名称:</label>
<span>{{ invoiceDetail.dealerName }}</span>
</div>
<div class="detail-item">
<label>开票日期:</label>
<span>{{ formatDate(invoiceDetail.invoiceDate) }}</span>
</div>
<div class="detail-item">
<label>开票金额:</label>
<span>{{ formatCurrency(invoiceDetail.invoiceAmount) }}</span>
<label>开票状态:</label>
<span :class="getInvoiceStatusClass(invoiceDetail.invoiceStatus)">
{{ getInvoiceStatusText(invoiceDetail.invoiceStatus) }}
</span>
</div>
<div class="detail-item">
<label>发票总金额:</label>
<span class="amount-text">{{ formatCurrency(invoiceDetail.totalAmount) }}</span>
</div>
<div class="detail-item">
<label>税率:</label>
...
...
@@ -300,19 +325,71 @@
</div>
<div class="detail-item">
<label>税额:</label>
<span
>{{ formatCurrency(invoiceDetail.taxAmount
) }}</span>
<span
class="amount-text">{{ formatCurrency((invoiceDetail.totalAmount || 0) * (invoiceDetail.taxRate || 0)
) }}</span>
</div>
<div class="detail-item">
<label>开票状态:</label>
<span :class="getInvoiceStatusClass(invoiceDetail.invoiceStatus)">
{{ getInvoiceStatusText(invoiceDetail.invoiceStatus) }}
</span>
<label>数据来源:</label>
<span>{{ invoiceDetail.dataSource || '-' }}</span>
</div>
<div class="detail-item">
<label>备注:</label>
<span>{{ invoiceDetail.remark || '-' }}</span>
<label>上传时间:</label>
<span>{{ formatTime(invoiceDetail.uploadTime || '') }}</span>
</div>
<div class="detail-item">
<label>创建时间:</label>
<span>{{ formatTime(invoiceDetail.createTime || '') }}</span>
</div>
<div class="detail-item">
<label>更新时间:</label>
<span>{{ formatTime(invoiceDetail.updateTime || '') }}</span>
</div>
</div>
</div>
<!-- 发票明细信息 -->
<div v-if="invoiceDetail.invoiceItems && invoiceDetail.invoiceItems.length > 0" class="detail-section">
<h4>发票明细信息</h4>
<div class="detail-table-container">
<table class="detail-table">
<thead>
<tr>
<th>产品编码</th>
<th>产品名称</th>
<th>数量</th>
<th>单价</th>
<th>金额</th>
<th>税率</th>
<th>税额</th>
</tr>
</thead>
<tbody>
<tr v-for="item in invoiceDetail.invoiceItems" :key="item.itemId">
<td>{{ item.productCode }}</td>
<td>{{ item.productName }}</td>
<td>{{ item.productQty }}</td>
<td>{{ formatCurrency(item.unitPrice) }}</td>
<td class="amount-text">{{ formatCurrency(item.itemAmount) }}</td>
<td>{{ item.taxRate ? (item.taxRate * 100).toFixed(2) + '%' : '-' }}</td>
<td class="amount-text">{{ formatCurrency(item.taxAmount || 0) }}</td>
</tr>
</tbody>
<tfoot>
<tr class="total-row">
<td colspan="4" class="total-label">合计:</td>
<td class="amount-text total-amount">{{ formatCurrency(invoiceDetail.totalAmount) }}</td>
<td>-</td>
<td class="amount-text total-amount">{{ formatCurrency((invoiceDetail.totalAmount || 0) * (invoiceDetail.taxRate || 0)) }}</td>
</tr>
</tfoot>
</table>
</div>
</div>
<!-- 操作按钮 -->
<div class="detail-actions">
<button @click="handleEdit(invoiceDetail)" class="edit-btn">✏️ 编辑</button>
<button @click="handlePrintInvoice(invoiceDetail)" class="print-btn">🖨️ 打印</button>
<button @click="closeDetailDialog" class="close-btn">关闭</button>
</div>
</div>
</div>
...
...
@@ -323,24 +400,27 @@
<script setup lang="ts">
import { ref, reactive, computed, onMounted } from 'vue'
import {
orderApi, type OrderInfo, type OrderQueryReq } from '../../api/order
'
import {
invoiceApi, type InvoiceInfo, type InvoiceQueryReq } from '../../api/invoice
'
// 响应式数据
const loading = ref(false)
const orderList = ref<
Order
Info[]>([])
const orderList = ref<
Invoice
Info[]>([])
const showDialog = ref(false)
const showDetailDialog = ref(false)
const isEdit = ref(false)
const invoiceDetail = ref<
any
>(null)
const invoiceDetail = ref<
InvoiceInfo | null
>(null)
// 搜索参数
const searchParams = reactive({
invoiceNo: '',
orderNo: '',
deliveryNo: '',
dealerCode: '',
dealerName: '',
invoiceStatus: undefined,
startDate: '',
endDate: '',
dataSource: '',
invoiceStartDate: '',
invoiceEndDate: '',
pageNum: 1,
pageSize: 10
})
...
...
@@ -424,7 +504,7 @@ const fetchOrders = async () => {
try {
loading.value = true
const params = { ...searchParams, pageNum: pagination.pageNum, pageSize: pagination.pageSize }
const response = await
orderApi.getOrder
List(params) as any
const response = await
invoiceApi.getInvoice
List(params) as any
console.log('发票管理API响应:', response)
// 由于request.ts的响应拦截器已经处理了code=200的情况,直接返回data
...
...
@@ -453,12 +533,15 @@ const handleSearch = () => {
const handleReset = () => {
Object.assign(searchParams, {
invoiceNo: '',
orderNo: '',
deliveryNo: '',
dealerCode: '',
dealerName: '',
invoiceStatus: undefined,
startDate: '',
endDate: ''
dataSource: '',
invoiceStartDate: '',
invoiceEndDate: ''
})
pagination.pageNum = 1
fetchOrders()
...
...
@@ -478,12 +561,12 @@ const handleAdd = () => {
showDialog.value = true
}
const handleEdit = (order:
Order
Info) => {
const handleEdit = (order:
Invoice
Info) => {
isEdit.value = true
Object.assign(formData, {
orderNo: order.orderNo,
invoiceNo:
(order as any).invoiceNo || ''
,
invoiceDate:
(order as any).invoiceTime || ''
,
invoiceNo:
order.invoiceNo
,
invoiceDate:
order.invoiceDate
,
invoiceAmount: order.totalAmount,
taxRate: 0,
taxAmount: 0,
...
...
@@ -492,13 +575,13 @@ const handleEdit = (order: OrderInfo) => {
showDialog.value = true
}
const handleView = async (order:
Order
Info) => {
const handleView = async (order:
Invoice
Info) => {
try {
const response = await
orderApi.getOrderDetail(order.order
Id) as any
const response = await
invoiceApi.getInvoiceDetail(order.invoice
Id) as any
console.log('发票管理详情API响应:', response)
// 由于request.ts的响应拦截器已经处理了code=200的情况,直接返回data
if (response && response.
order
Id) {
if (response && response.
invoice
Id) {
invoiceDetail.value = response
showDetailDialog.value = true
} else {
...
...
@@ -510,36 +593,16 @@ const handleView = async (order: OrderInfo) => {
}
}
const handleInvoiceStatus = async (order: OrderInfo) => {
const newStatus = order.invoiceStatus === 0 ? 1 : 0
const action = newStatus === 1 ? '开票' : '撤销开票'
if (confirm(`确定要${action}订单"${order.orderNo}"吗?`)) {
try {
await orderApi.updateInvoiceStatus(order.orderId, newStatus)
showMessage(`${action}成功`, 'success')
fetchOrders()
} catch (error) {
console.error(`${action}失败:`, error)
showMessage(`${action}失败, 请重试`, 'error')
}
}
}
const handleExport = () => {
showMessage('导出功能开发中...', 'warning')
}
const handlePrint
= (
) => {
const handlePrint
Invoice = (invoice: InvoiceInfo
) => {
showMessage('打印功能开发中...', 'warning')
}
const handleStatistics = () => {
showMessage('统计功能开发中...', 'warning')
}
const handlePrintInvoice = (order: OrderInfo) => {
showMessage(`打印发票 ${order.orderNo} 功能开发中...`, 'warning')
}
const handleSubmit = async () => {
try {
...
...
@@ -973,7 +1036,8 @@ onMounted(() => {
}
.dialog-content.large-dialog {
max-width: 1000px;
max-width: 1200px;
width: 95%;
}
.dialog-header {
...
...
@@ -1105,4 +1169,145 @@ onMounted(() => {
color: #333;
font-size: 16px;
}
/* 发票详情样式 */
.detail-content {
padding: 20px;
}
.detail-section {
margin-bottom: 30px;
}
.detail-section h4 {
margin: 0 0 15px 0;
padding: 10px 0;
border-bottom: 2px solid #007bff;
color: #007bff;
font-size: 16px;
font-weight: 600;
}
.detail-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 15px;
}
.detail-item {
display: flex;
align-items: center;
padding: 8px 0;
border-bottom: 1px solid #f0f0f0;
}
.detail-item label {
font-weight: 600;
color: #333;
min-width: 120px;
margin-right: 10px;
}
.detail-item span {
color: #666;
flex: 1;
}
.amount-text {
color: #e74c3c;
font-weight: 600;
}
.detail-table-container {
margin-top: 15px;
overflow-x: auto;
}
.detail-table {
width: 100%;
border-collapse: collapse;
font-size: 14px;
}
.detail-table th,
.detail-table td {
padding: 10px 8px;
text-align: left;
border: 1px solid #ddd;
}
.detail-table th {
background: #f8f9fa;
font-weight: 600;
color: #333;
}
.detail-table tbody tr:nth-child(even) {
background: #f8f9fa;
}
.detail-table tbody tr:hover {
background: #e9ecef;
}
.total-row {
background: #e9ecef !important;
font-weight: 600;
}
.total-label {
text-align: right;
font-weight: 600;
}
.total-amount {
color: #e74c3c;
font-weight: 700;
font-size: 15px;
}
.detail-actions {
margin-top: 20px;
padding-top: 20px;
border-top: 1px solid #eee;
display: flex;
gap: 10px;
justify-content: flex-end;
}
.detail-actions button {
padding: 8px 16px;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
transition: all 0.2s;
}
.detail-actions .edit-btn {
background: #28a745;
color: white;
}
.detail-actions .edit-btn:hover {
background: #218838;
}
.detail-actions .print-btn {
background: #17a2b8;
color: white;
}
.detail-actions .print-btn:hover {
background: #138496;
}
.detail-actions .close-btn {
background: #6c757d;
color: white;
}
.detail-actions .close-btn:hover {
background: #5a6268;
}
</style>
...
...
frontend/src/views/order/index.vue
View file @
fadab01
...
...
@@ -467,6 +467,8 @@ const searchParams = reactive<OrderQueryReq>({
invoiceStatus: undefined,
rebateCalcFlag: undefined,
verifyStatus: undefined,
minAmount: undefined,
maxAmount: undefined,
pageNum: 1,
pageSize: 10
})
...
...
@@ -593,7 +595,20 @@ const showMessage = (message: string, type: 'success' | 'error' | 'warning' = 's
const fetchOrders = async () => {
try {
loading.value = true
const params = { ...searchParams, pageNum: pagination.pageNum, pageSize: pagination.pageSize }
// 构造查询参数对象
const params: OrderQueryReq = {
orderNo: searchParams.orderNo || undefined,
dealerCode: searchParams.dealerCode || undefined,
dealerName: searchParams.dealerName || undefined,
deliveryStatus: searchParams.deliveryStatus,
invoiceStatus: searchParams.invoiceStatus,
rebateCalcFlag: searchParams.rebateCalcFlag,
verifyStatus: searchParams.verifyStatus,
minAmount: searchParams.minAmount,
maxAmount: searchParams.maxAmount,
pageNum: pagination.pageNum,
pageSize: pagination.pageSize
}
const response = await orderApi.getOrderList(params) as any
console.log('API响应:', response) // 添加调试日志
...
...
@@ -632,7 +647,9 @@ const handleReset = () => {
deliveryStatus: undefined,
invoiceStatus: undefined,
rebateCalcFlag: undefined,
verifyStatus: undefined
verifyStatus: undefined,
minAmount: undefined,
maxAmount: undefined
})
pagination.pageNum = 1
fetchOrders()
...
...
Please
register
or
login
to post a comment