index.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528
  1. <template>
  2. <div class="supervise-page">
  3. <!-- 搜索区域 + 操作按钮 -->
  4. <div class="search-wrapper" v-show="showSearch">
  5. <div class="search-row">
  6. <el-form :model="queryParams" :inline="true" class="search-form">
  7. <el-form-item label="项目名称">
  8. <el-input
  9. v-model="queryParams.projectName"
  10. placeholder="请输入项目名称"
  11. clearable
  12. style="width: 160px"
  13. @keyup.enter="getList"
  14. />
  15. </el-form-item>
  16. <el-form-item label="开始时间">
  17. <el-date-picker
  18. v-model="queryParams.startDate"
  19. type="date"
  20. placeholder="开始时间"
  21. value-format="YYYY-MM-DD HH:mm:ss"
  22. style="width: 150px"
  23. />
  24. </el-form-item>
  25. <el-form-item label="结束时间">
  26. <el-date-picker
  27. v-model="queryParams.endDate"
  28. type="date"
  29. placeholder="结束时间"
  30. value-format="YYYY-MM-DD HH:mm:ss"
  31. style="width: 150px"
  32. />
  33. </el-form-item>
  34. <el-form-item>
  35. <el-button type="primary" icon="Search" @click="getList"
  36. >搜索</el-button
  37. >
  38. <el-button icon="Refresh" @click="resetQuery">重置</el-button>
  39. </el-form-item>
  40. </el-form>
  41. <div class="right-actions">
  42. <el-button type="primary" plain icon="Plus" @click="handleAdd"
  43. >新增督查</el-button
  44. >
  45. <right-toolbar
  46. v-model:showSearch="showSearch"
  47. @queryTable="getList"
  48. />
  49. </div>
  50. </div>
  51. </div>
  52. <!-- 表格区域 -->
  53. <div class="table-wrapper">
  54. <el-table
  55. v-loading="loading"
  56. :data="wpsList"
  57. border
  58. stripe
  59. :header-cell-style="headerCellStyle"
  60. class="data-table"
  61. >
  62. <el-table-column label="序号" type="index" width="60" align="center" />
  63. <el-table-column
  64. label="项目名称"
  65. prop="sProjectName"
  66. :show-overflow-tooltip="true"
  67. min-width="160"
  68. align="center"
  69. />
  70. <el-table-column
  71. label="督察情况"
  72. prop="supervision"
  73. :show-overflow-tooltip="true"
  74. min-width="180"
  75. align="center"
  76. />
  77. <el-table-column
  78. label="开始时间"
  79. prop="startDate"
  80. width="160"
  81. align="center"
  82. />
  83. <el-table-column
  84. label="结束时间"
  85. prop="endDate"
  86. width="160"
  87. align="center"
  88. />
  89. <el-table-column label="操作" align="center" width="160" fixed="right">
  90. <template #default="scope">
  91. <div class="action-buttons">
  92. <el-button
  93. link
  94. type="primary"
  95. icon="Edit"
  96. @click="handleEdit(scope.row)"
  97. >修改</el-button
  98. >
  99. <el-button
  100. link
  101. type="danger"
  102. icon="Delete"
  103. @click="handleDelete(scope.row)"
  104. >删除</el-button
  105. >
  106. </div>
  107. </template>
  108. </el-table-column>
  109. </el-table>
  110. <!-- 分页 -->
  111. <div class="pagination-wrap" v-show="total > 0">
  112. <pagination
  113. :total="total"
  114. v-model:page="pageNum"
  115. v-model:limit="pageSize"
  116. @pagination="getList"
  117. />
  118. </div>
  119. </div>
  120. <!-- 编辑对话框 -->
  121. <el-dialog
  122. :title="dialogTitle"
  123. v-model="dialogVisible"
  124. width="650px"
  125. append-to-body
  126. :close-on-click-modal="false"
  127. class="form-dialog"
  128. >
  129. <el-form
  130. ref="formRef"
  131. :model="form"
  132. :rules="formRules"
  133. label-width="100px"
  134. class="project-form"
  135. >
  136. <div class="form-section">
  137. <div class="section-title">基本信息</div>
  138. <el-row :gutter="20">
  139. <el-col :span="24">
  140. <el-form-item label="关联项目" prop="smId">
  141. <el-select
  142. v-model="form.smId"
  143. placeholder="请选择关联项目"
  144. filterable
  145. clearable
  146. style="width: 100%"
  147. :loading="projectLoading"
  148. @change="handleProjectChange"
  149. >
  150. <el-option
  151. v-for="item in riverProjectOptions"
  152. :key="item.guid"
  153. :label="item.sProjectName"
  154. :value="item.guid"
  155. />
  156. </el-select>
  157. </el-form-item>
  158. </el-col>
  159. <el-col :span="24">
  160. <el-form-item label="项目名称" prop="sProjectName">
  161. <el-input
  162. v-model="form.sProjectName"
  163. placeholder="请输入项目名称"
  164. />
  165. </el-form-item>
  166. </el-col>
  167. </el-row>
  168. </div>
  169. <div class="form-section">
  170. <div class="section-title">督察信息</div>
  171. <el-row :gutter="20">
  172. <el-col :span="24">
  173. <el-form-item label="督察情况" prop="supervision">
  174. <el-input
  175. v-model="form.supervision"
  176. type="textarea"
  177. :rows="4"
  178. placeholder="请输入督察情况"
  179. />
  180. </el-form-item>
  181. </el-col>
  182. <el-col :span="12">
  183. <el-form-item label="开始时间" prop="startDate">
  184. <el-date-picker
  185. v-model="form.startDate"
  186. type="datetime"
  187. value-format="YYYY-MM-DD HH:mm:ss"
  188. placeholder="选择开始时间"
  189. style="width: 100%"
  190. />
  191. </el-form-item>
  192. </el-col>
  193. <el-col :span="12">
  194. <el-form-item label="结束时间" prop="endDate">
  195. <el-date-picker
  196. v-model="form.endDate"
  197. type="datetime"
  198. value-format="YYYY-MM-DD HH:mm:ss"
  199. placeholder="选择结束时间"
  200. style="width: 100%"
  201. />
  202. </el-form-item>
  203. </el-col>
  204. </el-row>
  205. </div>
  206. </el-form>
  207. <template #footer>
  208. <div class="dialog-footer">
  209. <el-button @click="dialogVisible = false">取消</el-button>
  210. <el-button type="primary" @click="submitForm" :loading="submitLoading"
  211. >确定</el-button
  212. >
  213. </div>
  214. </template>
  215. </el-dialog>
  216. </div>
  217. </template>
  218. <script setup>
  219. import { ref, reactive, onMounted } from "vue";
  220. import { listWps, addWps, updateWps, delWps } from "@/api/hzz/wps";
  221. import { getAllProject } from "@/api/hzz/riverproject";
  222. import { ElMessage, ElMessageBox } from "element-plus";
  223. const showSearch = ref(true);
  224. const loading = ref(false);
  225. const submitLoading = ref(false);
  226. const total = ref(0);
  227. const pageNum = ref(1);
  228. const pageSize = ref(10);
  229. const wpsList = ref([]);
  230. const queryParams = ref({ projectName: "", startDate: "", endDate: "" });
  231. const riverProjectOptions = ref([]);
  232. const projectLoading = ref(false);
  233. const getRiverProjectOptions = async () => {
  234. projectLoading.value = true;
  235. try {
  236. const res = await getAllProject();
  237. riverProjectOptions.value = res.data || [];
  238. } finally {
  239. projectLoading.value = false;
  240. }
  241. };
  242. const handleProjectChange = (guid) => {
  243. const selected = riverProjectOptions.value.find((item) => item.guid === guid);
  244. form.sProjectName = selected ? selected.sProjectName : "";
  245. };
  246. const dialogVisible = ref(false);
  247. const dialogTitle = ref("");
  248. const formRef = ref(null);
  249. const form = reactive({});
  250. const formRules = {
  251. supervision: [
  252. { required: true, message: "督察情况不能为空", trigger: "blur" },
  253. ],
  254. };
  255. const headerCellStyle = {
  256. background: "#f5f7fa",
  257. color: "#333",
  258. fontWeight: "600",
  259. fontSize: "14px",
  260. textAlign: "center",
  261. };
  262. const getList = async () => {
  263. loading.value = true;
  264. try {
  265. const res = await listWps({
  266. ...queryParams.value,
  267. pageNum: pageNum.value,
  268. pageSize: pageSize.value,
  269. });
  270. wpsList.value = res.rows || [];
  271. total.value = res.total || 0;
  272. } finally {
  273. loading.value = false;
  274. }
  275. };
  276. const resetQuery = () => {
  277. queryParams.value = { projectName: "", startDate: "", endDate: "" };
  278. getList();
  279. };
  280. const handleAdd = () => {
  281. dialogTitle.value = "新增督查";
  282. Object.keys(form).forEach((k) => delete form[k]);
  283. dialogVisible.value = true;
  284. };
  285. const handleEdit = (row) => {
  286. dialogTitle.value = "修改督查";
  287. Object.assign(form, row);
  288. dialogVisible.value = true;
  289. };
  290. const handleDelete = async (row) => {
  291. try {
  292. await ElMessageBox.confirm(
  293. "确认删除该督查记录?删除后不可恢复。",
  294. "删除确认",
  295. {
  296. type: "warning",
  297. confirmButtonText: "确认删除",
  298. cancelButtonText: "取消",
  299. },
  300. );
  301. await delWps(row.guid);
  302. ElMessage.success("删除成功");
  303. getList();
  304. } catch {
  305. // 取消删除
  306. }
  307. };
  308. const submitForm = async () => {
  309. if (!formRef.value) return;
  310. try {
  311. await formRef.value.validate();
  312. } catch {
  313. ElMessage.warning("请完善必填信息");
  314. return;
  315. }
  316. submitLoading.value = true;
  317. try {
  318. if (form.guid) {
  319. await updateWps(form);
  320. ElMessage.success("修改成功");
  321. } else {
  322. await addWps(form);
  323. ElMessage.success("新增成功");
  324. }
  325. dialogVisible.value = false;
  326. getList();
  327. } catch {
  328. ElMessage.error("操作失败");
  329. } finally {
  330. submitLoading.value = false;
  331. }
  332. };
  333. onMounted(() => {
  334. getList();
  335. getRiverProjectOptions();
  336. });
  337. </script>
  338. <style scoped>
  339. .supervise-page {
  340. height: 100%;
  341. background: #f0f2f5;
  342. display: flex;
  343. flex-direction: column;
  344. padding: 16px;
  345. gap: 12px;
  346. overflow: hidden;
  347. }
  348. /* 搜索区域 */
  349. .search-wrapper {
  350. background: #fff;
  351. padding: 16px 20px;
  352. border-radius: 10px;
  353. box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
  354. flex-shrink: 0;
  355. }
  356. .search-row {
  357. display: flex;
  358. justify-content: space-between;
  359. align-items: center;
  360. flex-wrap: wrap;
  361. gap: 8px;
  362. }
  363. .search-form {
  364. display: flex;
  365. align-items: center;
  366. flex-wrap: wrap;
  367. }
  368. .search-form :deep(.el-form-item) {
  369. margin-bottom: 0;
  370. margin-right: 12px;
  371. }
  372. .search-form :deep(.el-input__wrapper) {
  373. border-radius: 6px;
  374. }
  375. .search-form :deep(.el-button) {
  376. border-radius: 6px;
  377. }
  378. .right-actions {
  379. display: flex;
  380. align-items: center;
  381. gap: 8px;
  382. }
  383. .right-actions .el-button {
  384. border-radius: 6px;
  385. font-weight: 500;
  386. }
  387. /* 表格区域 */
  388. .table-wrapper {
  389. flex: 1;
  390. background: #fff;
  391. border-radius: 10px;
  392. box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
  393. padding: 16px;
  394. display: flex;
  395. flex-direction: column;
  396. overflow: hidden;
  397. }
  398. .data-table {
  399. flex: 1;
  400. border-radius: 6px;
  401. overflow: hidden;
  402. }
  403. .data-table :deep(.el-table__body-wrapper) .el-table__row:hover {
  404. background-color: #f0f7ff !important;
  405. }
  406. :deep(.el-popper) {
  407. max-width: 800px !important;
  408. }
  409. .action-buttons {
  410. display: flex;
  411. justify-content: center;
  412. gap: 8px;
  413. }
  414. .action-buttons .el-button {
  415. font-size: 13px;
  416. padding: 4px 10px;
  417. }
  418. .pagination-wrap {
  419. padding-top: 12px;
  420. flex-shrink: 0;
  421. }
  422. /* 对话框 */
  423. .form-dialog :deep(.el-dialog) {
  424. border-radius: 12px;
  425. overflow: hidden;
  426. }
  427. .form-dialog :deep(.el-dialog__header) {
  428. background: linear-gradient(135deg, #667eea, #764ba2);
  429. padding: 16px 24px;
  430. margin: 0;
  431. text-align: center;
  432. }
  433. .form-dialog :deep(.el-dialog__title) {
  434. color: #fff;
  435. font-size: 16px;
  436. font-weight: 600;
  437. }
  438. .form-dialog :deep(.el-dialog__headerbtn) {
  439. top: 16px;
  440. }
  441. .form-dialog :deep(.el-dialog__close) {
  442. color: #fff;
  443. font-size: 18px;
  444. }
  445. .form-dialog :deep(.el-dialog__close:hover) {
  446. color: #f0f0f0;
  447. }
  448. .form-dialog :deep(.el-dialog__body) {
  449. padding: 24px;
  450. max-height: 60vh;
  451. overflow-y: auto;
  452. }
  453. .form-dialog :deep(.el-dialog__footer) {
  454. padding: 16px 24px;
  455. border-top: 1px solid #f0f0f0;
  456. text-align: center;
  457. }
  458. /* 表单样式 */
  459. .project-form .form-section {
  460. margin-bottom: 20px;
  461. }
  462. .project-form .form-section:last-child {
  463. margin-bottom: 0;
  464. }
  465. .section-title {
  466. font-size: 14px;
  467. font-weight: 600;
  468. color: #333;
  469. margin-bottom: 16px;
  470. padding-bottom: 8px;
  471. border-bottom: 2px solid #667eea;
  472. text-align: center;
  473. }
  474. .project-form :deep(.el-form-item__label) {
  475. font-weight: 500;
  476. color: #555;
  477. }
  478. .project-form :deep(.el-input__wrapper) {
  479. border-radius: 6px;
  480. transition: all 0.2s;
  481. }
  482. .project-form :deep(.el-textarea__inner) {
  483. border-radius: 6px;
  484. }
  485. .project-form :deep(.el-date-editor) .el-input__wrapper {
  486. border-radius: 6px;
  487. }
  488. /* 对话框底部按钮 */
  489. .dialog-footer {
  490. display: flex;
  491. justify-content: center;
  492. gap: 12px;
  493. }
  494. .dialog-footer .el-button {
  495. border-radius: 6px;
  496. font-weight: 500;
  497. padding: 10px 24px;
  498. }
  499. </style>