index.vue 15 KB

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