admin.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. <template>
  2. <div class="app-container calendar-list-container">
  3. <!-- 查询和其他操作 -->
  4. <div class="filter-container">
  5. <el-input clearable class="filter-item" style="width: 200px;" placeholder="请输入用户名称" v-model="listQuery.username">
  6. </el-input>
  7. <el-input clearable class="filter-item" style="width: 200px;" placeholder="请输入用户昵称" v-model="listQuery.nickname">
  8. </el-input>
  9. <el-button class="filter-item" type="primary" v-waves icon="el-icon-search" @click="handleQuery">查找</el-button>
  10. <el-button class="filter-item" icon="el-icon-refresh" @click="resetQuery">重置</el-button>
  11. <el-button class="filter-item" type="primary" @click="handleCreate" icon="el-icon-plus">添加</el-button>
  12. <el-button class="filter-item" :loading="downloadLoading" v-waves icon="el-icon-download" @click="handleDownload">导出</el-button>
  13. </div>
  14. <!-- 查询结果 -->
  15. <el-table size="small" :data="list" v-loading="listLoading" element-loading-text="正在查询中。。。" border fit highlight-current-row>
  16. <!--<el-table-column align="center" width="100px" label="用户ID" prop="id" sortable>
  17. </el-table-column>-->
  18. <el-table-column type="index" label="序号" header-align="center" align="center">
  19. </el-table-column>
  20. <el-table-column align="center" min-width="100px" label="用户名称" prop="username">
  21. </el-table-column>
  22. <el-table-column align="center" min-width="100px" label="用户昵称" prop="nickname">
  23. </el-table-column>
  24. <el-table-column align="center" min-width="100px" label="用户头像" prop="avatar">
  25. <template slot-scope="scope">
  26. <img class="user-avatar" :src="scope.row.avatar?scope.row.avatar:require('@/assets/avatar.gif')">
  27. </template>
  28. </el-table-column>
  29. <el-table-column align="center" label="操作" width="250" class-name="small-padding fixed-width">
  30. <template slot-scope="scope">
  31. <el-button type="primary" size="small" @click="handleUpdate(scope.row, false)">编辑</el-button>
  32. <el-button type="primary" size="small" @click="handleUpdate(scope.row, true)">角色</el-button>
  33. <el-button type="danger" size="small" @click="handleDelete(scope.row)">删除</el-button>
  34. </template>
  35. </el-table-column>
  36. </el-table>
  37. <!-- 分页 -->
  38. <div class="pagination-container">
  39. <el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="listQuery.page"
  40. :page-sizes="[10,20,30,50]" :page-size="listQuery.limit" layout="total, sizes, prev, pager, next, jumper" :total="total">
  41. </el-pagination>
  42. </div>
  43. <!-- 添加或修改对话框 -->
  44. <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible">
  45. <template v-if="!dialogFlag">
  46. <el-form :rules="rules" ref="dataForm" :model="dataForm" status-icon label-position="left" label-width="120px" style='width: 400px; margin-left:50px;'>
  47. <!-- <el-form-item label="用户名称" prop="username">
  48. <el-input v-if="dialogStatus=='create'" v-model="dataForm.username" auto-complete="off"></el-input>
  49. <el-input v-else v-model="dataForm.username" disabled auto-complete="off"></el-input>
  50. </el-form-item> -->
  51. <el-form-item label="用户" prop="username">
  52. <el-select :disabled="dialogStatus=='create'?false:true" v-model="dataForm.username" filterable clearable placeholder="请选择" style="width: 280px">
  53. <el-option :key="item.loginId" v-for="item in recipientsList" :label="item.deptName+'_'+item.userName+'_'+item.employeNo" :value="item.loginId">
  54. </el-option>
  55. </el-select>
  56. </el-form-item>
  57. <el-form-item label="用户密码" prop="password">
  58. <el-input type="password" v-model="dataForm.password" auto-complete="off"></el-input>
  59. </el-form-item>
  60. <el-form-item label="确认密码" prop="checkPassword">
  61. <el-input type="password" v-model="dataForm.checkPassword" auto-complete="off"></el-input>
  62. </el-form-item>
  63. <el-form-item label="用户昵称" prop="nickname">
  64. <el-input v-model="dataForm.nickname"></el-input>
  65. </el-form-item>
  66. <!--<el-form-item label="关联微信" prop="phone">
  67. <el-tooltip class="item" effect="dark" content="输入手机号码" placement="top-start">
  68. <el-input ref="phone" v-model="dataForm.phone" @blur="getWxUserId"></el-input>
  69. </el-tooltip>
  70. </el-form-item>-->
  71. <el-form-item label="关联微信用户" prop="userId">
  72. <el-select
  73. style="width: 280px"
  74. v-model="dataForm.userId"
  75. :filterable="selectfilterable"
  76. :remote="selectremote"
  77. placeholder="请输入关键词"
  78. :remote-method="remoteMethod"
  79. :loading="selectLoading">
  80. <el-option
  81. v-for="item in optionsOrgUser"
  82. :key="item.id"
  83. :label="item.userName"
  84. :value="item.id">
  85. </el-option>
  86. </el-select>
  87. </el-form-item>
  88. <el-form-item label="用户头像" prop="avatar">
  89. <el-input v-model="dataForm.avatar"></el-input>
  90. <el-upload action="#" list-type="picture" :show-file-list="false" :limit="1" :http-request="uploadAvatar">
  91. <el-button size="small" type="primary">点击上传</el-button>
  92. </el-upload>
  93. </el-form-item>
  94. </el-form>
  95. </template>
  96. <template v-else>
  97. <el-form status-icon label-position="left" label-width="100px" style='width: 400px; margin-left:50px;'>
  98. <el-form-item label="用户角色">
  99. <el-select v-model="role" multiple placeholder="请选择">
  100. <el-option
  101. v-for="item in roleList"
  102. :key="item.id"
  103. :label="item.roleName"
  104. :value="item.id">
  105. </el-option>
  106. </el-select>
  107. </el-form-item>
  108. </el-form>
  109. </template>
  110. <div slot="footer" class="dialog-footer">
  111. <el-button @click="dialogFormVisible = false">取消</el-button>
  112. <template v-if="!dialogFlag">
  113. <el-button v-if="dialogStatus=='create'" type="primary" @click="createData">确定</el-button>
  114. <el-button v-else type="primary" @click="updateData">确定</el-button>
  115. </template>
  116. <template v-if="dialogFlag">
  117. <el-button type="primary" @click="updateUserRoles">确定</el-button>
  118. </template>
  119. </div>
  120. </el-dialog>
  121. </div>
  122. </template>
  123. <style>
  124. .avatar-uploader .el-upload {
  125. border: 1px dashed #d9d9d9;
  126. border-radius: 6px;
  127. cursor: pointer;
  128. position: relative;
  129. overflow: hidden;
  130. }
  131. .avatar-uploader .el-upload:hover {
  132. border-color: #409EFF;
  133. }
  134. .avatar-uploader-icon {
  135. font-size: 28px;
  136. color: #8c939d;
  137. width: 178px;
  138. height: 178px;
  139. line-height: 178px;
  140. text-align: center;
  141. }
  142. .avatar {
  143. width: 178px;
  144. height: 178px;
  145. display: block;
  146. }
  147. .user-avatar{
  148. width: 50px;
  149. height: 50px;
  150. border-radius: 50%;
  151. }
  152. </style>
  153. <script>
  154. import { listAdmin, createAdmin, updateAdmin, deleteAdmin, getWxUserId, getUser} from '@/api/admin'
  155. import { selectUserByUserName } from "@/api/organize"
  156. import { roleList, selectAdminRole, addAdminRole } from '@/api/role'
  157. import { createStorage } from '@/api/storage'
  158. import { allUserList } from "@/api/public";
  159. import waves from '@/directive/waves' // 水波纹指令
  160. export default {
  161. name: 'Admin',
  162. directives: {
  163. waves
  164. },
  165. data() {
  166. var validateUserName = (rule,value,callback) => {
  167. if (value === '') {
  168. callback(new Error('请输入用户名'))
  169. } else {
  170. if(this.dialogStatus === 'create'){
  171. getUser({userName:value}).then(response=>{
  172. if (response.data.data){
  173. callback(new Error("用户名已存在"))
  174. } else {
  175. callback()
  176. }
  177. })
  178. } else {
  179. callback()
  180. }
  181. }
  182. }
  183. var validatePass = (rule, value, callback) => {
  184. if (value === '') {
  185. callback(new Error('请输入密码'))
  186. } else {
  187. const reg = /([0-9]+[a-zA-Z]+|[a-zA-Z]+[0-9]+)[0-9a-zA-Z]*/;
  188. //const reg = /^(?!\d+$)[\da-zA-Z]+$/;
  189. if (!reg.test(value)) {
  190. callback(new Error('请输入字母、数字组合'))
  191. }
  192. if (this.dataForm.checkPassword !== '') {
  193. this.$refs.dataForm.validateField('checkPassword')
  194. }
  195. callback()
  196. }
  197. }
  198. var validatePass2 = (rule, value, callback) => {
  199. if (value === '') {
  200. callback(new Error('请再次输入密码'))
  201. } else if (value !== this.dataForm.password) {
  202. callback(new Error('两次输入密码不一致!'))
  203. } else {
  204. callback()
  205. }
  206. }
  207. return {
  208. recipientsList: [],
  209. list: null,
  210. role: undefined,
  211. total: null,
  212. listLoading: true,
  213. selectLoading: false,
  214. selectfilterable: true,
  215. selectremote: true,
  216. optionsOrgUser: null,
  217. listQuery: {
  218. page: 1,
  219. limit: 20,
  220. username: undefined,
  221. nickname: undefined,
  222. sort: '+id'
  223. },
  224. dataForm: {
  225. id: undefined,
  226. username: undefined,
  227. nickname: undefined,
  228. password: undefined,
  229. checkPassword: undefined,
  230. avatar: undefined,
  231. userId: undefined,
  232. phone: undefined
  233. },
  234. typeDate: {
  235. imgBelongs:"3"
  236. },
  237. dialogFormVisible: false,
  238. dialogStatus: '',
  239. textMap: {
  240. update: '编辑',
  241. create: '创建'
  242. },
  243. rules: {
  244. username: [{ required: true, message: '用户不能为空', trigger: 'blur' }],
  245. nickname: [{ required: true, message: '用户昵称不能为空', trigger: 'blur' }],
  246. password: [
  247. { required: true, message: '密码不能为空', trigger: 'blur' },
  248. { min:8, max:18, message: '长度在 8 到 18 个字符' },
  249. { validator: validatePass, trigger: 'blur' }
  250. ],
  251. checkPassword: [
  252. { required: true, message: '密码不能为空', trigger: 'blur' },
  253. { validator: validatePass2, trigger: 'blur' }
  254. ],
  255. phone: [{required: true, message: '手机号码不能为空', trigger: 'blur'}],
  256. userId: [{required: true, message: '关联微信用户不能为空', trigger: 'blur'}]
  257. },
  258. downloadLoading: false,
  259. roleList: [
  260. {
  261. value: 1,
  262. label: 'admin'
  263. }
  264. ],
  265. dialogFlag: false
  266. }
  267. },
  268. created() {
  269. this.getList();
  270. this.getRoleList();
  271. this.getAllUserList();
  272. },
  273. methods: {
  274. getAllUserList() {
  275. allUserList().then(response => {
  276. this.recipientsList = response.data.data;
  277. }).catch(() => {});
  278. },
  279. getList() {
  280. this.listLoading = true
  281. listAdmin(this.listQuery).then(response => {
  282. this.list = response.data.data.items
  283. this.total = response.data.data.total
  284. this.listLoading = false
  285. }).catch(() => {
  286. this.list = []
  287. this.total = 0
  288. this.listLoading = false
  289. })
  290. },
  291. handleQuery() {
  292. this.listQuery.page = 1
  293. this.getList()
  294. },
  295. /** 重置按钮操作 */
  296. resetQuery() {
  297. this.listQuery = {
  298. username: undefined,
  299. nickname: undefined,
  300. sort: '+id'
  301. };
  302. this.handleQuery();
  303. },
  304. handleSizeChange(val) {
  305. this.listQuery.limit = val
  306. this.getList()
  307. },
  308. handleCurrentChange(val) {
  309. this.listQuery.page = val
  310. this.getList()
  311. },
  312. resetForm() {
  313. this.dataForm = {
  314. id: undefined,
  315. username: undefined,
  316. password: undefined,
  317. checkPassword: undefined,
  318. avatar: undefined
  319. }
  320. this.role = []
  321. },
  322. uploadAvatar(item) {
  323. const formData = new FormData()
  324. formData.append('file', item.file)
  325. createStorage(formData).then(res => {
  326. this.dataForm.avatar = res.data.data.url
  327. }).catch(() => {
  328. this.$message.error('上传失败,请重新上传')
  329. })
  330. },
  331. remoteMethod(query){
  332. this.selectLoading = true;
  333. selectUserByUserName({"userName":query}).then(res => {
  334. this.optionsOrgUser = res.data.data
  335. this.selectLoading = false;
  336. })
  337. },
  338. handleCreate() {
  339. this.resetForm()
  340. this.dialogFlag = false
  341. this.dialogStatus = 'create'
  342. this.dialogFormVisible = true
  343. this.$nextTick(() => {
  344. this.$refs['dataForm'].clearValidate()
  345. })
  346. },
  347. createData() {
  348. this.$refs['dataForm'].validate((valid) => {
  349. if (valid) {
  350. createAdmin(this.dataForm).then(response => {
  351. this.list.unshift(response.data.data)
  352. this.dialogFormVisible = false
  353. this.$notify({
  354. title: '成功',
  355. message: '创建成功',
  356. type: 'success',
  357. duration: 2000
  358. })
  359. })
  360. }
  361. })
  362. },
  363. handleUpdate(row, type) {
  364. this.dialogFlag = type
  365. this.dataForm = Object.assign({}, row)
  366. this.dialogStatus = 'update'
  367. this.dialogFormVisible = true
  368. if (!type) {
  369. this.$nextTick(() => {
  370. this.$refs['dataForm'].clearValidate()
  371. })
  372. } else {
  373. this.getUserRoles()
  374. }
  375. },
  376. updateData() {
  377. this.$refs['dataForm'].validate((valid) => {
  378. if (valid) {
  379. updateAdmin(this.dataForm).then(() => {
  380. for (const v of this.list) {
  381. if (v.id === this.dataForm.id) {
  382. const index = this.list.indexOf(v)
  383. this.list.splice(index, 1, this.dataForm)
  384. break
  385. }
  386. }
  387. this.dialogFormVisible = false
  388. this.$notify({
  389. title: '成功',
  390. message: '更新成功',
  391. type: 'success',
  392. duration: 2000
  393. })
  394. })
  395. }
  396. })
  397. },
  398. handleDelete(row) {
  399. deleteAdmin(row).then(response => {
  400. this.$notify({
  401. title: '成功',
  402. message: '删除成功',
  403. type: 'success',
  404. duration: 2000
  405. })
  406. const index = this.list.indexOf(row)
  407. this.list.splice(index, 1)
  408. })
  409. },
  410. handleDownload() {
  411. this.downloadLoading = true
  412. import('@/vendor/Export2Excel').then(excel => {
  413. const tHeader = ['用户ID', '用户名称','用户昵称', '用户头像']
  414. const filterVal = ['id', 'username', 'nickname', 'avatar']
  415. excel.export_json_to_excel2(tHeader, this.list, filterVal, '用户信息')
  416. this.downloadLoading = false
  417. })
  418. },
  419. getRoleList() {
  420. roleList({ page: 1, limit: 100 })
  421. .then(response => {
  422. this.roleList = response.data.data.items
  423. })
  424. },
  425. getUserRoles() {
  426. selectAdminRole({ userId: this.dataForm.id })
  427. .then(response => {
  428. var role = response.data.data
  429. if (role) {
  430. role = role.map( function(val) {
  431. return val - 0
  432. })
  433. } else {
  434. role = []
  435. }
  436. this.role = role
  437. })
  438. },
  439. updateUserRoles() {
  440. addAdminRole({ roleList: this.role.join(','), userId: this.dataForm.id })
  441. .then(response => {
  442. this.dialogFormVisible = false
  443. this.$notify({
  444. title: '成功',
  445. message: '更新成功',
  446. type: 'success',
  447. duration: 2000
  448. })
  449. })
  450. },
  451. getWxUserId() {
  452. console.log(this.dataForm.phone)
  453. if(this.dataForm.phone) {
  454. getWxUserId({'phone' : this.dataForm.phone}).then(response => {
  455. let userId = response.data.data.userId
  456. if(userId != 0) {
  457. this.dataForm.userId = userId
  458. } else {
  459. this.$alert('无法查询该手机关联的微信用户Id,请重新输入', '提示', {
  460. type: 'warning',
  461. callback: action => {
  462. this.dataForm.phone = undefined
  463. this.$refs['phone'].focus()
  464. }
  465. })
  466. }
  467. }).catch(() => {
  468. })
  469. }
  470. }
  471. }
  472. }
  473. </script>