Showing
26 changed files
with
506 additions
and
68 deletions
| ... | @@ -87,7 +87,7 @@ public class InvoiceMainController { | ... | @@ -87,7 +87,7 @@ public class InvoiceMainController { |
| 87 | 87 | ||
| 88 | @Operation(summary = "删除发票", description = "根据发票ID逻辑删除发票") | 88 | @Operation(summary = "删除发票", description = "根据发票ID逻辑删除发票") |
| 89 | @DeleteMapping("/{invoiceId}") | 89 | @DeleteMapping("/{invoiceId}") |
| 90 | - @PreAuthorize("hasAuthority('invoice:delete')") | 90 | + @PreAuthorize("hasAuthority('invoice:remove')") |
| 91 | public ApiRes<Void> deleteInvoice( | 91 | public ApiRes<Void> deleteInvoice( |
| 92 | @Parameter(description = "发票ID", required = true) @PathVariable Long invoiceId) { | 92 | @Parameter(description = "发票ID", required = true) @PathVariable Long invoiceId) { |
| 93 | try { | 93 | try { |
| ... | @@ -141,3 +141,4 @@ public class InvoiceMainController { | ... | @@ -141,3 +141,4 @@ public class InvoiceMainController { |
| 141 | } | 141 | } |
| 142 | } | 142 | } |
| 143 | 143 | ||
| 144 | + | ... | ... |
| ... | @@ -14,3 +14,4 @@ import org.apache.ibatis.annotations.Mapper; | ... | @@ -14,3 +14,4 @@ import org.apache.ibatis.annotations.Mapper; |
| 14 | public interface DeliveryItemMapper extends BaseMapper<DeliveryItem> { | 14 | public interface DeliveryItemMapper extends BaseMapper<DeliveryItem> { |
| 15 | } | 15 | } |
| 16 | 16 | ||
| 17 | + | ... | ... |
| ... | @@ -14,3 +14,4 @@ import org.apache.ibatis.annotations.Mapper; | ... | @@ -14,3 +14,4 @@ import org.apache.ibatis.annotations.Mapper; |
| 14 | public interface DeliveryMainMapper extends BaseMapper<DeliveryMain> { | 14 | public interface DeliveryMainMapper extends BaseMapper<DeliveryMain> { |
| 15 | } | 15 | } |
| 16 | 16 | ||
| 17 | + | ... | ... |
| ... | @@ -14,3 +14,4 @@ import org.apache.ibatis.annotations.Mapper; | ... | @@ -14,3 +14,4 @@ import org.apache.ibatis.annotations.Mapper; |
| 14 | public interface InvoiceItemMapper extends BaseMapper<InvoiceItem> { | 14 | public interface InvoiceItemMapper extends BaseMapper<InvoiceItem> { |
| 15 | } | 15 | } |
| 16 | 16 | ||
| 17 | + | ... | ... |
| ... | @@ -14,3 +14,4 @@ import org.apache.ibatis.annotations.Mapper; | ... | @@ -14,3 +14,4 @@ import org.apache.ibatis.annotations.Mapper; |
| 14 | public interface InvoiceMainMapper extends BaseMapper<InvoiceMain> { | 14 | public interface InvoiceMainMapper extends BaseMapper<InvoiceMain> { |
| 15 | } | 15 | } |
| 16 | 16 | ||
| 17 | + | ... | ... |
| ... | @@ -69,3 +69,4 @@ public interface DeliveryMainService extends IService<DeliveryMain> { | ... | @@ -69,3 +69,4 @@ public interface DeliveryMainService extends IService<DeliveryMain> { |
| 69 | boolean updateDeliveryStatus(Long deliveryId, Integer deliveryStatus); | 69 | boolean updateDeliveryStatus(Long deliveryId, Integer deliveryStatus); |
| 70 | } | 70 | } |
| 71 | 71 | ||
| 72 | + | ... | ... |
| ... | @@ -69,3 +69,4 @@ public interface InvoiceMainService extends IService<InvoiceMain> { | ... | @@ -69,3 +69,4 @@ public interface InvoiceMainService extends IService<InvoiceMain> { |
| 69 | boolean updateInvoiceStatus(Long invoiceId, Integer invoiceStatus); | 69 | boolean updateInvoiceStatus(Long invoiceId, Integer invoiceStatus); |
| 70 | } | 70 | } |
| 71 | 71 | ||
| 72 | + | ... | ... |
| ... | @@ -112,6 +112,7 @@ public class InvoiceMainServiceImpl extends ServiceImpl<InvoiceMainMapper, Invoi | ... | @@ -112,6 +112,7 @@ public class InvoiceMainServiceImpl extends ServiceImpl<InvoiceMainMapper, Invoi |
| 112 | 112 | ||
| 113 | InvoiceMain invoiceMain = new InvoiceMain(); | 113 | InvoiceMain invoiceMain = new InvoiceMain(); |
| 114 | BeanUtils.copyProperties(addReq, invoiceMain); | 114 | BeanUtils.copyProperties(addReq, invoiceMain); |
| 115 | + invoiceMain.setUpdateTime(LocalDateTime.now()); | ||
| 115 | invoiceMain.setCreateTime(LocalDateTime.now()); | 116 | invoiceMain.setCreateTime(LocalDateTime.now()); |
| 116 | invoiceMain.setUpdateTime(LocalDateTime.now()); | 117 | invoiceMain.setUpdateTime(LocalDateTime.now()); |
| 117 | invoiceMain.setDelFlag("0"); | 118 | invoiceMain.setDelFlag("0"); | ... | ... |
| ... | @@ -7,31 +7,10 @@ export {} | ... | @@ -7,31 +7,10 @@ export {} |
| 7 | 7 | ||
| 8 | declare module 'vue' { | 8 | declare module 'vue' { |
| 9 | export interface GlobalComponents { | 9 | export interface GlobalComponents { |
| 10 | - ElButton: typeof import('element-plus/es')['ElButton'] | ||
| 11 | - ElCard: typeof import('element-plus/es')['ElCard'] | ||
| 12 | - ElDatePicker: typeof import('element-plus/es')['ElDatePicker'] | ||
| 13 | - ElDescriptions: typeof import('element-plus/es')['ElDescriptions'] | ||
| 14 | - ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem'] | ||
| 15 | - ElDialog: typeof import('element-plus/es')['ElDialog'] | ||
| 16 | - ElForm: typeof import('element-plus/es')['ElForm'] | ||
| 17 | - ElFormItem: typeof import('element-plus/es')['ElFormItem'] | ||
| 18 | - ElIcon: typeof import('element-plus/es')['ElIcon'] | ||
| 19 | - ElInput: typeof import('element-plus/es')['ElInput'] | ||
| 20 | - ElInputNumber: typeof import('element-plus/es')['ElInputNumber'] | ||
| 21 | - ElOption: typeof import('element-plus/es')['ElOption'] | ||
| 22 | - ElPagination: typeof import('element-plus/es')['ElPagination'] | ||
| 23 | - ElSelect: typeof import('element-plus/es')['ElSelect'] | ||
| 24 | - ElTable: typeof import('element-plus/es')['ElTable'] | ||
| 25 | - ElTableColumn: typeof import('element-plus/es')['ElTableColumn'] | ||
| 26 | - ElTag: typeof import('element-plus/es')['ElTag'] | ||
| 27 | - ElText: typeof import('element-plus/es')['ElText'] | ||
| 28 | Header: typeof import('./src/components/layout/Header.vue')['default'] | 10 | Header: typeof import('./src/components/layout/Header.vue')['default'] |
| 29 | RouterLink: typeof import('vue-router')['RouterLink'] | 11 | RouterLink: typeof import('vue-router')['RouterLink'] |
| 30 | RouterView: typeof import('vue-router')['RouterView'] | 12 | RouterView: typeof import('vue-router')['RouterView'] |
| 31 | Sidebar: typeof import('./src/components/layout/Sidebar.vue')['default'] | 13 | Sidebar: typeof import('./src/components/layout/Sidebar.vue')['default'] |
| 32 | SidebarItem: typeof import('./src/components/layout/SidebarItem.vue')['default'] | 14 | SidebarItem: typeof import('./src/components/layout/SidebarItem.vue')['default'] |
| 33 | } | 15 | } |
| 34 | - export interface ComponentCustomProperties { | ||
| 35 | - vLoading: typeof import('element-plus/es')['ElLoadingDirective'] | ||
| 36 | - } | ||
| 37 | } | 16 | } | ... | ... |
| ... | @@ -63,7 +63,7 @@ | ... | @@ -63,7 +63,7 @@ |
| 63 | <!-- 操作按钮区域 --> | 63 | <!-- 操作按钮区域 --> |
| 64 | <div class="action-section"> | 64 | <div class="action-section"> |
| 65 | <div class="action-buttons"> | 65 | <div class="action-buttons"> |
| 66 | - <button @click="handleAdd" class="action-btn primary">➕ 新增出库</button> | 66 | + <button @click="handleAdd" class="action-btn primary">✨ 新增</button> |
| 67 | <button @click="handleExport" class="action-btn secondary">📋 导出</button> | 67 | <button @click="handleExport" class="action-btn secondary">📋 导出</button> |
| 68 | </div> | 68 | </div> |
| 69 | </div> | 69 | </div> |
| ... | @@ -178,8 +178,16 @@ | ... | @@ -178,8 +178,16 @@ |
| 178 | <h4>出库基本信息</h4> | 178 | <h4>出库基本信息</h4> |
| 179 | <div class="detail-grid"> | 179 | <div class="detail-grid"> |
| 180 | <div class="detail-item"> | 180 | <div class="detail-item"> |
| 181 | - <label>出库单号:</label> | 181 | + <label>出库单ID:</label> |
| 182 | - <span>{{ deliveryDetail.deliveryNo }}</span> | 182 | + <span>{{ orderDetail.deliveryId }}</span> |
| 183 | + </div> | ||
| 184 | + <div class="detail-item"> | ||
| 185 | + <label>出库单编号:</label> | ||
| 186 | + <span>{{ orderDetail.deliveryNo }}</span> | ||
| 187 | + </div> | ||
| 188 | + <div class="detail-item"> | ||
| 189 | + <label>关联订单编号:</label> | ||
| 190 | + <span>{{ orderDetail.orderNo }}</span> | ||
| 183 | </div> | 191 | </div> |
| 184 | <div class="detail-item"> | 192 | <div class="detail-item"> |
| 185 | <label>关联订单编号:</label> | 193 | <label>关联订单编号:</label> |
| ... | @@ -195,11 +203,7 @@ | ... | @@ -195,11 +203,7 @@ |
| 195 | </div> | 203 | </div> |
| 196 | <div class="detail-item"> | 204 | <div class="detail-item"> |
| 197 | <label>出库日期:</label> | 205 | <label>出库日期:</label> |
| 198 | - <span>{{ formatDate(deliveryDetail.deliveryDate) }}</span> | 206 | + <span>{{ formatDate(orderDetail.deliveryDate) }}</span> |
| 199 | - </div> | ||
| 200 | - <div class="detail-item"> | ||
| 201 | - <label>出库总金额:</label> | ||
| 202 | - <span>{{ formatCurrency(deliveryDetail.totalAmount) }}</span> | ||
| 203 | </div> | 207 | </div> |
| 204 | <div class="detail-item"> | 208 | <div class="detail-item"> |
| 205 | <label>出库状态:</label> | 209 | <label>出库状态:</label> |
| ... | @@ -208,33 +212,47 @@ | ... | @@ -208,33 +212,47 @@ |
| 208 | </span> | 212 | </span> |
| 209 | </div> | 213 | </div> |
| 210 | <div class="detail-item"> | 214 | <div class="detail-item"> |
| 215 | + <label>仓库编码:</label> | ||
| 216 | + <span>{{ orderDetail.warehouseCode }}</span> | ||
| 217 | + </div> | ||
| 218 | + <div class="detail-item"> | ||
| 219 | + <label>数据来源:</label> | ||
| 220 | + <span>{{ orderDetail.dataSource || '-' }}</span> | ||
| 221 | + </div> | ||
| 222 | + <div class="detail-item"> | ||
| 223 | + <label>上传时间:</label> | ||
| 224 | + <span>{{ formatTime(orderDetail.uploadTime || '') }}</span> | ||
| 225 | + </div> | ||
| 226 | + <div class="detail-item"> | ||
| 211 | <label>创建时间:</label> | 227 | <label>创建时间:</label> |
| 212 | - <span>{{ formatTime(deliveryDetail.createTime || '') }}</span> | 228 | + <span>{{ formatTime(orderDetail.createTime || '') }}</span> |
| 229 | + </div> | ||
| 230 | + <div class="detail-item"> | ||
| 231 | + <label>更新时间:</label> | ||
| 232 | + <span>{{ formatTime(orderDetail.updateTime || '') }}</span> | ||
| 213 | </div> | 233 | </div> |
| 214 | </div> | 234 | </div> |
| 215 | </div> | 235 | </div> |
| 216 | 236 | ||
| 217 | - <div class="detail-section" v-if="deliveryDetail.deliveryItems && deliveryDetail.deliveryItems.length > 0"> | 237 | + <div class="detail-section" v-if="orderDetail.deliveryItems && orderDetail.deliveryItems.length > 0"> |
| 218 | <h4>出库明细</h4> | 238 | <h4>出库明细</h4> |
| 219 | <table class="detail-table"> | 239 | <table class="detail-table"> |
| 220 | <thead> | 240 | <thead> |
| 221 | <tr> | 241 | <tr> |
| 222 | <th>产品编码</th> | 242 | <th>产品编码</th> |
| 223 | <th>产品名称</th> | 243 | <th>产品名称</th> |
| 224 | - <th>产品型号</th> | ||
| 225 | <th>出库数量</th> | 244 | <th>出库数量</th> |
| 226 | <th>出库单价</th> | 245 | <th>出库单价</th> |
| 227 | - <th>出库总价</th> | 246 | + <th>出库金额</th> |
| 228 | </tr> | 247 | </tr> |
| 229 | </thead> | 248 | </thead> |
| 230 | <tbody> | 249 | <tbody> |
| 231 | - <tr v-for="item in deliveryDetail.deliveryItems" :key="item.itemId"> | 250 | + <tr v-for="item in orderDetail.deliveryItems" :key="item.deliveryItemId"> |
| 232 | <td>{{ item.productCode }}</td> | 251 | <td>{{ item.productCode }}</td> |
| 233 | <td>{{ item.productName }}</td> | 252 | <td>{{ item.productName }}</td> |
| 234 | - <td>{{ item.productModel }}</td> | 253 | + <td>{{ item.deliveryQty }}</td> |
| 235 | - <td>{{ item.productQty }}</td> | 254 | + <td>{{ formatCurrency(item.deliveryPrice) }}</td> |
| 236 | - <td>{{ formatCurrency(item.unitPrice) }}</td> | 255 | + <td>{{ formatCurrency(item.deliveryAmount) }}</td> |
| 237 | - <td>{{ formatCurrency(item.totalPrice) }}</td> | ||
| 238 | </tr> | 256 | </tr> |
| 239 | </tbody> | 257 | </tbody> |
| 240 | </table> | 258 | </table> | ... | ... |
| ... | @@ -71,7 +71,7 @@ | ... | @@ -71,7 +71,7 @@ |
| 71 | <!-- 操作按钮区域 --> | 71 | <!-- 操作按钮区域 --> |
| 72 | <div class="action-section"> | 72 | <div class="action-section"> |
| 73 | <div class="action-buttons"> | 73 | <div class="action-buttons"> |
| 74 | - <button @click="handleAdd" class="action-btn primary">✨ 新增发票</button> | 74 | + <button @click="handleAdd" class="action-btn primary">✨ 新增</button> |
| 75 | <button @click="handleExport" class="action-btn secondary">📋 导出</button> | 75 | <button @click="handleExport" class="action-btn secondary">📋 导出</button> |
| 76 | </div> | 76 | </div> |
| 77 | </div> | 77 | </div> |
| ... | @@ -101,7 +101,7 @@ | ... | @@ -101,7 +101,7 @@ |
| 101 | <th>开票日期</th> | 101 | <th>开票日期</th> |
| 102 | <th>发票金额</th> | 102 | <th>发票金额</th> |
| 103 | <th>开票状态</th> | 103 | <th>开票状态</th> |
| 104 | - <th>开票时间</th> | 104 | + <th>上传时间</th> |
| 105 | <th>关联订单编号</th> | 105 | <th>关联订单编号</th> |
| 106 | <th>操作</th> | 106 | <th>操作</th> |
| 107 | </tr> | 107 | </tr> |
| ... | @@ -124,6 +124,7 @@ | ... | @@ -124,6 +124,7 @@ |
| 124 | <td class="action-col"> | 124 | <td class="action-col"> |
| 125 | <button @click="handleView(order)" class="view-btn">👁️ 查看</button> | 125 | <button @click="handleView(order)" class="view-btn">👁️ 查看</button> |
| 126 | <button @click="handleEdit(order)" class="edit-btn">✏️ 编辑</button> | 126 | <button @click="handleEdit(order)" class="edit-btn">✏️ 编辑</button> |
| 127 | + <button @click="handleDelete(order)" class="delete-btn">🗑️ 删除</button> | ||
| 127 | </td> | 128 | </td> |
| 128 | </tr> | 129 | </tr> |
| 129 | </tbody> | 130 | </tbody> |
| ... | @@ -177,7 +178,7 @@ | ... | @@ -177,7 +178,7 @@ |
| 177 | 178 | ||
| 178 | <!-- 新增/编辑发票对话框 --> | 179 | <!-- 新增/编辑发票对话框 --> |
| 179 | <div v-if="showDialog" class="dialog-overlay" @click="closeDialog"> | 180 | <div v-if="showDialog" class="dialog-overlay" @click="closeDialog"> |
| 180 | - <div class="dialog-content" @click.stop> | 181 | + <div class="dialog-content large-dialog" @click.stop> |
| 181 | <div class="dialog-header"> | 182 | <div class="dialog-header"> |
| 182 | <h3>{{ isEdit ? '编辑发票' : '新增发票' }}</h3> | 183 | <h3>{{ isEdit ? '编辑发票' : '新增发票' }}</h3> |
| 183 | <button @click="closeDialog" class="close-btn">×</button> | 184 | <button @click="closeDialog" class="close-btn">×</button> |
| ... | @@ -206,11 +207,41 @@ | ... | @@ -206,11 +207,41 @@ |
| 206 | </div> | 207 | </div> |
| 207 | <div class="form-row"> | 208 | <div class="form-row"> |
| 208 | <div class="form-item"> | 209 | <div class="form-item"> |
| 210 | + <label>出库单编号:</label> | ||
| 211 | + <input | ||
| 212 | + v-model="formData.deliveryNo" | ||
| 213 | + class="form-input" | ||
| 214 | + placeholder="请输入出库单编号" | ||
| 215 | + /> | ||
| 216 | + </div> | ||
| 217 | + <div class="form-item"> | ||
| 218 | + <label class="required">经销商编码:</label> | ||
| 219 | + <input | ||
| 220 | + v-model="formData.dealerCode" | ||
| 221 | + class="form-input" | ||
| 222 | + placeholder="请输入经销商编码" | ||
| 223 | + required | ||
| 224 | + /> | ||
| 225 | + </div> | ||
| 226 | + </div> | ||
| 227 | + <div class="form-row"> | ||
| 228 | + <div class="form-item"> | ||
| 229 | + <label class="required">经销商名称:</label> | ||
| 230 | + <input | ||
| 231 | + v-model="formData.dealerName" | ||
| 232 | + class="form-input" | ||
| 233 | + placeholder="请输入经销商名称" | ||
| 234 | + required | ||
| 235 | + /> | ||
| 236 | + </div> | ||
| 237 | + </div> | ||
| 238 | + <div class="form-row"> | ||
| 239 | + <div class="form-item"> | ||
| 209 | <label class="required">开票日期:</label> | 240 | <label class="required">开票日期:</label> |
| 210 | <input | 241 | <input |
| 211 | v-model="formData.invoiceDate" | 242 | v-model="formData.invoiceDate" |
| 212 | class="form-input" | 243 | class="form-input" |
| 213 | - type="datetime-local" | 244 | + type="date" |
| 214 | required | 245 | required |
| 215 | /> | 246 | /> |
| 216 | </div> | 247 | </div> |
| ... | @@ -221,7 +252,8 @@ | ... | @@ -221,7 +252,8 @@ |
| 221 | class="form-input" | 252 | class="form-input" |
| 222 | type="number" | 253 | type="number" |
| 223 | step="0.01" | 254 | step="0.01" |
| 224 | - placeholder="请输入开票金额" | 255 | + placeholder="开票金额(自动计算)" |
| 256 | + readonly | ||
| 225 | required | 257 | required |
| 226 | /> | 258 | /> |
| 227 | </div> | 259 | </div> |
| ... | @@ -235,6 +267,7 @@ | ... | @@ -235,6 +267,7 @@ |
| 235 | type="number" | 267 | type="number" |
| 236 | step="0.01" | 268 | step="0.01" |
| 237 | placeholder="请输入税率" | 269 | placeholder="请输入税率" |
| 270 | + @input="calculateTaxAmount" | ||
| 238 | /> | 271 | /> |
| 239 | </div> | 272 | </div> |
| 240 | <div class="form-item"> | 273 | <div class="form-item"> |
| ... | @@ -244,10 +277,84 @@ | ... | @@ -244,10 +277,84 @@ |
| 244 | class="form-input" | 277 | class="form-input" |
| 245 | type="number" | 278 | type="number" |
| 246 | step="0.01" | 279 | step="0.01" |
| 247 | - placeholder="请输入税额" | 280 | + placeholder="税额(自动计算)" |
| 281 | + readonly | ||
| 248 | /> | 282 | /> |
| 249 | </div> | 283 | </div> |
| 250 | </div> | 284 | </div> |
| 285 | + | ||
| 286 | + <!-- 发票明细信息 --> | ||
| 287 | + <div class="form-section"> | ||
| 288 | + <div class="section-header"> | ||
| 289 | + <h4>发票明细</h4> | ||
| 290 | + <button type="button" @click="addInvoiceItem" class="add-item-btn">+ 添加明细</button> | ||
| 291 | + </div> | ||
| 292 | + <div class="invoice-items-container"> | ||
| 293 | + <div v-for="(item, index) in formData.invoiceItems" :key="index" class="invoice-item"> | ||
| 294 | + <div class="item-row-single"> | ||
| 295 | + <div class="form-item" style="flex: 0 0 120px;"> | ||
| 296 | + <label>产品编码:</label> | ||
| 297 | + <input | ||
| 298 | + v-model="item.productCode" | ||
| 299 | + class="form-input" | ||
| 300 | + placeholder="产品编码" | ||
| 301 | + /> | ||
| 302 | + </div> | ||
| 303 | + <div class="form-item" style="flex: 1 1 200px; min-width: 150px;"> | ||
| 304 | + <label>产品名称:</label> | ||
| 305 | + <input | ||
| 306 | + v-model="item.productName" | ||
| 307 | + class="form-input" | ||
| 308 | + placeholder="产品名称" | ||
| 309 | + /> | ||
| 310 | + </div> | ||
| 311 | + <div class="form-item" style="flex: 0 0 80px;"> | ||
| 312 | + <label>数量:</label> | ||
| 313 | + <input | ||
| 314 | + v-model.number="item.productQty" | ||
| 315 | + class="form-input" | ||
| 316 | + type="number" | ||
| 317 | + @input="calculateInvoiceItemTotal(item)" | ||
| 318 | + /> | ||
| 319 | + </div> | ||
| 320 | + <div class="form-item" style="flex: 0 0 100px;"> | ||
| 321 | + <label>单价:</label> | ||
| 322 | + <input | ||
| 323 | + v-model.number="item.unitPrice" | ||
| 324 | + class="form-input" | ||
| 325 | + type="number" | ||
| 326 | + step="0.01" | ||
| 327 | + @input="calculateInvoiceItemTotal(item)" | ||
| 328 | + /> | ||
| 329 | + </div> | ||
| 330 | + <div class="form-item" style="flex: 0 0 100px;"> | ||
| 331 | + <label>金额:</label> | ||
| 332 | + <input | ||
| 333 | + v-model.number="item.itemAmount" | ||
| 334 | + class="form-input" | ||
| 335 | + type="number" | ||
| 336 | + step="0.01" | ||
| 337 | + readonly | ||
| 338 | + /> | ||
| 339 | + </div> | ||
| 340 | + <div class="form-item" style="flex: 0 0 100px;"> | ||
| 341 | + <label>税额:</label> | ||
| 342 | + <input | ||
| 343 | + v-model.number="item.taxAmount" | ||
| 344 | + class="form-input" | ||
| 345 | + type="number" | ||
| 346 | + step="0.01" | ||
| 347 | + readonly | ||
| 348 | + /> | ||
| 349 | + </div> | ||
| 350 | + <div class="form-item" style="flex: 0 0 60px;"> | ||
| 351 | + <button type="button" @click="removeInvoiceItem(index)" class="remove-item-btn">删除</button> | ||
| 352 | + </div> | ||
| 353 | + </div> | ||
| 354 | + </div> | ||
| 355 | + </div> | ||
| 356 | + </div> | ||
| 357 | + | ||
| 251 | <div class="form-row"> | 358 | <div class="form-row"> |
| 252 | <div class="form-item full-width"> | 359 | <div class="form-item full-width"> |
| 253 | <label>备注:</label> | 360 | <label>备注:</label> |
| ... | @@ -321,11 +428,11 @@ | ... | @@ -321,11 +428,11 @@ |
| 321 | </div> | 428 | </div> |
| 322 | <div class="detail-item"> | 429 | <div class="detail-item"> |
| 323 | <label>税率:</label> | 430 | <label>税率:</label> |
| 324 | - <span>{{ invoiceDetail.taxRate ? (invoiceDetail.taxRate * 100).toFixed(2) + '%' : '-' }}</span> | 431 | + <span>{{ invoiceDetail.taxRate ? invoiceDetail.taxRate + '%' : '-' }}</span> |
| 325 | </div> | 432 | </div> |
| 326 | <div class="detail-item"> | 433 | <div class="detail-item"> |
| 327 | <label>税额:</label> | 434 | <label>税额:</label> |
| 328 | - <span class="amount-text">{{ formatCurrency((invoiceDetail.totalAmount || 0) * (invoiceDetail.taxRate || 0)) }}</span> | 435 | + <span class="amount-text">{{ formatCurrency((invoiceDetail.totalAmount || 0) * (invoiceDetail.taxRate || 0) / 100) }}</span> |
| 329 | </div> | 436 | </div> |
| 330 | <div class="detail-item"> | 437 | <div class="detail-item"> |
| 331 | <label>数据来源:</label> | 438 | <label>数据来源:</label> |
| ... | @@ -363,22 +470,22 @@ | ... | @@ -363,22 +470,22 @@ |
| 363 | </tr> | 470 | </tr> |
| 364 | </thead> | 471 | </thead> |
| 365 | <tbody> | 472 | <tbody> |
| 366 | - <tr v-for="item in invoiceDetail.invoiceItems" :key="item.itemId"> | 473 | + <tr v-for="item in invoiceDetail.invoiceItems" :key="item.invoiceItemId"> |
| 367 | <td>{{ item.productCode }}</td> | 474 | <td>{{ item.productCode }}</td> |
| 368 | <td>{{ item.productName }}</td> | 475 | <td>{{ item.productName }}</td> |
| 369 | - <td>{{ item.productQty }}</td> | 476 | + <td>{{ item.invoiceQty }}</td> |
| 370 | - <td>{{ formatCurrency(item.unitPrice) }}</td> | 477 | + <td>{{ formatCurrency(item.unitPriceNoTax) }}</td> |
| 371 | - <td class="amount-text">{{ formatCurrency(item.itemAmount) }}</td> | 478 | + <td class="amount-text">{{ formatCurrency(item.amountNoTax) }}</td> |
| 372 | - <td>{{ item.taxRate ? (item.taxRate * 100).toFixed(2) + '%' : '-' }}</td> | 479 | + <td>{{ invoiceDetail.taxRate ? (invoiceDetail.taxRate / 100).toFixed(2) + '%' : '-' }}</td> |
| 373 | <td class="amount-text">{{ formatCurrency(item.taxAmount || 0) }}</td> | 480 | <td class="amount-text">{{ formatCurrency(item.taxAmount || 0) }}</td> |
| 374 | </tr> | 481 | </tr> |
| 375 | </tbody> | 482 | </tbody> |
| 376 | <tfoot> | 483 | <tfoot> |
| 377 | <tr class="total-row"> | 484 | <tr class="total-row"> |
| 378 | <td colspan="4" class="total-label">合计:</td> | 485 | <td colspan="4" class="total-label">合计:</td> |
| 379 | - <td class="amount-text total-amount">{{ formatCurrency(invoiceDetail.totalAmount) }}</td> | 486 | + <td class="amount-text total-amount">{{ formatCurrency(invoiceDetail.invoiceItems.reduce((sum, item) => sum + (item.amountNoTax || 0), 0)) }}</td> |
| 380 | <td>-</td> | 487 | <td>-</td> |
| 381 | - <td class="amount-text total-amount">{{ formatCurrency((invoiceDetail.totalAmount || 0) * (invoiceDetail.taxRate || 0)) }}</td> | 488 | + <td class="amount-text total-amount">{{ formatCurrency(invoiceDetail.invoiceItems.reduce((sum, item) => sum + (item.taxAmount || 0), 0)) }}</td> |
| 382 | </tr> | 489 | </tr> |
| 383 | </tfoot> | 490 | </tfoot> |
| 384 | </table> | 491 | </table> |
| ... | @@ -445,13 +552,18 @@ const totalPages = computed(() => Math.ceil(pagination.total / pagination.pageSi | ... | @@ -445,13 +552,18 @@ const totalPages = computed(() => Math.ceil(pagination.total / pagination.pageSi |
| 445 | 552 | ||
| 446 | // 表单数据 | 553 | // 表单数据 |
| 447 | const formData = reactive({ | 554 | const formData = reactive({ |
| 555 | + invoiceId: 0, | ||
| 448 | orderNo: '', | 556 | orderNo: '', |
| 449 | invoiceNo: '', | 557 | invoiceNo: '', |
| 558 | + deliveryNo: '', | ||
| 559 | + dealerCode: '', | ||
| 560 | + dealerName: '', | ||
| 450 | invoiceDate: '', | 561 | invoiceDate: '', |
| 451 | invoiceAmount: 0, | 562 | invoiceAmount: 0, |
| 452 | taxRate: 0, | 563 | taxRate: 0, |
| 453 | taxAmount: 0, | 564 | taxAmount: 0, |
| 454 | - remark: '' | 565 | + remark: '', |
| 566 | + invoiceItems: [] as any[] | ||
| 455 | }) | 567 | }) |
| 456 | 568 | ||
| 457 | // 状态相关方法 | 569 | // 状态相关方法 |
| ... | @@ -550,29 +662,148 @@ const handleReset = () => { | ... | @@ -550,29 +662,148 @@ const handleReset = () => { |
| 550 | const handleAdd = () => { | 662 | const handleAdd = () => { |
| 551 | isEdit.value = false | 663 | isEdit.value = false |
| 552 | Object.assign(formData, { | 664 | Object.assign(formData, { |
| 665 | + invoiceId: 0, | ||
| 553 | orderNo: '', | 666 | orderNo: '', |
| 554 | invoiceNo: '', | 667 | invoiceNo: '', |
| 668 | + deliveryNo: '', | ||
| 669 | + dealerCode: '', | ||
| 670 | + dealerName: '', | ||
| 555 | invoiceDate: '', | 671 | invoiceDate: '', |
| 556 | invoiceAmount: 0, | 672 | invoiceAmount: 0, |
| 557 | taxRate: 0, | 673 | taxRate: 0, |
| 558 | taxAmount: 0, | 674 | taxAmount: 0, |
| 559 | - remark: '' | 675 | + remark: '', |
| 676 | + invoiceItems: [] | ||
| 560 | }) | 677 | }) |
| 561 | showDialog.value = true | 678 | showDialog.value = true |
| 562 | } | 679 | } |
| 563 | 680 | ||
| 564 | -const handleEdit = (order: InvoiceInfo) => { | 681 | +// 发票明细相关方法 |
| 565 | - isEdit.value = true | 682 | +const addInvoiceItem = () => { |
| 566 | - Object.assign(formData, { | 683 | + const newItem = { |
| 567 | - orderNo: order.orderNo, | 684 | + productCode: '', |
| 568 | - invoiceNo: order.invoiceNo, | 685 | + productName: '', |
| 569 | - invoiceDate: order.invoiceDate, | 686 | + productQty: 1, |
| 570 | - invoiceAmount: order.totalAmount, | 687 | + unitPrice: 0, |
| 571 | - taxRate: 0, | 688 | + itemAmount: 0, |
| 572 | - taxAmount: 0, | 689 | + taxAmount: 0 |
| 573 | - remark: '' | 690 | + } |
| 691 | + formData.invoiceItems.push(newItem) | ||
| 692 | + // 计算新明细项目的金额 | ||
| 693 | + calculateInvoiceItemTotal(newItem) | ||
| 694 | +} | ||
| 695 | + | ||
| 696 | +const removeInvoiceItem = (index: number) => { | ||
| 697 | + formData.invoiceItems.splice(index, 1) | ||
| 698 | + // 删除明细项目后,重新计算开票金额和税额 | ||
| 699 | + calculateTaxAmount() | ||
| 700 | +} | ||
| 701 | + | ||
| 702 | +const calculateInvoiceItemTotal = (item: any) => { | ||
| 703 | + if (item.productQty && item.unitPrice) { | ||
| 704 | + item.itemAmount = parseFloat((item.productQty * item.unitPrice).toFixed(2)) | ||
| 705 | + } | ||
| 706 | + // 明细项目变化时,重新计算开票金额和税额 | ||
| 707 | + calculateTaxAmount() | ||
| 708 | +} | ||
| 709 | + | ||
| 710 | +const calculateTaxAmount = () => { | ||
| 711 | + // 计算开票金额(基于明细项目的金额总和) | ||
| 712 | + const totalAmount = formData.invoiceItems.reduce((sum, item) => { | ||
| 713 | + return sum + (item.itemAmount || 0) | ||
| 714 | + }, 0) | ||
| 715 | + | ||
| 716 | + console.log('计算开票金额:', { | ||
| 717 | + invoiceItems: formData.invoiceItems, | ||
| 718 | + totalAmount: totalAmount, | ||
| 719 | + taxRate: formData.taxRate | ||
| 720 | + }) | ||
| 721 | + | ||
| 722 | + // 更新开票金额(保留两位小数) | ||
| 723 | + formData.invoiceAmount = parseFloat(totalAmount.toFixed(2)) | ||
| 724 | + | ||
| 725 | + // 计算税额(基于主表税率) | ||
| 726 | + if (totalAmount && formData.taxRate) { | ||
| 727 | + formData.taxAmount = parseFloat((totalAmount * formData.taxRate / 100).toFixed(2)) | ||
| 728 | + | ||
| 729 | + // 更新明细项目的税额(基于主表税率) | ||
| 730 | + formData.invoiceItems.forEach(item => { | ||
| 731 | + if (item.itemAmount && formData.taxRate) { | ||
| 732 | + item.taxAmount = parseFloat((item.itemAmount * formData.taxRate / 100).toFixed(2)) | ||
| 733 | + } else { | ||
| 734 | + item.taxAmount = 0 | ||
| 735 | + } | ||
| 736 | + }) | ||
| 737 | + } else { | ||
| 738 | + formData.taxAmount = 0 | ||
| 739 | + // 清空明细项目的税额 | ||
| 740 | + formData.invoiceItems.forEach(item => { | ||
| 741 | + item.taxAmount = 0 | ||
| 742 | + }) | ||
| 743 | + } | ||
| 744 | + | ||
| 745 | + console.log('计算结果:', { | ||
| 746 | + invoiceAmount: formData.invoiceAmount, | ||
| 747 | + taxAmount: formData.taxAmount | ||
| 574 | }) | 748 | }) |
| 575 | - showDialog.value = true | 749 | +} |
| 750 | + | ||
| 751 | +const handleEdit = async (order: InvoiceInfo) => { | ||
| 752 | + try { | ||
| 753 | + // 调用详情API获取最新的发票信息 | ||
| 754 | + const response = await invoiceApi.getInvoiceDetail(order.invoiceId) as any | ||
| 755 | + console.log('发票编辑详情API响应:', response) | ||
| 756 | + | ||
| 757 | + if (response && response.invoiceId) { | ||
| 758 | + isEdit.value = true | ||
| 759 | + Object.assign(formData, { | ||
| 760 | + invoiceId: response.invoiceId, | ||
| 761 | + orderNo: response.orderNo, | ||
| 762 | + invoiceNo: response.invoiceNo, | ||
| 763 | + deliveryNo: response.deliveryNo || '', | ||
| 764 | + dealerCode: response.dealerCode, | ||
| 765 | + dealerName: response.dealerName, | ||
| 766 | + invoiceDate: response.invoiceDate, | ||
| 767 | + invoiceAmount: response.totalAmount, | ||
| 768 | + taxRate: response.taxRate || 0, | ||
| 769 | + taxAmount: (response.totalAmount || 0) * (response.taxRate || 0) / 100, | ||
| 770 | + remark: '', | ||
| 771 | + invoiceItems: (response.invoiceItems || []).map((item: any) => ({ | ||
| 772 | + invoiceItemId: item.invoiceItemId, | ||
| 773 | + invoiceId: item.invoiceId, | ||
| 774 | + invoiceNo: item.invoiceNo, | ||
| 775 | + orderNo: item.orderNo, | ||
| 776 | + productCode: item.productCode, | ||
| 777 | + productName: item.productName, | ||
| 778 | + productQty: item.invoiceQty, // 映射字段名 | ||
| 779 | + unitPrice: item.unitPriceNoTax, // 映射字段名 | ||
| 780 | + itemAmount: item.amountNoTax, // 映射字段名 | ||
| 781 | + taxAmount: item.taxAmount | ||
| 782 | + })) | ||
| 783 | + }) | ||
| 784 | + // 确保税额计算正确 | ||
| 785 | + calculateTaxAmount() | ||
| 786 | + showDialog.value = true | ||
| 787 | + } else { | ||
| 788 | + showMessage('获取发票详情失败', 'error') | ||
| 789 | + } | ||
| 790 | + } catch (error) { | ||
| 791 | + console.error('获取发票详情失败:', error) | ||
| 792 | + showMessage('获取发票详情失败, 请重试', 'error') | ||
| 793 | + } | ||
| 794 | +} | ||
| 795 | + | ||
| 796 | +const handleDelete = async (order: InvoiceInfo) => { | ||
| 797 | + if (confirm(`确定要删除发票"${order.invoiceNo}"吗?`)) { | ||
| 798 | + try { | ||
| 799 | + await invoiceApi.deleteInvoice(order.invoiceId) | ||
| 800 | + showMessage('删除发票成功', 'success') | ||
| 801 | + fetchOrders() // 刷新列表 | ||
| 802 | + } catch (error) { | ||
| 803 | + console.error('删除发票失败:', error) | ||
| 804 | + showMessage('删除发票失败, 请重试', 'error') | ||
| 805 | + } | ||
| 806 | + } | ||
| 576 | } | 807 | } |
| 577 | 808 | ||
| 578 | const handleView = async (order: InvoiceInfo) => { | 809 | const handleView = async (order: InvoiceInfo) => { |
| ... | @@ -606,8 +837,85 @@ const handlePrintInvoice = (invoice: InvoiceInfo) => { | ... | @@ -606,8 +837,85 @@ const handlePrintInvoice = (invoice: InvoiceInfo) => { |
| 606 | 837 | ||
| 607 | const handleSubmit = async () => { | 838 | const handleSubmit = async () => { |
| 608 | try { | 839 | try { |
| 609 | - showMessage('发票保存功能开发中...', 'warning') | 840 | + // 验证必填字段 |
| 841 | + if (!formData.orderNo || !formData.invoiceNo || !formData.dealerCode || !formData.dealerName || !formData.invoiceDate || !formData.invoiceAmount) { | ||
| 842 | + showMessage('请填写所有必填字段', 'error') | ||
| 843 | + return | ||
| 844 | + } | ||
| 845 | + | ||
| 846 | + // 验证明细 | ||
| 847 | + if (!formData.invoiceItems || formData.invoiceItems.length === 0) { | ||
| 848 | + showMessage('请至少添加一个发票明细', 'error') | ||
| 849 | + return | ||
| 850 | + } | ||
| 851 | + | ||
| 852 | + // 验证明细字段 | ||
| 853 | + for (let i = 0; i < formData.invoiceItems.length; i++) { | ||
| 854 | + const item = formData.invoiceItems[i] | ||
| 855 | + if (!item.productCode || !item.productName || !item.productQty || !item.unitPrice) { | ||
| 856 | + showMessage(`请填写第${i + 1}个明细的所有必填字段`, 'error') | ||
| 857 | + return | ||
| 858 | + } | ||
| 859 | + } | ||
| 860 | + | ||
| 861 | + if (isEdit.value) { | ||
| 862 | + // 编辑发票 | ||
| 863 | + const updateData = { | ||
| 864 | + invoiceId: formData.invoiceId, | ||
| 865 | + invoiceNo: formData.invoiceNo, | ||
| 866 | + orderNo: formData.orderNo, | ||
| 867 | + deliveryNo: formData.deliveryNo, | ||
| 868 | + dealerCode: formData.dealerCode, | ||
| 869 | + dealerName: formData.dealerName, | ||
| 870 | + totalAmount: formData.invoiceAmount, | ||
| 871 | + invoiceDate: formData.invoiceDate, | ||
| 872 | + invoiceStatus: 1, | ||
| 873 | + taxRate: formData.taxRate, | ||
| 874 | + dataSource: 'ERP系统', | ||
| 875 | + invoiceItems: formData.invoiceItems.map((item: any) => ({ | ||
| 876 | + itemId: item.invoiceItemId, | ||
| 877 | + productCode: item.productCode, | ||
| 878 | + productName: item.productName, | ||
| 879 | + invoiceQty: item.productQty, // 映射字段名 | ||
| 880 | + unitPriceNoTax: item.unitPrice, // 映射字段名 | ||
| 881 | + amountNoTax: item.itemAmount, // 映射字段名 | ||
| 882 | + taxRate: item.taxRate, | ||
| 883 | + taxAmount: item.taxAmount | ||
| 884 | + })) | ||
| 885 | + } | ||
| 886 | + | ||
| 887 | + await invoiceApi.updateInvoice(updateData) | ||
| 888 | + showMessage('发票更新成功', 'success') | ||
| 889 | + } else { | ||
| 890 | + // 新增发票 | ||
| 891 | + const addData = { | ||
| 892 | + invoiceNo: formData.invoiceNo, | ||
| 893 | + orderNo: formData.orderNo, | ||
| 894 | + deliveryNo: formData.deliveryNo, | ||
| 895 | + dealerCode: formData.dealerCode, | ||
| 896 | + dealerName: formData.dealerName, | ||
| 897 | + totalAmount: formData.invoiceAmount, | ||
| 898 | + invoiceDate: formData.invoiceDate, | ||
| 899 | + invoiceStatus: 1, | ||
| 900 | + taxRate: formData.taxRate, | ||
| 901 | + dataSource: 'ERP系统', | ||
| 902 | + invoiceItems: formData.invoiceItems.map((item: any) => ({ | ||
| 903 | + productCode: item.productCode, | ||
| 904 | + productName: item.productName, | ||
| 905 | + invoiceQty: item.productQty, // 映射字段名 | ||
| 906 | + unitPriceNoTax: item.unitPrice, // 映射字段名 | ||
| 907 | + amountNoTax: item.itemAmount, // 映射字段名 | ||
| 908 | + taxRate: item.taxRate, | ||
| 909 | + taxAmount: item.taxAmount | ||
| 910 | + })) | ||
| 911 | + } | ||
| 912 | + | ||
| 913 | + await invoiceApi.addInvoice(addData) | ||
| 914 | + showMessage('发票新增成功', 'success') | ||
| 915 | + } | ||
| 916 | + | ||
| 610 | closeDialog() | 917 | closeDialog() |
| 918 | + fetchOrders() // 刷新列表 | ||
| 611 | } catch (error) { | 919 | } catch (error) { |
| 612 | console.error('保存发票失败:', error) | 920 | console.error('保存发票失败:', error) |
| 613 | showMessage('保存发票失败, 请重试', 'error') | 921 | showMessage('保存发票失败, 请重试', 'error') |
| ... | @@ -883,6 +1191,19 @@ onMounted(() => { | ... | @@ -883,6 +1191,19 @@ onMounted(() => { |
| 883 | color: #333; | 1191 | color: #333; |
| 884 | } | 1192 | } |
| 885 | 1193 | ||
| 1194 | +.delete-btn { | ||
| 1195 | + background: #dc3545; | ||
| 1196 | + color: white; | ||
| 1197 | +} | ||
| 1198 | + | ||
| 1199 | +/* 只读字段样式 */ | ||
| 1200 | +.form-input[readonly] { | ||
| 1201 | + background-color: #f8f9fa; | ||
| 1202 | + color: #6c757d; | ||
| 1203 | + cursor: not-allowed; | ||
| 1204 | + border-color: #dee2e6; | ||
| 1205 | +} | ||
| 1206 | + | ||
| 886 | .status-btn { | 1207 | .status-btn { |
| 887 | background: #28a745; | 1208 | background: #28a745; |
| 888 | color: white; | 1209 | color: white; |
| ... | @@ -1310,4 +1631,101 @@ onMounted(() => { | ... | @@ -1310,4 +1631,101 @@ onMounted(() => { |
| 1310 | .detail-actions .close-btn:hover { | 1631 | .detail-actions .close-btn:hover { |
| 1311 | background: #5a6268; | 1632 | background: #5a6268; |
| 1312 | } | 1633 | } |
| 1634 | + | ||
| 1635 | +/* 发票明细样式 */ | ||
| 1636 | +.form-section { | ||
| 1637 | + margin: 20px 0; | ||
| 1638 | + border: 1px solid #e0e0e0; | ||
| 1639 | + border-radius: 6px; | ||
| 1640 | + padding: 15px; | ||
| 1641 | + background: #f9f9f9; | ||
| 1642 | +} | ||
| 1643 | + | ||
| 1644 | +.section-header { | ||
| 1645 | + display: flex; | ||
| 1646 | + justify-content: space-between; | ||
| 1647 | + align-items: center; | ||
| 1648 | + margin-bottom: 15px; | ||
| 1649 | + padding-bottom: 10px; | ||
| 1650 | + border-bottom: 1px solid #ddd; | ||
| 1651 | +} | ||
| 1652 | + | ||
| 1653 | +.section-header h4 { | ||
| 1654 | + margin: 0; | ||
| 1655 | + color: #333; | ||
| 1656 | + font-size: 16px; | ||
| 1657 | + font-weight: 600; | ||
| 1658 | +} | ||
| 1659 | + | ||
| 1660 | +.add-item-btn { | ||
| 1661 | + background: #28a745; | ||
| 1662 | + color: white; | ||
| 1663 | + border: none; | ||
| 1664 | + padding: 6px 12px; | ||
| 1665 | + border-radius: 4px; | ||
| 1666 | + cursor: pointer; | ||
| 1667 | + font-size: 12px; | ||
| 1668 | + transition: background 0.2s; | ||
| 1669 | +} | ||
| 1670 | + | ||
| 1671 | +.add-item-btn:hover { | ||
| 1672 | + background: #218838; | ||
| 1673 | +} | ||
| 1674 | + | ||
| 1675 | +.invoice-items-container { | ||
| 1676 | + max-height: 300px; | ||
| 1677 | + overflow-y: auto; | ||
| 1678 | +} | ||
| 1679 | + | ||
| 1680 | +.invoice-item { | ||
| 1681 | + background: white; | ||
| 1682 | + border: 1px solid #ddd; | ||
| 1683 | + border-radius: 4px; | ||
| 1684 | + padding: 10px; | ||
| 1685 | + margin-bottom: 10px; | ||
| 1686 | +} | ||
| 1687 | + | ||
| 1688 | +.item-row-single { | ||
| 1689 | + display: flex; | ||
| 1690 | + gap: 8px; | ||
| 1691 | + align-items: center; | ||
| 1692 | + flex-wrap: nowrap; | ||
| 1693 | +} | ||
| 1694 | + | ||
| 1695 | +.item-row-single .form-item { | ||
| 1696 | + flex: 0 0 auto; | ||
| 1697 | + margin-bottom: 0; | ||
| 1698 | + min-width: 0; | ||
| 1699 | +} | ||
| 1700 | + | ||
| 1701 | +.item-row-single .form-item label { | ||
| 1702 | + font-size: 11px; | ||
| 1703 | + color: #666; | ||
| 1704 | + margin-bottom: 2px; | ||
| 1705 | + display: block; | ||
| 1706 | +} | ||
| 1707 | + | ||
| 1708 | +.item-row-single .form-input { | ||
| 1709 | + width: 100%; | ||
| 1710 | + padding: 4px 6px; | ||
| 1711 | + font-size: 11px; | ||
| 1712 | + border: 1px solid #ddd; | ||
| 1713 | + border-radius: 3px; | ||
| 1714 | +} | ||
| 1715 | + | ||
| 1716 | +.remove-item-btn { | ||
| 1717 | + background: #dc3545; | ||
| 1718 | + color: white; | ||
| 1719 | + border: none; | ||
| 1720 | + padding: 4px 8px; | ||
| 1721 | + border-radius: 3px; | ||
| 1722 | + cursor: pointer; | ||
| 1723 | + font-size: 11px; | ||
| 1724 | + height: 28px; | ||
| 1725 | + transition: background 0.2s; | ||
| 1726 | +} | ||
| 1727 | + | ||
| 1728 | +.remove-item-btn:hover { | ||
| 1729 | + background: #c82333; | ||
| 1730 | +} | ||
| 1313 | </style> | 1731 | </style> | ... | ... |
-
Please register or login to post a comment