Add.vue 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. <template>
  2. <view>
  3. <up-form labelPosition="left" :model="modelForm" :rules="rulesForm" ref="formRef">
  4. <up-form-item label="姓名" prop="name" borderBottom labelWidth="70">
  5. <up-input v-model="modelForm.name" border="none" placeholder="请输入姓名"></up-input>
  6. </up-form-item>
  7. <up-form-item label="性别" prop="sex" borderBottom @click="() => (sexFlag = true)" labelWidth="70">
  8. <up-input v-model="displaySex" disabled disabledColor="#ffffff" placeholder="请选择性别" border="none"></up-input>
  9. <template #right>
  10. <up-icon name="arrow-right"></up-icon>
  11. </template>
  12. </up-form-item>
  13. <!-- <up-form-item
  14. label="关系"
  15. prop="label"
  16. borderBottom
  17. @click="() => (labelFlag = true)"
  18. labelWidth="70"
  19. >
  20. <up-input
  21. v-model="modelForm.label"
  22. disabled
  23. disabledColor="#ffffff"
  24. placeholder="请选择关系"
  25. border="none"
  26. ></up-input>
  27. <template #right>
  28. <up-icon name="arrow-right"></up-icon>
  29. </template>
  30. </up-form-item> -->
  31. <up-form-item label="年龄" prop="age" borderBottom labelWidth="70">
  32. <up-input v-model="modelForm.age" border="none" placeholder="请输入年龄"></up-input>
  33. </up-form-item>
  34. <up-form-item label="手机号" prop="telephone" borderBottom labelWidth="70">
  35. <up-input v-model="modelForm.telephone" border="none" placeholder="请输入手机号"></up-input>
  36. </up-form-item>
  37. <up-form-item label="地区" prop="area" borderBottom @click="onCityWx" labelWidth="70">
  38. <view class="inp"
  39. :class="modelForm.provinceName && modelForm.cityName && modelForm.districtName ? '' : 'address-inp'">
  40. {{ modelForm.provinceName ? modelForm.provinceName : '省' }} /
  41. {{ modelForm.cityName ? modelForm.cityName : '市' }} /
  42. {{ modelForm.districtName ? modelForm.districtName : '区' }}
  43. </view>
  44. <template #right>
  45. <up-icon name="map" size="22" @click="onCityWx"></up-icon>
  46. </template>
  47. </up-form-item>
  48. <up-form-item label="地址" prop="address" borderBottom labelWidth="70" @click="onCityWx">
  49. <up-input v-model="modelForm.address" border="none" placeholder="请输入地址"></up-input>
  50. </up-form-item>
  51. <up-form-item label="门牌号" prop="detailAddress" borderBottom labelWidth="70">
  52. <up-input v-model="modelForm.detailAddress" border="none" placeholder="请输入地址"></up-input>
  53. </up-form-item>
  54. </up-form>
  55. <up-action-sheet :show="sexFlag" :actions="sexOptions" @select="sexSelect"
  56. @close="sexFlag = false"></up-action-sheet>
  57. <up-action-sheet :show="labelFlag" :actions="relaTionsHip" @select="sexSelectsHip"
  58. @close="labelFlag = false"></up-action-sheet>
  59. </view>
  60. </template>
  61. <script setup>
  62. import { ref, reactive, computed } from 'vue'
  63. import { splitAddress } from '@/utils/adress'
  64. import config from '@/config'
  65. const mapKey = config.mapKey
  66. const formRef = ref(null)
  67. const modelForm = ref({
  68. name: '',
  69. sex: '',
  70. label: '',
  71. age: '',
  72. telephone: '',
  73. detailAddress: '',
  74. address: '',
  75. provinceName: '', // 省
  76. provinceCode: '',
  77. provinceInd: 0,
  78. cityName: '', // 市
  79. cityCode: '',
  80. cityInd: 0,
  81. districtName: '',
  82. districtCode: '',
  83. districtInd: 0,
  84. })
  85. const rulesForm = ref({
  86. name: [{
  87. type: 'string',
  88. required: true,
  89. message: '请填写姓名',
  90. trigger: ['blur', 'change'],
  91. },
  92. {
  93. // 此为同步验证,可以直接返回true或者false,如果是异步验证,稍微不同,见下方说明
  94. validator: (rule, value, callback) => {
  95. // 调用uview-plus自带的js验证规则,详见:https://uview-plus.jiangruyi.com/js/test.html
  96. return uni.$u.test.chinese(value)
  97. },
  98. message: '姓名必须为中文',
  99. // 触发器可以同时用blur和change,二者之间用英文逗号隔开
  100. trigger: ['change', 'blur'],
  101. },
  102. ],
  103. // sex: {
  104. // type: 'number',
  105. // required: true,
  106. // message: '请选择性别',
  107. // trigger: ['change', 'blur'],
  108. age: [{
  109. type: 'string',
  110. required: true,
  111. message: '请填写年龄',
  112. trigger: ['blur', 'change'],
  113. }
  114. ,
  115. {
  116. validator: (rule, value, callback) => {
  117. return uni.$u.test.digits(value)
  118. },
  119. message: '年龄必须为数字',
  120. // 触发器可以同时用blur和change,二者之间用英文逗号隔开
  121. trigger: ['change', 'blur'],
  122. },
  123. ],
  124. telephone: [{
  125. type: 'string',
  126. required: true,
  127. message: '请填写手机号',
  128. trigger: ['blur', 'change'],
  129. },
  130. {
  131. validator: (rule, value, callback) => {
  132. return uni.$u.test.mobile(value)
  133. },
  134. message: '请输入正确的11位手机号',
  135. trigger: ['change', 'blur'],
  136. }
  137. ],
  138. detailAddress: {
  139. type: 'string',
  140. required: true,
  141. message: '请填写门牌号',
  142. trigger: ['blur', 'change'],
  143. },
  144. address: {
  145. type: 'string',
  146. required: true,
  147. message: '请填写地址',
  148. trigger: ['blur', 'change'],
  149. },
  150. })
  151. let sexFlag = ref(false)
  152. let labelFlag = ref(false)
  153. let index = ref(0)
  154. const sexOptions = ref([
  155. {
  156. name: '男',
  157. value: 0,
  158. },
  159. {
  160. name: '女',
  161. value: 1,
  162. },
  163. ])
  164. const relaTionsHip = ref([
  165. {
  166. name: '父母',
  167. },
  168. {
  169. name: '子女',
  170. },
  171. {
  172. name: '兄弟',
  173. },
  174. {
  175. name: '朋友',
  176. },
  177. {
  178. name: '同学',
  179. },
  180. {
  181. name: '同事',
  182. },
  183. {
  184. name: '配偶',
  185. },
  186. ])
  187. const displaySex = computed({
  188. get() {
  189. const option = sexOptions.value.find(
  190. (item) => item.value === modelForm.value.sex
  191. )
  192. return option ? option.name : ''
  193. },
  194. set(newValue) {
  195. const option = sexOptions.value.find((item) => item.name === newValue)
  196. if (option) {
  197. modelForm.value.sex = option.value
  198. }
  199. },
  200. })
  201. // 性别选择处理
  202. function sexSelect(e) {
  203. modelForm.value.sex = e.value
  204. sexFlag.value = false
  205. }
  206. function sexSelectsHip(e) {
  207. modelForm.value.label = e.name
  208. labelFlag.value = false
  209. }
  210. // 使用腾讯地图 API 的函数
  211. function getAdcodeByCoordinates(latitude, longitude) {
  212. if (!mapKey) {
  213. console.error('腾讯地图key为空,请检查配置!');
  214. uni.showToast({
  215. title: '腾讯地图key为空',
  216. icon: 'error'
  217. });
  218. return Promise.reject('腾讯地图key为空');
  219. }
  220. const url = `https://apis.map.qq.com/ws/geocoder/v1/?location=${latitude},${longitude}&key=${mapKey}`;
  221. console.log('请求URL:', url);
  222. return new Promise((resolve, reject) => {
  223. uni.request({
  224. url: url,
  225. success: (res) => {
  226. if (res.data.status === 0) {
  227. const adInfo = res.data.result.ad_info;
  228. resolve({
  229. provinceName: adInfo.province,
  230. cityName: adInfo.city,
  231. districtName: adInfo.district,
  232. provinceCode: adInfo.adcode.slice(0, 2) + '0000', // 提取省编码
  233. cityCode: adInfo.adcode.slice(0, 4) + '00', // 提取市编码
  234. districtCode: adInfo.adcode // 提取区编码
  235. });
  236. } else {
  237. console.error('腾讯地图API错误:', res.data.message);
  238. reject('Error fetching adcode: ' + res.data.message);
  239. }
  240. },
  241. fail: (err) => {
  242. console.error('请求腾讯地图API失败:', err);
  243. reject(err);
  244. }
  245. });
  246. });
  247. }
  248. // 点击地图图标选择地址
  249. // 点击地址图标,选择位置并获取省市区编码
  250. async function onCityWx() {
  251. wx.chooseLocation({
  252. success: async function(res) {
  253. try {
  254. console.log('选择的地址:', res);
  255. // 调用腾讯地图 API 获取省市区编码
  256. const adcodeData = await getAdcodeByCoordinates(res.latitude, res.longitude);
  257. // 更新表单数据
  258. modelForm.value.provinceName = adcodeData.provinceName;
  259. modelForm.value.cityName = adcodeData.cityName;
  260. modelForm.value.districtName = adcodeData.districtName;
  261. modelForm.value.provinceCode = adcodeData.provinceCode;
  262. modelForm.value.cityCode = adcodeData.cityCode;
  263. modelForm.value.districtCode = adcodeData.districtCode;
  264. modelForm.value.address = res.address; // 完整地址
  265. modelForm.value.longitude = res.longitude;
  266. modelForm.value.latitude = res.latitude;
  267. console.log('获取到的省市区信息:', adcodeData);
  268. } catch (err) {
  269. console.error('获取省市区编码失败:', err);
  270. uni.showToast({
  271. title: '获取地址编码失败',
  272. icon: 'error'
  273. });
  274. }
  275. },
  276. fail: function(err) {
  277. console.error('选择位置失败:', err);
  278. uni.showToast({
  279. title: '获取地址失败',
  280. icon: 'error'
  281. });
  282. }
  283. });
  284. }
  285. defineExpose({
  286. modelForm: modelForm.value,
  287. })
  288. </script>
  289. <style></style>