鸿宇研学生前端代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

352 lines
9.3 KiB

  1. <template>
  2. <view>
  3. <uv-popup ref="popup" mode="bottom" bgColor="none" >
  4. <view class="popup__view">
  5. <view class="flex header">
  6. <view class="title">新增记录</view>
  7. <button class="btn" @click="close">关闭</button>
  8. </view>
  9. <view class="form">
  10. <uv-form
  11. ref="form"
  12. :model="form"
  13. :rules="rules"
  14. errorType="toast"
  15. >
  16. <view class="form-item">
  17. <uv-form-item prop="project" :customStyle="formItemStyle">
  18. <view class="form-item-label">
  19. <image class="icon" src="@/static/image/icon-require.png" mode="widthFix"></image>
  20. 关联项目
  21. </view>
  22. <view class="form-item-content">
  23. <view class="flex row" @click="openRelatePojectPicker">
  24. <view v-if="form.project" class="text">{{ projectDesc }}</view>
  25. <view v-else class="text placeholder">请选择关联项目</view>
  26. <uv-icon name="arrow-right" color="#C6C6C6" size="32rpx"></uv-icon>
  27. </view>
  28. <reloateProjectPopup ref="reloateProjectPopup" :options="projects" @confirm="onRelateProjectChange"></reloateProjectPopup>
  29. </view>
  30. </uv-form-item>
  31. </view>
  32. <view class="form-item">
  33. <uv-form-item prop="tripNum" :customStyle="formItemStyle">
  34. <view class="flex row">
  35. <view class="form-item-label">行程</view>
  36. <view class="form-item-content">
  37. <formRate v-model="form.tripNum"></formRate>
  38. </view>
  39. </view>
  40. </uv-form-item>
  41. </view>
  42. <view class="form-item">
  43. <uv-form-item prop="spotNum" :customStyle="formItemStyle">
  44. <view class="flex row">
  45. <view class="form-item-label">景点</view>
  46. <view class="form-item-content">
  47. <formRate v-model="form.spotNum"></formRate>
  48. </view>
  49. </view>
  50. </uv-form-item>
  51. </view>
  52. <view class="form-item">
  53. <uv-form-item prop="mentorNum" :customStyle="formItemStyle">
  54. <view class="flex row">
  55. <view class="form-item-label">导师</view>
  56. <view class="form-item-content">
  57. <formRate v-model="form.mentorNum"></formRate>
  58. </view>
  59. </view>
  60. </uv-form-item>
  61. </view>
  62. <view class="form-item">
  63. <uv-form-item prop="images" :customStyle="formItemStyle">
  64. <view class="form-item-label">上传图片</view>
  65. <view class="form-item-content">
  66. <formUpload v-model="form.images"></formUpload>
  67. </view>
  68. </uv-form-item>
  69. </view>
  70. <view class="form-item" v-for="(item, index) in questions" :key="item.id">
  71. <uv-form-item :prop="`texts[${index}]`" :customStyle="formItemStyle">
  72. <view class="form-item-label">
  73. <image class="icon" src="@/static/image/icon-require.png" mode="widthFix"></image>
  74. {{ item.label }}
  75. </view>
  76. <view class="form-item-content">
  77. <formTextarea v-model="form.texts[index]"></formTextarea>
  78. </view>
  79. </uv-form-item>
  80. </view>
  81. </uv-form>
  82. </view>
  83. <view class="footer">
  84. <button class="flex btn" @click="onPublish">发布</button>
  85. </view>
  86. </view>
  87. </uv-popup>
  88. </view>
  89. </template>
  90. <script>
  91. import reloateProjectPopup from './reloateProjectPopup.vue'
  92. import formTextarea from '@/pages_order/components/formTextarea.vue'
  93. import formUpload from '@/pages_order/components/formUpload.vue'
  94. import formRate from '@/pages_order/components/formRate.vue'
  95. export default {
  96. components: {
  97. reloateProjectPopup,
  98. formTextarea,
  99. formUpload,
  100. formRate,
  101. },
  102. data() {
  103. return {
  104. form: {
  105. project: null,
  106. tripNum: null,
  107. spotNum: null,
  108. mentorNum: null,
  109. images: [],
  110. texts: [],
  111. },
  112. rules: {
  113. // todo
  114. },
  115. projects: [],
  116. questions: [],
  117. }
  118. },
  119. computed: {
  120. projectDesc() {
  121. const { project } = this.form
  122. const target = this.projects?.find?.(item => item.id === project)
  123. return target?.name || ''
  124. },
  125. },
  126. methods: {
  127. getData() {
  128. // todo
  129. this.projects = [
  130. {
  131. id: '001',
  132. name: '亲子•坝上双草原6日 |乌兰布统+锡林郭勒+长城',
  133. },
  134. {
  135. id: '002',
  136. name: '青青草原•云中岭 |5-10公里AB线强度可选',
  137. },
  138. {
  139. id: '003',
  140. name: '新疆天山行7/9日丨醉美伊犁&吐鲁番双套餐',
  141. },
  142. {
  143. id: '004',
  144. name: '九色甘南|人间净土6日/7日深度游',
  145. },
  146. {
  147. id: '005',
  148. name: '北疆全景12日| 入疆首推!阿勒泰+伊犁+吐鲁番',
  149. },
  150. {
  151. id: '006',
  152. name: '塞上江南•神奇宁夏5日|穿越大漠与历史对话',
  153. },
  154. {
  155. id: '007',
  156. name: '尊享•天山环线9日| 伊犁全景+独库,头等舱大巴',
  157. },
  158. ]
  159. this.questions = [
  160. {
  161. id: '001',
  162. label: '这次研学之旅,整体给你留下了怎样的印象?用几个词或几句话简单概括一下',
  163. },
  164. {
  165. id: '002',
  166. label: '在整个行程中,你最喜欢的部分是哪里?为什么?',
  167. },
  168. {
  169. id: '003',
  170. label: '你觉得这次研学的行程安排是否合理?有没有哪些地方让你觉得特别满意或需要改进的?',
  171. },
  172. ]
  173. },
  174. async open() {
  175. await this.getData()
  176. const texts = this.questions.map(() => '')
  177. this.form = {
  178. project: null,
  179. tripNum: null,
  180. spotNum: null,
  181. mentorNum: null,
  182. images: [],
  183. texts,
  184. }
  185. this.$refs.popup.open()
  186. },
  187. close() {
  188. this.$refs.popup.close()
  189. },
  190. openRelatePojectPicker() {
  191. this.$refs.reloateProjectPopup.open(this.form.project?.id || null)
  192. },
  193. onRelateProjectChange(id) {
  194. this.form.project = id
  195. },
  196. async onPublish() {
  197. try {
  198. await this.$refs.form.validate()
  199. const {
  200. } = this.form
  201. const params = {
  202. }
  203. // todo: fetch
  204. // await this.$fetch('updateAddress', params)
  205. uni.showToast({
  206. icon: 'success',
  207. title: '发布成功',
  208. });
  209. this.$emit('submitted')
  210. this.close()
  211. } catch (err) {
  212. console.log('onSave err', err)
  213. }
  214. },
  215. },
  216. }
  217. </script>
  218. <style lang="scss" scoped>
  219. .popup__view {
  220. width: 100vw;
  221. display: flex;
  222. flex-direction: column;
  223. box-sizing: border-box;
  224. background: #FFFFFF;
  225. border-top-left-radius: 32rpx;
  226. border-top-right-radius: 32rpx;
  227. }
  228. .header {
  229. position: relative;
  230. width: 100%;
  231. padding: 24rpx 0;
  232. box-sizing: border-box;
  233. border-bottom: 2rpx solid #EEEEEE;
  234. .title {
  235. font-family: PingFang SC;
  236. font-weight: 500;
  237. font-size: 34rpx;
  238. line-height: 1.4;
  239. color: #181818;
  240. }
  241. .btn {
  242. font-family: PingFang SC;
  243. font-weight: 500;
  244. font-size: 32rpx;
  245. line-height: 1.4;
  246. color: #8B8B8B;
  247. position: absolute;
  248. top: 26rpx;
  249. left: 40rpx;
  250. }
  251. }
  252. .form {
  253. max-height: 75vh;
  254. padding: 32rpx 40rpx;
  255. box-sizing: border-box;
  256. overflow-y: auto;
  257. &-item {
  258. padding: 8rpx 0 6rpx 0;
  259. & + & {
  260. padding-top: 24rpx;
  261. border-top: 2rpx solid #EEEEEE;
  262. }
  263. &-label {
  264. margin-bottom: 14rpx;
  265. display: flex;
  266. align-items: center;
  267. font-family: PingFang SC;
  268. font-weight: 400;
  269. font-size: 26rpx;
  270. line-height: 1.4;
  271. color: #181818;
  272. .icon {
  273. margin-right: 8rpx;
  274. width: 16rpx;
  275. height: auto;
  276. }
  277. }
  278. &-content {
  279. .text {
  280. padding: 2rpx 0;
  281. font-family: PingFang SC;
  282. font-weight: 400;
  283. font-size: 32rpx;
  284. line-height: 1.4;
  285. &.placeholder {
  286. color: #C6C6C6;
  287. }
  288. }
  289. }
  290. }
  291. }
  292. .row {
  293. justify-content: space-between;
  294. .form-label {
  295. margin: 0;
  296. }
  297. }
  298. .footer {
  299. width: 100%;
  300. padding: 32rpx 40rpx;
  301. box-sizing: border-box;
  302. border-top: 2rpx solid #F1F1F1;
  303. .btn {
  304. width: 100%;
  305. padding: 14rpx 0;
  306. box-sizing: border-box;
  307. font-family: PingFang SC;
  308. font-weight: 500;
  309. font-size: 36rpx;
  310. line-height: 1.4;
  311. color: #FFFFFF;
  312. background-image: linear-gradient(to right, #21FEEC, #019AF9);
  313. border: 2rpx solid #00A9FF;
  314. border-radius: 41rpx;
  315. }
  316. }
  317. </style>