UserModal.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. <template>
  2. <a-modal
  3. :width="modalWidth"
  4. :visible="visible"
  5. :confirmLoading="confirmLoading"
  6. :okButtonProps="{ props: {disabled: disableSubmit} }"
  7. @ok="handleSubmit"
  8. @cancel="handleCancel"
  9. cancelText="关闭"
  10. wrapClassName="ant-modal-cust-warp"
  11. style="top:5%;height: auto;overflow-y: hidden">
  12. <template slot="title">
  13. <div style="width: 100%;">
  14. <span>{{ title }}</span>
  15. <span style="display:inline-block;width:calc(100% - 56px);padding-top: 2px;padding-right:10px;text-align: right">
  16. <a-button @click="togglescreen" style="height:18px;width:18px;padding: 0;border-width: 2px">&nbsp;&nbsp;</a-button>
  17. </span>
  18. </div>
  19. </template>
  20. <a-spin :spinning="confirmLoading">
  21. <a-form :form="form">
  22. <a-form-item label="用户账号" :labelCol="labelCol" :wrapperCol="wrapperCol" hasFeedback>
  23. <a-input placeholder="请输入用户账号" v-decorator="[ 'username', validatorRules.username]" :readOnly="!!model.id"/>
  24. </a-form-item>
  25. <template v-if="!model.id">
  26. <a-form-item label="登陆密码" :labelCol="labelCol" :wrapperCol="wrapperCol" hasFeedback >
  27. <a-input type="password" placeholder="请输入登陆密码" v-decorator="[ 'password', validatorRules.password]" />
  28. </a-form-item>
  29. <a-form-item label="确认密码" :labelCol="labelCol" :wrapperCol="wrapperCol" hasFeedback >
  30. <a-input type="password" @blur="handleConfirmBlur" placeholder="请重新输入登陆密码" v-decorator="[ 'confirmpassword', validatorRules.confirmpassword]"/>
  31. </a-form-item>
  32. </template>
  33. <a-form-item label="用户名称" :labelCol="labelCol" :wrapperCol="wrapperCol" hasFeedback >
  34. <a-input placeholder="请输入用户名称" v-decorator="[ 'realname', validatorRules.realname]" />
  35. </a-form-item>
  36. <a-form-item label="角色分配" :labelCol="labelCol" :wrapperCol="wrapperCol" hasFeedback >
  37. <a-select
  38. mode="multiple"
  39. style="width: 100%"
  40. placeholder="请选择用户角色"
  41. v-model="selectedRole">
  42. <a-select-option v-for="(role,roleindex) in roleList" :key="roleindex.toString()" :value="role.id">
  43. {{ role.roleName }}
  44. </a-select-option>
  45. </a-select>
  46. </a-form-item>
  47. <a-form-item label="头像" :labelCol="labelCol" :wrapperCol="wrapperCol">
  48. <a-upload
  49. listType="picture-card"
  50. class="avatar-uploader"
  51. :showUploadList="false"
  52. :action="uploadAction"
  53. :data="{'isup':1}"
  54. :headers="headers"
  55. :beforeUpload="beforeUpload"
  56. @change="handleChange"
  57. >
  58. <img v-if="model.avatar" :src="getAvatarView()" alt="头像" style="height:104px;max-width:300px"/>
  59. <div v-else>
  60. <a-icon :type="uploadLoading ? 'loading' : 'plus'" />
  61. <div class="ant-upload-text">上传</div>
  62. </div>
  63. </a-upload>
  64. </a-form-item>
  65. <a-form-item label="生日" :labelCol="labelCol" :wrapperCol="wrapperCol" hasFeedback >
  66. <a-date-picker
  67. style="width: 100%"
  68. placeholder="请选择生日"
  69. v-decorator="['birthday', {initialValue:!model.birthday?null:moment(model.birthday,dateFormat)}]"/>
  70. </a-form-item>
  71. <a-form-item label="性别" :labelCol="labelCol" :wrapperCol="wrapperCol" hasFeedback >
  72. <a-select
  73. v-decorator="[ 'sex', {initialValue:model.sex && model.sex.toString()}]"
  74. placeholder="请选择性别">
  75. <a-select-option value="1">男</a-select-option>
  76. <a-select-option value="2">女</a-select-option>
  77. </a-select>
  78. </a-form-item>
  79. <a-form-item label="邮箱" :labelCol="labelCol" :wrapperCol="wrapperCol" hasFeedback >
  80. <a-input placeholder="请输入邮箱" v-decorator="[ 'email', validatorRules.email]" />
  81. </a-form-item>
  82. <a-form-item label="手机号码" :labelCol="labelCol" :wrapperCol="wrapperCol" hasFeedback >
  83. <a-input placeholder="请输入手机号码" v-decorator="[ 'phone', validatorRules.phone]" />
  84. </a-form-item>
  85. </a-form>
  86. </a-spin>
  87. </a-modal>
  88. </template>
  89. <script>
  90. import pick from 'lodash.pick'
  91. import moment from 'moment'
  92. import Vue from 'vue'
  93. import { ACCESS_TOKEN } from "@/store/mutation-types"
  94. import {doMian,addUser,editUser,queryUserRole,queryall,checkUsername} from '@/api/api'
  95. export default {
  96. name: "RoleModal",
  97. data () {
  98. return {
  99. modalWidth:800,
  100. modaltoggleFlag:true,
  101. confirmDirty: false,
  102. disableSubmit:false,
  103. dateFormat:"YYYY-MM-DD",
  104. validatorRules:{
  105. username:{
  106. rules: [{
  107. required: true, message: '请输入用户账号!'
  108. },{
  109. validator: this.validateUsername,
  110. }]
  111. },
  112. password:{
  113. rules: [{
  114. required: true, message: '请输入密码!',
  115. }, {
  116. validator: this.validateToNextPassword,
  117. }],
  118. },
  119. confirmpassword:{
  120. rules: [{
  121. required: true, message: '请重新输入登陆密码!',
  122. }, {
  123. validator: this.compareToFirstPassword,
  124. }],
  125. },
  126. realname:{rules: [{ required: true, message: '请输入用户名称!' }]},
  127. phone:{rules: [{validator: this.validatePhone}]},
  128. email:{rules: [{type: 'email', message: '请输入正确格式的电子邮箱!',}]},
  129. roles:{}
  130. // sex:{initialValue:((!this.model.sex)?"": (this.model.sex+""))}
  131. },
  132. title:"操作",
  133. visible: false,
  134. model: {},
  135. roleList:[],
  136. selectedRole:[],
  137. labelCol: {
  138. xs: { span: 24 },
  139. sm: { span: 5 },
  140. },
  141. wrapperCol: {
  142. xs: { span: 24 },
  143. sm: { span: 16 },
  144. },
  145. uploadLoading:false,
  146. confirmLoading: false,
  147. headers:{},
  148. form:this.$form.createForm(this),
  149. url: {
  150. fileUpload:doMian+"sys/common/upload",
  151. imgerver:doMian+"sys/common/view",
  152. },
  153. }
  154. },
  155. created () {
  156. const token = Vue.ls.get(ACCESS_TOKEN);
  157. this.headers = {"X-Access-Token":token}
  158. },
  159. computed:{
  160. uploadAction:function () {
  161. return this.url.fileUpload;
  162. }
  163. },
  164. methods: {
  165. togglescreen(){
  166. if(this.modaltoggleFlag){
  167. this.modalWidth = window.innerWidth;
  168. }else{
  169. this.modalWidth = 800;
  170. }
  171. this.modaltoggleFlag = !this.modaltoggleFlag;
  172. },
  173. initialRoleList(){
  174. queryall().then((res)=>{
  175. if(res.success){
  176. this.roleList = res.result;
  177. }else{
  178. console.log(res.message);
  179. }
  180. });
  181. },
  182. loadUserRoles(userid){
  183. queryUserRole({userid:userid}).then((res)=>{
  184. if(res.success){
  185. this.selectedRole = res.result;
  186. }else{
  187. console.log(res.message);
  188. }
  189. });
  190. },
  191. add () {
  192. this.edit({});
  193. },
  194. edit (record) {
  195. this.initialRoleList();
  196. this.form.resetFields();
  197. if(record.hasOwnProperty("id")){
  198. this.loadUserRoles(record.id);
  199. }
  200. this.visible = true;
  201. this.model = Object.assign({}, record);
  202. let filedsVal = pick(this.model,'username','password','realname','email','phone');
  203. filedsVal.confirmpassword = this.model.password;
  204. this.$nextTick(() => {
  205. this.form.setFieldsValue(filedsVal);
  206. });
  207. },
  208. close () {
  209. this.$emit('close');
  210. this.visible = false;
  211. this.disableSubmit = false;
  212. this.selectedRole = [];
  213. },
  214. moment,
  215. handleSubmit () {
  216. const that = this;
  217. // 触发表单验证
  218. this.form.validateFields((err, values) => {
  219. if (!err) {
  220. that.confirmLoading = true;
  221. let avatar = that.model.avatar;
  222. if(!values.birthday){
  223. values.birthday = '';
  224. }else{
  225. values.birthday = values.birthday.format(this.dateFormat);
  226. }
  227. let formData = Object.assign(this.model, values);
  228. formData.avatar = avatar;
  229. formData.selectedroles = this.selectedRole.length>0?this.selectedRole.join(","):'';
  230. let obj;
  231. if(!this.model.id){
  232. obj=addUser(formData);
  233. }else{
  234. obj=editUser(formData);
  235. }
  236. obj.then((res)=>{
  237. if(res.success){
  238. that.$message.success(res.message);
  239. that.$emit('ok');
  240. }else{
  241. that.$message.warning(res.message);
  242. }
  243. }).finally(() => {
  244. that.confirmLoading = false;
  245. that.close();
  246. })
  247. }
  248. })
  249. },
  250. handleCancel () {
  251. this.close()
  252. },
  253. validateToNextPassword (rule, value, callback) {
  254. const form = this.form;
  255. if (value && this.confirmDirty) {
  256. form.validateFields(['confirm'], { force: true })
  257. }
  258. callback();
  259. },
  260. compareToFirstPassword (rule, value, callback) {
  261. const form = this.form;
  262. if (value && value !== form.getFieldValue('password')) {
  263. callback('两次输入的密码不一样!');
  264. } else {
  265. callback()
  266. }
  267. },
  268. validatePhone(rule, value, callback){
  269. if(!value || new RegExp(/^1[3|4|5|7|8][0-9]\d{8}$/).test(value)){
  270. callback();
  271. }else{
  272. callback("请输入正确格式的手机号码!");
  273. }
  274. },
  275. validateUsername(rule, value, callback){
  276. var params = {
  277. id:this.model.id,
  278. username:value
  279. };
  280. checkUsername(params).then((res)=>{
  281. if(res.success){
  282. callback();
  283. }else{
  284. callback("用户账号已存在!");
  285. }
  286. });
  287. },
  288. handleConfirmBlur (e) {
  289. const value = e.target.value
  290. this.confirmDirty = this.confirmDirty || !!value
  291. },
  292. normFile (e) {
  293. console.log('Upload event:', e)
  294. if (Array.isArray(e)) {
  295. return e
  296. }
  297. return e && e.fileList
  298. },
  299. beforeUpload: function(file){
  300. var fileType = file.type;
  301. if(fileType.indexOf('image')<0){
  302. this.$message.warning('请上传图片');
  303. return false;
  304. }
  305. //TODO 验证文件大小
  306. },
  307. handleChange (info) {
  308. if (info.file.status === 'uploading') {
  309. this.uploadLoading = true
  310. return
  311. }
  312. if (info.file.status === 'done') {
  313. var response = info.file.response;
  314. this.uploadLoading = false;
  315. console.log(response);
  316. if(response.success){
  317. this.model.avatar = response.message;
  318. }else{
  319. this.$message.warning(response.message);
  320. }
  321. }
  322. },
  323. getAvatarView(){
  324. return this.url.imgerver +"/"+ this.model.avatar;
  325. },
  326. }
  327. }
  328. </script>
  329. <style scoped>
  330. .avatar-uploader > .ant-upload {
  331. width:104px;
  332. height:104px;
  333. }
  334. .ant-upload-select-picture-card i {
  335. font-size: 49px;
  336. color: #999;
  337. }
  338. .ant-upload-select-picture-card .ant-upload-text {
  339. margin-top: 8px;
  340. color: #666;
  341. }
  342. .ant-table-tbody .ant-table-row td{
  343. padding-top:10px;
  344. padding-bottom:10px;
  345. }
  346. </style>