devicePerson-list.vue 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686
  1. <template>
  2. <div>
  3. <el-breadcrumb separator=">">
  4. <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
  5. <el-breadcrumb-item>
  6. <a href="#">系统管理</a>
  7. </el-breadcrumb-item>
  8. <el-breadcrumb-item>
  9. <a href="#">设备人员管理</a>
  10. </el-breadcrumb-item>
  11. </el-breadcrumb>
  12. <el-divider></el-divider>
  13. <!--
  14. 要resetFields起作用,必须配置:model和prop
  15. -->
  16. <el-form
  17. ref="queryForm"
  18. :model="queryModel"
  19. :rules="ruleValidate"
  20. inline
  21. class="demo-form-inline"
  22. >
  23. <div>
  24. <el-form-item label="绑定设备名称" prop="deviceId">
  25. <el-select
  26. v-model="queryModel.deviceId"
  27. size="mini"
  28. filterable
  29. clearable
  30. remote
  31. style="width:220px;"
  32. placeholder="请输入关键词"
  33. :remote-method="queryDevice"
  34. >
  35. <el-option
  36. v-for="device in deviceResult"
  37. :key="device.id"
  38. :label="device.aliasName"
  39. :value="device.id"
  40. ></el-option>
  41. </el-select>
  42. </el-form-item>
  43. <el-form-item label="姓名" prop="name">
  44. <el-input type="text" size="mini" v-model="queryModel.name"></el-input>
  45. </el-form-item>
  46. <el-form-item label="手机号" prop="phone">
  47. <el-input type="text" size="mini" v-model="queryModel.phone"></el-input>
  48. </el-form-item>
  49. <el-form-item label="身份证" prop="idCard">
  50. <el-input type="text" size="mini" v-model="queryModel.idCard"></el-input>
  51. </el-form-item>
  52. <el-form-item>
  53. <el-button
  54. type="primary"
  55. size="mini"
  56. icon="ios-search"
  57. @click="handleQuery"
  58. :loading="loading"
  59. >查询</el-button>&nbsp;
  60. <el-button
  61. type="info"
  62. size="mini"
  63. style="margin-left: 8px"
  64. @click="handleReset('queryForm')"
  65. >重置</el-button>&nbsp;
  66. </el-form-item>
  67. </div>
  68. <div>
  69. <el-form-item label="单位" prop="parentId">
  70. <el-select-tree
  71. size="mini"
  72. :props="props"
  73. :options="companyResult"
  74. :value="queryModel.parentId"
  75. @getValue="getSelectedValue($event)"
  76. height="200"
  77. ></el-select-tree>&nbsp;
  78. <el-checkbox v-model="queryModel.subordinate">是否包含下级单位</el-checkbox>
  79. </el-form-item>
  80. <el-form-item label="是否上传照片" prop="isUploadPhoto">
  81. <el-select
  82. v-model="queryModel.isUploadPhoto"
  83. size="mini"
  84. filterable
  85. placeholder="请选择"
  86. style="width:120px"
  87. >
  88. <el-option value label="全部"></el-option>
  89. <el-option value="1" label="已上传"></el-option>
  90. <el-option value="0" label="未上传"></el-option>
  91. </el-select>
  92. </el-form-item>
  93. <el-form-item label="是否同步" prop="isBound">
  94. <el-select
  95. v-model="queryModel.isBound"
  96. size="mini"
  97. filterable
  98. placeholder="请选择"
  99. style="width:120px"
  100. >
  101. <el-option value label="全部"></el-option>
  102. <el-option value="1" label="已同步"></el-option>
  103. <el-option value="0" label="未同步"></el-option>
  104. </el-select>
  105. </el-form-item>
  106. </div>
  107. <div>
  108. <el-form-item v-if="position1Show" :label="position1" prop="position1">
  109. <el-input type="text" size="mini" v-model="queryModel.position1"></el-input>
  110. </el-form-item>
  111. <el-form-item v-if="position2Show" :label="position2" prop="position2">
  112. <el-input type="text" size="mini" v-model="queryModel.position2"></el-input>
  113. </el-form-item>
  114. <el-form-item v-if="position3Show" :label="position3" prop="position3">
  115. <el-input type="text" size="mini" v-model="queryModel.position3"></el-input>
  116. </el-form-item>
  117. <el-form-item v-if="position4Show" :label="position4" prop="position4">
  118. <el-input type="text" size="mini" v-model="queryModel.position4"></el-input>
  119. </el-form-item>
  120. <el-form-item v-if="position5Show" :label="position5" prop="position5">
  121. <el-input type="text" size="mini" v-model="queryModel.position5"></el-input>
  122. </el-form-item>
  123. </div>
  124. </el-form>
  125. <el-divider></el-divider>
  126. <el-row class="button-group">
  127. <el-button
  128. type="primary"
  129. size="small"
  130. plain
  131. icon="el-icon-refresh"
  132. :disabled="multipleSelection.length==0"
  133. @click="dataSync"
  134. >数据同步</el-button>
  135. </el-row>
  136. <el-table
  137. ref="formTable"
  138. :data="tableData"
  139. v-loading="loading"
  140. stripe
  141. :height="tableHeight"
  142. @sort-change="sortChange"
  143. @selection-change="handleSelectionChange"
  144. >
  145. <el-table-column type="selection" width="55"></el-table-column>
  146. <el-table-column prop="personInfo.id" label="序号" width="80" fixed="left"></el-table-column>
  147. <el-table-column prop="personInfo.name" label="姓名" width="80" fixed="left"></el-table-column>
  148. <el-table-column prop="personInfo.faceImageUrl" label="人员照片" width="80" fixed="left">
  149. <template v-if="row.personInfo.faceImageUrl" slot-scope="{row}">
  150. <a :href="row.personInfo.faceImageUrl" target="_blank">
  151. <el-avatar
  152. :size="48"
  153. shape="circle"
  154. :src="row.personInfo.faceImageUrl+'?x-oss-process=image/resize,m_fill,w_64,h_64'"
  155. :key="row.personInfo.id"
  156. ></el-avatar>
  157. </a>
  158. </template>
  159. </el-table-column>
  160. <el-table-column prop="personInfo.companyName" label="单位" width="250"></el-table-column>
  161. <el-table-column prop="personInfo.phone" label="手机号" width="180"></el-table-column>
  162. <el-table-column prop="personInfo.idCard" label="身份证" width="100" show-overflow-tooltip></el-table-column>
  163. <el-table-column prop="deviceInfo.aliasName" label="绑定设备" width="150" show-overflow-tooltip></el-table-column>
  164. <el-table-column prop="isBound" label="是否同步到设备" width="150" show-overflow-tooltip>
  165. <template slot-scope="{row}">{{row.isBound ? "是" : "否"}}</template>
  166. </el-table-column>
  167. <el-table-column
  168. prop="personInfo.position1"
  169. :label="position1"
  170. width="180"
  171. v-if="position1Show"
  172. ></el-table-column>
  173. <el-table-column
  174. prop="personInfo.position2"
  175. :label="position2"
  176. width="180"
  177. v-if="position2Show"
  178. ></el-table-column>
  179. <el-table-column
  180. prop="personInfo.position3"
  181. :label="position3"
  182. width="180"
  183. v-if="position3Show"
  184. ></el-table-column>
  185. <el-table-column
  186. prop="personInfo.position4"
  187. :label="position4"
  188. width="180"
  189. v-if="position4Show"
  190. ></el-table-column>
  191. <el-table-column
  192. prop="personInfo.position5"
  193. :label="position5"
  194. width="180"
  195. v-if="position5Show"
  196. ></el-table-column>
  197. <el-table-column prop="personInfo.openId" label="是否绑定公众号" width="180">
  198. <template slot-scope="{row}">{{row.personInfo.openId == null ? "否" : "是"}}</template>
  199. </el-table-column>
  200. <!-- <el-table-column prop="personInfo.faceBound" label="是否同步人脸信息" width="180">
  201. <template slot-scope="{row}">{{row.personInfo.faceBound ? "是" : "否"}}</template>
  202. </el-table-column>-->
  203. <el-table-column prop="personInfo.popedom" label="用户身份" width="200">
  204. <template slot-scope="{row}">
  205. <el-row>
  206. <el-col :span="10" v-if="row.personInfo.popedom.indexOf('1')!= -1">个人用户</el-col>
  207. <el-col :span="10" v-if="row.personInfo.popedom.indexOf('2')!= -1">单位管理员</el-col>
  208. <el-col :span="10" v-if="row.personInfo.popedom.indexOf('3')!= -1">监管专员</el-col>
  209. </el-row>
  210. </template>
  211. </el-table-column>
  212. <el-table-column label="人脸授权">
  213. <template slot-scope="{row}">
  214. <el-switch
  215. v-model="row.personInfo.faceEnabled"
  216. active-color="#13ce66"
  217. inactive-color="#ff4949"
  218. disabled
  219. ></el-switch>
  220. </template>
  221. </el-table-column>
  222. <el-table-column label="刷卡授权">
  223. <template slot-scope="{row}">
  224. <el-switch
  225. v-model="row.personInfo.cardEnabled"
  226. active-color="#13ce66"
  227. inactive-color="#ff4949"
  228. disabled
  229. ></el-switch>
  230. </template>
  231. </el-table-column>
  232. <el-table-column label="手机授权">
  233. <template slot-scope="{row}">
  234. <el-switch
  235. v-model="row.personInfo.appEnabled"
  236. active-color="#13ce66"
  237. inactive-color="#ff4949"
  238. disabled
  239. ></el-switch>
  240. </template>
  241. </el-table-column>
  242. <!-- <el-table-column label="密码">
  243. <template slot-scope="{row}">
  244. <el-switch v-model="row.passwordEnabled" @change="enabledTo(row.id,'face')" active-color="#13ce66" inactive-color="#ff4949"></el-switch>
  245. </template>
  246. </el-table-column>-->
  247. <el-table-column label="访客授权">
  248. <template slot-scope="{row}">
  249. <el-switch
  250. v-model="row.personInfo.guestEnabled"
  251. active-color="#13ce66"
  252. inactive-color="#ff4949"
  253. disabled
  254. ></el-switch>
  255. </template>
  256. </el-table-column>
  257. <el-table-column label="接收微信通知">
  258. <template slot-scope="{row}">
  259. <el-switch
  260. v-model="row.personInfo.wechatNoticeEnabled"
  261. active-color="#13ce66"
  262. inactive-color="#ff4949"
  263. disabled
  264. ></el-switch>
  265. </template>
  266. </el-table-column>
  267. <el-table-column label="操作" width="80" fixed="right">
  268. <template slot-scope="{row}">
  269. <el-row>
  270. <el-col>
  271. <span v-if="row.isBound">
  272. <el-link
  273. type="primary"
  274. :underline="false"
  275. :disabled="true"
  276. @click="uploadData(row)"
  277. >数据同步</el-link>
  278. </span>
  279. <span v-else>
  280. <el-link type="primary" :underline="false" @click="uploadData(row)">数据同步</el-link>
  281. </span>
  282. </el-col>
  283. </el-row>
  284. </template>
  285. </el-table-column>
  286. </el-table>
  287. <el-pagination
  288. :current-page.sync="pageIndex"
  289. :total="totalElements"
  290. :page-sizes="pageSizeList"
  291. @current-change="changePage"
  292. @size-change="pageSizeChange"
  293. layout="total, sizes, prev, pager, next, jumper"
  294. ></el-pagination>
  295. </div>
  296. </template>
  297. <script>
  298. import Constant from "@/constant";
  299. import personInfoApi from "@/api/base/personInfo";
  300. import companyInfoApi from "@/api/base/companyInfo";
  301. import companyPositionApi from "@/api/base/companyPosition";
  302. import deviceInfoApi from "@/api/base/deviceInfo";
  303. import personDeviceRelationApi from "@/api/base/personDeviceRelation";
  304. import SelectTree from "@/components/SelectTree";
  305. import { getToken } from "@/utils/auth"; // get token from cookie
  306. import NProgress from "nprogress"; // progress bar
  307. import "nprogress/nprogress.css"; // progress bar style
  308. export default {
  309. data() {
  310. var self = this;
  311. return {
  312. ruleValidate: {
  313. deviceId: [{ required: true, message: "不能为空", trigger: "blur" }]
  314. },
  315. queryModel: {
  316. companyCode: "",
  317. parentId: "",
  318. name: "",
  319. phone: "",
  320. idCard: "",
  321. isBound: "",
  322. isUploadPhoto: "",
  323. subordinate: false,
  324. position1: "",
  325. position2: "",
  326. position3: "",
  327. position4: "",
  328. position5: "",
  329. deviceId: ""
  330. },
  331. loading: false,
  332. tableData: [],
  333. pageIndex: 1,
  334. pageSize: 30,
  335. totalPages: 0,
  336. totalElements: 0,
  337. field: "",
  338. direction: "",
  339. pageSizeList: [30, 100, 500],
  340. multipleSelection: [],
  341. showModal: false,
  342. modalTitle: "",
  343. businessKey: "",
  344. companyResult: [],
  345. uploadCompanyId: "",
  346. batchImportVisible: false,
  347. batchImportFileList: [],
  348. disabled: false,
  349. position1: "",
  350. position2: "",
  351. position3: "",
  352. position4: "",
  353. position5: "",
  354. position1Show: false,
  355. position2Show: false,
  356. position3Show: false,
  357. position4Show: false,
  358. position5Show: false,
  359. personId: "",
  360. deviceResult: [],
  361. boundDeviceId: "",
  362. boundUnDeviceId: "",
  363. xlsLoading: false,
  364. tableHeight: "",
  365. boundDeviceDisabled: false,
  366. treeData: [],
  367. props: {
  368. // 配置项(必选)
  369. value: "id",
  370. label: "name",
  371. children: "children"
  372. }
  373. };
  374. },
  375. created() {
  376. var self = this;
  377. companyInfoApi.list().then(function(response) {
  378. var jsonData = response.data;
  379. if (jsonData.result) {
  380. if (jsonData.data != null && jsonData.data != "") {
  381. self.companyResult = jsonData.data;
  382. }
  383. }
  384. });
  385. companyPositionApi.detailForCompany().then(function(response) {
  386. var jsonData = response.data.data;
  387. if (jsonData.position1Name != null && jsonData.position1Name != "") {
  388. self.position1 = jsonData.position1Name;
  389. self.position1Show = true;
  390. }
  391. if (jsonData.position2Name != null && jsonData.position2Name != "") {
  392. self.position2 = jsonData.position2Name;
  393. self.position2Show = true;
  394. }
  395. if (jsonData.position3Name != null && jsonData.position3Name != "") {
  396. self.position3 = jsonData.position3Name;
  397. self.position3Show = true;
  398. }
  399. if (jsonData.position4Name != null && jsonData.position4Name != "") {
  400. self.position4 = jsonData.position4Name;
  401. self.position4Show = true;
  402. }
  403. if (jsonData.position5Name != null && jsonData.position5Name != "") {
  404. self.position5 = jsonData.position5Name;
  405. self.position5Show = true;
  406. }
  407. });
  408. this.queryDevice("");
  409. this.loadTree();
  410. },
  411. methods: {
  412. queryDevice(aliasName) {
  413. var self = this;
  414. var formData = new FormData();
  415. formData.append("aliasName", aliasName);
  416. formData.append("limit", 10);
  417. deviceInfoApi.query(formData).then(function(response) {
  418. var jsonData = response.data;
  419. if (jsonData.result) {
  420. if (jsonData.data != null && jsonData.data != "") {
  421. self.deviceResult = jsonData.data;
  422. }
  423. }
  424. });
  425. },
  426. getSelectedValue(value) {
  427. this.queryModel.parentId = value;
  428. },
  429. loadTree() {
  430. var formData = new FormData();
  431. companyInfoApi.loadChildren(formData).then(resp => {
  432. var jsonData = resp.data;
  433. if (jsonData.result) {
  434. this.treeData = jsonData.data;
  435. } else {
  436. this.$message.error(jsonData.message + "");
  437. }
  438. });
  439. },
  440. loadChildren(tree, treeNode, resolve) {
  441. console.log(tree);
  442. var formData = new FormData();
  443. formData.append("parentId", tree.id);
  444. companyInfoApi.loadChildren(formData).then(resp => {
  445. var jsonData = resp.data;
  446. if (jsonData.result) {
  447. resolve(jsonData.data);
  448. } else {
  449. this.$message.error(jsonData.message + "");
  450. }
  451. });
  452. },
  453. handleQuery() {
  454. var self = this;
  455. this.$refs["queryForm"].validate(valid => {
  456. if (valid) {
  457. self.changePage(1);
  458. }
  459. });
  460. },
  461. changePage(pageIndex) {
  462. var self = this;
  463. self.loading = true;
  464. self.pageIndex = pageIndex;
  465. var formData = new FormData();
  466. formData.append("pageIndex", self.pageIndex);
  467. formData.append("pageSize", self.pageSize);
  468. if (self.queryModel.parentId == null) {
  469. self.queryModel.parentId = "";
  470. }
  471. formData.append("companyCode", self.queryModel.companyCode);
  472. formData.append("parentId", self.queryModel.parentId);
  473. formData.append("subordinate", self.queryModel.subordinate);
  474. formData.append("name", self.queryModel.name);
  475. formData.append("phone", self.queryModel.phone);
  476. formData.append("idCard", self.queryModel.idCard);
  477. formData.append("isBound", self.queryModel.isBound);
  478. formData.append("isUploadPhoto", self.queryModel.isUploadPhoto);
  479. formData.append("position1", self.queryModel.position1);
  480. formData.append("position2", self.queryModel.position2);
  481. formData.append("position3", self.queryModel.position3);
  482. formData.append("position4", self.queryModel.position4);
  483. formData.append("position5", self.queryModel.position5);
  484. formData.append("deviceId", self.queryModel.deviceId);
  485. if (this.field != null) {
  486. formData.append("field", this.field);
  487. }
  488. if (this.direction != null) {
  489. formData.append("direction", this.direction);
  490. }
  491. personDeviceRelationApi
  492. .devicePersonList(formData)
  493. .then(function(response) {
  494. self.loading = false;
  495. var jsonData = response.data.data;
  496. self.tableData = jsonData.data;
  497. self.totalPages = jsonData.totalPages;
  498. self.totalElements = jsonData.recordsTotal;
  499. //45为分页栏的高度
  500. //页面高度-列表上面的高度-分页栏高度
  501. self.tableHeight =
  502. window.innerHeight - self.$refs.formTable.$el.offsetTop - 45;
  503. })
  504. .catch(error => {
  505. self.loading = false;
  506. // self.$message.error(error + "");
  507. });
  508. },
  509. pageSizeChange(pageSize) {
  510. this.pageSize = pageSize;
  511. this.changePage(this.pageIndex);
  512. },
  513. sortChange(data) {
  514. this.field = data.column.field;
  515. this.changePage(this.pageIndex);
  516. },
  517. handleSelectionChange(val) {
  518. this.multipleSelection = val;
  519. },
  520. handleReset(name) {
  521. this.$refs[name].resetFields();
  522. },
  523. uploadData(record) {
  524. //同步人脸数据
  525. var self = this;
  526. self.loading = true;
  527. var uploadSync = new Array(0);
  528. uploadSync.push(record.personInfo.id);
  529. var formData = new FormData();
  530. formData.append("personId", uploadSync);
  531. formData.append("deviceId", record.deviceId);
  532. personDeviceRelationApi
  533. .devicePersonSync(formData)
  534. .then(function(response) {
  535. var jsonData = response.data;
  536. self.loading = false;
  537. if (jsonData.result) {
  538. if (jsonData.data) {
  539. self.changePage(self.pageIndex);
  540. self.$message({
  541. type: "success",
  542. message: "同步成功!"
  543. });
  544. } else {
  545. if (jsonData.message != null) {
  546. //下载有错误信息提示的报表
  547. //window.open(response.data);
  548. self.$message({
  549. showClose: true,
  550. dangerouslyUseHTMLString: true,
  551. message:
  552. "错误" +
  553. `,<a href="${jsonData.message}" target="_blank">点击下载错误报表</a>&nbsp;`,
  554. duration: 30000
  555. });
  556. }
  557. }
  558. } else {
  559. self.$message({
  560. type: "warning",
  561. message: jsonData.message
  562. });
  563. }
  564. });
  565. },
  566. dataSync() {
  567. //批量同步人脸
  568. var self = this;
  569. var idList = this.multipleSelection.map(record => {
  570. return record.personInfo.id;
  571. });
  572. this.$confirm("是否确认同步选中项?", "提示", {
  573. confirmButtonText: "确定",
  574. cancelButtonText: "取消",
  575. type: "warning"
  576. })
  577. .then(() => {
  578. self.loading = true;
  579. var formData = new FormData();
  580. formData.append("personIds", idList);
  581. formData.append("deviceId", self.queryModel.deviceId);
  582. personDeviceRelationApi
  583. .devicePersonsSync(formData)
  584. .then(function(response) {
  585. var jsonData = response.data;
  586. self.loading = false;
  587. if (jsonData.result) {
  588. if (jsonData.data) {
  589. self.changePage(self.pageIndex);
  590. self.$message({
  591. type: "success",
  592. message: "同步成功!"
  593. });
  594. } else {
  595. if (jsonData.message != null) {
  596. //下载有错误信息提示的报表
  597. //window.open(response.data);
  598. self.$message({
  599. showClose: true,
  600. dangerouslyUseHTMLString: true,
  601. message:
  602. "错误" +
  603. `,<a href="${jsonData.message}" target="_blank">点击下载错误报表</a>&nbsp;`,
  604. duration: 30000
  605. });
  606. }
  607. }
  608. } else {
  609. self.$message({
  610. type: "warning",
  611. message: jsonData.message
  612. });
  613. }
  614. });
  615. })
  616. .catch(() => {
  617. self.loading = false;
  618. });
  619. }
  620. },
  621. async mounted() {
  622. var self = this;
  623. this.queryDevice("");
  624. },
  625. components: {
  626. "el-select-tree": SelectTree
  627. }
  628. };
  629. </script>
  630. <style lang="scss" scoped>
  631. .el-breadcrumb {
  632. margin: 10px;
  633. line-height: 20px;
  634. }
  635. .el-divider {
  636. margin: 5px 0;
  637. }
  638. .demo-form-inline {
  639. margin-left: 10px;
  640. text-align: left;
  641. }
  642. .button-group {
  643. margin-left: 10px;
  644. text-align: left;
  645. }
  646. .el-select-dropdown__wrap .el-scrollbar__wrap {
  647. margin: 0px;
  648. max-height: 10;
  649. overflow: scroll;
  650. }
  651. </style>