bdaf80f9bfb713e759b3786b7f62f734140c23f3.svn-base 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523
  1. <template>
  2. <a-drawer
  3. :title="title"
  4. :maskClosable="true"
  5. :width="drawerWidth"
  6. placement="right"
  7. :closable="true"
  8. @close="handleCancel"
  9. :visible="visible"
  10. style="height: 100%;overflow: auto;padding-bottom: 53px;">
  11. <template slot="title">
  12. <div style="width: 100%;">
  13. <span>{{ title }}</span>
  14. <span style="display:inline-block;width:calc(100% - 51px);padding-right:10px;text-align: right">
  15. <a-button @click="toggleScreen" icon="appstore" style="height:20px;width:20px;border:0px"></a-button>
  16. </span>
  17. </div>
  18. </template>
  19. <a-spin :spinning="confirmLoading">
  20. <a-form-model ref="form" :model="model" :rules="validatorRules">
  21. <a-form-model-item label="用户账号" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="username">
  22. <a-input placeholder="请输入用户账号" v-model="model.username" :readOnly="!!model.id"/>
  23. </a-form-model-item>
  24. <template v-if="!model.id">
  25. <a-form-model-item label="登录密码" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="password" >
  26. <a-input type="password" placeholder="请输入登录密码" v-model="model.password" />
  27. </a-form-model-item>
  28. <a-form-model-item label="确认密码" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="confirmpassword" >
  29. <a-input type="password" @blur="handleConfirmBlur" placeholder="请重新输入登录密码" v-model="model.confirmpassword"/>
  30. </a-form-model-item>
  31. </template>
  32. <a-form-model-item label="用户姓名" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="realname">
  33. <a-input placeholder="请输入用户姓名" v-model="model.realname" />
  34. </a-form-model-item>
  35. <!-- <a-form-model-item label="工号" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="workNo">-->
  36. <!-- <a-input placeholder="请输入工号" v-model="model.workNo" />-->
  37. <!-- </a-form-model-item>-->
  38. <a-form-model-item label="职务" :labelCol="labelCol" :wrapperCol="wrapperCol">
  39. <j-select-position placeholder="请选择职务" :multiple="false" v-model="model.post"/>
  40. </a-form-model-item>
  41. <a-form-model-item label="行政区划" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="xzqh">
  42. <a-input placeholder="请输入行政区划" v-model="model.xzqh" />
  43. </a-form-model-item>
  44. <a-form-model-item label="角色分配" :labelCol="labelCol" :wrapperCol="wrapperCol" v-show="!roleDisabled" >
  45. <j-multi-select-tag
  46. :disabled="disableSubmit"
  47. v-model="model.selectedroles"
  48. :options="rolesOptions"
  49. placeholder="请选择角色">
  50. </j-multi-select-tag>
  51. </a-form-model-item>
  52. <!--部门分配-->
  53. <a-form-model-item label="部门分配" :labelCol="labelCol" :wrapperCol="wrapperCol" v-show="!departDisabled">
  54. <j-select-depart v-model="model.selecteddeparts" :multi="true" @back="backDepartInfo" :backDepart="true" :treeOpera="true">></j-select-depart>
  55. </a-form-model-item>
  56. <!--租户分配-->
  57. <a-form-model-item label="租户分配" :labelCol="labelCol" :wrapperCol="wrapperCol" v-show="!departDisabled">
  58. <j-multi-select-tag
  59. :disabled="disableSubmit"
  60. v-model="model.relTenantIds"
  61. :options="tenantsOptions"
  62. placeholder="请选择租户">
  63. </j-multi-select-tag>
  64. </a-form-model-item>
  65. <a-form-model-item label="身份" :labelCol="labelCol" :wrapperCol="wrapperCol">
  66. <a-radio-group v-model="model.userIdentity" @change="identityChange">
  67. <a-radio :value="1">普通用户</a-radio>
  68. <a-radio :value="2">上级</a-radio>
  69. </a-radio-group>
  70. </a-form-model-item>
  71. <a-form-model-item label="负责部门" :labelCol="labelCol" :wrapperCol="wrapperCol" v-if="departIdShow==true">
  72. <j-multi-select-tag
  73. :disabled="disableSubmit"
  74. v-model="model.departIds"
  75. :options="nextDepartOptions"
  76. placeholder="请选择负责部门">
  77. </j-multi-select-tag>
  78. </a-form-model-item>
  79. <a-form-model-item label="头像" :labelCol="labelCol" :wrapperCol="wrapperCol">
  80. <j-image-upload class="avatar-uploader" text="上传" v-model="model.avatar" ></j-image-upload>
  81. </a-form-model-item>
  82. <a-form-model-item label="生日" :labelCol="labelCol" :wrapperCol="wrapperCol">
  83. <a-date-picker
  84. style="width: 100%"
  85. placeholder="请选择生日"
  86. v-model="model.birthday"
  87. :format="dateFormat"
  88. :getCalendarContainer="node => node.parentNode"/>
  89. </a-form-model-item>
  90. <a-form-model-item label="性别" :labelCol="labelCol" :wrapperCol="wrapperCol">
  91. <a-select v-model="model.sex" placeholder="请选择性别" :getPopupContainer= "(target) => target.parentNode">
  92. <a-select-option :value="1">男</a-select-option>
  93. <a-select-option :value="2">女</a-select-option>
  94. </a-select>
  95. </a-form-model-item>
  96. <a-form-model-item label="邮箱" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="email">
  97. <a-input placeholder="请输入邮箱" v-model="model.email" />
  98. </a-form-model-item>
  99. <a-form-model-item label="手机号码" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="phone">
  100. <a-input placeholder="请输入手机号码" v-model="model.phone" />
  101. </a-form-model-item>
  102. <a-form-model-item label="座机" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="telephone">
  103. <a-input placeholder="请输入座机" v-model="model.telephone" />
  104. </a-form-model-item>
  105. <a-form-model-item label="工作流引擎" :labelCol="labelCol" :wrapperCol="wrapperCol">
  106. <j-dict-select-tag v-model="model.activitiSync" placeholder="请选择是否同步工作流引擎" :type="'radio'" dictCode="activiti_sync"/>
  107. </a-form-model-item>
  108. </a-form-model>
  109. </a-spin>
  110. <div class="drawer-bootom-button" v-show="!disableSubmit">
  111. <a-popconfirm title="确定放弃编辑?" @confirm="handleCancel" okText="确定" cancelText="取消">
  112. <a-button style="margin-right: .8rem">取消</a-button>
  113. </a-popconfirm>
  114. <a-button @click="handleSubmit" type="primary" :loading="confirmLoading">提交</a-button>
  115. </div>
  116. </a-drawer>
  117. </template>
  118. <script>
  119. import moment from 'moment'
  120. import Vue from 'vue'
  121. import { ACCESS_TOKEN } from "@/store/mutation-types"
  122. import { getAction } from '@/api/manage'
  123. import { addUser,editUser,queryUserRole,queryall } from '@/api/api'
  124. import { disabledAuthFilter } from "@/utils/authFilter"
  125. import { duplicateCheck } from '@/api/api'
  126. export default {
  127. name: "UserModal",
  128. components: {
  129. },
  130. data () {
  131. return {
  132. departDisabled: false, //是否是我的部门调用该页面
  133. roleDisabled: false, //是否是角色维护调用该页面
  134. modalWidth:800,
  135. drawerWidth:700,
  136. modaltoggleFlag:true,
  137. confirmDirty: false,
  138. userId:"", //保存用户id
  139. disableSubmit:false,
  140. dateFormat:"YYYY-MM-DD",
  141. validatorRules:{
  142. username:[{required: true, message: '请输入用户账号!'},
  143. {validator: this.validateUsername,}],
  144. password: [{required: true,pattern:/^(?=.*[a-zA-Z])(?=.*\d)(?=.*[~!@#$%^&*()_+`\-={}:";'<>?,./]).{8,}$/,message: '密码由8位数字、大小写字母和特殊符号组成!'},
  145. {validator: this.validateToNextPassword,trigger: 'change'}],
  146. confirmpassword: [{required: true, message: '请重新输入登录密码!',},
  147. { validator: this.compareToFirstPassword,}],
  148. realname:[{ required: true, message: '请输入用户名称!' }],
  149. phone: [{required: true, message: '请输入手机号!'}, {validator: this.validatePhone}],
  150. email: [{validator: this.validateEmail}],
  151. roles:{},
  152. // workNo:[ { required: true, message: '请输入工号' },
  153. // { validator: this.validateWorkNo }],
  154. telephone: [{ pattern: /^0\d{2,3}-[1-9]\d{6,7}$/, message: '请输入正确的座机号码' },]
  155. },
  156. departIdShow:false,
  157. title:"操作",
  158. visible: false,
  159. model: {},
  160. labelCol: {
  161. xs: { span: 24 },
  162. sm: { span: 5 },
  163. },
  164. wrapperCol: {
  165. xs: { span: 24 },
  166. sm: { span: 16 },
  167. },
  168. uploadLoading:false,
  169. confirmLoading: false,
  170. headers:{},
  171. url: {
  172. fileUpload: window._CONFIG['domianURL']+"/sys/common/upload",
  173. userWithDepart: "/sys/user/userDepartList", // 引入为指定用户查看部门信息需要的url
  174. userId:"/sys/user/generateUserId", // 引入生成添加用户情况下的url
  175. syncUserByUserName:"/act/process/extActProcess/doSyncUserByUserName",//同步用户到工作流
  176. queryTenantList: '/sys/tenant/queryList'
  177. },
  178. tenantsOptions: [],
  179. rolesOptions:[],
  180. nextDepartOptions:[],
  181. }
  182. },
  183. created () {
  184. const token = Vue.ls.get(ACCESS_TOKEN);
  185. this.headers = {"X-Access-Token":token}
  186. this.initRoleList()
  187. this.initTenantList()
  188. },
  189. computed:{
  190. uploadAction:function () {
  191. return this.url.fileUpload;
  192. }
  193. },
  194. methods: {
  195. add () {
  196. this.refresh();
  197. this.edit({activitiSync:'1',userIdentity:1});
  198. },
  199. edit (record) {
  200. let that = this;
  201. that.visible = true;
  202. //根据屏幕宽度自适应抽屉宽度
  203. this.resetScreenSize();
  204. that.userId = record.id;
  205. that.model = Object.assign({},{selectedroles:'',selecteddeparts:''}, record);
  206. //身份为上级显示负责部门,否则不显示
  207. if(this.model.userIdentity==2){
  208. this.departIdShow=true;
  209. }else{
  210. this.departIdShow=false;
  211. }
  212. if(record.hasOwnProperty("id")){
  213. that.getUserRoles(record.id);
  214. that.getUserDeparts(record.id);
  215. }
  216. console.log('that.model=',that.model)
  217. },
  218. isDisabledAuth(code){
  219. return disabledAuthFilter(code);
  220. },
  221. //窗口最大化切换
  222. toggleScreen(){
  223. if(this.modaltoggleFlag){
  224. this.modalWidth = window.innerWidth;
  225. }else{
  226. this.modalWidth = 800;
  227. }
  228. this.modaltoggleFlag = !this.modaltoggleFlag;
  229. },
  230. // 根据屏幕变化,设置抽屉尺寸
  231. resetScreenSize(){
  232. let screenWidth = document.body.clientWidth;
  233. if(screenWidth < 500){
  234. this.drawerWidth = screenWidth;
  235. }else{
  236. this.drawerWidth = 700;
  237. }
  238. },
  239. //初始化租户字典
  240. initTenantList(){
  241. getAction(this.url.queryTenantList).then(res=>{
  242. if(res.success){
  243. this.tenantsOptions = res.result.map((item,index,arr)=>{
  244. let c = {label:item.name, value: item.id+""}
  245. return c;
  246. })
  247. console.log('this.tenantsOptions: ',this.tenantsOptions)
  248. }
  249. })
  250. },
  251. //初始化角色字典
  252. initRoleList(){
  253. queryall().then((res)=>{
  254. if(res.success){
  255. this.rolesOptions = res.result.map((item,index,arr)=>{
  256. let c = {label:item.roleName, value:item.id}
  257. return c;
  258. })
  259. console.log('this.rolesOptions: ',this.rolesOptions)
  260. }
  261. });
  262. },
  263. getUserRoles(userid){
  264. queryUserRole({userid:userid}).then((res)=>{
  265. if(res.success){
  266. this.model.selectedroles = res.result.join(",");
  267. console.log('that.model.selectedroles=',this.model.selectedroles)
  268. }
  269. });
  270. },
  271. getUserDeparts(userid){
  272. let that = this;
  273. getAction(that.url.userWithDepart,{userId:userid}).then((res)=>{
  274. if(res.success){
  275. let departOptions=[];
  276. let selectDepartKeys=[]
  277. for (let i = 0; i < res.result.length; i++) {
  278. selectDepartKeys.push(res.result[i].key);
  279. //新增负责部门选择下拉框
  280. departOptions.push({
  281. value: res.result[i].key,
  282. label: res.result[i].title
  283. })
  284. }
  285. that.model.selecteddeparts = selectDepartKeys.join(",")
  286. that.nextDepartOptions=departOptions;
  287. console.log('that.nextDepartOptions=',that.nextDepartOptions)
  288. }
  289. })
  290. },
  291. backDepartInfo(info) {
  292. this.model.departIds = this.model.selecteddeparts;
  293. this.nextDepartOptions = info.map((item,index,arr)=>{
  294. let c = {label:item.text, value: item.value+""}
  295. return c;
  296. })
  297. },
  298. refresh () {
  299. this.userId=""
  300. this.nextDepartOptions=[];
  301. this.departIdShow=false;
  302. },
  303. close () {
  304. this.$emit('close');
  305. this.visible = false;
  306. this.disableSubmit = false;
  307. this.nextDepartOptions=[];
  308. this.departIdShow=false;
  309. this.$refs.form.resetFields();
  310. },
  311. moment,
  312. handleSubmit () {
  313. const that = this;
  314. // 触发表单验证
  315. this.$refs.form.validate(valid => {
  316. if (valid) {
  317. that.confirmLoading = true;
  318. //如果是上级择传入departIds,否则为空
  319. if(this.model.userIdentity!==2){
  320. this.model.departIds="";
  321. }
  322. let obj;
  323. if(!this.model.id){
  324. this.model.id = this.userId;
  325. obj=addUser(this.model);
  326. }else{
  327. obj=editUser(this.model);
  328. }
  329. obj.then((res)=>{
  330. if(res.success){
  331. that.$message.success(res.message);
  332. that.$emit('ok');
  333. }else{
  334. that.$message.warning(res.message);
  335. }
  336. }).finally(() => {
  337. that.confirmLoading = false;
  338. that.close();
  339. })
  340. }else{
  341. return false;
  342. }
  343. })
  344. },
  345. handleCancel () {
  346. this.close()
  347. },
  348. validateToNextPassword (rule, value, callback) {
  349. const confirmpassword=this.model.confirmpassword;
  350. if (value && confirmpassword && value !== confirmpassword) {
  351. callback('两次输入的密码不一样!');
  352. }
  353. if (value && this.confirmDirty) {
  354. this.$refs.form.validateField(['confirmpassword']);
  355. }
  356. callback();
  357. },
  358. compareToFirstPassword (rule, value, callback) {
  359. if (value && value !== this.model.password) {
  360. callback('两次输入的密码不一样!');
  361. } else {
  362. callback()
  363. }
  364. },
  365. validatePhone(rule, value, callback){
  366. if(!value){
  367. callback()
  368. }else{
  369. if(new RegExp(/^1[3|4|5|7|8|9][0-9]\d{8}$/).test(value)){
  370. var params = {
  371. tableName: 'sys_user',
  372. fieldName: 'phone',
  373. fieldVal: value,
  374. dataId: this.userId
  375. };
  376. duplicateCheck(params).then((res) => {
  377. if (res.success) {
  378. callback()
  379. } else {
  380. callback("手机号已存在!")
  381. }
  382. })
  383. }else{
  384. callback("请输入正确格式的手机号码!");
  385. }
  386. }
  387. },
  388. validateEmail(rule, value, callback){
  389. if(!value){
  390. callback()
  391. }else{
  392. if(new RegExp(/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/).test(value)){
  393. var params = {
  394. tableName: 'sys_user',
  395. fieldName: 'email',
  396. fieldVal: value,
  397. dataId: this.userId
  398. };
  399. duplicateCheck(params).then((res) => {
  400. console.log(res)
  401. if (res.success) {
  402. callback()
  403. } else {
  404. callback("邮箱已存在!")
  405. }
  406. })
  407. }else{
  408. callback("请输入正确格式的邮箱!")
  409. }
  410. }
  411. },
  412. validateUsername(rule, value, callback){
  413. var params = {
  414. tableName: 'sys_user',
  415. fieldName: 'username',
  416. fieldVal: value,
  417. dataId: this.userId
  418. };
  419. duplicateCheck(params).then((res) => {
  420. if (res.success) {
  421. callback()
  422. } else {
  423. callback("用户名已存在!")
  424. }
  425. })
  426. },
  427. // validateWorkNo(rule, value, callback){
  428. // var params = {
  429. // tableName: 'sys_user',
  430. // fieldName: 'work_no',
  431. // fieldVal: value,
  432. // dataId: this.userId
  433. // };
  434. // duplicateCheck(params).then((res) => {
  435. // if (res.success) {
  436. // callback()
  437. // } else {
  438. // callback("工号已存在!")
  439. // }
  440. // })
  441. // },
  442. handleConfirmBlur(e) {
  443. const value = e.target.value;
  444. this.confirmDirty = this.confirmDirty || !!value
  445. },
  446. beforeUpload: function(file){
  447. var fileType = file.type;
  448. if(fileType.indexOf('image')<0){
  449. this.$message.warning('请上传图片');
  450. return false;
  451. }
  452. //TODO 验证文件大小
  453. },
  454. identityChange(e){
  455. if(e.target.value===1){
  456. this.departIdShow=false;
  457. }else{
  458. this.departIdShow=true;
  459. }
  460. }
  461. }
  462. }
  463. </script>
  464. <style scoped>
  465. .avatar-uploader > .ant-upload {
  466. width:104px;
  467. height:104px;
  468. }
  469. .ant-upload-select-picture-card i {
  470. font-size: 49px;
  471. color: #999;
  472. }
  473. .ant-upload-select-picture-card .ant-upload-text {
  474. margin-top: 8px;
  475. color: #666;
  476. }
  477. .ant-table-tbody .ant-table-row td{
  478. padding-top:10px;
  479. padding-bottom:10px;
  480. }
  481. .drawer-bootom-button {
  482. position: absolute;
  483. bottom: -8px;
  484. width: 100%;
  485. border-top: 1px solid #e8e8e8;
  486. padding: 10px 16px;
  487. text-align: right;
  488. left: 0;
  489. background: #fff;
  490. border-radius: 0 0 2px 2px;
  491. }
  492. </style>