index.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. <template>
  2. <div class="p-2">
  3. <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
  4. <div v-show="showSearch" class="mb-[10px]">
  5. <el-card shadow="hover">
  6. <el-form ref="queryFormRef" :model="queryParams" :inline="true">
  7. <el-form-item label="客户编号" prop="customerNo">
  8. <el-input v-model="queryParams.customerNo" placeholder="请输入客户编号" clearable @keyup.enter="handleQuery" />
  9. </el-form-item>
  10. <el-form-item label="客户名称" prop="customerNo">
  11. <el-input v-model="queryParams.customerNo" placeholder="请输入客户名称" clearable @keyup.enter="handleQuery" />
  12. </el-form-item>
  13. <el-form-item label="申请状态" prop="serviceTime">
  14. <el-select v-model="queryParams.serviceTime" placeholder="请选择服务时长" clearable>
  15. <el-option v-for="dict in service_time_type" :key="dict.value" :label="dict.label" :value="dict.value" />
  16. </el-select>
  17. </el-form-item>
  18. <el-form-item label="开始时间" prop="serviceStartTime">
  19. <el-date-picker
  20. clearable
  21. v-model="queryParams.serviceStartTime"
  22. type="date"
  23. value-format="YYYY-MM-DD"
  24. placeholder="请选择服务开始时间"
  25. />
  26. </el-form-item>
  27. <el-form-item label="开始时间" prop="serviceEndTime">
  28. <el-date-picker clearable v-model="queryParams.serviceEndTime" type="date" value-format="YYYY-MM-DD" placeholder="请选择服务开始时间" />
  29. </el-form-item>
  30. <el-form-item label="技术顾问" prop="technicalAdviser">
  31. <el-input v-model="queryParams.technicalAdviser" placeholder="请输入技术顾问姓名" clearable @keyup.enter="handleQuery" />
  32. </el-form-item>
  33. <el-form-item>
  34. <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
  35. <el-button icon="Refresh" @click="resetQuery">重置</el-button>
  36. </el-form-item>
  37. </el-form>
  38. </el-card>
  39. </div>
  40. </transition>
  41. <el-card shadow="never">
  42. <template #header>
  43. <el-row :gutter="10" class="mb8">
  44. <el-col :span="20"><span>维保客户信息列表</span> </el-col>
  45. <el-col :span="1.5">
  46. <el-button style="float: right" type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['customer:maintainInfo:add']"
  47. >新增维保</el-button
  48. >
  49. </el-col>
  50. <el-col :span="1.5">
  51. <el-button
  52. style="float: right"
  53. type="primary"
  54. plain
  55. icon="User"
  56. @click="handleAllotAdviser()"
  57. v-hasPermi="['customer:maintainInfo:allot']"
  58. >分配技术顾问</el-button
  59. >
  60. </el-col>
  61. </el-row>
  62. </template>
  63. <el-table v-loading="loading" border :data="maintainInfoList" @selection-change="handleSelectionChange">
  64. <el-table-column type="selection" width="55" align="center" />
  65. <el-table-column label="企业名称" align="center" prop="customerName" />
  66. <el-table-column label="维保类型" align="center" prop="maintainType">
  67. <template #default="scope">
  68. <dict-tag :options="maintenance_type" :value="scope.row.maintainType" />
  69. </template>
  70. </el-table-column>
  71. <el-table-column label="起始时间" align="center" prop="serviceStartTime" width="180">
  72. <template #default="scope">
  73. <span>{{ parseTime(scope.row.serviceStartTime, '{y}-{m}-{d}') }}</span>
  74. </template>
  75. </el-table-column>
  76. <el-table-column label="结束时间" align="center" prop="serviceEndTime" width="180">
  77. <template #default="scope">
  78. <span>{{ parseTime(scope.row.serviceEndTime, '{y}-{m}-{d}') }}</span>
  79. </template>
  80. </el-table-column>
  81. <el-table-column label="维保次数限制" align="center" prop="maintenLimit" />
  82. <el-table-column label="维保次数" align="center" prop="maintainCount" />
  83. <el-table-column label="主要技术顾问" align="center" prop="technicalAdviser" />
  84. <el-table-column label="主要维保项目" align="center" prop="serviceContent">
  85. <template #default="scope">
  86. <dict-tag :options="service_content" :value="scope.row.serviceContent ? scope.row.serviceContent.split(',') : []" />
  87. </template>
  88. </el-table-column>
  89. <el-table-column label="状态" align="center" prop="status">
  90. <template #default="scope">
  91. <dict-tag :options="sys_normal_disable" :value="scope.row.status" />
  92. </template>
  93. </el-table-column>
  94. <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
  95. <template #default="scope">
  96. <el-button link type="primary" icon="User" @click="handleAllotAdviser(scope.row)" v-hasPermi="['customer:maintainInfo:add']"
  97. >分配技术顾问</el-button
  98. >
  99. <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['customer:maintainInfo:edit']">编辑</el-button>
  100. </template>
  101. </el-table-column>
  102. </el-table>
  103. <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
  104. </el-card>
  105. <!-- 分配技术顾问对话框 -->
  106. <allot-technical-adviser-dialog v-model="allotDialogVisible" :edit-data="currentAdviserData" @confirm="handleAllotConfirm" />
  107. </div>
  108. </template>
  109. <script setup name="MaintainInfo" lang="ts">
  110. import {
  111. listMaintainInfo,
  112. getMaintainInfo,
  113. delMaintainInfo,
  114. addMaintainInfo,
  115. updateMaintainInfo,
  116. allotTechnicalAdviser
  117. } from '@/api/customer/maintainInfo';
  118. import { MaintainInfoVO, MaintainInfoQuery, MaintainInfoForm, AllotTechnicalAdviserForm } from '@/api/customer/maintainInfo/types';
  119. import AllotTechnicalAdviserDialog from './dialog/allotTechnicalAdviser.vue';
  120. const router = useRouter();
  121. const { proxy } = getCurrentInstance() as ComponentInternalInstance;
  122. const { service_content, service_time_type, maintenance_type, sys_normal_disable } = toRefs<any>(
  123. proxy?.useDict('service_content', 'service_time_type', 'maintenance_type', 'sys_normal_disable')
  124. );
  125. const maintainInfoList = ref<MaintainInfoVO[]>([]);
  126. const buttonLoading = ref(false);
  127. const loading = ref(true);
  128. const showSearch = ref(true);
  129. const ids = ref<Array<string | number>>([]);
  130. const single = ref(true);
  131. const multiple = ref(true);
  132. const total = ref(0);
  133. const queryFormRef = ref<ElFormInstance>();
  134. const maintainInfoFormRef = ref<ElFormInstance>();
  135. const dialog = reactive<DialogOption>({
  136. visible: false,
  137. title: ''
  138. });
  139. // 分配技术顾问对话框
  140. const allotDialogVisible = ref(false);
  141. const currentAdviserData = ref<any>(null);
  142. const currentMaintainId = ref<string | number>();
  143. const initFormData: MaintainInfoForm = {
  144. id: undefined,
  145. customerId: undefined,
  146. maintainNo: undefined,
  147. customerNo: undefined,
  148. applicantName: undefined,
  149. applicantPhone: undefined,
  150. serviceTime: undefined,
  151. monthMainten: undefined,
  152. remainingMainten: undefined,
  153. maintenLimit: undefined,
  154. serviceContent: [],
  155. otherService: undefined,
  156. serviceStartTime: undefined,
  157. serviceEndTime: undefined,
  158. maintainStatus: undefined,
  159. serviceEngineerId: undefined,
  160. serviceEngineer: undefined,
  161. engineerPhone: undefined,
  162. technicalAdviserId: undefined,
  163. technicalAdviser: undefined,
  164. technicalAdviserPhone: undefined,
  165. maintainFile: undefined,
  166. maintainType: undefined,
  167. status: undefined,
  168. remark: undefined
  169. };
  170. const data = reactive<PageData<MaintainInfoForm, MaintainInfoQuery>>({
  171. form: { ...initFormData },
  172. queryParams: {
  173. pageNum: 1,
  174. pageSize: 10,
  175. customerId: undefined,
  176. maintainNo: undefined,
  177. customerNo: undefined,
  178. applicantName: undefined,
  179. applicantPhone: undefined,
  180. serviceTime: undefined,
  181. monthMainten: undefined,
  182. remainingMainten: undefined,
  183. maintenLimit: undefined,
  184. serviceContent: undefined,
  185. otherService: undefined,
  186. serviceStartTime: undefined,
  187. serviceEndTime: undefined,
  188. maintainStatus: undefined,
  189. serviceEngineerId: undefined,
  190. serviceEngineer: undefined,
  191. engineerPhone: undefined,
  192. technicalAdviserId: undefined,
  193. technicalAdviser: undefined,
  194. technicalAdviserPhone: undefined,
  195. maintainFile: undefined,
  196. maintainType: undefined,
  197. status: undefined,
  198. platformCode: undefined,
  199. params: {}
  200. },
  201. rules: {}
  202. });
  203. const { queryParams, form, rules } = toRefs(data);
  204. /** 查询维保记录列表 */
  205. const getList = async () => {
  206. loading.value = true;
  207. const res = await listMaintainInfo(queryParams.value);
  208. maintainInfoList.value = res.rows;
  209. total.value = res.total;
  210. loading.value = false;
  211. };
  212. /** 取消按钮 */
  213. const cancel = () => {
  214. reset();
  215. dialog.visible = false;
  216. };
  217. /** 表单重置 */
  218. const reset = () => {
  219. form.value = { ...initFormData };
  220. maintainInfoFormRef.value?.resetFields();
  221. };
  222. /** 搜索按钮操作 */
  223. const handleQuery = () => {
  224. queryParams.value.pageNum = 1;
  225. getList();
  226. };
  227. /** 重置按钮操作 */
  228. const resetQuery = () => {
  229. queryFormRef.value?.resetFields();
  230. handleQuery();
  231. };
  232. /** 多选框选中数据 */
  233. const handleSelectionChange = (selection: MaintainInfoVO[]) => {
  234. ids.value = selection.map((item) => item.id);
  235. single.value = selection.length != 1;
  236. multiple.value = !selection.length;
  237. };
  238. /** 新增按钮操作 */
  239. const handleAdd = () => {
  240. router.push({
  241. path: '/customer/increment-add'
  242. });
  243. };
  244. /** 修改按钮操作 */
  245. const handleUpdate = async (row?: MaintainInfoVO) => {
  246. const _id = row?.id || ids.value[0];
  247. router.push({
  248. path: '/customer/increment-add',
  249. query: { id: _id, status: 'edit' }
  250. });
  251. };
  252. /** 提交按钮 */
  253. const submitForm = () => {
  254. maintainInfoFormRef.value?.validate(async (valid: boolean) => {
  255. if (valid) {
  256. buttonLoading.value = true;
  257. form.value.serviceContent = form.value.serviceContent.join(',');
  258. if (form.value.id) {
  259. await updateMaintainInfo(form.value).finally(() => (buttonLoading.value = false));
  260. } else {
  261. await addMaintainInfo(form.value).finally(() => (buttonLoading.value = false));
  262. }
  263. proxy?.$modal.msgSuccess('操作成功');
  264. dialog.visible = false;
  265. await getList();
  266. }
  267. });
  268. };
  269. /** 删除按钮操作 */
  270. const handleDelete = async (row?: MaintainInfoVO) => {
  271. const _ids = row?.id || ids.value;
  272. await proxy?.$modal.confirm('是否确认删除维保记录编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
  273. await delMaintainInfo(_ids);
  274. proxy?.$modal.msgSuccess('删除成功');
  275. await getList();
  276. };
  277. /** 导出按钮操作 */
  278. const handleExport = () => {
  279. proxy?.download(
  280. 'customer/maintainInfo/export',
  281. {
  282. ...queryParams.value
  283. },
  284. `maintainInfo_${new Date().getTime()}.xlsx`
  285. );
  286. };
  287. /** 打开分配技术顾问对话框 */
  288. const handleAllotAdviser = (row?: MaintainInfoVO) => {
  289. if (row) {
  290. // 单行操作
  291. currentMaintainId.value = row.id;
  292. currentAdviserData.value = {
  293. technicalAdviserId: row.technicalAdviserId,
  294. contactPhone: row.technicalAdviserPhone
  295. };
  296. } else {
  297. // 批量操作
  298. if (ids.value.length === 0) {
  299. proxy?.$modal.msgWarning('请选择要分配技术顾问的维保记录');
  300. return;
  301. }
  302. currentMaintainId.value = undefined;
  303. currentAdviserData.value = null;
  304. }
  305. allotDialogVisible.value = true;
  306. };
  307. /** 确认分配技术顾问 */
  308. const handleAllotConfirm = async (data: any) => {
  309. try {
  310. // 单行操作
  311. if (currentMaintainId.value) {
  312. const params: AllotTechnicalAdviserForm = {
  313. id: currentMaintainId.value,
  314. technicalAdviserId: data.technicalAdviserId,
  315. technicalAdviser: data.technicalAdviser,
  316. technicalAdviserPhone: data.contactPhone
  317. };
  318. await allotTechnicalAdviser(params);
  319. proxy?.$modal.msgSuccess('分配技术顾问成功');
  320. } else {
  321. // 批量操作
  322. const promises = ids.value.map((id) => {
  323. const params: AllotTechnicalAdviserForm = {
  324. id: id,
  325. technicalAdviserId: data.technicalAdviserId,
  326. technicalAdviser: data.technicalAdviser,
  327. technicalAdviserPhone: data.contactPhone
  328. };
  329. return allotTechnicalAdviser(params);
  330. });
  331. await Promise.all(promises);
  332. proxy?.$modal.msgSuccess('批量分配技术顾问成功');
  333. }
  334. await getList();
  335. } catch (error) {
  336. console.error('分配技术顾问失败:', error);
  337. proxy?.$modal.msgError('分配技术顾问失败');
  338. }
  339. };
  340. onMounted(() => {
  341. getList();
  342. });
  343. </script>