x-form.vue 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. <template>
  2. <view>
  3. <u--form labelPosition="top" labelWidth="auto" :model="model" :rules="rules" ref="uForm">
  4. <view v-for="(item,index) in list" :key="index">
  5. <u-form-item :required="item.required ? true : false" :label="item.label" :prop="item.field"
  6. v-if="item.type == 'input' && !item.visible">
  7. <view class="card_form_item">
  8. <u--input v-model="model[`${item.field}`]" :disabled="item.disabled ? true : false"
  9. :placeholder="item.placeholder"></u--input>
  10. </view>
  11. </u-form-item>
  12. <u-form-item :required="item.required ? true : false" :label="item.label" :prop="item.field"
  13. v-else-if="item.type == 'radio' && !item.visible">
  14. <view class="card_form_item" style="margin-top: 10rpx;">
  15. <u-radio-group v-model="model[`${item.field}`]" placement="row">
  16. <u-radio shape="circle" :customStyle="{marginRight: '20px'}"
  17. v-for="(item1, index2) in item.options" :key="index2" :label="item1.label"
  18. :name="item1.value"></u-radio>
  19. </u-radio-group>
  20. </view>
  21. </u-form-item>
  22. <u-form-item :required="item.required ? true : false" :label="item.label" :prop="item.field"
  23. v-else-if="item.type == 'cascader' || item.type == 'select' && !item.visible">
  24. <view class="card_form_item">
  25. <u--input :placeholder="item.placeholder" suffixIcon="arrow-down"
  26. v-model="model[`${item.field}`]" @focus="change(item)"></u--input>
  27. </view>
  28. </u-form-item>
  29. <u-form-item :required="item.required ? true : false" :label="item.label" :prop="item.field"
  30. v-else-if="item.type == 'upload' && !item.visible">
  31. <view class="card_form_item">
  32. <u-upload :fileList="fileList1" name="1" multiple :maxCount="10" @afterRead="afterRead"
  33. @delete="deletePic"></u-upload>
  34. </view>
  35. </u-form-item>
  36. <u-form-item :required="item.required ? true : false" :label="item.label" :prop="item.field"
  37. v-else-if="item.type == 'textarea' && !item.visible">
  38. <view class="card_form_item">
  39. <u--textarea v-model="model[`${item.field}`]" autoHeight
  40. :placeholder="item.placeholder"></u--textarea>
  41. </view>
  42. </u-form-item>
  43. <u-form-item :required="item.required ? true : false" :label="item.label" :prop="item.field"
  44. v-else-if="item.type == 'line' && !item.visible">
  45. <view class="card_form_item">
  46. <u-line></u-line>
  47. </view>
  48. </u-form-item>
  49. <u-form-item labelPosition="left" :label="item.label" :prop="item.field"
  50. v-else-if="item.type == 'default' && !item.visible">
  51. <view class="card_form_item" style="display: flex;justify-content: flex-end">
  52. <u-switch v-model="model[`${item.field}`]" inactiveColor="rgb(230, 230, 230)"
  53. size="20"></u-switch>
  54. </view>
  55. </u-form-item>
  56. </view>
  57. </u--form>
  58. <u-picker :show="singleShow" :columns="columns" keyName="label" @cancel="singleShow = false"></u-picker>
  59. <u-picker :show="show" ref="uPicker" :columns="addressColumns" :defaultIndex="areaDetault" keyName="label"
  60. @confirm="confirm" @change="changeHandler" @cancel="cancel"></u-picker>
  61. <view style="width: 100%;height: 170rpx;"></view>
  62. <view class="check_btn">
  63. <view class="btn_submit">
  64. <u-button type="primary" :text="btnTitle" @click="clientele"></u-button>
  65. </view>
  66. </view>
  67. </view>
  68. </template>
  69. <script>
  70. const ENV = require('@/.env.js')
  71. import {
  72. urbanArea
  73. } from '@/static/js/districtCode.js'
  74. export default {
  75. name: 'x-form',
  76. props: {
  77. list: {
  78. type: Array,
  79. default () {
  80. return []
  81. }
  82. },
  83. model: {
  84. type: Object,
  85. default () {
  86. return {}
  87. }
  88. },
  89. rules: {
  90. type: Object,
  91. default () {
  92. return {}
  93. }
  94. },
  95. userType: {
  96. type: Number,
  97. default () {
  98. return null
  99. }
  100. },
  101. btnTitle: {
  102. type: String,
  103. default () {
  104. return '提交'
  105. }
  106. }
  107. },
  108. data() {
  109. return {
  110. singleShow: false,
  111. show: false,
  112. areaData: urbanArea(), //原始数据
  113. addressColumns: [], //数据数组
  114. areaDetault: [], //默认选中数据
  115. fileList1: [],
  116. columns: [],
  117. }
  118. },
  119. mounted() {},
  120. methods: {
  121. change(value) {
  122. console.log(value,25)
  123. if (value.type == 'cascader') {
  124. this.show = true
  125. this.addressColumns = [
  126. this.areaData,
  127. this.areaData[0].children,
  128. ];
  129. this.$nextTick(() => {
  130. if (this.model.hr) {
  131. this.setDefault()
  132. }
  133. })
  134. } else {
  135. this.columns = value.options
  136. this.singleShow = true
  137. }
  138. },
  139. confirm(value) {
  140. let arr = value.value
  141. let arr1 = []
  142. let arr2 = []
  143. arr.forEach(item => {
  144. arr1.push(item.value)
  145. arr2.push(item.label)
  146. })
  147. this.model.hr = arr1.join('/')
  148. this.model.region = arr2.join('/')
  149. this.show = false
  150. this.$emit('confirm', value)
  151. },
  152. cancel() {
  153. this.show = false
  154. },
  155. // 补全客户资料
  156. clientele() {
  157. this.$refs.uForm.validate().then(res => {
  158. this.$emit('clientele')
  159. }).catch(errors => {
  160. // uni.$u.toast('校验失败')
  161. })
  162. },
  163. // 新增图片
  164. async afterRead(event) {
  165. // 当设置 multiple 为 true 时, file 为数组格式,否则为对象格式
  166. let lists = [].concat(event.file)
  167. let fileListLen = this[`fileList${event.name}`].length
  168. lists.map((item) => {
  169. this[`fileList${event.name}`].push({
  170. ...item,
  171. status: 'uploading',
  172. message: '上传中'
  173. })
  174. })
  175. for (let i = 0; i < lists.length; i++) {
  176. const result = await this.uploadFilePromise(lists[i].url)
  177. let item = this[`fileList${event.name}`][fileListLen]
  178. this[`fileList${event.name}`].splice(fileListLen, 1, Object.assign(item, {
  179. status: 'success',
  180. message: '',
  181. url: result
  182. }))
  183. fileListLen++
  184. }
  185. var arr = []
  186. this.fileList1.forEach(item1 => {
  187. arr.push(item1.url)
  188. })
  189. this.model.addressImg = arr.join()
  190. this.$refs.uForm.validateField('addressImg')
  191. },
  192. // 删除图片
  193. deletePic(event) {
  194. this[`fileList${event.name}`].splice(event.index, 1)
  195. },
  196. uploadFilePromise(url) {
  197. return new Promise((resolve, reject) => {
  198. let a = uni.uploadFile({
  199. url: ENV.APP_DEV_URL + '/api/upload', // 仅为示例,非真实的接口地址
  200. filePath: url,
  201. name: 'file',
  202. // formData: {
  203. // user: 'test'
  204. // },
  205. header: {
  206. 'Authorization': 'Bearer ' + uni.getStorageSync('access_token'),
  207. },
  208. success: (res) => {
  209. let state = JSON.parse(res.data)
  210. setTimeout(() => {
  211. if (state.code == 200) {
  212. resolve(state.data)
  213. }
  214. }, 1000)
  215. }
  216. });
  217. })
  218. },
  219. // 根据回显数据设置默认选中项
  220. setDefault() {
  221. // 户籍所在地
  222. let temp = []
  223. temp = this.model.hr.split('/')
  224. let index, index1 = 0
  225. let arr, arr1 = []
  226. //市区对应每列的第几个
  227. this.areaData.forEach((item, i) => {
  228. if (item.value == temp[0]) {
  229. index = i
  230. item.children.forEach((val, ind) => {
  231. if (val.value == temp[1]) {
  232. index1 = ind
  233. }
  234. })
  235. }
  236. })
  237. //匹配省市区对应每列的第几个
  238. arr = this.areaData.map(e => {
  239. return e
  240. })
  241. arr1 = this.areaData[index].children.map(e => {
  242. return e
  243. })
  244. this.addressColumns = [arr, arr1]
  245. this.areaDetault = [index, index1]
  246. },
  247. // 选中时执行
  248. changeHandler(e) {
  249. const {
  250. columnIndex,
  251. index,
  252. indexs,
  253. picker = this.$refs.uPicker
  254. } = e
  255. if (columnIndex === 0) {
  256. const children1 = this.areaData[index].children.map(e1 => {
  257. return e1
  258. })
  259. picker.setColumnValues(1, children1)
  260. if (columnIndex === 1) {
  261. const children3 = this.areaData[indexs[0]].children[indexs[1]].children.map(e2 => {
  262. return e2
  263. })
  264. picker.setColumnValues(2, children3)
  265. }
  266. }
  267. },
  268. }
  269. }
  270. </script>
  271. <style lang="scss">
  272. .card_form_item {
  273. width: 100%;
  274. }
  275. .check_btn {
  276. z-index: 2024;
  277. position: fixed;
  278. display: flex;
  279. align-items: center;
  280. justify-content: center;
  281. left: 0;
  282. right: 0;
  283. bottom: 0;
  284. background-color: #fff;
  285. border-top: 1rpx solid #f7f7f7;
  286. padding-bottom: constant(safe-area-inset-bottom); //兼容 IOS<11.2
  287. padding-bottom: env(safe-area-inset-bottom); //兼容 IOS>11.2
  288. }
  289. .btn_submit {
  290. margin-top: 10rpx;
  291. padding-bottom: 20rpx;
  292. width: calc(100% - 80rpx);
  293. }
  294. </style>