index.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. <template>
  2. <view class="wrap">
  3. <u-form :model="model" :rules="rules" ref="uForm" :errorType="errorType">
  4. <u-form-item :leftIconStyle="{color: '#888', fontSize: '32rpx'}" left-icon="account" label-width="120" :label-position="labelPosition" label="姓名" prop="name">
  5. <u-input :border="border" placeholder="请输入姓名" v-model="model.name" type="text"></u-input>
  6. </u-form-item>
  7. <u-form-item :label-position="labelPosition" label="性别" prop="sex">
  8. <u-input :border="border" type="select" :select-open="actionSheetShow" v-model="model.sex" placeholder="请选择性别" @click="actionSheetShow = true"></u-input>
  9. </u-form-item>
  10. <u-form-item :label-position="labelPosition" label="简介" prop="intro">
  11. <u-input type="textarea" :border="border" placeholder="请填写简介" v-model="model.intro" />
  12. </u-form-item>
  13. <u-form-item :label-position="labelPosition" label="密码" prop="password">
  14. <u-input :password-icon="true" :border="border" type="password" v-model="model.password" placeholder="请输入密码"></u-input>
  15. </u-form-item>
  16. <u-form-item :label-position="labelPosition" label="确认密码" label-width="150" prop="rePassword">
  17. <u-input :border="border" type="password" v-model="model.rePassword" placeholder="请确认密码"></u-input>
  18. </u-form-item>
  19. <u-form-item :label-position="labelPosition" label="水果品种" label-width="150" prop="likeFruit">
  20. <u-checkbox-group @change="checkboxGroupChange" :width="radioCheckWidth" :wrap="radioCheckWrap">
  21. <u-checkbox v-model="item.checked" v-for="(item, index) in checkboxList" :key="index" :name="item.name">{{ item.name }}</u-checkbox>
  22. </u-checkbox-group>
  23. </u-form-item>
  24. <u-form-item :label-position="labelPosition" label="结算方式" prop="payType" label-width="150">
  25. <u-radio-group v-model="radio" @change="radioGroupChange" :width="radioCheckWidth" :wrap="radioCheckWrap">
  26. <u-radio shape="circle" v-for="(item, index) in radioList" :key="index" :name="item.name">{{ item.name }}</u-radio>
  27. </u-radio-group>
  28. </u-form-item>
  29. <u-form-item :label-position="labelPosition" label="所在地区" prop="region" label-width="150">
  30. <u-input :border="border" type="select" :select-open="pickerShow" v-model="model.region" placeholder="请选择地区" @click="pickerShow = true"></u-input>
  31. </u-form-item>
  32. <u-form-item :label-position="labelPosition" label="商品类型" prop="goodsType" label-width="150">
  33. <u-input :border="border" type="select" :select-open="selectShow" v-model="model.goodsType" placeholder="请选择商品类型" @click="selectShow = true"></u-input>
  34. </u-form-item>
  35. <u-form-item :rightIconStyle="{color: '#888', fontSize: '32rpx'}" right-icon="kefu-ermai" :label-position="labelPosition" label="手机号码" prop="phone" label-width="150">
  36. <u-input :border="border" placeholder="请输入手机号" v-model="model.phone" type="number"></u-input>
  37. </u-form-item>
  38. <u-form-item :label-position="labelPosition" label="验证码" prop="code" label-width="150">
  39. <u-input :border="border" placeholder="请输入验证码" v-model="model.code" type="text"></u-input>
  40. <u-button slot="right" type="success" size="mini" @click="getCode">{{codeTips}}</u-button>
  41. </u-form-item>
  42. <!-- 此处switch的slot为right,如果不填写slot名,也即<u-switch v-model="model.remember"></u-switch>,将会左对齐 -->
  43. <u-form-item :label-position="labelPosition" label="记住密码" prop="remember" label-width="150">
  44. <u-switch v-model="model.remember" slot="right"></u-switch>
  45. </u-form-item>
  46. <u-form-item :label-position="labelPosition" label="上传图片" prop="photo" label-width="150">
  47. <u-upload width="160" height="160"></u-upload>
  48. </u-form-item>
  49. </u-form>
  50. <view class="agreement">
  51. <u-checkbox v-model="check" @change="checkboxChange"></u-checkbox>
  52. <view class="agreement-text">
  53. 勾选代表同意uView的版权协议
  54. </view>
  55. </view>
  56. <u-button @click="submit">提交</u-button>
  57. <u-action-sheet :list="actionSheetList" v-model="actionSheetShow" @click="actionSheetCallback"></u-action-sheet>
  58. <u-select mode="single-column" :list="selectList" v-model="selectShow" @confirm="selectConfirm"></u-select>
  59. <u-picker mode="region" v-model="pickerShow" @confirm="regionConfirm"></u-picker>
  60. <u-verification-code seconds="60" ref="uCode" @change="codeChange"></u-verification-code>
  61. <view class="u-config-wrap">
  62. <view class="u-config-title u-border-bottom">
  63. 参数配置
  64. </view>
  65. <view class="u-config-item">
  66. <view class="u-item-title">label对齐方式</view>
  67. <u-subsection :list="['左边', '上方']" @change="labelPositionChange"></u-subsection>
  68. </view>
  69. <view class="u-config-item">
  70. <view class="u-item-title">边框</view>
  71. <u-subsection :current="borderCurrent" :list="['显示', '隐藏']" @change="borderChange"></u-subsection>
  72. </view>
  73. <view class="u-config-item">
  74. <view class="u-item-title">radio、checkbox样式</view>
  75. <u-subsection :list="['自适应', '换行', '50%宽度']" @change="radioCheckboxChange"></u-subsection>
  76. </view>
  77. <view class="u-config-item">
  78. <view class="u-item-title">错误提示方式</view>
  79. <u-subsection :list="['message', 'toast', '下划线', '输入框']" @change="errorChange"></u-subsection>
  80. </view>
  81. </view>
  82. </view>
  83. </template>
  84. <script>
  85. export default {
  86. data() {
  87. let that = this;
  88. return {
  89. model: {
  90. name: '',
  91. sex: '',
  92. likeFruit: '',
  93. intro: '',
  94. payType: '支付宝',
  95. agreement: false,
  96. region: '',
  97. goodsType: '',
  98. phone: '',
  99. code: '',
  100. password: '',
  101. rePassword: '',
  102. remember: false,
  103. photo: ''
  104. },
  105. selectList: [
  106. {
  107. value: '电子产品',
  108. label: '电子产品'
  109. },
  110. {
  111. value: '服装',
  112. label: '服装'
  113. },
  114. {
  115. value: '工艺品',
  116. label: '工艺品'
  117. }
  118. ],
  119. rules: {
  120. name: [
  121. {
  122. required: true,
  123. message: '请输入姓名',
  124. trigger: 'blur' ,
  125. },
  126. {
  127. min: 3,
  128. max: 5,
  129. message: '姓名长度在3到5个字符',
  130. trigger: ['change','blur'],
  131. },
  132. {
  133. // 此为同步验证,可以直接返回true或者false,如果是异步验证,稍微不同,见下方说明
  134. validator: (rule, value, callback) => {
  135. // 调用uView自带的js验证规则,详见:https://www.uviewui.com/js/test.html
  136. return this.$u.test.chinese(value);
  137. },
  138. message: '姓名必须为中文',
  139. // 触发器可以同时用blur和change,二者之间用英文逗号隔开
  140. trigger: ['change','blur'],
  141. },
  142. // 异步验证,用途:比如用户注册时输入完账号,后端检查账号是否已存在
  143. // {
  144. // trigger: ['blur'],
  145. // // 异步验证需要通过调用callback(),并且在里面抛出new Error()
  146. // // 抛出的内容为需要提示的信息,和其他方式的message属性的提示一样
  147. // asyncValidator: (rule, value, callback) => {
  148. // this.$u.post('/ebapi/public_api/index').then(res => {
  149. // // 如果验证出错,需要在callback()抛出new Error('错误提示信息')
  150. // if(res.error) {
  151. // callback(new Error('姓名重复'));
  152. // } else {
  153. // // 如果没有错误,也要执行callback()回调
  154. // callback();
  155. // }
  156. // })
  157. // },
  158. // }
  159. ],
  160. sex: [
  161. {
  162. required: true,
  163. message: '请选择性别',
  164. trigger: 'change'
  165. },
  166. ],
  167. intro: [
  168. {
  169. required: true,
  170. message: '请填写简介'
  171. },
  172. {
  173. min: 5,
  174. message: '简介不能少于5个字',
  175. trigger: 'change' ,
  176. },
  177. // 正则校验示例,此处用正则校验是否中文,此处仅为示例,因为uView有this.$u.test.chinese可以判断是否中文
  178. {
  179. pattern: /^[\u4e00-\u9fa5]+$/gi,
  180. message: '简介只能为中文',
  181. trigger: 'change',
  182. },
  183. ],
  184. likeFruit: [
  185. {
  186. required: true,
  187. message: '请选择您喜欢的水果',
  188. trigger: 'change',
  189. type: 'array',
  190. }
  191. ],
  192. payType: [
  193. {
  194. required: true,
  195. message: '请选择任意一种支付方式',
  196. trigger: 'change',
  197. }
  198. ],
  199. region: [
  200. {
  201. required: true,
  202. message: '请选择地区',
  203. trigger: 'change',
  204. }
  205. ],
  206. goodsType: [
  207. {
  208. required: true,
  209. message: '请选择商品类型',
  210. trigger: 'change',
  211. }
  212. ],
  213. phone: [
  214. {
  215. required: true,
  216. message: '请输入手机号',
  217. trigger: ['change','blur'],
  218. },
  219. {
  220. validator: (rule, value, callback) => {
  221. // 调用uView自带的js验证规则,详见:https://www.uviewui.com/js/test.html
  222. return this.$u.test.mobile(value);
  223. },
  224. message: '手机号码不正确',
  225. // 触发器可以同时用blur和change,二者之间用英文逗号隔开
  226. trigger: ['change','blur'],
  227. }
  228. ],
  229. code: [
  230. {
  231. required: true,
  232. message: '请输入验证码',
  233. trigger: ['change','blur'],
  234. },
  235. {
  236. type: 'number',
  237. message: '验证码只能为数字',
  238. trigger: ['change','blur'],
  239. }
  240. ],
  241. password: [
  242. {
  243. required: true,
  244. message: '请输入密码',
  245. trigger: ['change','blur'],
  246. },
  247. {
  248. // 正则不能含有两边的引号
  249. pattern: /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]+\S{5,12}$/,
  250. message: '需同时含有字母和数字,长度在6-12之间',
  251. trigger: ['change','blur'],
  252. }
  253. ],
  254. rePassword: [
  255. {
  256. required: true,
  257. message: '请重新输入密码',
  258. trigger: ['change','blur'],
  259. },
  260. {
  261. validator: (rule, value, callback) => {
  262. return value === this.model.password;
  263. },
  264. message: '两次输入的密码不相等',
  265. trigger: ['change','blur'],
  266. }
  267. ],
  268. },
  269. border: false,
  270. check: false,
  271. selectStatus: 'close',
  272. checkboxList: [
  273. {
  274. name: '荔枝',
  275. checked: false,
  276. disabled: false
  277. },
  278. {
  279. name: '香蕉',
  280. checked: false,
  281. disabled: false
  282. },
  283. {
  284. name: '橙子',
  285. checked: false,
  286. disabled: false
  287. },
  288. {
  289. name: '草莓',
  290. checked: false,
  291. disabled: false
  292. }
  293. ],
  294. radioList: [
  295. {
  296. name: '支付宝',
  297. checked: true,
  298. disabled: false
  299. },
  300. {
  301. name: '微信',
  302. checked: false,
  303. disabled: false
  304. },
  305. {
  306. name: '银联',
  307. checked: false,
  308. disabled: false
  309. },
  310. {
  311. name: '现金',
  312. checked: false,
  313. disabled: false
  314. }
  315. ],
  316. radio: '支付宝',
  317. actionSheetList: [
  318. {
  319. text: '男'
  320. },
  321. {
  322. text: '女'
  323. },
  324. {
  325. text: '保密'
  326. }
  327. ],
  328. actionSheetShow: false,
  329. pickerShow: false,
  330. selectShow: false,
  331. radioCheckWidth: 'auto',
  332. radioCheckWrap: false,
  333. labelPosition: 'left',
  334. codeTips: '',
  335. errorType: ['message'],
  336. };
  337. },
  338. onLoad() {
  339. },
  340. computed: {
  341. borderCurrent() {
  342. return this.border ? 0 : 1;
  343. }
  344. },
  345. onReady() {
  346. this.$refs.uForm.setRules(this.rules);
  347. },
  348. methods: {
  349. submit() {
  350. this.$refs.uForm.validate(valid => {
  351. if (valid) {
  352. if(!this.model.agreement) return this.$u.toast('请勾选协议');
  353. console.log('验证通过');
  354. } else {
  355. console.log('验证失败');
  356. }
  357. });
  358. },
  359. // 点击actionSheet回调
  360. actionSheetCallback(index) {
  361. uni.hideKeyboard();
  362. this.model.sex = this.actionSheetList[index].text;
  363. },
  364. // checkbox选择发生变化
  365. checkboxGroupChange(e) {
  366. this.model.likeFruit = e;
  367. },
  368. // radio选择发生变化
  369. radioGroupChange(e) {
  370. this.model.payType = e;
  371. },
  372. // 勾选版权协议
  373. checkboxChange(e) {
  374. this.model.agreement = e.value;
  375. },
  376. // 选择地区回调
  377. regionConfirm(e) {
  378. this.model.region = e.province.label + '-' + e.city.label + '-' + e.area.label;
  379. },
  380. // 选择商品类型回调
  381. selectConfirm(e) {
  382. this.model.goodsType = '';
  383. e.map((val, index) => {
  384. this.model.goodsType += this.model.goodsType == '' ? val.label : '-' + val.label;
  385. })
  386. },
  387. borderChange(index) {
  388. this.border = !index;
  389. },
  390. radioCheckboxChange(index) {
  391. if(index == 0) {
  392. this.radioCheckWrap = false;
  393. this.radioCheckWidth = 'auto';
  394. } else if(index == 1) {
  395. this.radioCheckWrap = true;
  396. this.radioCheckWidth = 'auto';
  397. } else if(index == 2) {
  398. this.radioCheckWrap = false;
  399. this.radioCheckWidth = '50%';
  400. }
  401. },
  402. labelPositionChange(index) {
  403. this.labelPosition = index == 0 ? 'left' : 'top';
  404. },
  405. codeChange(text) {
  406. this.codeTips = text;
  407. },
  408. // 获取验证码
  409. getCode() {
  410. if(this.$refs.uCode.canGetCode) {
  411. // 模拟向后端请求验证码
  412. uni.showLoading({
  413. title: '正在获取验证码',
  414. mask: true
  415. })
  416. setTimeout(() => {
  417. uni.hideLoading();
  418. // 这里此提示会被this.start()方法中的提示覆盖
  419. this.$u.toast('验证码已发送');
  420. // 通知验证码组件内部开始倒计时
  421. this.$refs.uCode.start();
  422. }, 2000);
  423. } else {
  424. this.$u.toast('倒计时结束后再发送');
  425. }
  426. },
  427. errorChange(index) {
  428. if(index == 0) this.errorType = ['message'];
  429. if(index == 1) this.errorType = ['toast'];
  430. if(index == 2) this.errorType = ['border-bottom'];
  431. if(index == 3) this.errorType = ['border'];
  432. }
  433. }
  434. };
  435. </script>
  436. <style scoped lang="scss">
  437. .wrap {
  438. padding: 30rpx;
  439. }
  440. .agreement {
  441. display: flex;
  442. align-items: center;
  443. margin: 40rpx 0;
  444. .agreement-text {
  445. padding-left: 8rpx;
  446. color: $u-tips-color;
  447. }
  448. }
  449. </style>