drawer.vue 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. <template>
  2. <ele-modal
  3. title="售后工单查询"
  4. custom-class="ele-dialog-form long-dialog-form"
  5. :visible.sync="visible"
  6. :before-close="handleClose"
  7. :close-on-click-modal="false"
  8. :close-on-press-escape="false"
  9. append-to-body
  10. width="70%"
  11. :maxable="true"
  12. :resizable="true"
  13. >
  14. <el-card shadow="never" v-loading="loading">
  15. <work-search
  16. class="seep-search"
  17. ref="workSearch"
  18. :levelList="levelList"
  19. @search="reload"
  20. ></work-search>
  21. <ele-pro-table
  22. ref="table"
  23. :columns="columns"
  24. :datasource="datasource"
  25. row-key="id"
  26. height="calc(100vh - 500px)"
  27. class="dict-table"
  28. >
  29. <template v-slot:toolbar></template>
  30. <template v-slot:faultLevel="{ row }">
  31. {{ levelData[row.faultLevel] || '' }}
  32. </template>
  33. <template v-slot:selection="{ row }">
  34. <div class="radio-container">
  35. <el-radio
  36. v-model="selectedRowId"
  37. :label="row.id"
  38. @change="() => selectedRow = row"
  39. ><span></span></el-radio>
  40. </div>
  41. </template>
  42. </ele-pro-table>
  43. </el-card>
  44. <div class="btns" slot="footer">
  45. <el-button
  46. type="primary"
  47. size="small"
  48. :disabled="!selectedRow"
  49. @click="handleConfirm"
  50. >
  51. 确认
  52. </el-button>
  53. <el-button size="small" @click="handleClose">关闭</el-button>
  54. </div>
  55. </ele-modal>
  56. </template>
  57. <script>
  58. import workSearch from './work-search.vue';
  59. import { getSalesWorkOrder } from '@/api/salesServiceManagement/index';
  60. import { getByCode } from '@/api/system/dictionary-data';
  61. import dictMixins from '@/mixins/dictMixins';
  62. export default {
  63. mixins: [dictMixins],
  64. components: {
  65. workSearch
  66. },
  67. data() {
  68. return {
  69. visible: false,
  70. loading: false,
  71. levelData: {},
  72. levelList: [],
  73. selectedRowId: null,
  74. selectedRow: null, // 存储选中的完整行数据
  75. columns: [
  76. {
  77. columnKey: 'selection',
  78. label: '选择',
  79. slot: 'selection',
  80. align: 'center',
  81. showOverflowTooltip: true,
  82. fixed: 'left' // 固定选择列在左侧,避免滚动后看不到
  83. },
  84. {
  85. columnKey: 'index',
  86. label: '序号',
  87. type: 'index',
  88. width: 55,
  89. align: 'center',
  90. showOverflowTooltip: true,
  91. fixed: 'left'
  92. },
  93. {
  94. prop: 'code',
  95. label: '工单编号',
  96. align: 'center',
  97. showOverflowTooltip: true,
  98. minWidth: 150
  99. },
  100. {
  101. prop: 'planCode',
  102. label: '计划单号',
  103. align: 'center',
  104. showOverflowTooltip: true,
  105. minWidth: 110
  106. },
  107. {
  108. prop: 'planName',
  109. label: '计划名称',
  110. align: 'center',
  111. showOverflowTooltip: true,
  112. minWidth: 110
  113. },
  114. {
  115. prop: 'executeUserName',
  116. label: '报工人',
  117. align: 'center',
  118. showOverflowTooltip: true,
  119. minWidth: 110
  120. },
  121. {
  122. prop: 'accepterUserName',
  123. label: '验收人',
  124. align: 'center',
  125. showOverflowTooltip: true,
  126. minWidth: 110
  127. },
  128. {
  129. slot: 'faultLevel',
  130. prop: 'faultLevel',
  131. label: '故障等级',
  132. align: 'center',
  133. showOverflowTooltip: true,
  134. minWidth: 110
  135. },
  136. {
  137. prop: 'contactName',
  138. label: '客户名称',
  139. align: 'center',
  140. showOverflowTooltip: true,
  141. minWidth: 110
  142. },
  143. {
  144. prop: 'categoryName',
  145. label: '设备名称',
  146. align: 'center',
  147. minWidth: 110,
  148. showOverflowTooltip: true,
  149. formatter: (row) => {
  150. if (!row.deviceDetails) return '';
  151. return row.deviceDetails.map((el) => el.categoryName).join(',');
  152. }
  153. },
  154. {
  155. prop: 'accepterTime',
  156. label: '验收时间',
  157. align: 'center',
  158. showOverflowTooltip: true,
  159. minWidth: 110
  160. },
  161. {
  162. prop: 'totalCost',
  163. label: '费用( 元 )',
  164. align: 'center',
  165. showOverflowTooltip: true,
  166. minWidth: 110
  167. },
  168. {
  169. columnKey: 'inFactDuration',
  170. label: '工时',
  171. align: 'center',
  172. resizable: false,
  173. showOverflowTooltip: true,
  174. minWidth: 120,
  175. formatter: (row) => {
  176. if (row.inFactDuration || row.inFactDuration === 0) {
  177. return `${((row.inFactDuration - 0) / 60).toFixed(1)} 小时`;
  178. }
  179. return '';
  180. }
  181. },
  182. {
  183. prop: 'orderStatus',
  184. label: '状态',
  185. align: 'center',
  186. showOverflowTooltip: true,
  187. minWidth: 110,
  188. formatter: (row) => {
  189. const statusMap = {
  190. 0: '待执行',
  191. 1: '已接收',
  192. 2: '执行中',
  193. 3: '待验收',
  194. 4: '待评价',
  195. 5: '已完成',
  196. 6: '验收不通过'
  197. };
  198. return statusMap[row.orderStatus] || '';
  199. }
  200. }
  201. ]
  202. };
  203. },
  204. created() {
  205. this.getLevelCode('fault_level');
  206. },
  207. methods: {
  208. open() {
  209. this.visible = true;
  210. this.reload();
  211. },
  212. async getLevelCode(code) {
  213. const res = await getByCode(code);
  214. if (res?.code === '0') {
  215. this.levelData = res.data.reduce((obj, el) => {
  216. const key = Object.keys(el)[0];
  217. obj[key] = Object.values(el)[0];
  218. return obj;
  219. }, {});
  220. this.levelList = res.data.map((el) => ({
  221. label: Object.values(el)[0],
  222. value: Object.keys(el)[0]
  223. }));
  224. }
  225. },
  226. datasource({ page, limit, where }) {
  227. this.loading = true;
  228. const params = {
  229. pageNum: page,
  230. size: limit,
  231. ...where
  232. };
  233. return getSalesWorkOrder(params).finally(() => {
  234. this.loading = false;
  235. });
  236. },
  237. reload(where = {}) {
  238. this.$refs.table?.reload({
  239. pageNum: 1,
  240. where: where
  241. });
  242. },
  243. // 新增:确认按钮逻辑,向父组件传递选中数据
  244. handleConfirm() {
  245. if (this.selectedRow) {
  246. console.log(this.selectedRow)
  247. this.$emit('changeParent', this.selectedRow);
  248. this.handleClose(); // 确认后关闭弹窗
  249. }
  250. },
  251. handleClose() {
  252. this.visible = false;
  253. // 重置选中状态,避免下次打开残留选中
  254. this.selectedRowId = null;
  255. this.selectedRow = null;
  256. this.$refs.table?.reload({ pageNum: 1 });
  257. }
  258. }
  259. };
  260. </script>
  261. <style lang="scss" scoped>
  262. .seep-search {
  263. margin-bottom: 16px;
  264. ::v-deep .el-input__inner {
  265. padding: 0 5px 0 10px;
  266. }
  267. }
  268. .btns {
  269. text-align: center;
  270. padding: 10px 0;
  271. button:first-child { // 给确认按钮加右边距,和关闭按钮分隔
  272. margin-right: 8px;
  273. }
  274. }
  275. ::v-deep .ele-pro-table {
  276. margin-top: 8px;
  277. }
  278. ::v-deep .el-radio {
  279. vertical-align: middle;
  280. }
  281. .radio-container {
  282. text-align: center; /* 让单选框居中 */
  283. line-height: 1; /* 消除行高导致的多余空间 */
  284. }
  285. ::v-deep .radio-container .el-radio {
  286. display: inline-block; /* 确保单选框独占空间 */
  287. }
  288. </style>