Merge remote-tracking branch 'origin/master'

This commit is contained in:
sunhaoyuan 2025-11-24 17:35:07 +08:00
commit 7a6baac3e7
5 changed files with 432 additions and 111 deletions

View File

@ -14,8 +14,7 @@
<el-row :gutter="10" class="mb8"> <el-row :gutter="10" class="mb8">
<el-col :span="1.5"> <el-col :span="1.5">
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport" <el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport"
:loading="exportLoading" :loading="exportLoading">导出
>导出
</el-button> </el-button>
</el-col> </el-col>
<right-toolbar :showSearch.sync="showSearch"></right-toolbar> <right-toolbar :showSearch.sync="showSearch"></right-toolbar>
@ -54,9 +53,7 @@
</el-table> </el-table>
<!-- 分页组件 --> <!-- 分页组件 -->
<pagination style="margin-bottom: 2rem" v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" <pagination style="margin-bottom: 2rem" v-show="total > 0" :total="total" :page.sync="queryParams.pageNo"
:limit.sync="queryParams.pageSize" :limit.sync="queryParams.pageSize" @pagination="getList" />
@pagination="getList"
/>
<el-dialog title="单据处理" :visible.sync="dialogVisible" width="80%" v-dialogDrag append-to-body> <el-dialog title="单据处理" :visible.sync="dialogVisible" width="80%" v-dialogDrag append-to-body>
<!-- 车辆信息显示区域 --> <!-- 车辆信息显示区域 -->
@ -87,27 +84,24 @@
<el-row :gutter="10" class="mb8"> <el-row :gutter="10" class="mb8">
<el-col :span="1.5"> <el-col :span="1.5">
<el-button type="primary" v-if="type" plain icon="el-icon-plus" size="mini" @click="handleAddWares" <el-button type="primary" v-if="type" plain icon="el-icon-plus" size="mini"
>添加配件</el-button> @click="handleAddWares">添加配件</el-button>
</el-col> </el-col>
</el-row> </el-row>
<el-table <el-table @cell-mouse-enter="handleCellEnter" @cell-mouse-leave="handleCellLeave" @cell-click="handleCellClick"
@cell-mouse-enter="handleCellEnter" el-table v-loading="dialogLoading" :data="items" :stripe="true" :show-overflow-tooltip="true"
@cell-mouse-leave="handleCellLeave" :row-class-name="getRowClass" @selection-change="handleSelect" :key="tableKey" ref="tableRef">
@cell-click="handleCellClick"
el-table v-loading="dialogLoading"
:data="items" :stripe="true"
:show-overflow-tooltip="true"
:row-class-name="getRowClass"
@selection-change="handleSelect"
:key="tableKey"
ref="tableRef"
>
<el-table-column type="selection" width="80" align="center" /> <el-table-column type="selection" width="80" align="center" />
<el-table-column label="名称" align="center" prop="waresName" :show-overflow-tooltip="true" /> <el-table-column label="名称" align="center" prop="waresName" :show-overflow-tooltip="true" />
<el-table-column label="配件添加人" align="center" prop="addUserName" width="180" /> <el-table-column label="配件添加人" align="center" prop="addUserName" width="180" />
<el-table-column label="售价" align="center" prop="salePrice" width="180"/> <el-table-column label="售价" align="center" prop="salePrice" width="180">
<div class="item" slot-scope="scope">
<el-input @blur="save(scope.row)" class="item__input" v-model="scope.row.salePrice" placeholder="请输入售价">
</el-input>
<span class="item__txt">{{ scope.row.salePrice }}</span>
</div>
</el-table-column>
<el-table-column label="领料数量" v-if="type" align="center" prop="waresCount" width="180"> <el-table-column label="领料数量" v-if="type" align="center" prop="waresCount" width="180">
<div class="item" slot-scope="scope"> <div class="item" slot-scope="scope">
<el-input @blur="save(scope.row)" class="item__input" v-model="scope.row.waresCount" <el-input @blur="save(scope.row)" class="item__input" v-model="scope.row.waresCount"
@ -171,16 +165,9 @@
</el-descriptions> </el-descriptions>
<el-collapse> <el-collapse>
<el-collapse-item v-for="[key, value] in partList" :title="key + `(${value.length})`"> <el-collapse-item v-for="[key, value] in partList" :title="key + `(${value.length})`">
<el-table <el-table :data="value" :stripe="true" :show-overflow-tooltip="true" show-summary
:data="value" :summary-method="getSummaries" @cell-mouse-enter="handleCellEnter" @cell-mouse-leave="handleCellLeave"
:stripe="true" @cell-click="handleCellClick">
:show-overflow-tooltip="true"
show-summary
:summary-method="getSummaries"
@cell-mouse-enter="handleCellEnter"
@cell-mouse-leave="handleCellLeave"
@cell-click="handleCellClick"
>
<el-table-column label="序号" align="center"> <el-table-column label="序号" align="center">
<template scope="scope"> <template scope="scope">
<span>{{ scope.$index + 1 }}</span> <span>{{ scope.$index + 1 }}</span>
@ -198,17 +185,11 @@
<div class="item" slot-scope="scope"> <div class="item" slot-scope="scope">
<el-select class="item__input" clearable ref="selectTree" v-model="scope.row.wares.type" <el-select class="item__input" clearable ref="selectTree" v-model="scope.row.wares.type"
@change="save(scope.row)"> @change="save(scope.row)">
<el-option v-for="server in optionData(serverList)" <el-option v-for="server in optionData(serverList)" :key="server.value" :label="server.label"
:key="server.value"
:label="server.label"
:value="server.value" style="display: none" /> :value="server.value" style="display: none" />
<el-tree class="item__input" ref="selectedTree" <el-tree class="item__input" ref="selectedTree" :data="serverList" :props="treeProps"
:data="serverList" highlight-current @node-click="handleNodeClick($event, scope.row)"
:props="treeProps" :expand-on-click-node="expandOnClickNode" default-expand-all />
highlight-current
@node-click="handleNodeClick($event, scope.row)"
:expand-on-click-node="expandOnClickNode"
default-expand-all/>
</el-select> </el-select>
<span class="item__txt">{{ getTypeById(scope.row.wares.type) }}</span> <span class="item__txt">{{ getTypeById(scope.row.wares.type) }}</span>
</div> </div>
@ -232,8 +213,7 @@
<div class="item" slot-scope="scope"> <div class="item" slot-scope="scope">
<el-select class="item__input" v-model="scope.row.wares.unit" @blur="save(scope.row)"> <el-select class="item__input" v-model="scope.row.wares.unit" @blur="save(scope.row)">
<el-option v-for="dict in getDictDatasToType(DICT_TYPE.REPAIR_UNIT)" :key="dict.value" <el-option v-for="dict in getDictDatasToType(DICT_TYPE.REPAIR_UNIT)" :key="dict.value"
:label="dict.label" :label="dict.label" :value="dict.value" />
:value="dict.value"/>
</el-select> </el-select>
<span class="item__txt"> <span class="item__txt">
<dict-tag :type="DICT_TYPE.REPAIR_UNIT" v-model="scope.row.wares.unit" /> <dict-tag :type="DICT_TYPE.REPAIR_UNIT" v-model="scope.row.wares.unit" />
@ -271,8 +251,7 @@
</el-table-column> </el-table-column>
<el-table-column label="操作" fixed="right" align="center" width="150"> <el-table-column label="操作" fixed="right" align="center" width="150">
<template v-slot="scope"> <template v-slot="scope">
<el-button size="mini" type="text" icon="el-icon-delete" @click="deleteItem(scope.$index)" <el-button size="mini" type="text" icon="el-icon-delete" @click="deleteItem(scope.$index)">删除
>删除
</el-button> </el-button>
</template> </template>
</el-table-column> </el-table-column>
@ -357,7 +336,7 @@ export default {
// cell // cell
clickCellMap: {}, clickCellMap: {},
// //
editProp: ['wares.warehouse', 'wares.type', 'waresCount', 'wares.purPrice', 'wares.price', 'remark', 'wares.code', 'waresCount', 'wares.model', 'wares.unit'], editProp: ['wares.warehouse', 'wares.type', 'waresCount', 'wares.purPrice', 'wares.price', 'remark', 'wares.code', 'waresCount', 'wares.model', 'wares.unit','salePrice'],
remark: null, remark: null,
tableKey: 0, tableKey: 0,
query: null, query: null,
@ -504,6 +483,7 @@ export default {
soiType: this.type ? '02' : "04", soiType: this.type ? '02' : "04",
goodsId: item.waresId, goodsId: item.waresId,
goodsCount: item.waresCount, goodsCount: item.waresCount,
goodsPrice: item.salePrice
} }
})] })]
this.formData.ids = this.allSelectRows.map(item => item.id) this.formData.ids = this.allSelectRows.map(item => item.id)
@ -846,13 +826,15 @@ export default {
<style scoped lang="scss"> <style scoped lang="scss">
::v-deep .el-table .stock td { ::v-deep .el-table .stock td {
color: #ff0000 !important; /* 红色背景 */ color: #ff0000 !important;
/* 红色背景 */
} }
.item { .item {
.item__input { .item__input {
display: none; display: none;
width: 100px; width: 100px;
/* 调整elementUI中样式 如果不需要调整请忽略 */ /* 调整elementUI中样式 如果不需要调整请忽略 */
.el-input__inner { .el-input__inner {
height: 24px !important; height: 24px !important;

View File

@ -0,0 +1,314 @@
<template>
<el-dialog
title="选择A单"
:visible.sync="dialogVisible"
width="900px"
append-to-body
class="parent-ticket-dialog"
:close-on-click-modal="false"
>
<div class="dialog-content">
<!-- 搜索区域 -->
<div class="search-area">
<el-input
v-model="searchParams.ticketNo"
placeholder="请输入A单关键词"
clearable
style="width: 300px"
@clear="handleSearch"
@keyup.enter.native="handleSearch"
>
<el-button slot="append" icon="el-icon-search" @click="handleSearch" />
</el-input>
<el-button type="primary" @click="handleSearch" style="margin-left: 10px">
搜索
</el-button>
<el-button @click="resetSearch">重置</el-button>
</div>
<!-- 表格区域 -->
<div class="table-area">
<el-table
ref="ticketTable"
v-loading="loading"
:data="ticketList"
:stripe="true"
:highlight-current-row="true"
@row-click="handleRowClick"
style="width: 100%"
height="400"
>
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column label="A单编号" prop="ticketNo" width="180" align="center">
<template slot-scope="{ row }">
<span class="ticket-no">{{ row.ticketNo }}</span>
</template>
</el-table-column>
<el-table-column label="客户姓名" prop="userName" width="120" align="center" />
<el-table-column label="车牌号" prop="carNo" width="120" align="center" />
<el-table-column label="创建时间" width="160" align="center">
<template slot-scope="{ row }">
{{ formatTime(row.ticketTime) }}
</template>
</el-table-column>
<el-table-column label="状态" width="100" align="center">
<template slot-scope="{ row }">
<el-tag
:type="getStatusType(row.ticketsStatus)"
size="small"
>
{{ getStatusText(row.ticketsStatus) }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="100" align="center">
<template slot-scope="{ row }">
<el-button
type="text"
size="small"
@click="handleSelect(row)"
>
选择
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<div class="pagination-area">
<pagination
v-show="total > 0"
:total="total"
:page.sync="searchParams.pageNo"
:limit.sync="searchParams.pageSize"
@pagination="getTicketList"
/>
</div>
</div>
<!-- 选中信息显示 -->
<div v-if="selectedTicket" class="selected-info">
<el-alert
title="已选中A单"
type="success"
:closable="false"
show-icon
>
<div class="selected-details">
<span><strong>单号</strong>{{ selectedTicket.ticketNo }}</span>
<span><strong>客户</strong>{{ selectedTicket.userName }}</span>
<span><strong>车牌</strong>{{ selectedTicket.carNo }}</span>
</div>
</el-alert>
</div>
</div>
<div slot="footer" class="dialog-footer">
<el-button @click="handleCancel">取消</el-button>
<el-button
type="primary"
:disabled="!selectedTicket"
@click="handleConfirm"
>
确定选择
</el-button>
</div>
</el-dialog>
</template>
<script>
import { getTicketsPage } from "@/api/repair/tickets/Tickets";
import Pagination from "@/components/Pagination";
export default {
name: "ParentTicketDialog",
components: {
Pagination
},
props: {
visible: {
type: Boolean,
default: false
}
},
data() {
return {
dialogVisible: false,
loading: false,
ticketList: [],
total: 0,
selectedTicket: null,
searchParams: {
pageNo: 1,
pageSize: 10,
ticketNo: null,
ticketType: "01", // A
}
};
},
watch: {
visible: {
immediate: true,
handler(val) {
this.dialogVisible = val;
if (val) {
this.resetSelection();
this.getTicketList();
}
}
},
dialogVisible(val) {
this.$emit("update:visible", val);
}
},
methods: {
// A
async getTicketList() {
this.loading = true;
try {
const res = await getTicketsPage(this.searchParams);
this.ticketList = res.data.records || [];
this.total = res.data.total || 0;
} catch (error) {
console.error("获取A单列表失败:", error);
this.$modal.msgError("获取A单列表失败");
} finally {
this.loading = false;
}
},
//
handleSearch() {
this.searchParams.pageNo = 1;
this.getTicketList();
},
//
resetSearch() {
this.searchParams = {
pageNo: 1,
pageSize: 10,
ticketNo: null,
ticketType: "01",
ticketsStatus: "01"
};
this.getTicketList();
},
//
handleRowClick(row) {
this.selectedTicket = row;
},
//
handleSelect(row) {
this.selectedTicket = row;
},
//
formatTime(time) {
if (!time) return "-";
return this.parseTime(time, "{y}-{m}-{d} {h}:{m}");
},
//
getStatusType(status) {
const statusMap = {
"01": "success", //
"02": "warning", //
"03": "info", //
"04": "danger" //
};
return statusMap[status] || "info";
},
//
getStatusText(status) {
const statusMap = {
"01": "未结算",
"02": "已结算",
"03": "已挂单",
"04": "已取消"
};
return statusMap[status] || "未知";
},
//
resetSelection() {
this.selectedTicket = null;
this.searchParams.pageNo = 1;
this.searchParams.ticketNo = null;
},
//
handleCancel() {
this.dialogVisible = false;
},
//
handleConfirm() {
if (this.selectedTicket) {
this.$emit("selected", this.selectedTicket);
this.dialogVisible = false;
}
}
}
};
</script>
<style scoped lang="scss">
.parent-ticket-dialog {
.dialog-content {
padding: 0 20px;
}
.search-area {
margin-bottom: 20px;
display: flex;
align-items: center;
}
.table-area {
margin-bottom: 20px;
.ticket-no {
font-weight: bold;
color: #409EFF;
}
}
.selected-info {
margin-top: 20px;
.selected-details {
display: flex;
justify-content: space-between;
margin-top: 8px;
span {
margin-right: 20px;
}
}
}
.pagination-area {
margin-top: 15px;
text-align: right;
}
}
::v-deep .el-dialog__body {
padding: 20px;
}
::v-deep .el-table {
.el-table__body tr:hover > td {
background-color: #f5f7fa;
cursor: pointer;
}
.current-row {
background-color: #ecf5ff !important;
}
}
</style>

View File

@ -32,6 +32,21 @@
</el-option> </el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="工单类型" prop="ticketType">
<el-select
v-model="queryParams.ticketType"
placeholder="请选择"
clearable
>
<el-option
v-for="item in this.getDictDatas('repair_tickets_type')"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="工种" prop="workType"> <el-form-item label="工种" prop="workType">
<el-select <el-select
v-model="queryParams.workType" v-model="queryParams.workType"
@ -179,6 +194,14 @@
/> />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="工单类型" align="center">
<template slot-scope="scope">
<dict-tag
:type="DICT_TYPE.REPAIR_TICKETS_TYPE"
v-model="scope.row.ticketType"
/>
</template>
</el-table-column>
<el-table-column <el-table-column
label="客户名称" label="客户名称"
align="center" align="center"
@ -699,7 +722,7 @@ export default {
pageSize: 10, pageSize: 10,
ticketNo: null, ticketNo: null,
searchTimeArray: [], searchTimeArray: [],
ticketsStatus: this.isType, // ticketsStatus: this.isType,
selectType: 'all', selectType: 'all',
...this.externalQueryParams ...this.externalQueryParams
}, },

View File

@ -854,8 +854,8 @@ export default {
if (type == 'js') { if (type == 'js') {
this.settlementFormData = { this.settlementFormData = {
ticketId: row.id, ticketId: row.id,
money: row.totalPrice, money: row.totalPrice + row.btickets?.reduce((sum, item) => sum + item.totalPrice, 0),
actualMoney: row.totalPrice, actualMoney: row.totalPrice + row.btickets.reduce((sum, item) => sum + item.totalPrice, 0),
discountType: this.defaultDiscountType, discountType: this.defaultDiscountType,
discount: 0 discount: 0
} }

View File

@ -25,7 +25,7 @@
车辆选择 车辆选择
</template> </template>
<CarChoose v-if="selectUser && selectUser.id" v-model="selectCar" :cus-name="selectUser.cusName" <CarChoose v-if="selectUser && selectUser.id" v-model="selectCar" :cus-name="selectUser.cusName"
:customer-info="selectUser" :in-list="carInData" /> :customer-info="selectUser" :in-list="carInData" :car-list="carList" />
<span v-else>请先选择客户</span> <span v-else>请先选择客户</span>
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item> <el-descriptions-item>
@ -471,6 +471,7 @@ export default {
finaCouponList: [], finaCouponList: [],
userInData: null, userInData: null,
carInData: null, carInData: null,
carList: null,
ticketChooseDialogVisible: false, // A ticketChooseDialogVisible: false, // A
busiAndCusList: [], // busiAndCusList: [], //
channelList: [], // channelList: [], //
@ -813,6 +814,7 @@ export default {
...cusRes.data, ...cusRes.data,
isRes: true isRes: true
} }
this.carList = cusRes.carLi
// //
const carRes = await getByLicenseNumber(car) const carRes = await getByLicenseNumber(car)
this.carInData = { this.carInData = {