index.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  1. <template>
  2. <div id="department">
  3. <search-box :formList="formList" @search="search" @init="init" />
  4. <table-list
  5. :tableSets="tableSet"
  6. :tableData="tableData"
  7. :navText="navText"
  8. @addClick="addClick"
  9. :loading="loading"
  10. :rowKey="rowKey"
  11. >
  12. <template slot="btn" slot-scope="props">
  13. <el-button type="text" @click="addClick(props.scope.row, 2)"
  14. >新增</el-button
  15. >
  16. <el-button type="text" @click="addClick(props.scope.row, 0)"
  17. >修改</el-button
  18. >
  19. <el-button type="text" @click="del(props.scope.row)">删除</el-button>
  20. </template>
  21. </table-list>
  22. <!-- <pagination
  23. :total="total"
  24. :pageSize="pageSize"
  25. :currentPage="currentPage"
  26. @handleSizeChange="handleSizeChange"
  27. @handleCurrentChange="handleCurrentChange"
  28. /> -->
  29. <el-dialog
  30. :visible.sync="dialogVisible"
  31. width="480px"
  32. :show-close="false"
  33. :close-on-click-modal="false"
  34. >
  35. <div slot="title" class="hearders">
  36. <div class="leftTitle">
  37. {{ statusPop === 1 ? "添加" : statusPop === 0 ? "修改" : "添加下级" }}
  38. </div>
  39. <div class="rightBoxs">
  40. <img src="@/assets/images/Close@2x.png" alt="" @click="close" />
  41. </div>
  42. </div>
  43. <div>
  44. <el-form
  45. label-position="right"
  46. label-width="80px"
  47. :model="listData"
  48. :rules="rules"
  49. ref="listData"
  50. >
  51. <el-form-item
  52. v-for="(items, indexs) in listitem"
  53. :key="indexs"
  54. :label="items.label"
  55. :prop="items.prop"
  56. >
  57. <el-radio-group
  58. v-if="items.scope === 'status'"
  59. v-model="listData[items.prop]"
  60. >
  61. <el-radio
  62. v-for="(item, index) in items.options"
  63. :key="index"
  64. :label="item.value"
  65. >{{ item.label }}</el-radio
  66. >
  67. </el-radio-group>
  68. <treeselect
  69. v-else-if="items.scope === 'selectMore'"
  70. v-model="listData[items.prop]"
  71. :options="optionsCascader"
  72. :normalizer="normalizer"
  73. :show-count="true"
  74. placeholder="选择上级菜单"
  75. />
  76. <el-input-number
  77. style="width: 100%"
  78. v-else-if="items.scope === 'numberIndex'"
  79. v-model="listData[items.prop]"
  80. controls-position="right"
  81. :min="0"
  82. :max="99"
  83. ></el-input-number>
  84. <el-input v-else v-model="listData[items.prop]"></el-input>
  85. </el-form-item>
  86. </el-form>
  87. </div>
  88. <span slot="footer" class="dialog-footer">
  89. <el-button @click="close">取 消</el-button>
  90. <el-button type="primary" @click="submit('listData')">确 定</el-button>
  91. </span>
  92. </el-dialog>
  93. </div>
  94. </template>
  95. <script>
  96. import Treeselect from "@riophae/vue-treeselect";
  97. import "@riophae/vue-treeselect/dist/vue-treeselect.css";
  98. import searchBox from "@/components/searchBox";
  99. import tableList from "@/components/tableList";
  100. import pagination from "@/components/pagination";
  101. export default {
  102. components: { Treeselect, searchBox, tableList, pagination },
  103. data() {
  104. return {
  105. loading: false, //当前表单加载是否加载动画
  106. rowKey: "deptId",
  107. navText: {
  108. title: "部门管理",
  109. index: 0,
  110. ch: "条",
  111. num: false,
  112. choice: false,
  113. addHide: false,
  114. backFatherBtn: {
  115. status: false,
  116. title: "未定义",
  117. },
  118. },
  119. //搜索
  120. formList: [
  121. {
  122. label: "部门名称",
  123. prop: "deptName",
  124. placeholder: "请输入部门名称",
  125. },
  126. {
  127. label: "状态",
  128. prop: "status",
  129. placeholder: "请选择状态",
  130. scope: "select",
  131. options: [
  132. {
  133. label: "启用",
  134. value: 1,
  135. },
  136. {
  137. label: "停用",
  138. value: 0,
  139. },
  140. ],
  141. },
  142. ],
  143. // 表单
  144. tableSet: [
  145. {
  146. label: "部门名称",
  147. prop: "deptName",
  148. hidden: true,
  149. },
  150. {
  151. label: "排序",
  152. prop: "orderNum",
  153. hidden: true,
  154. },
  155. {
  156. label: "状态",
  157. prop: "status",
  158. hidden: true,
  159. scope: "status",
  160. },
  161. {
  162. label: "创建时间",
  163. prop: "createTime",
  164. hidden: true,
  165. },
  166. ],
  167. tableData: [], //表单数据
  168. total: 0, //一共多少条
  169. pageSize: 999, //每页多少条数据
  170. currentPage: 1, //当前页码
  171. // 弹窗字段
  172. listitem: [
  173. {
  174. label: "上级部门",
  175. prop: "parentId",
  176. scope: "selectMore",
  177. },
  178. {
  179. label: "部门名称",
  180. prop: "deptName",
  181. },
  182. {
  183. label: "显示排序",
  184. prop: "orderNum",
  185. scope: "numberIndex",
  186. },
  187. {
  188. label: "负责人",
  189. prop: "leader",
  190. },
  191. {
  192. label: "联系电话",
  193. prop: "phone",
  194. },
  195. {
  196. label: "邮箱",
  197. prop: "email",
  198. },
  199. {
  200. label: "部门状态",
  201. prop: "status",
  202. scope: "status",
  203. options: [
  204. {
  205. label: "启用",
  206. value: "1",
  207. },
  208. {
  209. label: "关闭",
  210. value: "0",
  211. },
  212. ],
  213. },
  214. ],
  215. // 弹窗数据
  216. listData: {},
  217. statusPop: -1,
  218. dialogVisible: false,
  219. optionsCascader: [], //弹窗分类数据
  220. //表单验证
  221. rules: {
  222. parentId: [
  223. { required: true, message: "请选择上级部门", trigger: "change" },
  224. ],
  225. deptName: [
  226. { required: true, message: "请输入部门名称", trigger: "blur" },
  227. ],
  228. orderNum: [
  229. { required: true, message: "请输入显示排序", trigger: "blur" },
  230. ],
  231. // leader: [{ required: true, message: "请填写负责人", trigger: "blur" }],
  232. status: [
  233. { required: true, message: "请选择部门状态", trigger: "change" },
  234. ],
  235. },
  236. };
  237. },
  238. mounted() {
  239. this.search();
  240. },
  241. methods: {
  242. search(v) {
  243. this.loading = true;
  244. if (v === undefined) {
  245. v = {
  246. statusArray: "0,1",
  247. pageSize: this.pageSize,
  248. pageNum: this.currentPage,
  249. };
  250. }
  251. var data = {
  252. deptName: v.deptName || "",
  253. statusArray: v.status === undefined ? "0,1" : v.status,
  254. pageSize: this.pageSize,
  255. pageNum: this.currentPage,
  256. };
  257. this.$api
  258. .obtainDeptList(data)
  259. .then((res) => {
  260. this.initSelect();
  261. this.tableData = this.handleTree(
  262. res.data,
  263. "deptId",
  264. "parentId",
  265. "children"
  266. );
  267. this.total = res.data.length;
  268. this.navText.index = res.data.length;
  269. this.loading = false;
  270. })
  271. .catch((err) => {
  272. this.loading = false;
  273. });
  274. },
  275. initSelect() {
  276. var data = {
  277. deptName: "",
  278. statusArray: "0,1",
  279. pageSize: this.pageSize,
  280. pageNum: this.currentPage,
  281. };
  282. this.$api
  283. .obtainDeptList(data)
  284. .then((res) => {
  285. var bf = [
  286. {
  287. deptId: 0,
  288. parentId: null,
  289. deptName: "主分类",
  290. },
  291. ];
  292. bf = bf.concat(res.data);
  293. this.optionsCascader = this.handleTree(
  294. bf,
  295. "deptId",
  296. "parentId",
  297. "children"
  298. );
  299. })
  300. .catch((err) => {});
  301. },
  302. init() {
  303. this.search();
  304. },
  305. del(v) {
  306. this.$confirm("此操作将删除该条部门数据, 是否继续?", "提示", {
  307. confirmButtonText: "确定",
  308. cancelButtonText: "取消",
  309. type: "warning",
  310. })
  311. .then(() => {
  312. var data = v;
  313. data.status = -1;
  314. this.$api.editDept(data).then((res) => {
  315. if (res.code === 200) {
  316. this.$message.success("删除成功");
  317. this.search();
  318. this.dialogVisible = false;
  319. }
  320. });
  321. })
  322. .catch(() => {
  323. this.$message({
  324. type: "info",
  325. message: "已取消删除",
  326. });
  327. });
  328. },
  329. addClick(v, int) {
  330. if (v === undefined) {
  331. this.statusPop = 1;
  332. this.listData = {};
  333. } else {
  334. this.statusPop = int;
  335. if (int === 2) {
  336. this.listData = {
  337. parentId: v.deptId,
  338. };
  339. } else {
  340. var data = v.deptId;
  341. this.$api.obtainDeptId(data).then((res) => {
  342. this.listData = res.data;
  343. });
  344. }
  345. }
  346. this.dialogVisible = true;
  347. },
  348. submit(formName) {
  349. this.$refs[formName].validate((valid) => {
  350. if (valid) {
  351. this.rulesTableSumbit();
  352. } else {
  353. return false;
  354. }
  355. });
  356. },
  357. rulesTableSumbit() {
  358. var data = this.listData;
  359. if (this.statusPop === 0) {
  360. this.$api.editDept(data).then((res) => {
  361. if (res.code === 200) {
  362. this.$message.success("修改成功");
  363. this.search();
  364. this.dialogVisible = false;
  365. }
  366. });
  367. } else {
  368. this.$api.addDept(data).then((res) => {
  369. if (res.code === 200) {
  370. this.$message.success("新增成功");
  371. this.search();
  372. this.dialogVisible = false;
  373. }
  374. });
  375. }
  376. },
  377. close() {
  378. this.dialogVisible = false;
  379. },
  380. normalizer(node) {
  381. if (node.children && !node.children.length) {
  382. delete node.children;
  383. }
  384. return {
  385. id: node.deptId,
  386. label: node.deptName,
  387. children: node.children,
  388. };
  389. },
  390. handleSizeChange(v) {
  391. this.pageSize = v;
  392. this.currentPage = 1;
  393. this.search();
  394. },
  395. handleCurrentChange(v) {
  396. this.currentPage = v;
  397. this.search();
  398. },
  399. },
  400. };
  401. </script>
  402. <style lang="less" scoped>
  403. /deep/.el-button {
  404. border-radius: 8px;
  405. }
  406. /deep/.el-dialog {
  407. border-radius: 8px;
  408. .el-dialog__header {
  409. padding: 0;
  410. .hearders {
  411. height: 40px;
  412. display: flex;
  413. align-items: center;
  414. justify-content: space-between;
  415. padding: 0px 18px 0px 20px;
  416. border-bottom: 1px solid #e2e2e2;
  417. .leftTitle {
  418. font-size: 14px;
  419. font-weight: bold;
  420. color: #2f4378;
  421. }
  422. .rightBoxs {
  423. display: flex;
  424. align-items: center;
  425. img {
  426. width: 14px;
  427. height: 14px;
  428. margin-left: 13px;
  429. cursor: pointer;
  430. }
  431. }
  432. }
  433. }
  434. .el-dialog__footer {
  435. padding: 0;
  436. .dialog-footer {
  437. padding: 0px 40px;
  438. height: 70px;
  439. border-top: 1px solid #e2e2e2;
  440. display: flex;
  441. align-items: center;
  442. justify-content: flex-end;
  443. }
  444. }
  445. }
  446. .imgBox {
  447. width: 100%;
  448. // height: 210px;
  449. border: 1px solid #e2e2e2;
  450. border-radius: 8px;
  451. padding: 8px 8px 3px;
  452. display: flex;
  453. flex-direction: column;
  454. align-items: center;
  455. .imgLabel {
  456. flex: 1;
  457. width: 100%;
  458. border: 1px dotted #e2e2e2;
  459. color: #999;
  460. font-size: 14px;
  461. cursor: pointer;
  462. border-radius: 8px;
  463. .msPhoto {
  464. display: flex;
  465. justify-content: center;
  466. align-items: center;
  467. max-width: 100%;
  468. max-height: 270px;
  469. img {
  470. max-width: 100%;
  471. max-height: 270px;
  472. }
  473. }
  474. .imgbbx {
  475. display: flex;
  476. flex-direction: column;
  477. align-items: center;
  478. justify-content: center;
  479. width: 100%;
  480. height: 100%;
  481. i {
  482. font-weight: bold;
  483. margin: 14px 0;
  484. font-size: 24px;
  485. }
  486. }
  487. }
  488. p {
  489. margin: 5px 0px;
  490. }
  491. }
  492. </style>