Account.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. <template>
  2. <schema-table
  3. ref="table"
  4. :schema="schema"
  5. >
  6. <confirm-dialog
  7. ref="editDialog"
  8. title="新增账号"
  9. @confirm="onSave"
  10. >
  11. <template #default>
  12. <div class="c-grid-form u-align-self--center">
  13. <span class="c-grid-form__label u-required">
  14. 账号
  15. </span>
  16. <div
  17. class="u-width has-info"
  18. data-info="仅可包含数字、字母"
  19. >
  20. <el-input
  21. v-model.trim="user.username"
  22. placeholder="4~20个字符"
  23. maxlength="20"
  24. clearable
  25. />
  26. </div>
  27. <span class="c-grid-form__label">
  28. 姓名
  29. </span>
  30. <el-input
  31. v-model.trim="user.name"
  32. class="u-width"
  33. placeholder="账号使用者姓名"
  34. maxlength="20"
  35. clearable
  36. />
  37. <span class="c-grid-form__label u-required">
  38. 手机
  39. </span>
  40. <el-input
  41. v-model.trim="user.phone"
  42. class="u-width"
  43. placeholder="账号使用者手机号码"
  44. maxlength="13"
  45. clearable
  46. />
  47. <span class="c-grid-form__label u-required">
  48. 邮箱
  49. </span>
  50. <el-input
  51. v-model.trim="user.email"
  52. class="u-width"
  53. placeholder="账号使用者电子邮箱"
  54. maxlength="50"
  55. clearable
  56. />
  57. <span class="c-grid-form__label">
  58. 部门
  59. </span>
  60. <div class="c-grid-form__auto u-overflow-x--auto">
  61. <el-tree
  62. ref="tree"
  63. class="inline-flex"
  64. :data="groups"
  65. node-key="path"
  66. :props="treeProps"
  67. :current-node-key="group.path"
  68. :default-expanded-keys="expandKeys"
  69. :expand-on-click-node="false"
  70. accordion
  71. highlight-current
  72. auto-expand-parent
  73. @node-click="onGroupClick"
  74. />
  75. </div>
  76. </div>
  77. </template>
  78. </confirm-dialog>
  79. <c-dialog
  80. ref="dialog"
  81. size="medium"
  82. title="设置"
  83. >
  84. <template #default>
  85. <settings
  86. :user="user"
  87. :tenant="tenant"
  88. :groups="groups"
  89. @del="onDel"
  90. @group="onGroupChange"
  91. />
  92. </template>
  93. </c-dialog>
  94. <confirm-dialog
  95. ref="eventDialog"
  96. title="自定义事件"
  97. @confirm="onConfirmEvents"
  98. >
  99. <el-checkbox-group
  100. v-model="selectedEvents"
  101. class="l-grid--info mini"
  102. >
  103. <el-checkbox
  104. v-for="item in events"
  105. :key="item.id"
  106. :label="item.id"
  107. >
  108. {{ item.label }}
  109. </el-checkbox>
  110. </el-checkbox-group>
  111. </confirm-dialog>
  112. </schema-table>
  113. </template>
  114. <script>
  115. import { mapGetters } from 'vuex'
  116. import {
  117. AlarmLevelInfo,
  118. SupportedAlarmStrategies
  119. } from '@/constant.js'
  120. import {
  121. validPhone,
  122. validEmail
  123. } from '@/utils/validate.js'
  124. import {
  125. getUsersByDepartment,
  126. addUser,
  127. updateUserName,
  128. toggleUser,
  129. updateUserInformLevel,
  130. getUserInforms
  131. } from '@/api/user.js'
  132. import Settings from './Settings.vue'
  133. const CustomEvents = Object.freeze([
  134. { id: 1, level: 0, label: '播控器离线' },
  135. { id: 17, level: 2, label: '播控器工作时段离线' },
  136. { id: 15, level: 2, label: '播控器人为离线' },
  137. { id: 9, level: 0, label: '播控器上线' },
  138. { id: 32, level: 2, label: '播控器非工作时段上线' },
  139. { id: 40, level: 2, label: '播控器上线失败' },
  140. { id: 35, level: 0, label: '接收卡提示性预警' },
  141. { id: 2, level: 2, label: '接收卡紧急预警' },
  142. { id: 36, level: 2, label: '手动关闭电源' },
  143. { id: 37, level: 2, label: '手动开启电源' },
  144. { id: 42, level: 2, label: '电源定时任务' },
  145. { id: 0, level: 1, label: '屏幕疑似黑屏' },
  146. { id: 13, level: 2, label: '屏幕黑屏' },
  147. { id: 10, level: 2, label: '屏幕内容疑似不合规' },
  148. // { id: 3, level: 2, label: '屏幕内容不合规(拼接器)' },
  149. { id: 11, level: 2, label: '屏幕内容不合规' },
  150. { id: 18, level: 0, label: '温度传感器提示告警' },
  151. { id: 19, level: 0, label: '温度传感器一级告警' },
  152. { id: 20, level: 0, label: '温度传感器二级告警' },
  153. { id: 21, level: 1, label: '温度传感器三级告警' },
  154. { id: 22, level: 2, label: '温度传感器四级告警' },
  155. { id: 23, level: 2, label: '位移传感器报警' },
  156. { id: 7, level: 2, label: '屏幕监控摄像头离线' },
  157. { id: 8, level: 2, label: '人流监测摄像头离线' },
  158. { id: 33, level: 0, label: '屏幕监控摄像头上线' },
  159. { id: 34, level: 0, label: '人流监测摄像头上线' }
  160. ])
  161. export default {
  162. name: 'Account',
  163. components: {
  164. Settings
  165. },
  166. props: {
  167. groups: {
  168. type: Array,
  169. required: true
  170. },
  171. group: {
  172. type: Object,
  173. required: true
  174. }
  175. },
  176. data () {
  177. return {
  178. schema: {
  179. list: this.getUsersByDepartment,
  180. condition: { recursive: 1 },
  181. buttons: [
  182. { type: 'add', on: this.onAdd }
  183. ],
  184. filters: [
  185. { key: 'recursive', type: 'checkbox', label: '级联' }
  186. ],
  187. cols: [
  188. { label: '部门', render: ({ path, tenant }) => this.groupMap[path || tenant] || '未知' },
  189. { prop: 'userName', label: '账号' },
  190. { label: '使用者', render: (data, h) => h('edit-input', {
  191. props: {
  192. value: data.name || '',
  193. placeholder: '-'
  194. },
  195. on: { edit: val => this.onEditName(data, val) }
  196. }), 'class-name': 'c-edit-column' },
  197. SupportedAlarmStrategies.length && { label: '消息推送', render: (data, h) => h('el-select', {
  198. staticClass: 'u-width--sm',
  199. props: {
  200. value: data.informLevel,
  201. size: 'small'
  202. },
  203. on: {
  204. change: val => this.updateInformLevel(val, data)
  205. }
  206. }, [
  207. data.informLevel === 9999 && h('i', {
  208. slot: 'prefix',
  209. staticClass: 'l-flex--row center el-icon-edit u-font-size--md has-active',
  210. staticStyle: {
  211. height: '100%'
  212. },
  213. on: { click: e => {
  214. e.stopPropagation()
  215. this.onEditEvents(data)
  216. } }
  217. }),
  218. h('el-option', {
  219. key: 'none',
  220. props: {
  221. value: -1,
  222. label: '不预警'
  223. }
  224. }),
  225. h('el-option', {
  226. key: 'info',
  227. props: {
  228. value: 0,
  229. label: `${AlarmLevelInfo[0]}及以上`
  230. }
  231. }),
  232. h('el-option', {
  233. key: 'warning',
  234. props: {
  235. value: 1,
  236. label: `${AlarmLevelInfo[1]}及以上`
  237. }
  238. }),
  239. h('el-option', {
  240. key: 'error',
  241. props: {
  242. value: 2,
  243. label: AlarmLevelInfo[2]
  244. }
  245. }),
  246. h('el-option', {
  247. key: 'terror',
  248. props: {
  249. value: 9999,
  250. label: AlarmLevelInfo[9999]
  251. }
  252. })
  253. ]), width: 180 },
  254. { type: 'tag', render: ({ userId, enabled }) => userId === this.userId
  255. ? null
  256. : {
  257. type: enabled ? 'success' : 'danger',
  258. label: enabled ? '启用' : '禁用'
  259. }, on: this.onToggle },
  260. { type: 'invoke', use: ({ userId }) => userId !== this.userId, render: [
  261. { label: '设置', on: this.onSettings }
  262. ] }
  263. ]
  264. },
  265. user: {},
  266. treeProps: { label: 'name', children: 'children' },
  267. events: CustomEvents,
  268. selectedEvents: []
  269. }
  270. },
  271. computed: {
  272. ...mapGetters(['tenant', 'userId']),
  273. expandKeys () {
  274. let groups = this.groups
  275. const group = this.group
  276. const arr = []
  277. const marks = group.path.split('/').filter(Boolean)
  278. let cpath = '/'
  279. while (marks.length > 1) {
  280. cpath += marks.shift()
  281. const tpath = cpath
  282. const temp = groups.find(({ path }) => path === tpath)
  283. arr.push(temp.path)
  284. groups = temp.children
  285. cpath += '/'
  286. }
  287. return arr.length ? arr : [this.tenant]
  288. },
  289. groupMap () {
  290. const map = {}
  291. this.createMap(this.groups, map)
  292. return map
  293. }
  294. },
  295. watch: {
  296. group () {
  297. this.$refs.table.pageTo(1)
  298. }
  299. },
  300. methods: {
  301. createMap (arr, map) {
  302. arr?.forEach(({ path, name, children }) => {
  303. map[path] = name
  304. this.createMap(children, map)
  305. })
  306. },
  307. getUsersByDepartment (params) {
  308. return getUsersByDepartment({
  309. departmentId: this.group.id,
  310. ...params
  311. })
  312. },
  313. onSettings (user) {
  314. this.user = user
  315. this.$refs.dialog.show()
  316. },
  317. onDel () {
  318. this.$refs.dialog.hide()
  319. this.$refs.table.decrease(1)
  320. },
  321. onGroupChange () {
  322. this.$refs.table.pageTo()
  323. },
  324. onAdd () {
  325. this.user = {
  326. username: '',
  327. name: ''
  328. }
  329. this.$department = { id: this.group.id, path: this.group.path, name: this.group.name }
  330. this.$refs.editDialog.show()
  331. },
  332. onGroupClick ({ id, path, name }) {
  333. this.$department = { id, path, name }
  334. },
  335. onSave (done) {
  336. const { username, phone, email } = this.user
  337. if (!username) {
  338. this.$message({
  339. type: 'warning',
  340. message: '请填写用户账号'
  341. })
  342. return
  343. }
  344. if (username.length < 4) {
  345. this.$message({
  346. type: 'warning',
  347. message: '用户账号过短'
  348. })
  349. return
  350. }
  351. if (!/^[\da-zA-Z]{4,}$/.test(username)) {
  352. this.$message({
  353. type: 'warning',
  354. message: '用户账号格式错误'
  355. })
  356. return
  357. }
  358. if (!phone) {
  359. this.$message({
  360. type: 'warning',
  361. message: '请填写手机号码'
  362. })
  363. return
  364. }
  365. if (!validPhone(phone)) {
  366. this.$message({
  367. type: 'warning',
  368. message: '用户手机号码格式错误'
  369. })
  370. return
  371. }
  372. if (!email) {
  373. this.$message({
  374. type: 'warning',
  375. message: '请填写电子邮箱'
  376. })
  377. return
  378. }
  379. if (!validEmail(email)) {
  380. this.$message({
  381. type: 'warning',
  382. message: '用户电子邮箱格式错误'
  383. })
  384. return
  385. }
  386. addUser({
  387. ...this.user,
  388. ...(
  389. this.$department.id
  390. ? { departmentId: this.$department.id, departmentName: this.$department.name }
  391. : { departmentName: '顶层部门' }
  392. )
  393. }).then(() => {
  394. done()
  395. if (this.$department.path.indexOf(this.group.path) === 0) {
  396. this.$refs.table.pageTo(1)
  397. }
  398. })
  399. },
  400. onEditName (user, { newVal, oldVal }) {
  401. if (newVal === oldVal) {
  402. return
  403. }
  404. user.name = newVal
  405. updateUserName(user.userId, newVal).catch(() => {
  406. user.name = oldVal
  407. })
  408. },
  409. onToggle (user) {
  410. const enabled = [1, 0][user.enabled]
  411. this.$confirm(
  412. `${enabled ? '启用' : '停用'}账号${user.userName}?`,
  413. '操作确认',
  414. { type: 'warning' }
  415. ).then(() => toggleUser(
  416. user,
  417. enabled
  418. )).then(() => {
  419. user.enabled = enabled
  420. })
  421. },
  422. updateInformLevel (val, user) {
  423. updateUserInformLevel(user, val).then(() => {
  424. user.informLevel = val
  425. if (val === 9999) {
  426. this.onEditEvents(user)
  427. }
  428. })
  429. },
  430. onEditEvents (user) {
  431. this.$user = user
  432. getUserInforms(user).then(({ data }) => {
  433. this.selectedEvents = data
  434. this.$refs.eventDialog.show()
  435. })
  436. },
  437. onConfirmEvents (done) {
  438. updateUserInformLevel(this.$user, 9999, this.selectedEvents).then(done)
  439. }
  440. }
  441. }
  442. </script>