index.vue 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432
  1. <template>
  2. <div class="app-container">
  3. <el-row :gutter="20">
  4. <!--部门数据-->
  5. <!-- <el-col :span="4" :xs="24">-->
  6. <!-- <div class="head-container">-->
  7. <!-- <el-input-->
  8. <!-- v-model="deptName"-->
  9. <!-- placeholder="请输入部门名称"-->
  10. <!-- clearable-->
  11. <!-- size="small"-->
  12. <!-- prefix-icon="el-icon-search"-->
  13. <!-- style="margin-bottom: 20px"-->
  14. <!-- />-->
  15. <!-- </div>-->
  16. <!-- <div class="head-container">-->
  17. <!-- <el-tree-->
  18. <!-- :data="deptOptions"-->
  19. <!-- :props="defaultProps"-->
  20. <!-- :expand-on-click-node="false"-->
  21. <!-- :filter-node-method="filterNode"-->
  22. <!-- ref="tree"-->
  23. <!-- default-expand-all-->
  24. <!-- @node-click="handleNodeClick"-->
  25. <!-- />-->
  26. <!-- </div>-->
  27. <!-- </el-col>-->
  28. <!--用户数据-->
  29. <el-col :span="24" :xs="24">
  30. <el-form
  31. :model="queryParams"
  32. ref="queryForm"
  33. size="small"
  34. :inline="true"
  35. v-show="showSearch"
  36. label-width="68px"
  37. >
  38. <el-form-item label="人员编号" prop="userId">
  39. <el-input
  40. v-model="queryParams.userId"
  41. placeholder="请输入人员编号"
  42. clearable
  43. style="width: 240px"
  44. oninput="value=value.replace(/[^\d.]/g,'')"
  45. @keyup.enter.native="handleQuery"
  46. />
  47. </el-form-item>
  48. <el-form-item label="姓名" prop="nickName">
  49. <el-input
  50. v-model="queryParams.nickName"
  51. placeholder="请输入姓名"
  52. clearable
  53. style="width: 240px"
  54. @keyup.enter.native="handleQuery"
  55. />
  56. </el-form-item>
  57. <el-form-item label="手机号码" prop="phonenumber" label-width="100px">
  58. <el-input
  59. v-model="queryParams.phonenumber"
  60. placeholder="请输入手机号码"
  61. clearable
  62. style="width: 240px"
  63. @keyup.enter.native="handleQuery"
  64. />
  65. </el-form-item>
  66. <el-form-item label="单位" prop="unitId">
  67. <treeselect
  68. style="width: 240px"
  69. v-model="queryParams.unitId"
  70. :options="UnitOptions"
  71. :normalizer="Unitnormalizer"
  72. :show-count="true"
  73. placeholder="请选择单位"
  74. />
  75. </el-form-item>
  76. <el-form-item label="角色" prop="roleId">
  77. <el-select
  78. style="width: 240px"
  79. v-model="queryParams.roleId"
  80. clearable
  81. placeholder="请选择角色"
  82. >
  83. <el-option
  84. v-for="item in roleOptions"
  85. :key="item.roleId"
  86. :label="item.roleName"
  87. :value="item.roleId"
  88. ></el-option>
  89. </el-select>
  90. </el-form-item>
  91. <!-- 这里查询的是玛氏岗位-->
  92. <el-form-item label="岗位" prop="workstationId">
  93. <treeselect
  94. style="width: 240px"
  95. v-model="queryParams.workstationId"
  96. :options="marsOptions"
  97. :normalizer="Marsnormalizer"
  98. placeholder="选择岗位"
  99. @change="handleWorkstationChange"
  100. />
  101. </el-form-item>
  102. <el-form-item label="状态" prop="status">
  103. <el-select
  104. v-model="queryParams.status"
  105. placeholder="用户状态"
  106. clearable
  107. style="width: 240px"
  108. >
  109. <el-option
  110. v-for="dict in dict.type.sys_normal_disable"
  111. :key="dict.value"
  112. :label="dict.label"
  113. :value="dict.value"
  114. />
  115. </el-select>
  116. </el-form-item>
  117. <!-- <el-form-item label="创建时间">-->
  118. <!-- <el-date-picker-->
  119. <!-- v-model="dateRange"-->
  120. <!-- style="width: 240px"-->
  121. <!-- value-format="yyyy-MM-dd"-->
  122. <!-- type="daterange"-->
  123. <!-- range-separator="-"-->
  124. <!-- start-placeholder="开始日期"-->
  125. <!-- end-placeholder="结束日期"-->
  126. <!-- ></el-date-picker>-->
  127. <!-- </el-form-item>-->
  128. <el-form-item>
  129. <el-button
  130. v-no-more-click
  131. type="primary"
  132. icon="el-icon-search"
  133. size="mini"
  134. @click="handleQuery"
  135. >搜索</el-button
  136. >
  137. <el-button
  138. v-no-more-click
  139. icon="el-icon-refresh"
  140. size="mini"
  141. @click="resetQuery"
  142. >重置</el-button
  143. >
  144. </el-form-item>
  145. </el-form>
  146. <el-row :gutter="10" class="mb8">
  147. <el-col :span="1.5">
  148. <el-button
  149. v-no-more-click
  150. type="primary"
  151. plain
  152. icon="el-icon-plus"
  153. size="mini"
  154. @click="handleAdd"
  155. v-hasPermi="['system:user:add']"
  156. >新增</el-button
  157. >
  158. </el-col>
  159. <el-col :span="1.5">
  160. <el-button
  161. v-no-more-click
  162. type="success"
  163. plain
  164. icon="el-icon-edit"
  165. size="mini"
  166. :disabled="single"
  167. @click="handleUpdate"
  168. v-hasPermi="['system:user:edit']"
  169. >修改</el-button
  170. >
  171. </el-col>
  172. <el-col :span="1.5">
  173. <el-button
  174. v-no-more-click
  175. type="danger"
  176. plain
  177. icon="el-icon-delete"
  178. size="mini"
  179. :disabled="multiple"
  180. @click="handleDelete"
  181. v-hasPermi="['system:user:remove']"
  182. >删除</el-button
  183. >
  184. </el-col>
  185. <el-col :span="1.5">
  186. <el-button
  187. v-no-more-click
  188. type="info"
  189. plain
  190. icon="el-icon-upload2"
  191. size="mini"
  192. @click="handleImport"
  193. v-hasPermi="['system:user:import']"
  194. >导入</el-button
  195. >
  196. </el-col>
  197. <el-col :span="1.5">
  198. <el-button
  199. v-no-more-click
  200. type="warning"
  201. plain
  202. icon="el-icon-download"
  203. size="mini"
  204. @click="handleExport"
  205. v-hasPermi="['system:user:export']"
  206. >导出</el-button
  207. >
  208. </el-col>
  209. <right-toolbar
  210. :showSearch.sync="showSearch"
  211. @queryTable="getList"
  212. :columns="columns"
  213. ></right-toolbar>
  214. </el-row>
  215. <el-table
  216. v-loading="loading"
  217. :data="userList"
  218. @selection-change="handleSelectionChange"
  219. >
  220. <el-table-column type="selection" width="50" align="center" />
  221. <el-table-column
  222. label="人员编号"
  223. align="center"
  224. key="userId"
  225. prop="userId"
  226. v-if="columns[0].visible"
  227. />
  228. <el-table-column
  229. label="姓名"
  230. align="center"
  231. key="nickName"
  232. prop="nickName"
  233. v-if="columns[1].visible"
  234. :show-overflow-tooltip="true"
  235. />
  236. <el-table-column
  237. label="手机号码"
  238. align="center"
  239. key="phonenumber"
  240. prop="phonenumber"
  241. v-if="columns[4].visible"
  242. width="120"
  243. />
  244. <el-table-column
  245. label="工号"
  246. align="center"
  247. key="userName"
  248. prop="userName"
  249. v-if="columns[2].visible"
  250. :show-overflow-tooltip="true"
  251. />
  252. <el-table-column
  253. label="单位"
  254. align="center"
  255. key="unitName"
  256. prop="unitName"
  257. v-if="columns[2].visible"
  258. :show-overflow-tooltip="true"
  259. />
  260. <el-table-column
  261. label="角色"
  262. align="center"
  263. key="roleName"
  264. prop="roleName"
  265. v-if="columns[2].visible"
  266. :show-overflow-tooltip="true"
  267. />
  268. <el-table-column
  269. label="邮件"
  270. align="center"
  271. key="email"
  272. prop="email"
  273. v-if="columns[2].visible"
  274. width="180"
  275. />
  276. <el-table-column
  277. label="岗位"
  278. align="center"
  279. key="workstationName"
  280. prop="workstationName"
  281. v-if="columns[2].visible"
  282. :show-overflow-tooltip="true"
  283. >
  284. <template slot-scope="scope">
  285. <el-button type="text" @click="HandleLookWorkStation(scope.row)"
  286. >查看</el-button
  287. >
  288. </template>
  289. </el-table-column>
  290. <el-table-column
  291. label="指纹"
  292. align="center"
  293. prop=""
  294. v-if="columns[2].visible"
  295. :show-overflow-tooltip="true"
  296. >
  297. <template slot-scope="scope">
  298. <el-button type="text" @click="HandleLookFaceOrFinger(scope.row,1)"
  299. >查看</el-button
  300. >
  301. </template>
  302. </el-table-column>
  303. <el-table-column
  304. label="人脸"
  305. align="center"
  306. prop=""
  307. v-if="columns[2].visible"
  308. :show-overflow-tooltip="true"
  309. >
  310. <template slot-scope="scope">
  311. <el-button type="text" @click="HandleLookFaceOrFinger(scope.row,2)"
  312. >查看</el-button
  313. >
  314. </template>
  315. </el-table-column>
  316. <!-- <el-table-column label="部门" align="center" key="deptName" prop="dept.deptName" v-if="columns[3].visible" :show-overflow-tooltip="true" />-->
  317. <el-table-column
  318. label="状态"
  319. align="center"
  320. key="status"
  321. v-if="columns[5].visible"
  322. >
  323. <template slot-scope="scope">
  324. <el-switch
  325. v-model="scope.row.status"
  326. active-value="0"
  327. inactive-value="1"
  328. @change="handleStatusChange(scope.row)"
  329. ></el-switch>
  330. </template>
  331. </el-table-column>
  332. <!-- <el-table-column label="创建时间" align="center" prop="createTime" v-if="columns[6].visible" width="160">-->
  333. <!-- <template slot-scope="scope">-->
  334. <!-- <span>{{ parseTime(scope.row.createTime) }}</span>-->
  335. <!-- </template>-->
  336. <!-- </el-table-column>-->
  337. <el-table-column
  338. label="操作"
  339. align="center"
  340. width="160"
  341. class-name="small-padding fixed-width"
  342. >
  343. <template slot-scope="scope" v-if="scope.row.userId !== 1">
  344. <el-button
  345. v-no-more-click
  346. size="mini"
  347. type="text"
  348. icon="el-icon-edit"
  349. @click="handleUpdate(scope.row)"
  350. v-hasPermi="['system:user:edit']"
  351. >修改</el-button
  352. >
  353. <el-button
  354. v-no-more-click
  355. size="mini"
  356. type="text"
  357. icon="el-icon-delete"
  358. @click="handleDelete(scope.row)"
  359. v-hasPermi="['system:user:remove']"
  360. >删除</el-button
  361. >
  362. <el-dropdown
  363. size="mini"
  364. @command="(command) => handleCommand(command, scope.row)"
  365. v-hasPermi="['system:user:resetPwd', 'system:user:edit']"
  366. >
  367. <span class="el-dropdown-link">
  368. <i class="el-icon-d-arrow-right el-icon--right"></i>更多
  369. </span>
  370. <el-dropdown-menu slot="dropdown">
  371. <el-dropdown-item
  372. command="handleResetPwd"
  373. icon="el-icon-key"
  374. v-hasPermi="['system:user:resetPwd']"
  375. >重置密码</el-dropdown-item
  376. >
  377. <el-dropdown-item
  378. command="handleAuthRole"
  379. icon="el-icon-circle-check"
  380. v-hasPermi="['system:user:edit']"
  381. >分配角色</el-dropdown-item
  382. >
  383. </el-dropdown-menu>
  384. </el-dropdown>
  385. </template>
  386. </el-table-column>
  387. </el-table>
  388. <pagination
  389. v-show="total > 0"
  390. :total="total"
  391. :page.sync="queryParams.pageNum"
  392. :limit.sync="queryParams.pageSize"
  393. @pagination="getList"
  394. />
  395. </el-col>
  396. </el-row>
  397. <!-- 添加或修改用户配置对话框 -->
  398. <el-dialog :title="title" :visible.sync="open" width="600px" append-to-body>
  399. <el-form ref="form" :model="form" :rules="rules" label-width="80px">
  400. <el-row>
  401. <el-col :span="12">
  402. <el-form-item label="姓名" prop="nickName">
  403. <el-input
  404. v-model="form.nickName"
  405. placeholder="请输入姓名"
  406. maxlength="30"
  407. />
  408. </el-form-item>
  409. </el-col>
  410. <el-col :span="12">
  411. <el-form-item label="手机号码" prop="phonenumber">
  412. <el-input
  413. v-model="form.phonenumber"
  414. placeholder="请输入手机号码"
  415. maxlength="11"
  416. />
  417. </el-form-item>
  418. </el-col>
  419. </el-row>
  420. <el-row>
  421. <el-col :span="12">
  422. <el-form-item label="工号" prop="userName">
  423. <el-input
  424. :disabled="form.userId !== undefined"
  425. v-model="form.userName"
  426. placeholder="请输入工号"
  427. maxlength="30"
  428. />
  429. </el-form-item>
  430. </el-col>
  431. <el-col :span="12">
  432. <el-form-item label="单位" prop="unitIds">
  433. <treeselect
  434. v-model="form.unitIds"
  435. :options="UnitOptions"
  436. :normalizer="Unitnormalizer"
  437. :show-count="true"
  438. placeholder="请选择单位"
  439. />
  440. </el-form-item>
  441. </el-col>
  442. </el-row>
  443. <el-row>
  444. <el-col :span="12">
  445. <el-form-item label="角色" prop="roleIds">
  446. <el-select
  447. v-model="form.roleIds"
  448. multiple
  449. placeholder="请选择角色"
  450. >
  451. <el-option
  452. v-for="item in roleOptions"
  453. :key="item.roleId"
  454. :label="item.roleName"
  455. :value="item.roleId"
  456. :disabled="item.status == 1"
  457. ></el-option>
  458. </el-select>
  459. </el-form-item>
  460. </el-col>
  461. <el-col :span="12">
  462. <el-form-item label="邮件" prop="email">
  463. <el-input
  464. v-model="form.email"
  465. placeholder="请输入邮件"
  466. maxlength="50"
  467. />
  468. </el-form-item>
  469. </el-col>
  470. </el-row>
  471. <el-row>
  472. <el-col :span="12">
  473. <!-- 玛氏岗位-->
  474. <el-form-item label="岗位" prop="workstationIds">
  475. <!-- <el-select v-model="form.workstationIds" clearable multiple placeholder="请选择岗位">-->
  476. <!-- <el-option-->
  477. <!-- v-for="item in MarsWordStationOptions"-->
  478. <!-- :key="item.workstationId"-->
  479. <!-- :label="item.workstationName"-->
  480. <!-- :value="item.workstationId"-->
  481. <!-- ></el-option>-->
  482. <!-- </el-select>-->
  483. <el-select
  484. size="small"
  485. v-model="form.workstationIds"
  486. placeholder="请选择"
  487. :popper-append-to-body="false"
  488. multiple
  489. clearable
  490. @remove-tag="removeTag"
  491. @clear="clearAll"
  492. >
  493. <el-option :value="selectTreeValue" class="setstyle" disabled>
  494. <el-input
  495. class="setinput"
  496. size="mini"
  497. placeholder="输入关键字进行过滤"
  498. clearable
  499. v-model="filterText"
  500. ></el-input>
  501. <el-tree
  502. :data="MarsWordStationOptions"
  503. default-expand-all
  504. show-checkbox
  505. node-key="id"
  506. ref="treeRef"
  507. highlight-current
  508. :filter-node-method="filterNode"
  509. :props="defaultProps"
  510. @check-change="handleCheckChange"
  511. ></el-tree>
  512. </el-option>
  513. </el-select>
  514. </el-form-item>
  515. </el-col>
  516. <el-col :span="12">
  517. <el-form-item label="状态">
  518. <el-radio-group v-model="form.status">
  519. <el-radio
  520. v-for="dict in dict.type.sys_normal_disable"
  521. :key="dict.value"
  522. :label="dict.value"
  523. >{{ dict.label }}</el-radio
  524. >
  525. </el-radio-group>
  526. </el-form-item>
  527. </el-col>
  528. </el-row>
  529. <el-row>
  530. <el-col :span="12">
  531. <el-form-item label="用户性别">
  532. <el-select v-model="form.sex" placeholder="请选择性别">
  533. <el-option
  534. v-for="dict in dict.type.sys_user_sex"
  535. :key="dict.value"
  536. :label="dict.label"
  537. :value="dict.value"
  538. ></el-option>
  539. </el-select>
  540. </el-form-item>
  541. </el-col>
  542. <el-col :span="12">
  543. <el-form-item label="归属部门" prop="deptId">
  544. <treeselect
  545. v-model="form.deptId"
  546. :options="deptOptions"
  547. :show-count="true"
  548. placeholder="请选择归属部门"
  549. />
  550. </el-form-item>
  551. </el-col>
  552. </el-row>
  553. <el-row>
  554. <el-col :span="12">
  555. <el-form-item
  556. v-if="form.userId == undefined"
  557. label="用户密码"
  558. prop="password"
  559. >
  560. <el-input
  561. v-model="form.password"
  562. placeholder="请输入用户密码"
  563. type="password"
  564. maxlength="20"
  565. show-password
  566. />
  567. </el-form-item>
  568. </el-col>
  569. </el-row>
  570. <el-row>
  571. <el-col :span="24">
  572. <el-form-item label="备注">
  573. <el-input
  574. v-model="form.remark"
  575. type="textarea"
  576. placeholder="请输入内容"
  577. ></el-input>
  578. </el-form-item>
  579. </el-col>
  580. </el-row>
  581. </el-form>
  582. <div slot="footer" class="dialog-footer">
  583. <el-button v-no-more-click type="primary" @click="submitForm"
  584. >确 定</el-button
  585. >
  586. <el-button v-no-more-click @click="cancel">取 消</el-button>
  587. </div>
  588. </el-dialog>
  589. <!-- 用户导入对话框 -->
  590. <el-dialog
  591. :title="upload.title"
  592. :visible.sync="upload.open"
  593. width="400px"
  594. append-to-body
  595. >
  596. <el-upload
  597. ref="upload"
  598. :limit="1"
  599. accept=".xlsx, .xls"
  600. :headers="upload.headers"
  601. :action="upload.url + '?updateSupport=' + upload.updateSupport"
  602. :disabled="upload.isUploading"
  603. :on-progress="handleFileUploadProgress"
  604. :on-success="handleFileSuccess"
  605. :auto-upload="false"
  606. drag
  607. >
  608. <i class="el-icon-upload"></i>
  609. <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
  610. <div class="el-upload__tip text-center" slot="tip">
  611. <!-- <div class="el-upload__tip" slot="tip">-->
  612. <!-- <el-checkbox v-model="upload.updateSupport" /> 是否更新已经存在的用户数据-->
  613. <!-- </div>-->
  614. <span>仅允许导入xls、xlsx格式文件。</span>
  615. <el-link
  616. type="primary"
  617. :underline="false"
  618. style="font-size: 12px; vertical-align: baseline"
  619. @click="importTemplate"
  620. >下载模板</el-link
  621. >
  622. </div>
  623. </el-upload>
  624. <div slot="footer" class="dialog-footer">
  625. <el-button v-no-more-click type="primary" @click="submitFileForm"
  626. >确 定</el-button
  627. >
  628. <el-button v-no-more-click @click="upload.open = false"
  629. >取 消</el-button
  630. >
  631. </div>
  632. </el-dialog>
  633. <!-- 查看用户人脸和指纹弹窗-->
  634. <el-dialog :title="title2" :visible.sync="open2" width="780px" append-to-body @close="handleDialogClose">
  635. <el-button
  636. v-no-more-click
  637. type="danger"
  638. plain
  639. icon="el-icon-delete"
  640. size="mini"
  641. :disabled="multiple"
  642. @click="handleDeleteFaceOrFinger"
  643. v-hasPermi="['system:user:remove']"
  644. >删除</el-button
  645. >
  646. <el-table :data="FaceOrFingerTableData" height="600" @selection-change="handleSelectionChange2">
  647. <el-table-column type="selection" width="50" align="center"></el-table-column>
  648. <el-table-column label="序号" width="100" type="index" :index='(index)=>{return (index+1) + (this.current-1)*this.size}'> </el-table-column>
  649. <el-table-column :label="this.title2=='人员指纹数据'?'指纹':'人脸'" align="center" prop="imageUrl">
  650. <template slot-scope="scope">
  651. <div class="img-box" >
  652. <el-image
  653. style="width: 50px; height: 50px;"
  654. :preview-teleported="true"
  655. class="images"
  656. :hide-on-click-modal=true
  657. :src="scope.row.imageUrl"
  658. :zoom-rate="1.2"
  659. :preview-src-list="[scope.row.imageUrl]"
  660. :initial-index="1"
  661. >
  662. </el-image>
  663. <i class="el-icon-zoom-in" id="eyeicon"></i>
  664. </div>
  665. </template>
  666. </el-table-column>
  667. <el-table-column
  668. label="操作"
  669. align="center"
  670. width="160"
  671. class-name="small-padding fixed-width"
  672. >
  673. <template slot-scope="scope">
  674. <el-button
  675. v-no-more-click
  676. size="mini"
  677. type="text"
  678. icon="el-icon-delete"
  679. @click="handleDeleteFaceOrFinger(scope.row)"
  680. >删除</el-button
  681. >
  682. </template>
  683. </el-table-column>
  684. </el-table>
  685. <pagination
  686. :total="total2"
  687. :page.sync="current"
  688. :limit.sync="size"
  689. @pagination="getFaceOrFingerList"
  690. />
  691. </el-dialog>
  692. </div>
  693. </template>
  694. <script>
  695. import {
  696. listUser,
  697. getUser,
  698. delUser,
  699. addUser,
  700. updateUser,
  701. resetUserPwd,
  702. changeUserStatus, getSysUserCharacteristicPage, deleteSysUserCharacteristicByRecordIds
  703. } from '@/api/system/user'
  704. import { listMarsDept } from "@/api/system/marsdept";
  705. import { getToken } from "@/utils/auth";
  706. import { treeselect } from "@/api/system/dept";
  707. import Treeselect from "@riophae/vue-treeselect";
  708. import "@riophae/vue-treeselect/dist/vue-treeselect.css";
  709. import { listUnit } from "@/api/system/unit";
  710. import Template from '@/views/print/printtemplate/list.vue'
  711. export default {
  712. name: "User",
  713. dicts: ["sys_normal_disable", "sys_user_sex"],
  714. components: { Template, Treeselect },
  715. data() {
  716. return {
  717. // 遮罩层
  718. loading: true,
  719. // 选中数组
  720. ids: [],
  721. // 非单个禁用
  722. single: true,
  723. // 非多个禁用
  724. multiple: true,
  725. // 显示搜索条件
  726. showSearch: true,
  727. // 总条数
  728. total: 0,
  729. // 用户表格数据
  730. userList: null,
  731. // 弹出层标题
  732. title: "",
  733. // 部门树选项
  734. deptOptions: undefined,
  735. // mars树选项
  736. marsOptions: [],
  737. // 单位树选项
  738. UnitOptions: undefined,
  739. // 是否显示弹出层
  740. open: false,
  741. // 部门名称
  742. deptName: undefined,
  743. // 默认密码
  744. initPassword: undefined,
  745. // 日期范围
  746. dateRange: [],
  747. // 岗位选项
  748. postOptions: [],
  749. // 角色选项
  750. roleOptions: [],
  751. // 表单参数
  752. form: {
  753. workstationIds: [],
  754. },
  755. defaultProps: {
  756. children: "children",
  757. label: "label",
  758. },
  759. // 用户导入参数
  760. upload: {
  761. // 是否显示弹出层(用户导入)
  762. open: false,
  763. // 弹出层标题(用户导入)
  764. title: "",
  765. // 是否禁用上传
  766. isUploading: false,
  767. // 是否更新已经存在的用户数据
  768. updateSupport: 0,
  769. // 设置上传的请求头部
  770. headers: { Authorization: "Bearer " + getToken() },
  771. // 上传的地址
  772. url: process.env.VUE_APP_BASE_API + "/system/user/importData",
  773. },
  774. // 查询参数
  775. queryParams: {
  776. pageNum: 1,
  777. pageSize: 10,
  778. userName: undefined,
  779. phonenumber: undefined,
  780. status: undefined,
  781. deptId: undefined,
  782. workstationId: undefined,
  783. roleId: undefined,
  784. userId: undefined,
  785. nickName: undefined,
  786. unitId: undefined,
  787. },
  788. // 列信息
  789. columns: [
  790. { key: 0, label: `用户编号`, visible: true },
  791. { key: 1, label: `用户名称`, visible: true },
  792. { key: 2, label: `用户昵称`, visible: true },
  793. { key: 3, label: `部门`, visible: true },
  794. { key: 4, label: `手机号码`, visible: true },
  795. { key: 5, label: `状态`, visible: true },
  796. { key: 6, label: `创建时间`, visible: true },
  797. ],
  798. // 表单校验
  799. rules: {
  800. userName: [
  801. { required: true, message: "用户名称不能为空", trigger: "blur" },
  802. {
  803. min: 2,
  804. max: 20,
  805. message: "用户名称长度必须介于 2 和 20 之间",
  806. trigger: "blur",
  807. },
  808. ],
  809. nickName: [
  810. { required: true, message: "用户昵称不能为空", trigger: "blur" },
  811. ],
  812. password: [
  813. { required: true, message: "用户密码不能为空", trigger: "blur" },
  814. {
  815. min: 5,
  816. max: 20,
  817. message: "用户密码长度必须介于 5 和 20 之间",
  818. trigger: "blur",
  819. },
  820. ],
  821. unitIds: [{ required: true, message: "单位不能为空", trigger: "blur" }],
  822. email: [
  823. {
  824. type: "email",
  825. message: "请输入正确的邮箱地址",
  826. trigger: ["blur", "change"],
  827. },
  828. ],
  829. workstationIds: [
  830. { required: true, message: "岗位不能为空", trigger: "blur" },
  831. ],
  832. roleIds: [{ required: true, message: "角色不能为空", trigger: "blur" }],
  833. phonenumber: [
  834. {
  835. pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
  836. message: "请输入正确的手机号码",
  837. trigger: "blur",
  838. },
  839. ],
  840. },
  841. MarsWordStationOptions: [], //玛氏岗位下拉
  842. orignMarsWorkstation: [], //玛氏岗位编辑回显
  843. selectTreeValue: [], //玛氏
  844. selectTreeArrIds: [], //玛氏
  845. filterText: "", //玛氏
  846. title2:'',//人脸或指纹弹框
  847. open2:false,//人脸或指纹弹窗
  848. FaceOrFingerTableData:[],//人脸或指纹
  849. total2:0,//人脸
  850. current:1,//人脸
  851. size:10,//人脸
  852. type:null,//人脸
  853. userId:undefined,//人脸
  854. };
  855. },
  856. watch: {
  857. // 根据名称筛选部门树
  858. deptName(val) {
  859. this.$refs.tree.filter(val);
  860. },
  861. filterText(val) {
  862. this.$refs.treeRef.filter(val);
  863. },
  864. "$route.query.workstationId": {
  865. immediate: true,
  866. handler(val) {
  867. console.log(val, "workstationId查询参数");
  868. this.queryParams.workstationId = val;
  869. this.getList();
  870. },
  871. },
  872. },
  873. created() {
  874. this.getList();
  875. this.getOtherList();
  876. this.getTreeselect();
  877. this.getConfigKey("sys.user.initPassword").then((response) => {
  878. this.initPassword = response.msg;
  879. });
  880. },
  881. beforeRouteEnter(to, from, next) {
  882. next((vm) => {
  883. vm.getOtherList();
  884. vm.getList();
  885. vm.getTreeselect();
  886. });
  887. },
  888. methods: {
  889. /** 查询用户列表 */
  890. getList() {
  891. this.loading = true;
  892. listUser(this.addDateRange(this.queryParams, this.dateRange)).then(
  893. (response) => {
  894. this.userList = response.rows;
  895. this.total = response.total;
  896. this.loading = false;
  897. }
  898. );
  899. },
  900. getOtherList() {
  901. getUser().then((response) => {
  902. this.roleOptions = response.roles;
  903. });
  904. const data = {
  905. size: -1,
  906. pages: 1,
  907. };
  908. listMarsDept(data).then((response) => {
  909. this.marsOptions = this.handleTree(
  910. response.data.records,
  911. "workstationId",
  912. "parentId"
  913. );
  914. this.MarsWordStationOptions = response.data.records; //给新增里的岗位
  915. this.orignMarsWorkstation = response.data.records; //给编辑回显文字
  916. this.$set(
  917. this,
  918. "MarsWordStationOptions",
  919. this.transformDataToTree(response.data.records)
  920. );
  921. });
  922. },
  923. //查看人脸关闭弹窗前清空数据
  924. handleDialogClose(){
  925. this.FaceOrFingerTableData=[]
  926. },
  927. // 查看人脸或者指纹弹框打开函数
  928. HandleLookFaceOrFinger(row,type){
  929. this.open2 = true;
  930. if(type=='1'){
  931. this.title2='人员指纹数据'
  932. }else if(type=='2'){
  933. this.title2='人员面部数据'
  934. }
  935. this.userId=row.userId;
  936. this.type=type;
  937. const data={
  938. current:this.current,
  939. size:this.size,
  940. userId: this.userId,
  941. type:this.type,
  942. }
  943. // 查看人员相应数据
  944. getSysUserCharacteristicPage(data).then((response) => {
  945. console.log(response,'人脸');
  946. this.FaceOrFingerTableData = response.data.records;
  947. this.total2=response.data.total;
  948. })
  949. },
  950. getFaceOrFingerList(){
  951. // type 1 指纹 2 人脸
  952. const data={
  953. current:this.current,
  954. size:this.size,
  955. userId: this.userId,
  956. type:this.type,
  957. }
  958. // 查看人员相应数据
  959. getSysUserCharacteristicPage(data).then((response) => {
  960. this.FaceOrFingerTableData = response.data.records;
  961. this.total2=response.data.total;
  962. })
  963. },
  964. //mars新增岗位数据转换
  965. transformDataToTree(data) {
  966. // 创建一个映射,用于快速查找节点
  967. const map = {};
  968. const tree = [];
  969. // 遍历数据,将每个节点放入映射中,并只保留 id 和 label 字段
  970. data.forEach((node) => {
  971. map[node.workstationId] = {
  972. id: node.workstationId,
  973. label: node.workstationName,
  974. children: [],
  975. };
  976. });
  977. // 再次遍历数据,构建树形结构
  978. data.forEach((node) => {
  979. if (node.parentId !== null && map[node.parentId]) {
  980. map[node.parentId].children.push(map[node.workstationId]);
  981. } else {
  982. tree.push(map[node.workstationId]);
  983. }
  984. });
  985. return tree;
  986. },
  987. // mars岗位移除Tag
  988. removeTag(value) {
  989. // 从 selectTreeValue 中删除该标签
  990. this.selectTreeValue = this.selectTreeValue.filter(
  991. (item) => item.id !== value.id
  992. );
  993. // 获取当前选中的节点列表
  994. let setList = this.$refs.treeRef.getCheckedNodes();
  995. // 过滤掉要取消选中的节点(通过比较 id 或其他标识符)
  996. setList = setList
  997. .filter((node) => node.label !== value)
  998. .map((item) => {
  999. return item.id;
  1000. });
  1001. this.$refs.treeRef.setCheckedKeys(setList, true);
  1002. },
  1003. // mars岗位全部删除
  1004. clearAll() {
  1005. this.selectTreeValue = [];
  1006. this.form.workstationIds = [];
  1007. this.$nextTick(() => {
  1008. this.$refs.treeRef.setCheckedNodes([]);
  1009. });
  1010. },
  1011. // mars岗位新增
  1012. handleCheckChange() {
  1013. // getCheckedNodes方法接收两个 boolean 类型的参数: 1. 是否只是叶子节点,默认值为 false 2. 是否包含半选节点,默认值为 false
  1014. let dataList = this.$refs.treeRef.getCheckedNodes(true);
  1015. this.selectTreeValue = [];
  1016. this.form.workstationIds = [];
  1017. this.selectTreeArrIds = [];
  1018. dataList.forEach((item) => {
  1019. this.selectTreeValue.push({ id: item.id, label: item.label });
  1020. this.form.workstationIds.push(item.label);
  1021. this.selectTreeArrIds.push(item.id);
  1022. });
  1023. },
  1024. handleWorkstationChange(value) {
  1025. this.queryParams.workstationId = value;
  1026. },
  1027. // 筛选节点
  1028. filterNode(value, data) {
  1029. if (!value) return true;
  1030. return data.label.indexOf(value) !== -1;
  1031. },
  1032. // 节点单击事件
  1033. handleNodeClick(data) {
  1034. this.queryParams.deptId = data.id;
  1035. this.handleQuery();
  1036. },
  1037. // 用户状态修改
  1038. handleStatusChange(row) {
  1039. let text = row.status === "0" ? "启用" : "停用";
  1040. this.$modal
  1041. .confirm('确认要"' + text + '""' + row.userName + '"用户吗?')
  1042. .then(function () {
  1043. return changeUserStatus(row.userId, row.status);
  1044. })
  1045. .then(() => {
  1046. this.$modal.msgSuccess(text + "成功");
  1047. })
  1048. .catch(function () {
  1049. row.status = row.status === "0" ? "1" : "0";
  1050. });
  1051. },
  1052. // 取消按钮
  1053. cancel() {
  1054. this.open = false;
  1055. this.reset();
  1056. },
  1057. // 表单重置
  1058. reset() {
  1059. this.form = {
  1060. userId: undefined,
  1061. deptId: undefined,
  1062. userName: undefined,
  1063. nickName: undefined,
  1064. password: undefined,
  1065. phonenumber: undefined,
  1066. email: undefined,
  1067. sex: undefined,
  1068. status: "0",
  1069. remark: undefined,
  1070. postIds: [],
  1071. roleIds: [],
  1072. unitIds: null,
  1073. workstationIds: null,
  1074. };
  1075. this.resetForm("form");
  1076. },
  1077. /** 搜索按钮操作 */
  1078. handleQuery() {
  1079. this.queryParams.pageNum = 1;
  1080. if(this.$route.query.workstationId){
  1081. this.queryParams.workstationId = this.$route.query.workstationId;
  1082. }else {
  1083. this.queryParams.workstationId=this.queryParams.workstationId
  1084. }
  1085. this.getList();
  1086. },
  1087. /** 重置按钮操作 */
  1088. resetQuery() {
  1089. this.dateRange = [];
  1090. this.resetForm("queryForm");
  1091. this.handleQuery();
  1092. // this.$router.push("/user/user");
  1093. },
  1094. // 多选框选中数据
  1095. handleSelectionChange(selection) {
  1096. this.ids = selection.map((item) => item.userId);
  1097. this.single = selection.length != 1;
  1098. this.multiple = !selection.length;
  1099. },
  1100. // 人脸指纹弹窗批量删除
  1101. handleSelectionChange2(selection) {
  1102. this.ids = selection.map((item) => item.recordId);
  1103. this.single = selection.length != 1;
  1104. this.multiple = !selection.length;
  1105. },
  1106. // 更多操作触发
  1107. handleCommand(command, row) {
  1108. switch (command) {
  1109. case "handleResetPwd":
  1110. this.handleResetPwd(row);
  1111. break;
  1112. case "handleAuthRole":
  1113. this.handleAuthRole(row);
  1114. break;
  1115. default:
  1116. break;
  1117. }
  1118. },
  1119. // 岗位查看页面跳转
  1120. HandleLookWorkStation(row) {
  1121. this.$router.push("/user/mars?userId=" + row.userId);
  1122. },
  1123. /** 查询部门下拉树结构 */
  1124. getTreeselect() {
  1125. treeselect().then((response) => {
  1126. debugger;
  1127. console.log(response.data, "部门下拉树形结构");
  1128. this.deptOptions = response.data;
  1129. });
  1130. const data = {
  1131. pages: 1,
  1132. size: -1,
  1133. };
  1134. listUnit(data).then((response) => {
  1135. console.log(response, "单位树");
  1136. this.UnitOptions = this.handleTree(response.data.records, "unitId");
  1137. });
  1138. },
  1139. // 单位树
  1140. Unitnormalizer(node) {
  1141. if (node.children && !node.children.length) {
  1142. delete node.children;
  1143. }
  1144. return {
  1145. id: node.unitId,
  1146. label: node.unitName,
  1147. children: node.children,
  1148. };
  1149. },
  1150. /** 转换mars岗位数据结构 */
  1151. Marsnormalizer(node) {
  1152. if (node.children && !node.children.length) {
  1153. delete node.children;
  1154. }
  1155. return {
  1156. id: node.workstationId,
  1157. label: node.workstationName,
  1158. children: node.children,
  1159. };
  1160. },
  1161. /** 新增按钮操作 */
  1162. handleAdd() {
  1163. this.reset();
  1164. this.getTreeselect();
  1165. getUser().then((response) => {
  1166. this.postOptions = response.posts;
  1167. this.roleOptions = response.roles;
  1168. this.open = true;
  1169. this.title = "新增用户";
  1170. this.form.password = this.initPassword;
  1171. });
  1172. this.$nextTick(() => {
  1173. this.$refs.treeRef.setCheckedKeys([]); // 清空选中的节点
  1174. this.selectTreeValue = []; // 清空已选中的值
  1175. this.form.workstationIds = []; // 清空工作站 IDs
  1176. this.selectTreeArrIds = []; // 清空工作站 ID 数组
  1177. });
  1178. },
  1179. /** 修改按钮操作 */
  1180. handleUpdate(row) {
  1181. this.reset();
  1182. this.getTreeselect();
  1183. const userId = row.userId || this.ids;
  1184. getUser(userId).then((response) => {
  1185. this.open = true;
  1186. this.form = response.data;
  1187. this.postOptions = response.posts;
  1188. this.roleOptions = response.roles;
  1189. this.form.postIds = response.postIds;
  1190. this.form.roleIds = response.roleIds;
  1191. if (response.unitIds) {
  1192. this.form.unitIds = response.unitIds;
  1193. }
  1194. // 岗位回显
  1195. if (response.workstationIds) {
  1196. let workstationNames = [];
  1197. response.workstationIds.forEach((id) => {
  1198. const foundItem = this.orignMarsWorkstation.find(
  1199. (item) => item.workstationId == id
  1200. );
  1201. console.log(foundItem, "foundItem");
  1202. if (foundItem) {
  1203. workstationNames.push(foundItem.workstationName);
  1204. console.log(workstationNames);
  1205. }
  1206. });
  1207. this.form.workstationIds = workstationNames;
  1208. this.$nextTick(() => {
  1209. this.$refs.treeRef.setCheckedKeys(response.workstationIds, true);
  1210. });
  1211. }
  1212. this.title = "修改用户";
  1213. this.form.password = "";
  1214. });
  1215. },
  1216. /** 重置密码按钮操作 */
  1217. handleResetPwd(row) {
  1218. this.$prompt('请输入"' + row.userName + '"的新密码', "提示", {
  1219. confirmButtonText: "确定",
  1220. cancelButtonText: "取消",
  1221. closeOnClickModal: false,
  1222. inputPattern: /^.{5,20}$/,
  1223. inputErrorMessage: "用户密码长度必须介于 5 和 20 之间",
  1224. })
  1225. .then(({ value }) => {
  1226. resetUserPwd(row.userId, value).then((response) => {
  1227. this.$modal.msgSuccess("修改成功,新密码是:" + value);
  1228. });
  1229. })
  1230. .catch(() => {});
  1231. },
  1232. /** 分配角色操作 */
  1233. handleAuthRole: function (row) {
  1234. const userId = row.userId;
  1235. this.$router.push("/system/user-auth/role/" + userId);
  1236. },
  1237. // 扁平数据
  1238. flattenArray(arr) {
  1239. return arr.reduce((acc, val) => {
  1240. return acc.concat(Array.isArray(val) ? this.flattenArray(val) : val);
  1241. }, []);
  1242. },
  1243. // 检查新增单位的时候是字符串还是多位数组 始终保持一维数组就行
  1244. ensureOneDimensionalArray(value) {
  1245. if (typeof value === "string") {
  1246. // 如果是字符串,转换为数组
  1247. return [value];
  1248. } else if (Array.isArray(value)) {
  1249. // 如果是数组,递归展平数组
  1250. return this.flattenArray(value);
  1251. } else {
  1252. // 如果是其他类型,返回空数组或根据需要处理
  1253. return [];
  1254. }
  1255. },
  1256. /** 提交按钮 */
  1257. submitForm: function () {
  1258. this.$refs["form"].validate((valid) => {
  1259. if (valid) {
  1260. if (this.form.userId != undefined) {
  1261. this.form.unitIds = this.ensureOneDimensionalArray(
  1262. this.form.unitIds
  1263. );
  1264. const data = {
  1265. ...this.form,
  1266. workstationIds: this.selectTreeArrIds,
  1267. };
  1268. updateUser(data).then((response) => {
  1269. this.$modal.msgSuccess("修改成功");
  1270. this.open = false;
  1271. this.getList();
  1272. });
  1273. } else {
  1274. // 文字转换
  1275. this.form.unitIds = this.ensureOneDimensionalArray(
  1276. this.form.unitIds
  1277. );
  1278. const data = {
  1279. ...this.form,
  1280. workstationIds: this.selectTreeArrIds,
  1281. };
  1282. addUser(data).then((response) => {
  1283. this.$modal.msgSuccess("新增成功");
  1284. this.open = false;
  1285. this.getList();
  1286. });
  1287. }
  1288. }
  1289. });
  1290. },
  1291. /** 删除按钮操作 */
  1292. // confirm('是否确认删除用户编号为"' + userIds + '"的数据项?')
  1293. handleDelete(row) {
  1294. const userIds = row.userId || this.ids;
  1295. this.$modal
  1296. .confirm("是否确认删除所选数据项?")
  1297. .then(function () {
  1298. return delUser(userIds);
  1299. })
  1300. .then(() => {
  1301. this.getList();
  1302. this.$modal.msgSuccess("删除成功");
  1303. })
  1304. .catch(() => {});
  1305. },
  1306. // 人脸指纹删除
  1307. handleDeleteFaceOrFinger(row) {
  1308. const userIds = row.recordId || this.ids;
  1309. this.$modal
  1310. .confirm("是否确认删除所选数据项?")
  1311. .then(function () {
  1312. return deleteSysUserCharacteristicByRecordIds(userIds);
  1313. })
  1314. .then(() => {
  1315. this.getFaceOrFingerList();
  1316. this.$modal.msgSuccess("删除成功");
  1317. })
  1318. .catch(() => {});
  1319. },
  1320. /** 导出按钮操作 */
  1321. handleExport() {
  1322. this.download(
  1323. "system/user/export",
  1324. {
  1325. ...this.queryParams,
  1326. },
  1327. `user_${new Date().getTime()}.xlsx`
  1328. );
  1329. },
  1330. /** 导入按钮操作 */
  1331. handleImport() {
  1332. this.upload.title = "用户导入";
  1333. this.upload.open = true;
  1334. },
  1335. /** 下载模板操作 */
  1336. importTemplate() {
  1337. this.download(
  1338. "system/user/importTemplate",
  1339. {},
  1340. `user_template_${new Date().getTime()}.xlsx`
  1341. );
  1342. },
  1343. // 文件上传中处理
  1344. handleFileUploadProgress(event, file, fileList) {
  1345. this.upload.isUploading = true;
  1346. },
  1347. // 文件上传成功处理
  1348. handleFileSuccess(response, file, fileList) {
  1349. this.upload.open = false;
  1350. this.upload.isUploading = false;
  1351. this.$refs.upload.clearFiles();
  1352. this.$alert(
  1353. "<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" +
  1354. response.msg +
  1355. "</div>",
  1356. "导入结果",
  1357. { dangerouslyUseHTMLString: true }
  1358. );
  1359. this.getList();
  1360. },
  1361. // 提交上传文件
  1362. submitFileForm() {
  1363. this.$refs.upload.submit();
  1364. },
  1365. },
  1366. };
  1367. </script>
  1368. <style lang="scss" scoped>
  1369. .container {
  1370. padding: 20px;
  1371. }
  1372. .setstyle {
  1373. height: auto;
  1374. padding: 0 !important;
  1375. .setinput {
  1376. padding: 6px;
  1377. }
  1378. }
  1379. //图片放大
  1380. .img-box {
  1381. width: 50px;
  1382. height: 50px;
  1383. position: relative;
  1384. margin-left: 45%;
  1385. #eyeicon {
  1386. display: none;
  1387. }
  1388. }
  1389. .img-box:hover {
  1390. background: #000;
  1391. .images {
  1392. opacity: 0.6;
  1393. }
  1394. #eyeicon {
  1395. display: block;
  1396. position: absolute;
  1397. top: 40%;
  1398. left: 32%;
  1399. z-index: 100;
  1400. color: white;
  1401. pointer-events: none;
  1402. }
  1403. }
  1404. </style>