index.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. <template>
  2. <view class="cust-form">
  3. <up-form labelPosition="left" :model="formData" ref="form_ref">
  4. <view v-for="item in column" :key="item.key + 'cust-form'" class="cust-form-item">
  5. <up-form-item v-if="item.type === 'input'" :label="item.label" :prop="item.key" borderBottom
  6. labelWidth="94" :required="item.required">
  7. <up-input v-model="formData[item.key]" border="none" :placeholder="'请输入' + item.label"></up-input>
  8. </up-form-item>
  9. <up-form-item v-if="item.type === 'select'" :label="item.label" :prop="item.key" borderBottom
  10. labelWidth="94" :required="item.required">
  11. <view @click.self="() => openActionSheet(item)">
  12. <up-input v-model="formData[item.key]" disabled disabledColor="#ffffff"
  13. :placeholder="'请选择' + item.label" border="none"></up-input>
  14. </view>
  15. <template #right>
  16. <up-icon name="arrow-right"></up-icon>
  17. </template>
  18. </up-form-item>
  19. <view v-if="item.type === 'phone-code'">
  20. <up-form-item label="手机号" prop="phonenumber" borderBottom labelWidth="94" :rules="[
  21. {
  22. type: 'string',
  23. required: true,
  24. len: 11,
  25. message: '请填写11位手机号',
  26. trigger: ['blur']
  27. }
  28. ]" >
  29. <up-input v-model="formData.phonenumber" border="none" placeholder="请输入手机号"
  30. :disabled="!isCode"></up-input>
  31. </up-form-item>
  32. <up-form-item label="验证码" prop="code" labelWidth="94" borderBottom :rules="[
  33. {
  34. type: 'string',
  35. required: true,
  36. len: 4,
  37. message: '请填写4位验证码',
  38. trigger: ['blur']
  39. }
  40. ]" >
  41. <up-input v-model="formData.code" border="none" placeholder="请填写验证码"></up-input>
  42. <template #right>
  43. <up-button @tap="getCode" :text="code_data.tips" type="success" size="mini"
  44. style="flex: 0.5;" :disabled="code_data.disabled"></up-button>
  45. </template>
  46. </up-form-item>
  47. </view>
  48. <up-form-item v-if="item.type === 'textarea'" :label="item.label" :prop="item.key" labelWidth="94"
  49. :required="item.required">
  50. <up-textarea :placeholder="'请输入' + item.label" v-model="formData[item.key]" count></up-textarea>
  51. </up-form-item>
  52. <up-form-item v-if="item.type === 'face'" :label="item.label" :prop="item.key" borderBottom
  53. labelWidth="94" :required="item.required">
  54. <up-button size="small" type="primary" text="前往人脸识别" @click="startFace"></up-button>
  55. </up-form-item>
  56. <up-form-item v-if="item.type === 'city'" :label="item.label" :prop="item.key" borderBottom
  57. labelWidth="94" :required="item.required">
  58. <pickerAddress @change="(info) => addressChange(info, item)"
  59. :selectValue="[formData.provinceInd, formData.cityInd, formData.districtInd]">
  60. <view class="inp"
  61. :class="formData.provinceName && formData.cityName && formData.districtName ? '' : 'address-inp'">
  62. {{ formData.provinceName ? formData.provinceName : '省' }} /
  63. {{ formData.cityName ? formData.cityName : '市' }} /
  64. {{ formData.districtName ? formData.districtName : '区' }}
  65. </view>
  66. </pickerAddress>
  67. <template #right>
  68. <up-icon name="map" size="22" @click="onCityWx(item)"></up-icon>
  69. </template>
  70. </up-form-item>
  71. <up-form-item v-if="item.type === 'cascader'" :label="item.label" :prop="item.key" borderBottom
  72. labelWidth="94" :required="item.required">
  73. <view @click.self="() => clickPick(item)">
  74. <up-input v-model="formData[item.key]" disabled disabledColor="#ffffff"
  75. :placeholder="'请选择' + item.label" border="none"></up-input>
  76. </view>
  77. <template #right>
  78. <up-icon name="arrow-right"></up-icon>
  79. </template>
  80. </up-form-item>
  81. </view>
  82. </up-form>
  83. <up-action-sheet :show="showSex" :actions="actions.option" :title="'请选择' + actions.label"
  84. @close="showSex = false" @select="ActionSheetSelect">
  85. </up-action-sheet>
  86. <up-code ref="uCode" @change="codeChange" seconds="60" @start="code_data.disabled = true"
  87. @end="code_data.disabled = false"></up-code>
  88. <Picker :columnData="options[actions.optionKey]" ref="pickerRef" @submit="ActionSheetSelect" />
  89. </view>
  90. </template>
  91. <script setup>
  92. import { onMounted, reactive, ref } from "vue";
  93. import Picker from '@/pages_home/components/picker/index.vue'
  94. import { sendCode } from '@/api/sm.js';
  95. import {
  96. onShow,
  97. onUnload
  98. } from "@dcloudio/uni-app";
  99. import { splitAddress, getCityCode,getAdressCode } from '@/utils/adress'
  100. import { regionAddresstree } from '@/api/home.js'
  101. import pickerAddress from '../pickerAddress/pickerAddress.vue'
  102. const props = defineProps({
  103. column: {
  104. type: Array,
  105. default: [],
  106. },
  107. isCode: {
  108. type: Boolean,
  109. default: true
  110. }
  111. });
  112. const formData = reactive({
  113. sex: null,
  114. city: null,
  115. provinceName: '', // 省
  116. provinceCode: '',
  117. provinceInd: 21,
  118. cityName: '', // 市
  119. cityCode: '',
  120. cityInd: 0,
  121. districtName: '',
  122. districtCode: '',
  123. districtInd: 17,
  124. // address: "永川区",
  125. // age: "1",
  126. // city: "重庆",
  127. // code: "1111",
  128. // idCard: "5002302000000000001",
  129. // name: "陈陈",
  130. // phonenumber: "18696601933",
  131. // sex: '男',
  132. // skillDescribe: "测试备注",
  133. });
  134. const form_ref = ref(null);
  135. const showSex = ref(false);
  136. const actions = ref({
  137. option: [],
  138. optionKey: 'businessManagementOption'
  139. });
  140. const pickerRef = ref(null)
  141. const options = reactive({
  142. businessManagementOption: []
  143. })
  144. const cityData = reactive({
  145. province: "重庆",
  146. city: "重庆市",
  147. area: "永川区",
  148. })
  149. const cityShow = ref(false)
  150. const code_data = reactive({
  151. disabled: false,
  152. tips: ''
  153. })
  154. const uCode = ref(null);
  155. function hideKeyboard() {
  156. uni.hideKeyboard()
  157. }
  158. function openActionSheet(row) {
  159. console.log(row);
  160. hideKeyboard();
  161. showSex.value = true;
  162. actions.value = row
  163. }
  164. function onCityShow() {
  165. console.log('onCityShow');
  166. cityShow.value = false;
  167. }
  168. function openCity(row) {
  169. console.log(row);
  170. cityShow.value = true
  171. actions.value = row
  172. }
  173. function onsetCity(e) {
  174. console.log('onsetCity', e);
  175. cityShow.value = false
  176. Object.assign(formData, {
  177. [actions.value.key]: e.address
  178. })
  179. console.log('formData', formData);
  180. }
  181. function ActionSheetSelect(e) {
  182. console.log('e', e);
  183. Object.assign(formData, {
  184. [actions.value.key]: e.key || e.name
  185. })
  186. if (actions.value.type === 'cascader') {
  187. Object.assign(formData, {
  188. [actions.value.key + 'key']: e.value
  189. })
  190. }
  191. console.log('formData.value', formData);
  192. // form_ref.value.validateField(actions.key)
  193. }
  194. async function getCode() {
  195. if (uCode.value.canGetCode) {
  196. // 模拟向后端请求验证码
  197. if (formData.phonenumber) {
  198. uni.showLoading({
  199. title: '正在获取验证码'
  200. })
  201. const res = await sendCode(formData.phonenumber);
  202. console.log(res);
  203. if (res.code == 200) {
  204. uni.hideLoading();
  205. uCode.value.start();
  206. uni.$u.toast('验证码已发送');
  207. }
  208. } else {
  209. uni.$u.toast('请输入手机号');
  210. }
  211. } else {
  212. uni.$u.toast('倒计时结束后再发送');
  213. }
  214. }
  215. function codeChange(text) {
  216. code_data.tips = text;
  217. }
  218. function startFace() {
  219. console.log('startFace', formData);
  220. }
  221. function setData(data) {
  222. console.log('setData=>data', data);
  223. Object.assign(formData, {
  224. ...data,
  225. sex: data.sex === 0 ? '男' : '女',
  226. })
  227. for (let i = 0; i < props.column.length; i++) {
  228. const element = props.column[i];
  229. if (element.type === 'cascader') {
  230. const key = data[element.key]
  231. // const key ='7'
  232. const lable = pickerRef.value.piceInit(key);
  233. console.log('element.type', lable, key, element.key);
  234. Object.assign(formData, {
  235. [element.key]: lable,
  236. [element.key + 'key']: key
  237. })
  238. console.log('eformData', formData);
  239. } else {
  240. }
  241. }
  242. }
  243. function onSubmit() {
  244. // 如果有错误,会在catch中返回报错信息数组,校验通过则在then中返回true
  245. return new Promise(async (resolve, reject) => {
  246. const res = await form_ref.value.validate();
  247. if (!res) {
  248. reject()
  249. return
  250. }
  251. resolve(formData);
  252. })
  253. }
  254. function onResetField() {
  255. form_ref.value.resetFields()
  256. form_ref.value.clearValidate()
  257. }
  258. function clickPick(row) {
  259. console.log('e', row);
  260. actions.value = row
  261. console.log('e', actions.value);
  262. pickerRef.value.show();
  263. }
  264. function addressChange(info, row) {
  265. actions.value = row
  266. console.log(info, '>>>>data');
  267. if (!info || !info.data) {
  268. console.error('Invalid address change info:', info);
  269. return;
  270. }
  271. if (!Array.isArray(info.data) || info.data.length < 3) {
  272. console.error('Invalid address data:', info.data);
  273. return;
  274. }
  275. const code = Array.isArray(info.code) ? info.code : ['', '', ''];
  276. let indexArray;
  277. if (Array.isArray(info.index)) {
  278. indexArray = info.index;
  279. } else if (info.index && typeof info.index[Symbol.iterator] === 'function') {
  280. indexArray = Array.from(info.index);
  281. } else {
  282. indexArray = [0, 0, 0];
  283. }
  284. Object.assign(formData, {
  285. provinceName: info.data[0],
  286. provinceCode: info.code[0],
  287. provinceInd: indexArray[0] || 0,
  288. cityName: info.data[1],
  289. cityCode: info.code[1],
  290. cityInd: indexArray[1] || 0,
  291. districtName: info.data[2],
  292. districtCode: info.code[2],
  293. districtInd: indexArray[2] || 0
  294. })
  295. console.log('formData===>', formData);
  296. }
  297. function onCityWx(row) {
  298. console.log('地区选点', row);
  299. wx.chooseLocation({
  300. success: async function (res) {
  301. console.log('res.address', res);
  302. const result = splitAddress(res.address);
  303. const res_dara = await regionAddresstree();
  304. const handlecityData = getCityCode([result.province, result.city, result.district].join(' '), res_dara.data)
  305. const api_res =await getAdressCode({ latitude: res.latitude, longitude: res.longitude },res_dara.data)
  306. console.log("=================>", handlecityData,api_res)
  307. addressChange(api_res.cityCode, row)
  308. Object.assign(formData, {
  309. // [row.key]: `${result.province}${result.city}${result.district}`,
  310. address: result.detail
  311. })
  312. },
  313. fail: function (err) {
  314. console.log(err);
  315. uni.showToast({
  316. title: '获取地址失败',
  317. icon: 'error',
  318. });
  319. },
  320. })
  321. }
  322. onShow(() => {
  323. })
  324. onUnload(() => {
  325. })
  326. onMounted(async () => {
  327. const rules = {};
  328. for (let i = 0; i < props.column.length; i++) {
  329. rules[props.column[i].key] = props.column[i].rules;
  330. if (props.column[i].type === 'cascader') {
  331. const res = await props.column[i].apifun();
  332. Object.assign(options, {
  333. [props.column[i].optionKey]: res
  334. })
  335. console.log('onMounted9999', options);
  336. }
  337. }
  338. form_ref.value && form_ref.value.setRules(rules)
  339. console.log('uni=====>', uni);
  340. })
  341. defineExpose({
  342. setData,//修改表单数据值
  343. onSubmit,//提交表单,先校验再提交
  344. onResetField,//表单重置
  345. })
  346. </script>
  347. <style lang="scss" scoped>
  348. // .cust-form-item{
  349. // position: relative;
  350. // }
  351. // .required-icon {
  352. // color: red;
  353. // position: absolute;
  354. // }</style>