index.vue 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. <template>
  2. <view class="content">
  3. <view class="one">
  4. <form @submit="formSubmit">
  5. <view class="value icon">
  6. <view class="title">头像</view>
  7. <view class="label">
  8. <image name="icon" class="image" mode="aspectFill" :src="form.icon||config.logoUrl"
  9. @tap="Preview"></image>
  10. </view>
  11. </view>
  12. <view class="remark">
  13. 实名信息(仅用于赛事报名、参赛证功能)
  14. </view>
  15. <view class="value other">
  16. <view class="title">姓名</view>
  17. <view class="label">
  18. <input name="name" class="input" :value="form.name" placeholder="请输入真实姓名" />
  19. </view>
  20. </view>
  21. <view class="value other margin">
  22. <view class="title">昵称</view>
  23. <view class="label">
  24. <input name="nickname" class="input" :value="form.nickname" placeholder="请输入昵称" />
  25. </view>
  26. </view>
  27. <view class="value other">
  28. <view class="title">性别</view>
  29. <view class="label">
  30. <picker name="sex" @change="sexChange" :value="index" :range="sexList" range-key="dictLabel">
  31. <view class="picker">{{form.sex||'请选择性别'}}</view>
  32. </picker>
  33. </view>
  34. </view>
  35. <view class="value other">
  36. <view class="title">手机号</view>
  37. <view class="label">
  38. <input name="phone" class="input" :value="form.phone" placeholder="请输入手机号" />
  39. </view>
  40. </view>
  41. <view class="value other">
  42. <view class="title">城市</view>
  43. <view class="label" @tap="toCity" name="city">
  44. <text v-if="form.city">{{form.city}}</text>
  45. <text v-else>请选择城市</text>
  46. </view>
  47. </view>
  48. <view class="value other">
  49. <view class="title">身高</view>
  50. <view class="label">
  51. <input name="height" class="input" :value="form.height" placeholder="请输入身高(cm)" />
  52. </view>
  53. </view>
  54. <view class="value other">
  55. <view class="title">体重</view>
  56. <view class="label">
  57. <input name="weight" class="input" :value="form.weight" placeholder="请输入体重(kg)" />
  58. </view>
  59. </view>
  60. <view class="value other margin">
  61. <view class="title">主要项目</view>
  62. <view class="label">
  63. <picker name="type" @change="typeChange" :value="index" :range="typeList" range-key="dictLabel">
  64. <view class="picker">{{form.type||'请选择主要项目'}}</view>
  65. </picker>
  66. </view>
  67. </view>
  68. <view class="value other">
  69. <view class="title">球龄</view>
  70. <view class="label">
  71. <picker name="ballYears" @change="ballYearsChange" :value="index" :range="ballYearsList"
  72. range-key="dictLabel">
  73. <view class="picker">{{form.ballYears||'请选择球龄'}}</view>
  74. </picker>
  75. </view>
  76. </view>
  77. <view class="value other">
  78. <view class="title">队内位置</view>
  79. <view class="label">
  80. <picker name="place" @change="placeChange" :value="index" :range="placeList"
  81. range-key="dictLabel">
  82. <view class="picker">{{form.place||'请选择队内位置'}}</view>
  83. </picker>
  84. </view>
  85. </view>
  86. <view class="button">
  87. <button type="primary" size="mini" form-type="submit">保存</button>
  88. </view>
  89. </form>
  90. </view>
  91. </view>
  92. </template>
  93. <script setup lang="ts">
  94. import { getCurrentInstance, computed, ref } from 'vue';
  95. //该依赖已内置不需要单独安装
  96. import { onLoad } from "@dcloudio/uni-app";
  97. // 请求接口
  98. const $api = getCurrentInstance()?.appContext.config.globalProperties.$api;
  99. const $config = getCurrentInstance()?.appContext.config.globalProperties.$config;
  100. const $apifile = getCurrentInstance()?.appContext.config.globalProperties.$apifile;
  101. // openid
  102. const openid = computed(() => {
  103. return uni.getStorageSync('openid');
  104. })
  105. // 基本信息
  106. const config = ref({ logoUrl: '' });
  107. // 用户信息
  108. const form = ref({ icon: '' });
  109. // 字典表
  110. const sexList = ref([]);
  111. const typeList = ref([]);
  112. const placeList = ref([]);
  113. const ballYearsList = ref([]);
  114. onLoad(async () => {
  115. await searchOther();
  116. await searchConfig();
  117. await search();
  118. uni.$on('setCity', function (city) {
  119. form.value.city = city
  120. })
  121. })
  122. // 查询其他信息
  123. const searchOther = async () => {
  124. let res;
  125. // 性别
  126. res = await $api(`dict/data/list`, 'GET', { dictType: 'sys_user_sex' });
  127. if (res.code === 200 && res.total > 0) sexList.value = res.rows
  128. // 主要项目
  129. res = await $api(`dict/data/list`, 'GET', { dictType: 'sys_user_type' });
  130. if (res.code === 200 && res.total > 0) typeList.value = res.rows
  131. // 队内位置
  132. res = await $api(`dict/data/list`, 'GET', { dictType: 'sys_user_place' });
  133. if (res.code === 200 && res.total > 0) placeList.value = res.rows
  134. // 球龄
  135. res = await $api(`dict/data/list`, 'GET', { dictType: 'sys_user_year' });
  136. if (res.code === 200 && res.total > 0) ballYearsList.value = res.rows
  137. };
  138. // config信息
  139. const searchConfig = async () => {
  140. config.value = uni.getStorageSync('config');
  141. };
  142. // 查询
  143. const search = async () => {
  144. const res = await $api(`matchUser/find`, 'GET', {
  145. openid: openid.value
  146. });
  147. if (res.code === 200) {
  148. if (res.data) {
  149. form.value = res.data
  150. form.value.sex = toData(form.value.sex, sexList.value)
  151. form.value.type = toData(form.value.type, typeList.value)
  152. form.value.place = toData(form.value.place, placeList.value)
  153. form.value.ballYears = toData(form.value.ballYears, ballYearsList.value)
  154. }
  155. else {
  156. uni.navigateTo({
  157. url: `/pages/login/index`,
  158. })
  159. }
  160. } else {
  161. uni.showToast({
  162. title: res.msg || '',
  163. icon: 'error',
  164. });
  165. }
  166. };
  167. // 处理字典表数据
  168. const toData = (value, list) => {
  169. if (value) return value = list[value].dictLabel
  170. };
  171. // 城市选择
  172. const toCity = () => {
  173. if (form.value.city) {
  174. uni.navigateTo({
  175. url: `/pagesHome/city/index?city=${form.value.city}`,
  176. })
  177. } else {
  178. uni.navigateTo({
  179. url: `/pagesHome/city/index`,
  180. })
  181. }
  182. };
  183. // 性别选择
  184. const sexChange = (e) => {
  185. const data = sexList.value[e.detail.value]
  186. if (data) form.value.sex = data.dictLabel
  187. };
  188. // 主要项目选择
  189. const typeChange = (e) => {
  190. const data = typeList.value[e.detail.value]
  191. if (data) form.value.type = data.dictLabel
  192. };
  193. // 队内位置别选择
  194. const placeChange = (e) => {
  195. const data = placeList.value[e.detail.value]
  196. if (data) form.value.place = data.dictLabel
  197. };
  198. // 球龄选择
  199. const ballYearsChange = (e) => {
  200. const data = ballYearsList.value[e.detail.value]
  201. if (data) form.value.ballYears = data.dictLabel
  202. };
  203. // 上传图片
  204. const Preview = () => {
  205. uni.chooseImage({
  206. count: 1,
  207. sizeType: ['original', 'compressed'],
  208. sourceType: ['album', 'camera'],
  209. success: async function (res) {
  210. let tempFile = JSON.parse(JSON.stringify(res.tempFilePaths));
  211. const arr = await $apifile(`/common/upload`, 'file', tempFile[0],
  212. 'file');
  213. if (arr.code == 200) {
  214. form.value.icon = arr.url
  215. } else {
  216. uni.showToast({
  217. title: arr.msg,
  218. icon: 'none'
  219. });
  220. }
  221. }
  222. });
  223. };
  224. // 去除obj里为null的数据
  225. const delEmptyQueryNodes = (obj = {}) => {
  226. Object.keys(obj).forEach((key) => {
  227. let value = obj[key];
  228. value && typeof value === 'object' && delEmptyQueryNodes(value);
  229. (value === '' || value === null || value === undefined || value.length === 0 || Object.keys(value).length === 0) && delete obj[key];
  230. });
  231. return obj;
  232. };
  233. // 保存
  234. const formSubmit = async (e) => {
  235. const data = delEmptyQueryNodes(e.detail.value)
  236. data.id = form.value.id
  237. if (form.value.icon) data.icon = form.value.icon
  238. if (form.value.city) data.city = form.value.city
  239. const arr = await $api(`matchUser`, 'put', data);
  240. if (arr.code === 200) {
  241. search();
  242. } else {
  243. uni.showToast({
  244. title: arr.msg,
  245. icon: 'error'
  246. });
  247. }
  248. };
  249. </script>
  250. <style lang="scss" scoped>
  251. .content {
  252. display: flex;
  253. flex-direction: column;
  254. width: 100vw;
  255. height: 100vh;
  256. background-color: var(--footColor);
  257. .one {
  258. .icon {
  259. padding: 2vw;
  260. }
  261. .margin {
  262. margin: 3vw 0 0 0;
  263. }
  264. .other {
  265. padding: 3vw 2vw;
  266. border-bottom: 1px solid var(--footColor);
  267. }
  268. .value {
  269. display: flex;
  270. justify-content: space-between;
  271. align-items: center;
  272. background-color: var(--mainColor);
  273. .label {
  274. .input {
  275. text-align: right;
  276. }
  277. .image {
  278. width: 15vw;
  279. height: 15vw;
  280. border-radius: 20vw;
  281. }
  282. }
  283. }
  284. .remark {
  285. padding: 4vw 2vw;
  286. text-align: center;
  287. color: var(--f99Color);
  288. font-size: var(--font18Size);
  289. }
  290. .button {
  291. margin: 2vw 0 0 0;
  292. text-align: center;
  293. button {
  294. font-size: var(--font14Size);
  295. border-radius: 2vw;
  296. background: linear-gradient(to right, #00BFFF, #3F94F1, #7B68EE);
  297. }
  298. }
  299. }
  300. }
  301. </style>