x-form.vue 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. <template>
  2. <!-- 表单 -->
  3. <view style="margin: 0rpx 20rpx 0rpx 30rpx;">
  4. <u-form :model="model" :rules="rules" labelPosition="left" ref="uForm" labelWidth="70">
  5. <view v-for="(item,index) in list" :key="index">
  6. <u-form-item :required="item.required ? true : false" :label="item.label" :prop="item.field"
  7. v-if="item.type == 'input' && customerName(item)">
  8. <view class="card_form_item">
  9. <u-input v-model="model[`${item.field}`]" :disabled="item.disabled ? true : false"
  10. :placeholder="item.placeholder"></u-input>
  11. <view class="card_sweep" v-if="item.field == 'tamperProofLabel' || item.field == 'code'"
  12. @click="sweep(item.field)">
  13. <u-icon name="scan" size="18px"></u-icon>
  14. <span>扫一扫</span>
  15. </view>
  16. </view>
  17. </u-form-item>
  18. <u-form-item :required="item.required ? true : false" :label="item.label" :prop="item.field"
  19. v-else-if="item.type == 'select'">
  20. <view class="card_form_item">
  21. <u-input :placeholder="item.placeholder" suffixIcon="arrow-down"
  22. v-model="model[`${item.field}`]" @focus="change(item)"></u-input>
  23. </view>
  24. </u-form-item>
  25. <u-form-item :required="item.required ? true : false" :label="item.label" :prop="item.field"
  26. v-else-if="item.type == 'selectiveSearch'">
  27. <view class="card_form_item">
  28. <view class="card_search_gray frame" @click="changeil(item)">
  29. <span v-if="model[`${item.field}`]">{{model[`${item.field}`]}}</span>
  30. <span class="title_gray" v-else>{{item.placeholder}}</span>
  31. <u-icon name="arrow-down" color="#c8c9cc" size="18"></u-icon>
  32. </view>
  33. </view>
  34. </u-form-item>
  35. <u-form-item :required="item.required ? true : false" :label="item.label" :prop="item.field"
  36. v-else-if="item.type == 'selectil'">
  37. <view class="card_form_item">
  38. <u-input :placeholder="item.placeholder" suffixIcon="arrow-down"
  39. v-model="model[`${item.field}`]" @focus="changeil(item)"></u-input>
  40. </view>
  41. </u-form-item>
  42. <u-form-item :required="item.required ? true : false" :label="item.label" :prop="item.field"
  43. v-else-if="item.type == 'textarea'">
  44. <view class="card_form_item">
  45. <u-textarea v-model="model[`${item.field}`]" autoHeight
  46. :placeholder="item.placeholder"></u-textarea>
  47. </view>
  48. </u-form-item>
  49. <u-form-item :required="item.required ? true : false" :label="item.label" :prop="item.field"
  50. v-else-if="item.type == 'upload' && !item.visible">
  51. <view class="card_form_item">
  52. <u-upload :fileList="fileList1" name="1" multiple :maxCount="10" @afterRead="afterRead"
  53. @delete="deletePic"></u-upload>
  54. </view>
  55. </u-form-item>
  56. </view>
  57. </u-form>
  58. <u-picker :defaultIndex="findIndex(model[fieldType], columns[0])" :show="show" :columns="columns"
  59. keyName="label" @confirm="confirm($event, fieldType)" @cancel="cancel"></u-picker>
  60. </view>
  61. </template>
  62. <script>
  63. const ENV = require('@/.env.js')
  64. export default {
  65. name: 'x-form',
  66. props: {
  67. list: {
  68. type: Array,
  69. default () {
  70. return []
  71. }
  72. },
  73. model: {
  74. type: Object,
  75. default () {
  76. return {}
  77. }
  78. },
  79. rules: {
  80. type: Object,
  81. default () {
  82. return {}
  83. }
  84. },
  85. },
  86. data() {
  87. return {
  88. show: false,
  89. columns: [],
  90. fieldType: '',
  91. fileList1: [],
  92. }
  93. },
  94. // 必须要在onReady生命周期,因为onLoad生命周期组件可能尚未创建完毕
  95. onReady() {
  96. this.$refs.uForm.setRules(this.rules);
  97. },
  98. methods: {
  99. customerName(value) {
  100. var userInfo = this.$cache.getCache('userInfo')
  101. if (userInfo.userType == 'customer') {
  102. if (value.field != 'customerName') {
  103. if (value.type == 'input') {
  104. return true
  105. }
  106. }
  107. } else {
  108. if (value.type == 'input') {
  109. return true
  110. }
  111. }
  112. },
  113. change(e) {
  114. this.columns = []
  115. this.fieldType = e.field
  116. this.show = true
  117. this.$nextTick(() => {
  118. this.columns.push(e.options)
  119. })
  120. },
  121. // 选择弹窗滚动
  122. changeil(value) {
  123. if (value.field == "status") {
  124. this.columns = []
  125. this.fieldType = value.field
  126. this.show = true
  127. this.$nextTick(() => {
  128. this.columns.push(value.options)
  129. })
  130. } else {
  131. this.$emit('selector', value)
  132. }
  133. },
  134. // 选择确定
  135. confirm(value, type) {
  136. this.show = false
  137. this.model[type] = value.value[0].label
  138. },
  139. // 点击确定
  140. cancel() {
  141. this.show = false
  142. },
  143. findIndex(code, list) {
  144. if (!code || !list) {
  145. return [0]
  146. }
  147. return [list.findIndex((item) => (item.label === code || item.label === code))]
  148. },
  149. // 新增图片
  150. async afterRead(event) {
  151. // 当设置 multiple 为 true 时, file 为数组格式,否则为对象格式
  152. let lists = [].concat(event.file)
  153. let fileListLen = this[`fileList${event.name}`].length
  154. lists.map((item) => {
  155. this[`fileList${event.name}`].push({
  156. ...item,
  157. status: 'uploading',
  158. message: '上传中'
  159. })
  160. })
  161. uni.showLoading({
  162. title: '上传中',
  163. mask: true,
  164. })
  165. for (let i = 0; i < lists.length; i++) {
  166. const result = await this.uploadFilePromise(lists[i].url)
  167. let item = this[`fileList${event.name}`][fileListLen]
  168. this[`fileList${event.name}`].splice(fileListLen, 1, Object.assign(item, {
  169. status: 'success',
  170. message: '',
  171. url: result
  172. }))
  173. fileListLen++
  174. }
  175. var arr = []
  176. this.fileList1.forEach(item1 => {
  177. arr.push(item1.url)
  178. })
  179. uni.hideLoading();
  180. this.model.tamperProofLabelImg = arr.join()
  181. this.$refs.uForm.validateField('tamperProofLabelImg')
  182. },
  183. // 删除图片
  184. deletePic(event) {
  185. this[`fileList${event.name}`].splice(event.index, 1)
  186. var arr = []
  187. this.fileList1.forEach(item1 => {
  188. arr.push(item1.url)
  189. })
  190. uni.hideLoading();
  191. this.model.tamperProofLabelImg = arr.join()
  192. },
  193. uploadFilePromise(url) {
  194. return new Promise((resolve, reject) => {
  195. let a = uni.uploadFile({
  196. url: ENV.APP_DEV_URL + '/api/upload', // 仅为示例,非真实的接口地址
  197. filePath: url,
  198. name: 'file',
  199. // formData: {
  200. // user: 'test'
  201. // },
  202. header: {
  203. 'Authorization': 'Bearer ' + uni.getStorageSync('access_token'),
  204. },
  205. success: (res) => {
  206. let state = JSON.parse(res.data)
  207. setTimeout(() => {
  208. if (state.code == 200) {
  209. resolve(state.data)
  210. }
  211. }, 100)
  212. }
  213. });
  214. })
  215. },
  216. // 扫一扫
  217. sweep(field) {
  218. // 允许从相机和相册扫码
  219. uni.scanCode({
  220. scanType: ['barCode', 'qrCode'],
  221. autoZoom: false,
  222. success: (res) => {
  223. if (res.result) {
  224. let url = res.result;
  225. this.model[field] = url
  226. } else {
  227. console.log('请重新扫描');
  228. return false;
  229. }
  230. },
  231. fail: (res) => {
  232. console.log('未识别到二维码1');
  233. }
  234. })
  235. },
  236. //子组件校验,传递到父组件
  237. async validateForm() {
  238. let flag = null
  239. await this.$refs.uForm.validate(valid => {}).then(res => {
  240. flag = true
  241. }).catch(err => {
  242. flag = false
  243. })
  244. return flag
  245. }
  246. },
  247. }
  248. </script>
  249. <style lang="scss">
  250. .card_form_item {
  251. display: flex;
  252. width: 100%;
  253. }
  254. .card_sweep {
  255. display: flex;
  256. flex-direction: column;
  257. justify-content: center;
  258. align-items: center;
  259. height: 70rpx;
  260. border: 1rpx solid #e5e5e5;
  261. border-radius: 8rpx;
  262. margin-left: 10rpx;
  263. span {
  264. margin: 0rpx 10rpx;
  265. display: flex;
  266. font-size: 22rpx;
  267. }
  268. }
  269. .card_search_gray {
  270. display: flex;
  271. flex-direction: row;
  272. align-items: center;
  273. justify-content: space-between;
  274. flex: 1;
  275. padding: 12rpx 18rpx;
  276. border-radius: 8rpx;
  277. line-height: 48rpx;
  278. }
  279. .title_gray {
  280. font-size: 30rpx;
  281. color: #c8c9cc;
  282. }
  283. // 伪元素1rpx边框
  284. .frame {
  285. position: relative; //重要
  286. }
  287. .frame::after {
  288. position: absolute;
  289. content: '';
  290. border: 2rpx solid #e7e6e4;
  291. border-radius: 16rpx;
  292. width: 200%;
  293. height: 200%;
  294. top: 0;
  295. left: 0;
  296. transform: scale(0.5);
  297. transform-origin: 0 0;
  298. pointer-events: none;
  299. /* 使伪元素不会阻止鼠标事件 */
  300. }
  301. </style>