account.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755
  1. <template>
  2. <div class="content-box">
  3. <div class="left">
  4. <!-- <el-icon :size="23" class="camera"><VideoCameraFilled /></el-icon> -->
  5. <span class="cameratxt">账号管理</span>
  6. </div>
  7. <div class="middle">
  8. <div class="filter">
  9. <div class="condition">
  10. <span>账号 : </span>
  11. <el-input
  12. clearable
  13. v-model="searchInput.carnumber"
  14. class="w-50 m-2"
  15. placeholder="请输入账号"
  16. style="width: 150px"
  17. />
  18. </div>
  19. <div class="condition">
  20. <span>创建时间 : </span>
  21. <el-date-picker
  22. v-model="searchInput.createTime"
  23. type="date"
  24. format="YYYY-MM-DD"
  25. value-format="YYYY-MM-DD"
  26. :prefix-icon="Calendar"
  27. placeholder="请选择时间"
  28. />
  29. </div>
  30. <el-button
  31. style="margin-left: 20px"
  32. color="rgba(61, 81, 232, 1)"
  33. type="primary"
  34. class="search"
  35. @click="searchBtn"
  36. ><el-icon><Search /></el-icon> <span>查询</span></el-button
  37. >
  38. <el-button
  39. style="margin-left: 20px !important"
  40. color="rgba(61, 81, 232, 1)"
  41. type="primary"
  42. class="search"
  43. @click="searchRefresh"
  44. ><el-icon><Refresh /></el-icon><span>重置</span></el-button
  45. >
  46. </div>
  47. <!-- 按钮列表 -->
  48. <div class="gongneng">
  49. <el-button type="primary" color="rgba(61, 81, 232, 1)" @click="addlist"
  50. ><el-icon><CirclePlus /></el-icon><span>新增账号</span></el-button
  51. >
  52. <el-button
  53. color="rgba(61, 81, 232, 1)"
  54. class="import"
  55. type="primary"
  56. @click="importExcel"
  57. ><img
  58. src="@/assets/import.png"
  59. style="width: 14px; height: 14px; margin-right: 4px"
  60. alt=""
  61. />
  62. <span>导出表单</span></el-button
  63. >
  64. </div>
  65. </div>
  66. <div class="footer">
  67. <el-table
  68. :row-class-name="tableRowClassName"
  69. :data="tableData.list"
  70. @selection-change="handleSelectionChange"
  71. style="width: 100%"
  72. :header-cell-style="{
  73. background: 'rgba(240, 243, 247, 1)',
  74. height: '50px',
  75. border: 0,
  76. }"
  77. >
  78. <!-- <el-table-column align="center" type="selection" width="80" /> -->
  79. <el-table-column
  80. width="150"
  81. align="center"
  82. label="序号"
  83. type="index"
  84. index="1"
  85. />
  86. <el-table-column align="center" prop="name" label="姓名" />
  87. <el-table-column align="center" prop="number" label="账号" />
  88. <el-table-column align="center" prop="create_time" label="创建时间" />
  89. <el-table-column align="center" label="操作" width="220">
  90. <template #default="scope">
  91. <el-button link type="primary" @click="edit(scope.row)"
  92. ><div class="look">编辑</div></el-button
  93. >
  94. <el-button link type="danger" @click="del(scope.row)"
  95. ><div class="looks">删除</div></el-button
  96. >
  97. </template>
  98. </el-table-column>
  99. </el-table>
  100. <!-- 添加车辆弹窗 -->
  101. <el-dialog
  102. class="addStaff"
  103. v-model="addDialogVisible"
  104. :close-on-click-modal="false"
  105. :close-on-press-escape="false"
  106. :title="dialongTitle"
  107. align-center
  108. width="609"
  109. :before-close="cancelAdd"
  110. >
  111. <el-form
  112. ref="ruleFormRef"
  113. :model="ruleForm"
  114. :rules="rules"
  115. label-width="100px"
  116. class="demo-ruleForm"
  117. :size="formSize"
  118. label-position="left"
  119. status-icon
  120. >
  121. <el-form-item label="账号 :" prop="account">
  122. <el-input
  123. v-model="ruleForm.account"
  124. placeholder="请输入账号"
  125. clearable
  126. />
  127. </el-form-item>
  128. <el-form-item label="密码 :" prop="pass">
  129. <el-input
  130. v-model="ruleForm.pass"
  131. placeholder="请输入密码"
  132. clearable
  133. />
  134. </el-form-item>
  135. <el-form-item
  136. label="昵称 :"
  137. prop="name"
  138. style="
  139. padding-bottom: 40px;
  140. border-bottom: 1px solid rgba(230, 230, 230, 1);
  141. "
  142. >
  143. <el-input
  144. v-model="ruleForm.name"
  145. placeholder="请输入昵称"
  146. clearable
  147. />
  148. </el-form-item>
  149. <el-form-item class="options">
  150. <el-button class="congzhi" @click="cancelAdd()">取消</el-button>
  151. <el-button
  152. color="rgba(61, 81, 232, 1)"
  153. class="queding"
  154. type="primary"
  155. @click="submitAdd(ruleFormRef)"
  156. >
  157. 确定
  158. </el-button>
  159. </el-form-item>
  160. </el-form>
  161. </el-dialog>
  162. </div>
  163. <!-- 分页组件 -->
  164. <el-pagination
  165. background
  166. :current-page="currentPage"
  167. :page-size="pageSize"
  168. layout="total, prev, pager, next, jumper, slot"
  169. :total="total"
  170. @update:current-page="handleCurrentChange"
  171. />
  172. </div>
  173. </template>
  174. <script setup>
  175. import { ref, reactive, nextTick, onBeforeMount, onUnmounted } from "vue";
  176. import { useRouter } from "vue-router";
  177. import { ElMessage, ElMessageBox } from "element-plus";
  178. import { Calendar } from "@element-plus/icons-vue";
  179. import { dayjs } from "element-plus";
  180. import lodash from "lodash";
  181. import axios from "axios";
  182. import { useStore } from "vuex";
  183. const store = useStore();
  184. const router = useRouter();
  185. // 表格数据
  186. const tableData = reactive({ list: [] });
  187. const activeIndex = ref(); // 默认跳转路由
  188. const dialongTitle = ref("新增账号"); // 弹窗标题
  189. const searchInput = reactive({
  190. carnumber: "",
  191. createTime: "",
  192. }); // 搜索按钮数据
  193. 5;
  194. const currentPage = ref(1); // 当前页
  195. const pageSize = ref(10);
  196. const total = ref(); // 当前总数
  197. const selectData = reactive({ list: [] }); // 多选框选择的数据
  198. const api = ref("");
  199. const addDialogVisible = ref(false); // 控制添加员工弹窗
  200. // 表单数据
  201. const formSize = ref("default");
  202. const ruleFormRef = ref();
  203. const ruleForm = reactive({
  204. name: "",
  205. account: "",
  206. pass: "",
  207. id: "",
  208. });
  209. // 表单验证
  210. const rules = reactive({
  211. account: [
  212. { required: true, message: "账号不能为空", trigger: "blur" },
  213. // { min: 3, max: 5, message: "Length should be 3 to 5", trigger: "blur" },
  214. {
  215. pattern: /^[a-zA-z]\w{3,15}$/,
  216. message: "请输入正确账号",
  217. trigger: "blur",
  218. },
  219. ],
  220. // ^(?=.*[0-9])(?=.*[A-Z])(?=.*[a-z])(?=.*[!@#$%^&*,\._\+(){}])[0-9a-zA-Z!@#$%^&*,\\._\+(){}]{8,20}$
  221. pass: [
  222. {
  223. required: true,
  224. message: "密码不能为空",
  225. trigger: "blur",
  226. },
  227. {
  228. min: 8,
  229. max: 20,
  230. pattern:
  231. /^(?=.*[0-9])(?=.*[A-Z])(?=.*[a-z])(?=.*[!@#$%^&*,\._\+(){}])[0-9a-zA-Z!@#$%^&*,\\._\+(){}]{8,20}$/,
  232. message: "请输入8-20位正确密码(大小写字母·字符·数字)",
  233. trigger: "blur",
  234. },
  235. ],
  236. name: [
  237. {
  238. required: true,
  239. message: "昵称不能为空",
  240. trigger: "blur",
  241. },
  242. ],
  243. // desc: [{ required: true, message: "Please input activity form", trigger: "blur" }],
  244. });
  245. // 获取账户列表
  246. const getList = async (message) => {
  247. // let res = await vidiconsApi.queryCamera(data);
  248. let data = new FormData();
  249. if (searchInput.createTime == null) {
  250. searchInput.createTime = "";
  251. }
  252. data.set("number", searchInput.carnumber);
  253. data.set("create_time", searchInput.createTime); //前面的key记得对应!
  254. data.set("page", currentPage.value);
  255. data.set("rows", pageSize.value); //前面的key记得对应!
  256. // let res = await adminApi.adminLogin(data);
  257. let res = await axios({
  258. method: "post",
  259. url: api.value + "/carBook/adminlist.action",
  260. headers: {
  261. token: sessionStorage.getItem("token"),
  262. },
  263. data: data,
  264. });
  265. if (res.status == 200) {
  266. if (message) {
  267. ElMessage({
  268. type: "success",
  269. showClose: true,
  270. message: message,
  271. center: true,
  272. });
  273. }
  274. tableData.list = res.data.rows;
  275. // currentPage.value = res.data.currentPage;
  276. total.value = res.data.total;
  277. } else {
  278. tableData.list = res.data.rows;
  279. currentPage.value = 1;
  280. total.value = res.data.total;
  281. ElMessage({
  282. type: "error",
  283. showClose: true,
  284. message: res.data.message,
  285. center: true,
  286. });
  287. if (res.data.message == "token错误") {
  288. router.push({
  289. path: `/login`,
  290. });
  291. }
  292. }
  293. };
  294. // 搜索功能
  295. const searchBtn = lodash.debounce(async () => {
  296. getList("查询成功");
  297. }, 300);
  298. // 重置搜索
  299. const searchRefresh = lodash.debounce(async () => {
  300. searchInput.carnumber = "";
  301. searchInput.createTime = "";
  302. currentPage.value = 1;
  303. getList();
  304. }, 300);
  305. //导出功能
  306. const importExcel = async () => {
  307. if (searchInput.createTime == null) {
  308. searchInput.createTime = "";
  309. }
  310. let data = new FormData();
  311. data.set("number", searchInput.carnumber);
  312. data.set("create_time", searchInput.createTime);
  313. let res = await axios({
  314. method: "post",
  315. url: api.value + "/carBook/admintoExcel.action",
  316. headers: {
  317. token: sessionStorage.getItem("token"),
  318. },
  319. data: data,
  320. });
  321. // console.log(res, "导出账号");
  322. if (res.data.code == 200) {
  323. // const elt = document.createElement("a");
  324. // elt.setAttribute(
  325. // "href",
  326. // "https://chtech.ncjti.edu.cn/carstop" + res.data.downurl
  327. // );
  328. // // elt.setAttribute("download", "file.xlsx");
  329. // // elt.style.display = "none";
  330. // document.body.appendChild(elt);
  331. var downloadPath = "https://chtech.ncjti.edu.cn/carstop" + res.data.downurl;
  332. console.log("获得地址数据:", downloadPath);
  333. var downloadLink = document.createElement("a");
  334. downloadLink.style.display = "none"; // 使其隐藏
  335. downloadLink.href = downloadPath;
  336. downloadLink.download = "";
  337. downloadLink.click();
  338. document.body.appendChild(downloadLink);
  339. document.body.removeChild(downloadLink);
  340. elt.click();
  341. ElMessage({
  342. type: "success",
  343. showClose: true,
  344. message: res.data.message,
  345. center: true,
  346. });
  347. } else {
  348. ElMessage({
  349. type: "error",
  350. showClose: true,
  351. message: res.data.message,
  352. center: true,
  353. });
  354. }
  355. };
  356. // 添加员工
  357. const addlist = () => {
  358. dialongTitle.value = "新增账号";
  359. addDialogVisible.value = true;
  360. ruleForm.name = "";
  361. ruleForm.account = "";
  362. ruleForm.pass = "";
  363. };
  364. // 取消添加员工
  365. const cancelAdd = () => {
  366. addDialogVisible.value = false;
  367. ruleFormRef.value.resetFields();
  368. };
  369. // 确认添加员工
  370. const submitAdd = async (formEl) => {
  371. if (!formEl) return;
  372. await formEl.validate(async (valid, fields) => {
  373. if (valid) {
  374. if (dialongTitle.value == "新增账号") {
  375. let data = {
  376. name: ruleForm.name,
  377. number: ruleForm.account,
  378. password: ruleForm.pass,
  379. };
  380. // let res = await admin.adminAdd(data);
  381. let res = await axios({
  382. method: "post",
  383. url: api.value + "/carBook/admininsert.action",
  384. headers: {
  385. "Content-Type": "application/json;charset=utf-8",
  386. token: sessionStorage.getItem("token"),
  387. },
  388. data: data,
  389. });
  390. // console.log(res, "添加账号");
  391. if (res.data.code == 200) {
  392. getList();
  393. ElMessage({
  394. type: "success",
  395. showClose: true,
  396. message: res.data.message,
  397. center: true,
  398. });
  399. addDialogVisible.value = false;
  400. ruleFormRef.value.resetFields();
  401. } else {
  402. ElMessage({
  403. type: "error",
  404. showClose: true,
  405. message: res.data.message,
  406. center: true,
  407. });
  408. }
  409. } else {
  410. let data = {
  411. name: ruleForm.name,
  412. number: ruleForm.account,
  413. password: ruleForm.pass,
  414. id: ruleForm.id,
  415. };
  416. // let res = await admin.adminAdd(data);
  417. let res = await axios({
  418. method: "post",
  419. url: api.value + "/carBook/adminupdate.action",
  420. headers: {
  421. "Content-Type": "application/json;charset=utf-8",
  422. token: sessionStorage.getItem("token"),
  423. },
  424. data: data,
  425. });
  426. // console.log(res, "修改账号");
  427. if (res.data.code == 200) {
  428. getList();
  429. ElMessage({
  430. type: "success",
  431. showClose: true,
  432. message: res.data.message,
  433. center: true,
  434. });
  435. addDialogVisible.value = false;
  436. ruleFormRef.value.resetFields();
  437. } else {
  438. ElMessage({
  439. type: "error",
  440. showClose: true,
  441. message: res.data.message,
  442. center: true,
  443. });
  444. }
  445. }
  446. } else {
  447. console.log("error submit!", fields);
  448. }
  449. });
  450. };
  451. //编辑按钮
  452. const edit = (row) => {
  453. dialongTitle.value = "编辑信息";
  454. addDialogVisible.value = true;
  455. console.log(row);
  456. ruleForm.pass = row.password;
  457. ruleForm.name = row.name;
  458. ruleForm.account = row.number;
  459. ruleForm.id = row.id;
  460. };
  461. //删除按钮
  462. const del = (row) => {
  463. console.log(row);
  464. ElMessageBox.confirm(`是否删除 ${row.number} 账号?`, "提示", {
  465. confirmButtonText: "确认",
  466. cancelButtonText: "取消",
  467. type: "warning",
  468. })
  469. .then(async () => {
  470. let data = new FormData();
  471. data.set("id", row.id);
  472. // let res = await adminApi.adminLogin(data);
  473. let res = await axios({
  474. method: "post",
  475. url: api.value + "/carBook/admindel.action",
  476. headers: {
  477. token: sessionStorage.getItem("token"),
  478. },
  479. data: data,
  480. });
  481. if (res.data.code == 200) {
  482. if (tableData.list.length == 1 && currentPage.value != 1) {
  483. currentPage.value = currentPage.value - 1;
  484. }
  485. getList();
  486. ElMessage({
  487. type: "success",
  488. showClose: true,
  489. message: res.data.message,
  490. center: true,
  491. });
  492. } else {
  493. ElMessage({
  494. type: "error",
  495. showClose: true,
  496. message: res.data.message,
  497. center: true,
  498. });
  499. }
  500. console.log(res);
  501. })
  502. .catch(() => {
  503. ElMessage({
  504. type: "info",
  505. message: "已取消删除",
  506. });
  507. });
  508. };
  509. // 多选框功能
  510. // const handleSelectionChange = (val) => {
  511. // console.log(val);
  512. // selectData.list = val;
  513. // };
  514. // 表格斑马纹颜色修改
  515. const tableRowClassName = ({ row, rowIndex }) => {
  516. if (rowIndex % 2 === 0) {
  517. return "even";
  518. } else if (rowIndex % 2 !== 0) {
  519. return "odd";
  520. }
  521. return "";
  522. };
  523. // 分页
  524. const handleCurrentChange = (value) => {
  525. // console.log(value);
  526. currentPage.value = value;
  527. getList();
  528. };
  529. onBeforeMount(() => {
  530. api.value = store.state.user.api;
  531. getList();
  532. });
  533. onUnmounted(() => {
  534. // document.removeEventListener("keyup", Enters);
  535. });
  536. </script>
  537. <style scoped lang="scss">
  538. .content-box {
  539. width: calc(100% - 40px);
  540. height: calc(100% - 105px);
  541. margin: 20px auto;
  542. background-color: #fff;
  543. color: #fff;
  544. display: flex;
  545. flex-direction: column;
  546. .left {
  547. width: calc(100% - 60px);
  548. display: flex;
  549. align-items: center;
  550. height: 60px;
  551. margin: 0 30px;
  552. border-bottom: 1px solid #ccc;
  553. color: #000;
  554. font-size: 18px;
  555. font-weight: 600;
  556. .camera {
  557. margin-right: 15px;
  558. color: #4392f7;
  559. }
  560. }
  561. .middle {
  562. width: calc(100% - 60px);
  563. margin: 0 auto;
  564. color: #000;
  565. // border-bottom: 1px solid rgb(231, 231, 231);
  566. .filter {
  567. display: flex;
  568. flex-wrap: wrap;
  569. align-items: center;
  570. margin: 10px 0 0 0;
  571. .search {
  572. margin-left: 0 !important;
  573. }
  574. .condition {
  575. display: flex;
  576. align-items: center;
  577. margin: 10px 30px 10px 0;
  578. :deep(.el-input .el-input__inner) {
  579. font-size: 16px;
  580. }
  581. span {
  582. margin: 0 10px 0 0;
  583. }
  584. }
  585. }
  586. .gongneng {
  587. margin: 10px 0;
  588. }
  589. :deep(.cont) {
  590. width: 60%;
  591. margin: 20px auto;
  592. }
  593. :deep(.download) {
  594. display: flex;
  595. align-items: center;
  596. margin: 10px;
  597. }
  598. :deep(.download span) {
  599. font-size: 16px;
  600. margin-left: 20px;
  601. }
  602. :deep(.cont .el-button) {
  603. margin-left: 60px;
  604. margin-bottom: 30px;
  605. }
  606. :deep(.cont .accomplish) {
  607. width: 100%;
  608. display: flex;
  609. justify-content: center;
  610. }
  611. :deep(.cont .accomplish .el-button) {
  612. width: 50%;
  613. margin: 0;
  614. }
  615. }
  616. .footer {
  617. width: calc(100% - 60px);
  618. flex:1;
  619. margin: 10px auto 10px;
  620. overflow: auto;
  621. .el-table--fit {
  622. height: 100%;
  623. :deep(.el-table__header-wrapper) {
  624. background-color: #000;
  625. font-size: 16px;
  626. color: #000;
  627. }
  628. :deep(.el-table__row) {
  629. height: 50px;
  630. font-size: 16px;
  631. color: #000;
  632. }
  633. :deep(.el-table__row td) {
  634. padding: 0;
  635. border: 0;
  636. }
  637. .el-button--primary {
  638. margin-left: 5px;
  639. }
  640. :deep(.el-table__body .even) {
  641. background-color: #fff;
  642. }
  643. :deep(.el-table__body .odd) {
  644. background-color: rgba(240, 243, 247, 1);
  645. }
  646. :deep(.look) {
  647. padding: 5px 10px;
  648. border-radius: 45px;
  649. border: 0.74px solid rgba(30, 125, 251, 1);
  650. }
  651. :deep(.looks) {
  652. padding: 5px 10px;
  653. border-radius: 45px;
  654. border: 0.74px solid #f56c6c;
  655. }
  656. }
  657. // 添加员工弹窗样式
  658. :deep(.addStaff) {
  659. // height: 420px;
  660. border-radius: 11px;
  661. .el-dialog__header {
  662. border-radius: 11px 11px 0 0;
  663. background: rgba(237, 241, 245, 1);
  664. font-weight: 600;
  665. margin: 0;
  666. .el-dialog__headerbtn {
  667. outline: none;
  668. }
  669. }
  670. .el-dialog__body {
  671. padding: 30px 20px 10px 20px;
  672. .el-input {
  673. width: 200px;
  674. .el-input__suffix-inner {
  675. color: rgba(61, 81, 232, 1);
  676. }
  677. }
  678. .options {
  679. margin-left: 320px;
  680. }
  681. }
  682. }
  683. }
  684. .el-pagination {
  685. // width: 1600px;
  686. width: calc(100% - 60px);
  687. height: 60px;
  688. margin: 0 30px;
  689. justify-content: flex-end;
  690. :deep(.el-pagination__total) {
  691. color: #000;
  692. }
  693. :deep(.el-pagination__goto) {
  694. color: #000;
  695. }
  696. :deep(.el-pagination__classifier) {
  697. color: #000;
  698. }
  699. :deep(.el-input__wrapper) {
  700. border: 1px solid rgba(0, 0, 0, 1);
  701. border-radius: 5px;
  702. box-shadow: none;
  703. }
  704. :deep(.el-pager li) {
  705. margin: 0 5px;
  706. border: 1px solid rgba(0, 0, 0, 1);
  707. border-radius: 5px;
  708. background-color: transparent;
  709. }
  710. :deep(.el-pager li.is-active) {
  711. background-color: rgba(30, 125, 251, 1);
  712. }
  713. :deep(.btn-prev) {
  714. margin-right: 5px;
  715. border: 1px solid rgba(0, 0, 0, 1);
  716. border-radius: 5px;
  717. background-color: transparent;
  718. }
  719. :deep(.btn-next) {
  720. margin-left: 5px;
  721. border: 1px solid rgba(0, 0, 0, 1);
  722. border-radius: 5px;
  723. background-color: transparent;
  724. }
  725. }
  726. }
  727. .el-input {
  728. width: 192px;
  729. }
  730. </style>