account.vue 19 KB

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