index.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546
  1. <template>
  2. <!-- 专业管理 -->
  3. <div id="professionalManagement">
  4. <search-box :formList="formList" @search="search" @init="init"></search-box>
  5. <table-list
  6. class="table_list"
  7. :tableSets="tableSet"
  8. :tableData="tableData"
  9. :navText="navText"
  10. :rowKey="rowKey"
  11. @load="loadse"
  12. @addClick="addClick"
  13. @emitData="emitData"
  14. :loading="loading"
  15. ref="pager"
  16. >
  17. <template slot="btn" slot-scope="props">
  18. <el-button type="text" @click="addChild(props.scope.row)"
  19. >添加下级</el-button
  20. >
  21. <el-button type="text" @click="modify(props.scope.row)">修改</el-button>
  22. <el-button type="text" @click="del(props.scope.row)">删除</el-button>
  23. </template>
  24. </table-list>
  25. <pagination
  26. :total="total"
  27. :pageSize="pageSize"
  28. :currentPage="currentPage"
  29. @handleSizeChange="handleSizeChange"
  30. @handleCurrentChange="handleCurrentChange"
  31. />
  32. <el-dialog
  33. :visible.sync="dialogBox"
  34. width="720px"
  35. :show-close="false"
  36. :destroy-on-close="true"
  37. :before-close="closeBefore"
  38. :fullscreen="fullscreen"
  39. >
  40. <div slot="title" class="hearders">
  41. <div class="leftTitle">{{ statusPop === 1 ? "添加" : "修改" }}</div>
  42. <div class="rightBoxs">
  43. <img
  44. src="@/assets/images/Max@2x.png"
  45. alt=""
  46. @click="fullscreen = !fullscreen"
  47. />
  48. <img src="@/assets/images/Close@2x.png" alt="" @click="closeBefore" />
  49. </div>
  50. </div>
  51. <el-row class="contentBox" :span="24">
  52. <el-col :span="24">
  53. <header>上级分类:</header>
  54. <treeselect
  55. v-if="statusPop === 2"
  56. v-model="poppleData.categoryId"
  57. :options="optionsCascader"
  58. :normalizer="normalizer"
  59. :show-count="true"
  60. placeholder="选择上级菜单"
  61. />
  62. <treeselect
  63. v-else
  64. v-model="poppleData.pid"
  65. :options="optionsCascader"
  66. :normalizer="normalizer"
  67. :show-count="true"
  68. placeholder="选择上级菜单"
  69. />
  70. </el-col>
  71. <el-col :span="12">
  72. <header>分类名称:</header>
  73. <el-input
  74. placeholder="请输入分类名称"
  75. v-model="poppleData.categoryName"
  76. />
  77. </el-col>
  78. <el-col :span="12">
  79. <header>排序:</header>
  80. <el-input-number
  81. style="width: 100%"
  82. v-model="poppleData.sort"
  83. controls-position="right"
  84. :min="0"
  85. placeholder="请输入排序"
  86. ></el-input-number>
  87. </el-col>
  88. <el-col :span="12">
  89. <header>备注:</header>
  90. <el-input placeholder="请输入备注" v-model="poppleData.remark" />
  91. </el-col>
  92. <el-col :span="12">
  93. <header>是否启用:</header>
  94. <el-radio-group v-model="poppleData.status">
  95. <el-radio :label="1">是</el-radio>
  96. <el-radio :label="0">否</el-radio>
  97. </el-radio-group>
  98. </el-col>
  99. </el-row>
  100. <div slot="footer" class="dialog-footer">
  101. <el-button @click="closeBefore">取 消</el-button>
  102. <el-button type="primary" @click="submitTable">确 定</el-button>
  103. </div>
  104. </el-dialog>
  105. </div>
  106. </template>
  107. <script>
  108. import Treeselect from "@riophae/vue-treeselect";
  109. import "@riophae/vue-treeselect/dist/vue-treeselect.css";
  110. import searchBox from "@/components/searchBox";
  111. import tableList from "@/components/tableList";
  112. import pagination from "@/components/pagination";
  113. export default {
  114. components: { Treeselect, searchBox, tableList, pagination },
  115. data() {
  116. return {
  117. rowKey: "categoryId", //根据XX分类
  118. loading: false, //当前表单加载是否加载动画
  119. navText: {
  120. title: "专业分类合计",
  121. index: 0,
  122. num: false,
  123. ch: "项",
  124. choice: false,
  125. backFatherBtn: {
  126. status: false,
  127. title: "未定义",
  128. },
  129. },
  130. formList: [
  131. {
  132. label: "分类名称",
  133. prop: "categoryName",
  134. placeholder: "输入分类名称",
  135. },
  136. {
  137. label: "启用状态",
  138. prop: "status",
  139. scope: "select",
  140. placeholder: "选择启用状态",
  141. options: [
  142. {
  143. label: "启用",
  144. value: 1,
  145. },
  146. {
  147. label: "关闭",
  148. value: 0,
  149. },
  150. ],
  151. },
  152. ], //搜索栏
  153. tableSet: [
  154. {
  155. label: "分类名称",
  156. prop: "categoryName",
  157. hidden: true,
  158. },
  159. {
  160. label: "应用状态",
  161. prop: "status",
  162. hidden: true,
  163. scope: "status",
  164. },
  165. {
  166. label: "排序",
  167. prop: "sort",
  168. hidden: true,
  169. },
  170. {
  171. label: "备注",
  172. prop: "remark",
  173. hidden: true,
  174. },
  175. ], //表头信息
  176. tableData: [], //表单数据
  177. total: 0, //一共多少条
  178. pageSize: 10, //每页多少条数据
  179. currentPage: 1, //当前页码
  180. dialogBox: false, //弹窗
  181. poppleData: {}, //弹窗表单数据
  182. optionsCascader: [], //弹窗分类数据
  183. fullscreen: false, //弹窗是否全屏
  184. statusPop: -1, //当前窗口处于什么状态 1是添加 0是修改 2是表单添加下级
  185. disableds: false, //是否禁止打开级联
  186. treeObj: {},
  187. };
  188. },
  189. created() {
  190. this.search();
  191. },
  192. mounted() {},
  193. methods: {
  194. /** 转换菜单数据结构 */
  195. normalizer(node) {
  196. if (node.children && !node.children.length) {
  197. delete node.children;
  198. }
  199. return {
  200. id: node.categoryId,
  201. label: node.categoryName,
  202. children: node.children,
  203. };
  204. },
  205. getCascader() {
  206. this.$api.inquireProfessionClassification().then((res) => {
  207. var setObj = res.rows.filter((item, index) => {
  208. return item.status !== -1;
  209. });
  210. setObj.unshift({
  211. categoryId: 0,
  212. categoryName: "主类型",
  213. });
  214. this.optionsCascader = this.arrayChangeType(setObj);
  215. console.log(this.optionsCascader ,66)
  216. });
  217. },
  218. // 表单列添加下级
  219. addChild(options) {
  220. this.poppleData = {
  221. status: 1,
  222. pid: options.pid,
  223. categoryId: options.categoryId,
  224. };
  225. this.statusPop = 2;
  226. this.dialogBox = true;
  227. },
  228. // 表单列修改
  229. modify(v) {
  230. this.poppleData = {
  231. categoryName: v.categoryName,
  232. categoryId: v.categoryId,
  233. pid: v.pid,
  234. sort: v.sort,
  235. remark: v.remark,
  236. status: v.status,
  237. };
  238. this.statusPop = 0;
  239. this.dialogBox = true;
  240. },
  241. //窗口关闭
  242. closeBefore() {
  243. this.$confirm("此操作将关闭窗口, 是否继续?", "提示", {
  244. confirmButtonText: "确定",
  245. cancelButtonText: "取消",
  246. type: "warning",
  247. })
  248. .then(() => {
  249. this.dialogBox = false;
  250. this.fullscreen = false;
  251. this.poppleData = {};
  252. })
  253. .catch(() => {});
  254. },
  255. submitTable() {
  256. console.log(this.poppleData);
  257. if (!this.poppleData.categoryName) {
  258. this.$message.error("请填写分类名称");
  259. return;
  260. }
  261. if (this.poppleData.sort === undefined) {
  262. this.$message.error("请填写排序");
  263. return;
  264. }
  265. if (this.poppleData.status === undefined) {
  266. this.$message.error("请选择是否启用");
  267. return;
  268. }
  269. // if (this.poppleData.categoryId === undefined) {
  270. // this.$message.error("请选择上级分类");
  271. // return;
  272. // } else {
  273. // if (this.poppleData.categoryId.length === 0) {
  274. // this.$message.error("请选择上级分类");
  275. // return;
  276. // } else {
  277. // if (typeof this.poppleData.categoryId === "object") {
  278. // this.poppleData.categoryId = this.poppleData.categoryId.pop();
  279. // }
  280. // }
  281. // }
  282. if (this.statusPop === 1 ||this.statusPop === 2 ) {
  283. this.poppleData.pid = this.poppleData.categoryId;
  284. delete this.poppleData.categoryId;
  285. this.$api
  286. .addProfessionClassification(this.poppleData)
  287. .then((res) => {
  288. if(res.code === 200){
  289. this.$message.success("添加成功");
  290. this.tableData = [];
  291. this.search();
  292. this.dialogBox = false;
  293. }
  294. })
  295. .catch((err) => {
  296. this.$message.error(err);
  297. });
  298. }
  299. if (this.statusPop === 0) {
  300. this.$api
  301. .modifyProfessionClassification(this.poppleData)
  302. .then((res) => {
  303. if(res.code === 200){
  304. this.$message.success("修改成功");
  305. this.tableData = [];
  306. this.search();
  307. this.dialogBox = false;
  308. }
  309. })
  310. .catch((err) => {
  311. this.$message.error(err);
  312. });
  313. }
  314. },
  315. // 表单列删除
  316. del(options) {
  317. var self = this;
  318. this.$confirm("此操作将删除该专业分类, 是否继续?", "提示", {
  319. confirmButtonText: "确定",
  320. cancelButtonText: "取消",
  321. type: "warning",
  322. })
  323. .then(() => {
  324. var data = {
  325. categoryId: options.categoryId,
  326. categoryName: options.categoryName,
  327. status: -1,
  328. };
  329. self.$api
  330. .modifyProfessionClassification(data)
  331. .then((res) => {
  332. self.$message.success("删除成功");
  333. self.tableData = [];
  334. self.search();
  335. })
  336. .catch((error) => {
  337. self.$message.error("删除失败,失败原因:" + error);
  338. });
  339. })
  340. .catch(() => {});
  341. },
  342. //添加表单列
  343. addClick() {
  344. this.poppleData = {
  345. status: 1,
  346. pid: 0,
  347. };
  348. this.statusPop = 1;
  349. this.dialogBox = true;
  350. },
  351. // 未定义
  352. emitData(v) {
  353. console.log(v);
  354. },
  355. // 接口数据转换级联类型
  356. arrayChangeType(options) {
  357. let result = [];
  358. if (!Array.isArray(options)) {
  359. return result;
  360. }
  361. options.forEach((item) => {
  362. delete item.children;
  363. });
  364. let map = {};
  365. options.forEach((item) => {
  366. map[item.categoryId] = item;
  367. });
  368. options.forEach((item) => {
  369. let parent = map[item.pid];
  370. if (parent) {
  371. (parent.children || (parent.children = [])).push(item);
  372. } else {
  373. result.push(item);
  374. }
  375. });
  376. return result;
  377. },
  378. sortBy(attr, rev) {
  379. //第二个参数没有传递 默认升序排列
  380. if (rev == undefined) {
  381. rev = 1;
  382. } else {
  383. rev = rev ? 1 : -1;
  384. }
  385. return function (a, b) {
  386. a = a[attr];
  387. b = b[attr];
  388. if (a < b) {
  389. return rev * -1;
  390. }
  391. if (a > b) {
  392. return rev * 1;
  393. }
  394. return 0;
  395. };
  396. },
  397. search(v) {
  398. this.loading = true;
  399. var self = this;
  400. var data = {
  401. status: "0,1",
  402. pageSize: this.pageSize,
  403. pageNum: this.currentPage,
  404. PId: 0,
  405. };
  406. this.$api
  407. .inquireProfessionClassification(data)
  408. .then((res) => {
  409. res.rows.forEach((item, index) => {
  410. item.hasChildren = true;
  411. });
  412. self.tableData = res.rows;
  413. console.log(self.tableData,33)
  414. self.tableData.sort(self.sortBy("sort", true));
  415. self.navText.index = res.total;
  416. self.total = res.total;
  417. self.loading = false;
  418. // self.getCascader();
  419. })
  420. .catch((err) => {
  421. this.loading = false;
  422. });
  423. },
  424. init() {
  425. this.search();
  426. },
  427. //点击多级触发异步
  428. async loadse(tree, treeNode, resolve) {
  429. this.treeObj[tree.categoryId] = { tree, treeNode, resolve };
  430. var data = {
  431. status: "0,1",
  432. PId: tree.categoryId,
  433. };
  434. const loadChildren = await this.$api.inquireProfessionClassification(
  435. data
  436. );
  437. if (Array.isArray(loadChildren.rows) && loadChildren.rows.length > 0) {
  438. loadChildren.rows.forEach((item) => {
  439. item.hasChildren = true;
  440. });
  441. loadChildren.rows.sort(this.sortBy("sort", true));
  442. resolve(loadChildren.rows); // 返回最终数据对象
  443. } else {
  444. tree.children = [];
  445. resolve([]);
  446. }
  447. },
  448. //点击多级触发异步
  449. // async loadse(tree, treeNode, resolve) {
  450. // this.treeObj[tree.categoryId] = { tree, treeNode, resolve };
  451. // var datasten = {
  452. // PId: tree.categoryId,
  453. // status: '0,1'
  454. // };
  455. // this.$api.inquireProfessionClassification(datasten).then((res) => {
  456. // res.rows.forEach((item, index) => {
  457. // item.hasChildren = true;
  458. // });
  459. // res.rows.sort(this.sortBy("sort", true));
  460. // if (res.rows.length === 0) {
  461. // this.$message.warning("暂无下级");
  462. // }
  463. // resolve(res.rows);
  464. // });
  465. // },
  466. handleSizeChange(v) {
  467. this.pageSize = v;
  468. this.currentPage = 1;
  469. this.search();
  470. },
  471. handleCurrentChange(v) {
  472. this.currentPage = v;
  473. this.search();
  474. },
  475. },
  476. };
  477. </script>
  478. <style lang="less" scoped>
  479. /deep/.el-button {
  480. border-radius: 8px;
  481. }
  482. /deep/.el-dialog {
  483. border-radius: 8px;
  484. .el-dialog__header {
  485. padding: 0;
  486. .hearders {
  487. height: 40px;
  488. display: flex;
  489. align-items: center;
  490. justify-content: space-between;
  491. padding: 0px 18px 0px 20px;
  492. border-bottom: 1px solid #e2e2e2;
  493. .leftTitle {
  494. font-size: 14px;
  495. font-weight: bold;
  496. color: #2f4378;
  497. }
  498. .rightBoxs {
  499. display: flex;
  500. align-items: center;
  501. img {
  502. width: 14px;
  503. height: 14px;
  504. margin-left: 13px;
  505. cursor: pointer;
  506. }
  507. }
  508. }
  509. }
  510. .el-dialog__body {
  511. padding: 0;
  512. .contentBox {
  513. padding: 20px 20px 5px;
  514. .el-col {
  515. padding: 0px 20px;
  516. margin-bottom: 30px;
  517. header {
  518. margin-bottom: 6px;
  519. color: #2f4378;
  520. font-size: 14px;
  521. }
  522. }
  523. }
  524. }
  525. .el-dialog__footer {
  526. padding: 0;
  527. .dialog-footer {
  528. padding: 0px 40px;
  529. height: 70px;
  530. border-top: 1px solid #e2e2e2;
  531. display: flex;
  532. align-items: center;
  533. justify-content: flex-end;
  534. }
  535. }
  536. }
  537. </style>