x-form.vue 9.5 KB

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