home.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537
  1. <template>
  2. <div class="mainContentBox">
  3. <div class="content-head">
  4. <div class="head-box-all">
  5. <div class="box-all">
  6. <el-checkbox
  7. v-model="checkAll"
  8. :indeterminate="isIndeterminate"
  9. @change="handleCheckAllChange"
  10. >
  11. </el-checkbox>
  12. <span>显示全部</span>
  13. </div>
  14. <div class="box-num">{{ checkedCities.length }}</div>
  15. <div class="box-text">工程类型</div>
  16. </div>
  17. <div class="head-box-group">
  18. <el-scrollbar>
  19. <el-checkbox-group
  20. v-model="checkedCities"
  21. @change="handleCheckedCitiesChange"
  22. >
  23. <div
  24. class="head-box-item"
  25. :class="[
  26. checkedCities.includes(type.engineeringType) ? 'active' : '',
  27. ]"
  28. v-for="type in typeList"
  29. :key="type.engineeringType"
  30. >
  31. <el-checkbox label="" :value="type.engineeringType"></el-checkbox>
  32. <div class="name">{{ type.engineeringType }}</div>
  33. <div class="num">{{ type.typeCount }}</div>
  34. </div>
  35. </el-checkbox-group>
  36. </el-scrollbar>
  37. </div>
  38. </div>
  39. <div class="content-body">
  40. <div class="cotent-btns">
  41. <div>工程列表</div>
  42. <div>
  43. <el-button type="primary" @click="showAddFun">
  44. <span class="add">+</span>
  45. 新增工程
  46. </el-button>
  47. <!-- <el-button class="active">-->
  48. <!-- <i />-->
  49. <!-- 按时间倒序-->
  50. <!-- </el-button>-->
  51. <!-- <el-button class="normal">-->
  52. <!-- <i />-->
  53. <!-- 按创建人姓名-->
  54. <!-- </el-button>-->
  55. </div>
  56. </div>
  57. <div class="content-scrollbar">
  58. <el-scrollbar>
  59. <div class="content-list">
  60. <div
  61. v-for="(item, index) in engineeringList"
  62. :key="index"
  63. class="content-list-item"
  64. >
  65. <div class="list-item-flex">
  66. <div class="list-itme-tit">
  67. {{ item.engineeringProductName }}
  68. </div>
  69. <div class="list-item-switch">
  70. <span class="item-gray">发布</span>
  71. <el-popconfirm
  72. width="220"
  73. @confirm="changeProjectStatus(item)"
  74. title="确定要修改发布状态吗?"
  75. >
  76. <template #reference>
  77. <el-switch :model-value="item.publishStatus" />
  78. </template>
  79. </el-popconfirm>
  80. </div>
  81. </div>
  82. <div class="list-item-flex">
  83. <div>
  84. <span class="item-gray">工程类型:</span
  85. >{{ item.engineeringType }}
  86. </div>
  87. <div>
  88. <span class="item-gray">版本:</span
  89. >{{ item.engineeringVersion }}
  90. </div>
  91. </div>
  92. <div class="list-item-flex">
  93. <div>
  94. <span class="item-gray">开发人员:</span>{{ item.creator }}
  95. </div>
  96. <div>
  97. <span class="item-gray">更新时间:</span>{{ item.updated }}
  98. </div>
  99. </div>
  100. <div class="list-item-btns">
  101. <span @click="toEdit(item)">
  102. <svg-icon icon-class="homeIcon2" />
  103. </span>
  104. <el-popconfirm
  105. width="220"
  106. :icon="InfoFilled"
  107. icon-color="#626AEF"
  108. title="确认要删除这个工程吗?"
  109. @cancel="onDelCancel"
  110. @confirm="deleteConfirm(item)"
  111. >
  112. <template #reference>
  113. <span>
  114. <svg-icon icon-class="homeIcon3" />
  115. </span>
  116. </template>
  117. <template #actions="{ confirm, cancel }">
  118. <el-button size="small" @click="cancel">取消</el-button>
  119. <el-button type="danger" size="small" @click="confirm">
  120. 确认删除
  121. </el-button>
  122. </template>
  123. </el-popconfirm>
  124. <span @click="gotoConfigProject(item)">
  125. <svg-icon icon-class="homeIcon4" />
  126. </span>
  127. <span @click="gotoExecuteTest(item)">
  128. <svg-icon icon-class="homeIcon1" />
  129. </span>
  130. </div>
  131. </div>
  132. </div>
  133. </el-scrollbar>
  134. </div>
  135. <el-pagination
  136. class="content-pag"
  137. background
  138. layout="sizes,prev, pager, next"
  139. :current-page="currentPage"
  140. :page-size="pageSize"
  141. :total="total"
  142. :page-sizes="[9, 12, 15, 18, 30]"
  143. @size-change="handleSizeChange"
  144. @current-change="handleCurrentChange"
  145. />
  146. </div>
  147. <AddComponent ref="addRef" @save-finish="getEngineeringList" />
  148. <DetailsComponent ref="detailRef" />
  149. </div>
  150. </template>
  151. <script lang="ts" setup>
  152. import { InfoFilled } from "@element-plus/icons-vue";
  153. import AddComponent from "./components/add.vue";
  154. import DetailsComponent from "./components/details.vue";
  155. import { ref } from "vue";
  156. import type { CheckboxValueType } from "element-plus";
  157. import {
  158. deleteProject,
  159. getProjectPage,
  160. getProjectTypeCount,
  161. updateProject,
  162. } from "@/api/project";
  163. import { useCommonStoreHook } from "@/store";
  164. const {
  165. currentProjectId,
  166. currentMenuIndex,
  167. pageSize,
  168. currentTestItemId,
  169. currentExecutionId,
  170. } = toRefs(useCommonStoreHook());
  171. const checkAll = ref(false);
  172. const isIndeterminate = ref(true);
  173. const checkedCities = ref<any[]>([]);
  174. const typeList = ref<any[]>([]);
  175. // 获取所有的工程类型
  176. const getEngineeringTypeList = () => {
  177. getProjectTypeCount().then((res) => {
  178. typeList.value = res.data?.statisticsList ?? [];
  179. });
  180. };
  181. const handleCheckAllChange = (val: CheckboxValueType) => {
  182. checkedCities.value = val
  183. ? typeList.value.map((item) => item.engineeringType)
  184. : [];
  185. isIndeterminate.value = false;
  186. getEngineeringList(false);
  187. };
  188. const handleCheckedCitiesChange = (value: CheckboxValueType[]) => {
  189. const checkedCount = value.length;
  190. checkAll.value = checkedCount === typeList.value.length;
  191. isIndeterminate.value =
  192. checkedCount > 0 && checkedCount < typeList.value.length;
  193. getEngineeringList(false);
  194. };
  195. interface VersionItem {
  196. id: string; // 主键 string
  197. engineeringProductName: string; // 产品名称 string
  198. engineeringType: string; // 工程类型 string
  199. engineeringVersion: string; // 工程版本 string
  200. creator: string; //创建人 string 开发人员
  201. updated: string; // 修改时间 string(date-time)
  202. created: string; // 创建时间string(date-time)
  203. deleted: string; // 删除标识;0-未删除;1-已删除 integer(int32)
  204. deptId: string; // 部门ID string
  205. orgId: string; // 组织ID string
  206. updator: string; // 上次修改人 string
  207. publishStatus: number; //发布状态:0-发布 1-未发布
  208. }
  209. /**
  210. * 显示新增弹框
  211. */
  212. const addRef = ref();
  213. const showAddFun = () => {
  214. addRef.value && addRef.value.openDialog();
  215. };
  216. const toEdit = (row) => {
  217. addRef.value &&
  218. addRef.value.openDialog(true, JSON.parse(JSON.stringify(row)));
  219. };
  220. // 发布
  221. const isLoading = ref(false);
  222. const changeProjectStatus = async (item: VersionItem) => {
  223. let p = {
  224. ...item,
  225. };
  226. p.publishStatus = !p.publishStatus;
  227. await updateProject(p);
  228. getEngineeringList(false);
  229. };
  230. /**
  231. * 显示新增弹框
  232. */
  233. const detailRef = ref();
  234. const showDetailsFun = (row: any) => {
  235. detailRef.value &&
  236. detailRef.value.openDialog(true, JSON.parse(JSON.stringify(row)));
  237. };
  238. // 获取列表数据
  239. const currentPage = ref(1);
  240. const total = ref(0);
  241. const engineeringList = ref<VersionItem[]>([]);
  242. const handleSizeChange = (val: number) => {
  243. currentPage.value = 1;
  244. pageSize.value = val;
  245. getEngineeringList();
  246. };
  247. const handleCurrentChange = (val: number) => {
  248. currentPage.value = val;
  249. getEngineeringList();
  250. };
  251. // const isAsc = ref();
  252. const getEngineeringList = (andGetTypes: boolean = true) => {
  253. getProjectPage({
  254. engineeringTypeList: [...checkedCities.value],
  255. // orders: [
  256. // {
  257. // column: "",
  258. // isAsc: true,
  259. // },
  260. // ],
  261. pageNo: currentPage.value,
  262. pageSize: pageSize.value,
  263. // publishStatus: 0,
  264. }).then((res) => {
  265. console.log(res);
  266. engineeringList.value = res.data.records;
  267. total.value = res.data.totalCount;
  268. });
  269. if (andGetTypes) {
  270. getEngineeringTypeList();
  271. }
  272. };
  273. onMounted(() => {
  274. getEngineeringList();
  275. });
  276. // 删除相关
  277. const onDelCancel = () => {};
  278. const deleteConfirm = async (item) => {
  279. await deleteProject(item.id);
  280. ElMessage.success("删除成功");
  281. getEngineeringList();
  282. };
  283. // 去到配置工程页面
  284. const router = useRouter();
  285. const gotoConfigProject = (project) => {
  286. currentProjectId.value = project.id;
  287. currentTestItemId.value = ""; // 要清空数据,不然进入配置页面会导致数据错误
  288. currentMenuIndex.value = 3;
  289. router.push({ name: "ProjectConfig", params: { engineerId: project.id } });
  290. };
  291. // 去到测试执行页面
  292. const gotoExecuteTest = (project) => {
  293. currentExecutionId.value = project.id;
  294. currentMenuIndex.value = 1;
  295. router.push({
  296. name: "RunTesting",
  297. query: {
  298. _refresh: Date.now(), // 每次跳转生成不同的时间戳
  299. },
  300. params: { engineerId: project.id },
  301. });
  302. };
  303. </script>
  304. <style scoped lang="scss">
  305. .mainContentBox {
  306. position: absolute;
  307. width: 100%;
  308. .content-head {
  309. color: var(--hj-white-1);
  310. // display: flex;
  311. height: 100px;
  312. background: $hj-white-1;
  313. // width: 100%;
  314. // overflow: hidden;
  315. // min-width: 0;
  316. .head-box-all {
  317. display: inline-block;
  318. padding: 6px;
  319. box-sizing: border-box;
  320. border-radius: 4px 0 0 4px;
  321. width: 90px;
  322. height: 100px;
  323. background: linear-gradient(270deg, #3b7cff 0%, #8aa9ec 100%);
  324. color: var(--hj-white-1);
  325. font-size: var(--hj-fs-12);
  326. text-align: center;
  327. .box-all {
  328. color: var(--hj-white-1);
  329. font-size: var(--hj-fs-12);
  330. }
  331. .box-num {
  332. text-align: center;
  333. font-size: var(--hj-fs-24);
  334. }
  335. }
  336. .head-box-group {
  337. display: inline-block;
  338. width: calc(100% - 100px);
  339. // flex: 1;
  340. .el-checkbox-group {
  341. // height: 100%;
  342. width: 100%;
  343. // overflow-x: auto;
  344. // overflow-y: hidden;
  345. white-space: nowrap;
  346. display: flex;
  347. align-content: center;
  348. align-items: center;
  349. flex-direction: row;
  350. .head-box-item {
  351. position: relative;
  352. flex: 0 0 182px;
  353. font-size: var(--hj-fs-14);
  354. margin-top: 16px;
  355. padding: 6px;
  356. margin-left: 12px;
  357. height: 67px;
  358. border: 1px solid #afb9d0;
  359. border-radius: 4px 4px 4px 4px;
  360. text-align: center;
  361. .el-checkbox {
  362. position: absolute;
  363. left: 6px;
  364. top: 0;
  365. }
  366. .name {
  367. line-height: 16px;
  368. margin-top: 12px;
  369. font-size: var(--hj-fs-14);
  370. color: var(--fc-color-5);
  371. }
  372. .num {
  373. line-height: 26px;
  374. font-size: var(--hj-fs-20);
  375. font-weight: bold;
  376. color: var(--fc-color-7);
  377. }
  378. &.active {
  379. background: linear-gradient(90deg, #3cbaff 0%, #3b7cff 100%);
  380. .name {
  381. color: var(--hj-white-1);
  382. }
  383. .num {
  384. color: var(--hj-white-1);
  385. }
  386. }
  387. }
  388. }
  389. }
  390. }
  391. .content-body {
  392. .cotent-btns {
  393. display: flex;
  394. justify-content: space-between;
  395. align-items: center;
  396. margin-top: 26px;
  397. margin-bottom: 12px;
  398. .add {
  399. width: 12px;
  400. height: 12px;
  401. line-height: 12px;
  402. border-radius: 12px;
  403. text-align: center;
  404. background-color: #fff;
  405. color: #3b7cff;
  406. margin-right: 10px;
  407. }
  408. .active,
  409. .normal {
  410. i {
  411. width: 14px;
  412. height: 14px;
  413. border-radius: 14px;
  414. vertical-align: middle;
  415. margin-right: 10px;
  416. }
  417. }
  418. .active {
  419. border: 1px solid #1989fa;
  420. color: #1871f8;
  421. i {
  422. border: 4px solid #3b7cff;
  423. }
  424. }
  425. .normal {
  426. i {
  427. border: 1px solid #d5d8de;
  428. }
  429. }
  430. }
  431. }
  432. .content-scrollbar {
  433. height: calc(100vh - 325px);
  434. }
  435. .content-list {
  436. width: 100%;
  437. display: grid;
  438. grid-template-columns: repeat(3, 1fr);
  439. gap: 20px;
  440. .content-list-item {
  441. border: 1px solid #ccc;
  442. box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.1);
  443. border-radius: 4px 4px 4px 4px;
  444. padding-top: 12px;
  445. background-color: $hj-white-1;
  446. }
  447. .list-item-flex {
  448. margin-bottom: 12px;
  449. padding: 0 20px;
  450. display: flex;
  451. justify-content: space-between;
  452. align-items: center;
  453. font-size: var(--hj-fs-12);
  454. color: var(--fc-color-5);
  455. .list-itme-tit {
  456. font-size: var(--hj-fs-14);
  457. font-weight: bold;
  458. }
  459. .list-item-switch {
  460. .item-gray {
  461. line-height: 32px;
  462. margin-right: 4px;
  463. }
  464. }
  465. .item-gray {
  466. color: var(--fc-color-3);
  467. }
  468. }
  469. .list-item-btns {
  470. height: 37px;
  471. line-height: 37px;
  472. color: var(--fc-color-6);
  473. display: flex;
  474. justify-content: space-around;
  475. border-top: 1px solid rgba(175, 185, 208, 0.3);
  476. span {
  477. cursor: pointer;
  478. }
  479. }
  480. }
  481. .content-pag {
  482. float: right;
  483. margin-right: 20px;
  484. margin-top: 20px;
  485. padding-bottom: 30px;
  486. }
  487. }
  488. </style>