应无所住,而生其心
排名
1
文章
872
粉丝
112
评论
163
net core webapi post传递参数
庸人 : 确实坑哈,我也是下班好了好几次,发现后台传递对象是可以的,但...
百度编辑器自定义模板
庸人 : 我建议换个编辑器,因为现在百度富文本已经停止维护了,用tinymec...
ICP备案 :渝ICP备18016597号-1
网站信息:2018-2025TNBLOG.NET
技术交流:群号656732739
联系我们:contact@tnblog.net
公网安备:50010702506256
欢迎加群交流技术

uni-app app,小程序 时间轴样式,时间轴效果。弹窗里边使用时间轴。悬浮菜单

2050人阅读 2024/5/31 17:21 总访问:5415592 评论:0 收藏:0 手机
分类: 前端


虽然可以用一些时间轴组件比如,timeline,但是有时候还是自己写点样式定制性好一点,不需要像组件那么通用。

时间轴效果一

效果图

具体的代码和样式

  1. <template>
  2. <view class="teaching-dynamics-container">
  3. <view class="tdc-course-info">
  4. <view class="tdc-grade"></view>
  5. <view class="tdc-coursename">《MySQL数据库设计与实现(第二版)》</view>
  6. </view>
  7. <view class="tdc-class-schedule">
  8. <view class="tdc-classinfo">
  9. <view class="tcs-classtag">班级:</view>
  10. <view class="tsc-classname">22级移动互联应用技术1班</view>
  11. </view>
  12. <view class="tdc-cs-schedule">
  13. <view class="tcs-cs-scheduletag">进度:</view>
  14. <view class="tsc-cs-schedulename">第3章 MySQL存储引擎和数据类型</view>
  15. </view>
  16. <view class="tdc-line"></view>
  17. <view class="tdc-cs-completeinfo">
  18. <view class="tdc-csc-warp">
  19. <view>应完成:</view>
  20. <view>60%</view>
  21. </view>
  22. <view class="tdc-csc-warp tdc-csc-warp-right">
  23. <view>完成:</view>
  24. <view>59%</view>
  25. </view>
  26. </view>
  27. </view>
  28. <view class="system-study-situation" style="margin-top: 35rpx">
  29. <view class="timeline-list">
  30. <block v-for="(item, index) in 3" :key="index">
  31. <view class="timeline-item">
  32. <view class="timeline-item_tail"></view>
  33. <view class="timeline-item_node">
  34. <view class="timeline-item-innode"></view>
  35. </view>
  36. <view class="timeline-item_wrapper">
  37. <view class="sss-title-complete">
  38. <view class="sss-title">
  39. <view>评估系统</view>
  40. <!-- <view class="sss-grade grade-excellent">优</view> -->
  41. <view class="sss-grade grade-excellent" :class="state.gradeStyle[index]">{{ state.gradeDesc[index] }}</view>
  42. </view>
  43. <view class="sss-complete-info">
  44. <view>完成80%</view>
  45. <view>应完成70%</view>
  46. </view>
  47. </view>
  48. <view class="sss-chapter-study-situation" v-for="(initem, inindex) in 2" :key="inindex">
  49. <view class="sss-css-item">
  50. <view class="sss-ci-title">第1章MySQL数据库基础</view>
  51. <view class="sss-ci-situation">未开始</view>
  52. </view>
  53. </view>
  54. </view>
  55. </view>
  56. </block>
  57. </view>
  58. </view>
  59. </view>
  60. </template>
  61. <script setup lang="ts" name="tasks">
  62. import { defineAsyncComponent, reactive, onMounted, toRefs, ref } from 'vue';
  63. const state = reactive({
  64. title: '更新',
  65. schoolID: null,
  66. // 优,良,差样式
  67. gradeStyle: {
  68. 0: "grade-excellent",
  69. 1: "grade-good",
  70. 2: "grade-bad",
  71. },
  72. // 优,良,差描述
  73. gradeDesc: {
  74. 0: "优",
  75. 1: "良",
  76. 2: "差",
  77. }
  78. })
  79. onMounted(() => {
  80. })
  81. </script>
  82. <!-- 时间轴的样式 -->
  83. <style lang="scss" scoped>
  84. .timeline-list {
  85. margin: 10rpx 0px 10px 5px;
  86. margin-top: 62rpx;
  87. font-size: 28rpx;
  88. list-style: none;
  89. }
  90. .timeline-item:last-child .timeline-item_tail {
  91. display: none;
  92. }
  93. .timeline-item {
  94. position: relative;
  95. padding-bottom: 20rpx;
  96. }
  97. .timeline-item_tail {
  98. position: absolute;
  99. left: 4rpx;
  100. height: 100%;
  101. border-left: 2rpx solid rgba(109, 209, 201, 0.3);
  102. // 时间轴左边的线修改为虚线
  103. border-left-style: dashed;
  104. }
  105. .timeline-item_node {
  106. position: absolute;
  107. background-color: #FFFFFF;
  108. border-radius: 50%;
  109. display: flex;
  110. justify-content: center;
  111. align-items: center;
  112. left: -8rpx;
  113. width: 22rpx;
  114. height: 22rpx;
  115. background: #fff;
  116. border: 2rpx solid #6DD1C9;
  117. .timeline-item-innode {
  118. width: 14rpx;
  119. height: 14rpx;
  120. background: #6DD1C9;
  121. border-radius: 50%;
  122. }
  123. }
  124. .timeline-item_wrapper {
  125. position: relative;
  126. padding: 26rpx 0rpx 0rpx 0rpx;
  127. margin-left: 39rpx;
  128. top: -34rpx;
  129. background-color: #ffffff;
  130. border-radius: 20rpx;
  131. // width: 600rpx;
  132. }
  133. .timeline-item_timestamp {
  134. color: #38254D;
  135. font-weight: bold;
  136. font-size: 30rpx;
  137. line-height: 32rpx;
  138. }
  139. .timeline-item_content {
  140. display: flex;
  141. flex-direction: column;
  142. margin-top: 20rpx;
  143. margin-bottom: 20rpx;
  144. text {
  145. font-size: 26rpx;
  146. color: #574966;
  147. line-height: 40rpx;
  148. }
  149. .btn {
  150. align-self: flex-end;
  151. font-size: 26rpx;
  152. color: #F06245;
  153. line-height: 60rpx;
  154. text-align: center;
  155. margin-top: -40rpx;
  156. width: 140rpx;
  157. height: 60rpx;
  158. border: 1rpx solid #F06245;
  159. border-radius: 30rpx;
  160. }
  161. }
  162. </style>
  163. <!-- 其他的内容样式 -->
  164. <style scoped="scoped" lang="scss">
  165. .teaching-dynamics-container {
  166. padding: 39rpx 30rpx 30rpx 30rpx;
  167. // 优秀
  168. .grade-excellent {
  169. background: #5ECDB6;
  170. }
  171. // 良好
  172. .grade-good {
  173. background: #FF8B64;
  174. }
  175. // 差
  176. .grade-bad {
  177. background: #FF6363;
  178. }
  179. .tdc-line {
  180. height: 1rpx;
  181. background: #ECEDEF;
  182. // background: #ff6666;
  183. margin-top: 25rpx;
  184. margin-bottom: 25rpx;
  185. }
  186. .tdc-course-info {
  187. display: flex;
  188. .tdc-grade {
  189. width: 54rpx;
  190. height: 36rpx;
  191. background: #5ECDB6;
  192. border-radius: 24rpx 24rpx 0rpx 24rpx;
  193. text-align: center;
  194. font-family: PingFang SC, PingFang SC;
  195. font-weight: 400;
  196. font-size: 24rpx;
  197. color: #FFFFFF;
  198. }
  199. .tdc-coursename {
  200. font-family: PingFang SC, PingFang SC;
  201. font-weight: 400;
  202. font-size: 28rpx;
  203. color: #313960;
  204. padding-left: 13rpx;
  205. }
  206. }
  207. .tdc-class-schedule {
  208. margin-top: 30rpx;
  209. // height: 196rpx;
  210. background: #F7F8FB;
  211. border-radius: 8rpx 8rpx 8rpx 8rpx;
  212. padding: 30rpx 30rpx;
  213. .tdc-classinfo {
  214. display: flex;
  215. padding-left: 46rpx;
  216. .tcs-classtag {
  217. color: #B3B3B3;
  218. font-size: 24rpx;
  219. font-family: PingFang SC, PingFang SC;
  220. }
  221. .tsc-classname {
  222. color: #313960;
  223. font-size: 24rpx;
  224. font-family: PingFang SC, PingFang SC;
  225. }
  226. }
  227. .tdc-cs-schedule {
  228. display: flex;
  229. margin-top: 20rpx;
  230. padding-left: 46rpx;
  231. .tcs-cs-scheduletag {
  232. color: #B3B3B3;
  233. font-size: 24rpx;
  234. font-family: PingFang SC, PingFang SC;
  235. }
  236. .tsc-cs-schedulename {
  237. color: #313960;
  238. font-size: 24rpx;
  239. font-family: PingFang SC, PingFang SC;
  240. }
  241. }
  242. .tdc-cs-completeinfo {
  243. display: flex;
  244. font-family: PingFang SC, PingFang SC;
  245. font-weight: 400;
  246. font-size: 24rpx;
  247. color: #55B6FF;
  248. padding-left: 46rpx;
  249. .tdc-csc-warp {
  250. display: flex;
  251. }
  252. }
  253. .tdc-csc-warp-right {
  254. margin-left: 100rpx;
  255. }
  256. }
  257. .system-study-situation {
  258. .sss-title-complete {
  259. display: flex;
  260. justify-content: space-between;
  261. align-items: center;
  262. .sss-title {
  263. font-size: 30rpx;
  264. color: #313960;
  265. display: flex;
  266. align-items: center;
  267. .sss-grade {
  268. width: 39rpx;
  269. height: 32rpx;
  270. // background: #5ECDB6;
  271. border-radius: 10rpx 8rpx 10rpx 8rpx;
  272. margin-left: 10rpx;
  273. // 微调一下间距
  274. margin-top: -4rpx;
  275. text-align: center;
  276. font-family: PingFang SC, PingFang SC;
  277. font-weight: 400;
  278. font-size: 24rpx;
  279. color: #FFFFFF;
  280. }
  281. }
  282. .sss-complete-info {
  283. display: flex;
  284. font-family: PingFang SC, PingFang SC;
  285. font-weight: 400;
  286. font-size: 24rpx;
  287. color: #313960;
  288. :last-child {
  289. margin-left: 20rpx;
  290. }
  291. }
  292. }
  293. .sss-chapter-study-situation {
  294. .sss-css-item {
  295. display: flex;
  296. justify-content: space-between;
  297. align-items: center;
  298. height: 73rpx;
  299. background: #F9F9F9;
  300. border-radius: 8rpx 8rpx 8rpx 8rpx;
  301. font-family: PingFang SC, PingFang SC;
  302. font-weight: 400;
  303. font-size: 24rpx;
  304. color: rgba(0, 0, 0, 0.6);
  305. margin-top: 20rpx;
  306. padding: 0px 15rpx;
  307. // .sss-ci-title {
  308. // }
  309. // .sss-ci-situation{
  310. // }
  311. }
  312. }
  313. }
  314. }
  315. </style>

时间轴效果2

注意横向滚动条的问题


有可能会因为宽度问题出现横向滚动条,注意根据实际情况微调一下样式即可。这里的样式是不会出现横向滚动条的,要改造样式的话注意一下因为宽度问题造成的横向滚动条即可。

一般因为宽度问题出现横向滚动条是因为这里的样式:

  1. .timeline-item_wrapper {
  2. position: relative;
  3. padding: 32rpx 24rpx;
  4. // ****就是这一句,宽度窄的时候不会出现横向滚动条,但是宽度撑满的时候就会出现了****
  5. left: 42rpx;
  6. top: -32rpx;
  7. background-color: #ffffff;
  8. border-radius: 20rpx;
  9. width: 600rpx;
  10. }

所以其实建议这样修改更科学一点(通过padding与margin-left来实现不使用left):

  1. .timeline-item_wrapper {
  2. position: relative;
  3. padding: 0rpx 0rpx 20rpx 25rpx;
  4. // 加一个left可能会出现横向滚动条,体验不太好,可以通过margin-left来设置就不会有问题了
  5. // left: 32rpx;
  6. margin-left: 32rpx;
  7. top: -6rpx;
  8. background-color: #ffffff;
  9. }

贴的其他例子中,如果timeline-item_wrapper里边使用left来实现位置调整的,都可能有这个问题,就不在累述了,根据上面的规则调整即可

效果图2

具体的代码和样式2

  1. <template>
  2. <view class="content">
  3. <view class="describle">
  4. 参加班级、寝室第1次扫除道并上传打扫完之后的图片<span style="color:#4D9DF5">(已完成3次)</span>
  5. </view>
  6. <view class="writeContent">
  7. <textarea style="background-color: #fff;width: 100%;"></textarea>
  8. </view>
  9. <view class="timeline-list">
  10. <block v-for="(item, index) in 3" :key="index">
  11. <view class="timeline-item">
  12. <view class="timeline-item_tail"></view>
  13. <view class="timeline-item_node"></view>
  14. <view class="timeline-item_wrapper">
  15. <div>已完成《参加班级扫除道》并上传照片</div>
  16. <div class="image-content">
  17. <image class="imgitem" @click="previewImg(0)" mode="scaleToFill"
  18. src="https://fuss10.elemecdn.com/a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg"></image>
  19. <image class="imgitem" @click="previewImg(1)"
  20. src="https://fuss10.elemecdn.com/0/6f/e35ff375812e6b0020b6b4e8f9583jpeg.jpeg"></image>
  21. </div>
  22. <div class="task_time">
  23. 2023-08-30 16:53:08
  24. </div>
  25. </view>
  26. </view>
  27. </block>
  28. </view>
  29. </view>
  30. </template>
  31. <script setup lang="ts">
  32. import { ref } from 'vue'
  33. const title = ref('Hello')
  34. // import UaTimeline from '@/component/ua-timeline/ua-timeline.vue'
  35. // import UaTimelineItem from '@/component/ua-timeline-item/ua-timeline-item.vue'
  36. const previewImg = (index = 0) => {
  37. console.log("预览!")
  38. uni.previewImage({
  39. urls: ['https://fuss10.elemecdn.com/a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg', 'https://fuss10.elemecdn.com/0/6f/e35ff375812e6b0020b6b4e8f9583jpeg.jpeg', 'https://fuss10.elemecdn.com/9/bb/e27858e973f5d7d3904835f46abbdjpeg.jpeg'],
  40. current: index
  41. });
  42. }
  43. </script>
  44. <style lang="scss" scoped>
  45. .content {
  46. background: #F4F6F9;
  47. .describle {
  48. // font-size: 32rpx;
  49. margin-top: 25rpx;
  50. font-family: PingFang SC-Regular, PingFang SC;
  51. font-weight: 400;
  52. }
  53. .writeContent {
  54. margin-top: 30rpx;
  55. }
  56. .taskContent {
  57. background-color: #fff;
  58. margin-top: 30rpx;
  59. padding-top: 10px;
  60. }
  61. .image-content {
  62. margin-top: 10px;
  63. display: flex;
  64. flex-wrap: wrap;
  65. justify-content: space-between;
  66. .imgitem {
  67. flex: 0 0 32%;
  68. /* 动态计算间距 */
  69. margin-right: calc(4% / 3);
  70. // margin-bottom: calc(5% / 3);
  71. margin-bottom: 6px; // width: 124px;
  72. height: 139px;
  73. background: #F6F6F6;
  74. border-radius: 0px 0px 0px 0px;
  75. opacity: 1;
  76. }
  77. /* 去除每行尾的多余边距 */
  78. .imgitem:nth-child(3n) {
  79. margin-right: 0;
  80. }
  81. /* 使最后一个元素的边距填满剩余空间 */
  82. .imgitem:last-child {
  83. margin-right: auto;
  84. }
  85. }
  86. }
  87. </style>
  88. <!-- 时间轴样式 -->
  89. <style lang="scss" scoped>
  90. .timeline-list {
  91. margin: 32rpx;
  92. margin-top: 62rpx;
  93. font-size: 28rpx;
  94. list-style: none;
  95. }
  96. .timeline-item:last-child .timeline-item_tail {
  97. display: none;
  98. }
  99. .timeline-item {
  100. position: relative;
  101. padding-bottom: 20rpx;
  102. }
  103. .timeline-item_tail {
  104. position: absolute;
  105. left: 4rpx;
  106. height: 100%;
  107. border-left: 2rpx solid rgba(109, 209, 201, 0.3);
  108. }
  109. .timeline-item_node {
  110. position: absolute;
  111. background-color: #FFFFFF;
  112. border-radius: 50%;
  113. display: flex;
  114. justify-content: center;
  115. align-items: center;
  116. left: -12rpx;
  117. width: 22rpx;
  118. height: 22rpx;
  119. background: #fff;
  120. border: 6rpx solid #6DD1C9;
  121. }
  122. .timeline-item_wrapper {
  123. position: relative;
  124. padding: 32rpx 24rpx;
  125. left: 42rpx;
  126. top: -32rpx;
  127. background-color: #ffffff;
  128. border-radius: 20rpx;
  129. width: 600rpx;
  130. }
  131. .timeline-item_timestamp {
  132. color: #38254D;
  133. font-weight: bold;
  134. font-size: 30rpx;
  135. line-height: 32rpx;
  136. }
  137. .timeline-item_content {
  138. display: flex;
  139. flex-direction: column;
  140. margin-top: 20rpx;
  141. margin-bottom: 20rpx;
  142. text {
  143. font-size: 26rpx;
  144. color: #574966;
  145. line-height: 40rpx;
  146. }
  147. .btn {
  148. align-self: flex-end;
  149. font-size: 26rpx;
  150. color: #F06245;
  151. line-height: 60rpx;
  152. text-align: center;
  153. margin-top: -40rpx;
  154. width: 140rpx;
  155. height: 60rpx;
  156. border: 1rpx solid #F06245;
  157. border-radius: 30rpx;
  158. }
  159. }
  160. </style>

时间轴效果3(在uni-app小程序弹窗里边使用的)

效果图3

具体的代码和样式3

这里实现了图片超过一行后会自适应布局的,一行显示4张图

弹窗里边的内容

  1. <template>
  2. <view class="monthTaskDetails-container">
  3. <view class="titleWrap">
  4. <view class="title">{{ title }}</view>
  5. <view class="closeTag" @tap="handleClose">×</view>
  6. </view>
  7. <view class="splitline"></view>
  8. <scroll-view scroll-y="true" style=" height: 700rpx;">
  9. <view class="timeline-list">
  10. <block v-for="(item, index) in 3" :key="index">
  11. <view class="timeline-item">
  12. <view class="timeline-item_tail"></view>
  13. <view class="timeline-item_node"></view>
  14. <view class="timeline-item_wrapper">
  15. <div>已完成《参加班级扫除道》并上传照片</div>
  16. <view class="image-content">
  17. <image class="imgitem" @click="previewImg(0)" mode="scaleToFill"
  18. src="https://fuss10.elemecdn.com/a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg">
  19. </image>
  20. <image class="imgitem" @click="previewImg(1)"
  21. src="https://fuss10.elemecdn.com/0/6f/e35ff375812e6b0020b6b4e8f9583jpeg.jpeg">
  22. </image>
  23. <image class="imgitem" @click="previewImg(2)"
  24. src="https://fuss10.elemecdn.com/d/e6/c4d93a3805b3ce3f323f7974e6f78jpeg.jpeg">
  25. </image>
  26. <image class="imgitem" @click="previewImg(3)"
  27. src="https://fuss10.elemecdn.com/3/28/bbf893f792f03a54408b3b7a7ebf0jpeg.jpeg">
  28. </image>
  29. <image class="imgitem" @click="previewImg(4)"
  30. src="https://fuss10.elemecdn.com/2/11/6535bcfb26e4c79b48ddde44f4b6fjpeg.jpeg">
  31. </image>
  32. <image class="imgitem" @click="previewImg(5)"
  33. src="https://fuss10.elemecdn.com/9/bb/e27858e973f5d7d3904835f46abbdjpeg.jpeg">
  34. </image>
  35. </view>
  36. <view class="extraData">
  37. <view class="task_time">
  38. 2023-08-30 16:53:08
  39. </view>
  40. <image class="deleteimg" src="../../static/delete.png">
  41. </image>
  42. </view>
  43. </view>
  44. </view>
  45. </block>
  46. </view>
  47. </scroll-view>
  48. </view>
  49. </template>
  50. <script setup lang="ts">
  51. import { ref, reactive } from 'vue'
  52. const props = defineProps({
  53. title: {
  54. type: String,
  55. default: "完成人次"
  56. },
  57. userList: {
  58. type: Array,
  59. default: []
  60. }
  61. })
  62. // 触发closePopup事件
  63. const emit = defineEmits(['closePopup'])
  64. const handleClose = () => {
  65. emit('closePopup', '参数')
  66. }
  67. // 图片预览
  68. const previewImg = (index = 0) => {
  69. uni.previewImage({
  70. urls: ['https://fuss10.elemecdn.com/a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg',
  71. 'https://fuss10.elemecdn.com/0/6f/e35ff375812e6b0020b6b4e8f9583jpeg.jpeg',
  72. 'https://fuss10.elemecdn.com/d/e6/c4d93a3805b3ce3f323f7974e6f78jpeg.jpeg',
  73. 'https://fuss10.elemecdn.com/3/28/bbf893f792f03a54408b3b7a7ebf0jpeg.jpeg',
  74. 'https://fuss10.elemecdn.com/2/11/6535bcfb26e4c79b48ddde44f4b6fjpeg.jpeg',
  75. 'https://fuss10.elemecdn.com/9/bb/e27858e973f5d7d3904835f46abbdjpeg.jpeg'],
  76. current: index
  77. });
  78. }
  79. </script>
  80. <style lang="scss" scoped>
  81. .monthTaskDetails-container {
  82. height: 799rpx;
  83. background-color: #fff;
  84. border-top-left-radius: 60rpx;
  85. border-top-right-radius: 60rpx;
  86. .titleWrap {
  87. display: flex;
  88. padding-top: 22rpx;
  89. padding-left: 20rpx;
  90. padding-right: 20rpx;
  91. justify-content: center;
  92. align-items: center;
  93. /* 垂直居中 */
  94. position: relative;
  95. .title {
  96. font-family: PingFang SC, PingFang SC;
  97. font-weight: bold;
  98. font-size: 36rpx;
  99. color: #313960;
  100. }
  101. .closeTag {
  102. position: absolute;
  103. right: 16rpx;
  104. padding: 10rpx 20rpx;
  105. font-size: 50rpx;
  106. }
  107. }
  108. .splitline {
  109. margin-left: -20rpx;
  110. margin-right: -20rpx;
  111. margin-top: 30rpx;
  112. height: 1rpx;
  113. background: #f3f3f3;
  114. }
  115. .image-content {
  116. margin-top: 10px;
  117. display: flex;
  118. flex-wrap: wrap;
  119. justify-content: space-between;
  120. .imgitem {
  121. flex: 0 0 23%;
  122. /* 动态计算间距 */
  123. margin-right: calc(8% / 3);
  124. margin-bottom: 15rpx;
  125. height: 200rpx;
  126. background: #F6F6F6;
  127. border-radius: 0px 0px 0px 0px;
  128. opacity: 1;
  129. }
  130. /* 去除每行尾的多余边距 */
  131. .imgitem:nth-child(4n) {
  132. margin-right: 0;
  133. }
  134. /* 使最后一个元素的边距填满剩余空间 */
  135. .imgitem:last-child {
  136. margin-right: auto;
  137. }
  138. }
  139. .extraData {
  140. display: flex;
  141. margin-top: 10rpx;
  142. align-items: center;
  143. .task_time {
  144. font-size: 24rpx;
  145. color: #909399;
  146. }
  147. .deleteimg {
  148. width: 22rpx;
  149. height: 22rpx;
  150. margin-left: 20rpx;
  151. margin-top: -2rpx;
  152. }
  153. }
  154. }
  155. </style>
  156. <!-- 时间轴样式 -->
  157. <style lang="scss" scoped>
  158. .timeline-list {
  159. margin: 32rpx;
  160. margin-top: 62rpx;
  161. font-size: 28rpx;
  162. list-style: none;
  163. }
  164. .timeline-item:last-child .timeline-item_tail {
  165. display: none;
  166. }
  167. .timeline-item {
  168. position: relative;
  169. padding-bottom: 20rpx;
  170. }
  171. // 时间轴的竖线样式
  172. .timeline-item_tail {
  173. position: absolute;
  174. left: 2rpx;
  175. height: 100%;
  176. border-left: 2rpx solid rgba(109, 209, 201, 0.3);
  177. }
  178. .timeline-item_node {
  179. position: absolute;
  180. background-color: #FFFFFF;
  181. border-radius: 50%;
  182. display: flex;
  183. justify-content: center;
  184. align-items: center;
  185. left: -12rpx;
  186. width: 17rpx;
  187. height: 17rpx;
  188. background: #fff;
  189. border: 6rpx solid #E5E5E5;
  190. }
  191. // 时间轴的第一个圈的颜色
  192. .timeline-item:first-child {
  193. .timeline-item_node {
  194. border: 6rpx solid #4D9DF5;
  195. }
  196. }
  197. .timeline-item_wrapper {
  198. position: relative;
  199. // padding: 32rpx 24rpx;
  200. padding: 32rpx calc(8% / 3) 32rpx 24rpx;
  201. left: 26rpx;
  202. top: -39rpx;
  203. background-color: #ffffff;
  204. border-radius: 20rpx;
  205. }
  206. .timeline-item_timestamp {
  207. color: #38254D;
  208. font-weight: bold;
  209. font-size: 30rpx;
  210. line-height: 32rpx;
  211. }
  212. .timeline-item_content {
  213. display: flex;
  214. flex-direction: column;
  215. margin-top: 20rpx;
  216. margin-bottom: 20rpx;
  217. text {
  218. font-size: 26rpx;
  219. color: #574966;
  220. line-height: 40rpx;
  221. }
  222. .btn {
  223. align-self: flex-end;
  224. font-size: 26rpx;
  225. color: #F06245;
  226. line-height: 60rpx;
  227. text-align: center;
  228. margin-top: -40rpx;
  229. width: 140rpx;
  230. height: 60rpx;
  231. border: 1rpx solid #F06245;
  232. border-radius: 30rpx;
  233. }
  234. }
  235. </style>

父组件,使用弹窗的地方

  1. <template>
  2. <view class="body-view">
  3. <uni-popup ref="monthTaskDetailsPopup" background-color="#fff" border-radius="60rpx 60rpx 0rpx 0rpx;" type="bottom">
  4. <monthTaskDetails @closePopup="closeMonthTaskDetails" title="参加班级扫除道"> </monthTaskDetails>
  5. </uni-popup>
  6. </view>
  7. </template>
  8. <script setup lang="ts">
  9. import monthTaskDetails from './component/monthTaskDetails.vue'
  10. let monthTaskDetailsPopup = ref()
  11. // 打开弹窗
  12. const showMonthTaskDetails = () => {
  13. monthTaskDetailsPopup.value.open()
  14. }
  15. // 关闭弹窗
  16. const closeMonthTaskDetails = () => {
  17. monthTaskDetailsPopup.value.close()
  18. }
  19. </script>

时间轴效果4(包含grid布局实现一行显示3个文字,图文消息,参与人员与缺勤人员,悬浮菜单等)

效果图4

具体的代码和样式4

  1. <template>
  2. <view class="content">
  3. <view class="describle">
  4. {{ state.taskName }}<text>(已完成3次)</text>
  5. </view>
  6. <!-- <view v-for="(stu, index) in 50" :key="index">
  7. {{index}}
  8. </view> -->
  9. <view class="timeline-list">
  10. <template v-for="item in 3" :key="item.id">
  11. <view class="timeline-item">
  12. <view class="timeline-item_tail" />
  13. <view class="timeline-item_node" />
  14. <view class="timeline-item_wrapper">
  15. <view class="stu-name">
  16. 王佳佳
  17. </view>
  18. <view class="task-content">已完成《参加班级扫除道》并上传照片</view>
  19. <view class="image-content">
  20. <image class="imgitem" v-for="(img, index) in state.imgLists" :key="index" mode="aspectFill" :src="img" />
  21. <view class="" style="flex: 1" />
  22. </view>
  23. <view class="task-person">
  24. <view class="participant-list">
  25. <!-- 参与人员 -->
  26. <view class="p-item" v-for="(stu, index) in 15" :key="index">
  27. <view class="tp-stu">小明{{ index }}:</view>
  28. <view class="tp-status">参与</view>
  29. </view>
  30. <!-- 缺勤人员 -->
  31. <view class="p-item" v-for="(stu, index) in 5" :key="index">
  32. <view class="tp-stu">小红{{ index }}:</view>
  33. <view class="tp-status-absence">缺勤</view>
  34. </view>
  35. </view>
  36. </view>
  37. <view class="task_time">
  38. 2024-7-24 12:30
  39. <!-- <text class="task-reject">删除</text> -->
  40. </view>
  41. </view>
  42. </view>
  43. </template>
  44. </view>
  45. <view class="task-complate-to"></view>
  46. </view>
  47. </template>
  48. <script setup lang="ts">
  49. import { ref, reactive } from 'vue'
  50. import { onLoad, onShow } from '@dcloudio/uni-app'
  51. import http from '@/common/request.ts'
  52. import config from '@/common/config.ts'
  53. import dayjs from 'dayjs'
  54. const state = reactive({
  55. taskName: '参加早迎接活动',
  56. imgLists: ['https://fuss10.elemecdn.com/a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg',
  57. 'https://fuss10.elemecdn.com/0/6f/e35ff375812e6b0020b6b4e8f9583jpeg.jpeg',
  58. 'https://fuss10.elemecdn.com/d/e6/c4d93a3805b3ce3f323f7974e6f78jpeg.jpeg',
  59. 'https://fuss10.elemecdn.com/3/28/bbf893f792f03a54408b3b7a7ebf0jpeg.jpeg',
  60. 'https://fuss10.elemecdn.com/2/11/6535bcfb26e4c79b48ddde44f4b6fjpeg.jpeg',
  61. 'https://fuss10.elemecdn.com/9/bb/e27858e973f5d7d3904835f46abbdjpeg.jpeg']
  62. })
  63. </script>
  64. <style lang="scss" scoped>
  65. .content {
  66. background: #f4f6f9;
  67. .describle {
  68. padding: 20rpx;
  69. font-weight: 400;
  70. font-size: 30rpx;
  71. color: #313960;
  72. border-top: 4rpx solid #ededed;
  73. text {
  74. margin-left: 20rpx;
  75. color: #4d9df5;
  76. font-size: 24rpx;
  77. }
  78. }
  79. .image-content {
  80. margin-top: 20rpx;
  81. display: flex;
  82. flex-wrap: wrap;
  83. // justify-content: space-between;
  84. .imgitem {
  85. width: 31%;
  86. /* 动态计算间距 */
  87. margin-right: calc(7% / 2);
  88. // margin-bottom: calc(5% / 3);
  89. margin-bottom: 20rpx;
  90. // height: width;
  91. height: 199rpx;
  92. background: #f6f6f6;
  93. border-radius: 0px 0px 0px 0px;
  94. opacity: 1;
  95. }
  96. /* 去除每行尾的多余边距 */
  97. .imgitem:nth-child(3n) {
  98. margin-right: 0px;
  99. }
  100. /* 使最后一个元素的边距填满剩余空间 */
  101. .imgitem:last-child {
  102. margin-right: auto;
  103. }
  104. }
  105. .task-complate-to {
  106. width: 108rpx;
  107. height: 108rpx;
  108. background: linear-gradient(180deg, #4d9df5 0%, #63cfff 100%);
  109. box-shadow: 0px 4rpx 10rpx 1rpx rgba(77, 157, 245, 0.32);
  110. border-radius: 50%;
  111. position: fixed;
  112. bottom: 102rpx;
  113. right: 30rpx;
  114. }
  115. .task-complate-to::before {
  116. content: ' ';
  117. width: 56rpx;
  118. border-bottom: 4rpx solid #ffffff;
  119. position: absolute;
  120. left: calc(50% - 28rpx);
  121. top: calc(50% - 2rpx);
  122. }
  123. .task-complate-to::after {
  124. content: ' ';
  125. height: 56rpx;
  126. border-right: 4rpx solid #ffffff;
  127. position: absolute;
  128. left: calc(50% - 2rpx);
  129. top: calc(50% - 28rpx);
  130. }
  131. }
  132. </style>
  133. <style lang="scss" scoped>
  134. .timeline-list {
  135. font-size: 28rpx;
  136. list-style: none;
  137. padding: 30rpx 30rpx 20rpx 30rpx;
  138. padding-bottom: 0;
  139. background-color: #ffffff;
  140. }
  141. .timeline-item:last-child .timeline-item_tail {
  142. display: none;
  143. }
  144. .timeline-item {
  145. position: relative;
  146. // padding-bottom: 20rpx;
  147. .timeline-item_tail {
  148. position: absolute;
  149. left: 6rpx;
  150. top: 0;
  151. bottom: 0;
  152. border-left: 2rpx solid rgba(109, 209, 201, 0.3);
  153. }
  154. .timeline-item_node {
  155. position: absolute;
  156. background-color: #ffffff;
  157. border-radius: 50%;
  158. display: flex;
  159. justify-content: center;
  160. align-items: center;
  161. left: -9rpx;
  162. width: 18rpx;
  163. height: 18rpx;
  164. background: #fff;
  165. border: 6rpx solid #6dd1c9;
  166. }
  167. .timeline-item_wrapper {
  168. position: relative;
  169. padding: 0rpx 0rpx 20rpx 25rpx;
  170. // 加一个left可能会出现横向滚动条,体验不太好,可以通过margin-left来设置就不会有问题了
  171. // left: 32rpx;
  172. margin-left: 32rpx;
  173. top: -6rpx;
  174. background-color: #ffffff;
  175. // margin-left: 42rpx;
  176. // border-radius: 20rpx;
  177. // width: 600rpx;
  178. .stu-name {
  179. font-size: 30rpx;
  180. font-weight: bold;
  181. color: #174a90;
  182. margin-bottom: 10rpx;
  183. }
  184. .task-content {
  185. color: #313960;
  186. font-size: 30rpx;
  187. font-weight: 400;
  188. }
  189. .task-person {
  190. margin-top: 20rpx;
  191. font-size: 24rpx;
  192. .p-item {
  193. display: flex;
  194. margin-bottom: 22rpx;
  195. .tp-stu {
  196. color: #313960;
  197. }
  198. }
  199. .participant-list {
  200. display: grid;
  201. /*每行显示四个,宽度由内容自适应*/
  202. grid-template-columns: repeat(3, auto);
  203. /*显示方式为左右无间距,中间均分*/
  204. justify-content: space-between;
  205. grid-column-gap: 19rpx;
  206. }
  207. .participant-list {
  208. .tp-status {
  209. color: #67c23a;
  210. background: #f0f9eb;
  211. border-radius: 4rpx;
  212. padding: 0 10rpx;
  213. }
  214. .tp-status-absence {
  215. color: #f56c6c;
  216. background: #fef0f0;
  217. border-radius: 4rpx;
  218. padding: 0 10rpx;
  219. }
  220. }
  221. }
  222. .task_time {
  223. margin-top: 4rpx;
  224. margin-bottom: 40rpx;
  225. color: #909399;
  226. font-size: 24rpx;
  227. .task-reject {
  228. color: #f56c6c;
  229. font-size: 24rpx;
  230. margin-left: 20rpx;
  231. }
  232. }
  233. }
  234. }
  235. </style>

包含vue绑定数据的也贴一下吧

上面那个是静态的可以直接复制进去看效果的,这个加了一点数据绑定解析的

  1. <template>
  2. <view class="content">
  3. <view class="describle">
  4. {{ state.taskName }}<text>(已完成{{ state.dataList.length }}次)</text>
  5. </view>
  6. <view class="timeline-list">
  7. <template v-for="(item, findex) in state.dataList" :key="findex">
  8. <view class="timeline-item">
  9. <view class="timeline-item_tail" />
  10. <view class="timeline-item_node" />
  11. <view class="timeline-item_wrapper">
  12. <view class="stu-name">
  13. 王佳佳
  14. </view>
  15. <view class="task-content">{{ item.comment }}</view>
  16. <view class="image-content">
  17. <image class="imgitem" v-for="(img, index) in JSON.parse(item.imgJson)" :key="index" mode="aspectFill"
  18. :src="GetImgUrl(img)" @tap="previewImg(item.imgJson, index)" />
  19. <view class="" style="flex: 1" />
  20. </view>
  21. <view class="task-person">
  22. <view class="participant-list">
  23. <!-- 参与人员 -->
  24. <view class="p-item" v-for="(stu, index) in item.groupUsers" :key="index">
  25. <view class="tp-stu">{{ stu }}:</view>
  26. <view class="tp-status">参与</view>
  27. </view>
  28. <!-- 缺勤人员 -->
  29. <view class="p-item" v-for="(stu, index) in item.noGroupUsers" :key="index">
  30. <view class="tp-stu">{{ stu }}:</view>
  31. <view class="tp-status-absence">缺勤</view>
  32. </view>
  33. </view>
  34. </view>
  35. <view class="task_time">
  36. {{dayjs(item.completeDateTime).format('YYYY-MM-DD HH:mm:ss')}}
  37. <!-- <text class="task-reject">删除</text> -->
  38. </view>
  39. </view>
  40. </view>
  41. </template>
  42. </view>
  43. <view class="task-complate-to" v-if="false"></view>
  44. </view>
  45. </template>
  46. <script setup lang="ts">
  47. import { ref, reactive } from 'vue'
  48. import { onLoad, onShow } from '@dcloudio/uni-app'
  49. import http from '@/common/request.ts'
  50. import config from '@/common/config.ts'
  51. import dayjs from 'dayjs'
  52. import { GetImgUrl } from '@/common/utils.ts'
  53. const state = reactive({
  54. taskName: '参加早迎接活动',
  55. dataList: [] as any
  56. })
  57. onLoad((e) => {
  58. state.taskName = e?.taskName
  59. // 设置页面标题
  60. if (e?.taskName && e?.taskName.length < 18) {
  61. uni.setNavigationBarTitle({
  62. title: e?.taskName
  63. });
  64. }
  65. uni.getStorage({
  66. key: 'studentCompleteDetails',
  67. success: function (res) {
  68. state.dataList = res.data
  69. console.log("跳转过来获得的数据", res.data);
  70. }
  71. });
  72. })
  73. // 图片预览
  74. const previewImg = (imgListJson: any, index = 0) => {
  75. let imgIdList = JSON.parse(imgListJson)
  76. let imgList = [] as any
  77. // 根据图片id获取图片的浏览地址
  78. for (let index = 0; index < imgIdList.length; index++) {
  79. const element = imgIdList[index];
  80. imgList.push(GetImgUrl(element))
  81. }
  82. uni.previewImage({
  83. urls: imgList,
  84. current: index
  85. });
  86. }
  87. </script>
  88. <style lang="scss" scoped>
  89. .content {
  90. background: #f4f6f9;
  91. .describle {
  92. padding: 20rpx;
  93. font-weight: 400;
  94. font-size: 30rpx;
  95. color: #313960;
  96. border-top: 4rpx solid #ededed;
  97. text {
  98. margin-left: 20rpx;
  99. color: #4d9df5;
  100. // font-size: 24rpx;
  101. }
  102. }
  103. .image-content {
  104. margin-top: 20rpx;
  105. display: flex;
  106. flex-wrap: wrap;
  107. // justify-content: space-between;
  108. .imgitem {
  109. width: 31%;
  110. /* 动态计算间距 */
  111. margin-right: calc(7% / 2);
  112. // margin-bottom: calc(5% / 3);
  113. margin-bottom: 20rpx;
  114. // height: width;
  115. height: 199rpx;
  116. background: #f6f6f6;
  117. border-radius: 0px 0px 0px 0px;
  118. opacity: 1;
  119. }
  120. /* 去除每行尾的多余边距 */
  121. .imgitem:nth-child(3n) {
  122. margin-right: 0px;
  123. }
  124. /* 使最后一个元素的边距填满剩余空间 */
  125. .imgitem:last-child {
  126. margin-right: auto;
  127. }
  128. }
  129. .task-complate-to {
  130. width: 108rpx;
  131. height: 108rpx;
  132. background: linear-gradient(180deg, #4d9df5 0%, #63cfff 100%);
  133. box-shadow: 0px 4rpx 10rpx 1rpx rgba(77, 157, 245, 0.32);
  134. border-radius: 50%;
  135. position: fixed;
  136. bottom: 102rpx;
  137. right: 30rpx;
  138. }
  139. .task-complate-to::before {
  140. content: ' ';
  141. width: 56rpx;
  142. border-bottom: 4rpx solid #ffffff;
  143. position: absolute;
  144. left: calc(50% - 28rpx);
  145. top: calc(50% - 2rpx);
  146. }
  147. .task-complate-to::after {
  148. content: ' ';
  149. height: 56rpx;
  150. border-right: 4rpx solid #ffffff;
  151. position: absolute;
  152. left: calc(50% - 2rpx);
  153. top: calc(50% - 28rpx);
  154. }
  155. }
  156. </style>
  157. <style lang="scss" scoped>
  158. .timeline-list {
  159. font-size: 28rpx;
  160. list-style: none;
  161. padding: 30rpx 30rpx 20rpx 30rpx;
  162. padding-bottom: 0;
  163. background-color: #ffffff;
  164. }
  165. .timeline-item:last-child .timeline-item_tail {
  166. display: none;
  167. }
  168. .timeline-item {
  169. position: relative;
  170. // padding-bottom: 20rpx;
  171. .timeline-item_tail {
  172. position: absolute;
  173. left: 6rpx;
  174. top: 0;
  175. bottom: 0;
  176. border-left: 2rpx solid rgba(109, 209, 201, 0.3);
  177. }
  178. .timeline-item_node {
  179. position: absolute;
  180. background-color: #ffffff;
  181. border-radius: 50%;
  182. display: flex;
  183. justify-content: center;
  184. align-items: center;
  185. left: -9rpx;
  186. width: 18rpx;
  187. height: 18rpx;
  188. background: #fff;
  189. border: 6rpx solid #6dd1c9;
  190. }
  191. .timeline-item_wrapper {
  192. position: relative;
  193. padding: 0rpx 0rpx 20rpx 25rpx;
  194. // 加一个left可能会出现横向滚动条,体验不太好,可以通过margin-left来设置就不会有问题了
  195. // left: 32rpx;
  196. margin-left: 32rpx;
  197. top: -6rpx;
  198. background-color: #ffffff;
  199. // margin-left: 42rpx;
  200. // border-radius: 20rpx;
  201. // width: 600rpx;
  202. .stu-name {
  203. font-size: 30rpx;
  204. font-weight: bold;
  205. color: #174a90;
  206. margin-bottom: 10rpx;
  207. }
  208. .task-content {
  209. color: #313960;
  210. font-size: 30rpx;
  211. font-weight: 400;
  212. }
  213. .task-person {
  214. margin-top: 20rpx;
  215. font-size: 24rpx;
  216. .p-item {
  217. display: flex;
  218. margin-bottom: 22rpx;
  219. .tp-stu {
  220. color: #313960;
  221. }
  222. }
  223. .participant-list {
  224. display: grid;
  225. /*每行显示四个,宽度由内容自适应*/
  226. grid-template-columns: repeat(3, auto);
  227. /*显示方式为左右无间距,中间均分*/
  228. justify-content: space-between;
  229. grid-column-gap: 19rpx;
  230. }
  231. .participant-list {
  232. .tp-status {
  233. color: #67c23a;
  234. background: #f0f9eb;
  235. border-radius: 4rpx;
  236. padding: 0 10rpx;
  237. }
  238. .tp-status-absence {
  239. color: #f56c6c;
  240. background: #fef0f0;
  241. border-radius: 4rpx;
  242. padding: 0 10rpx;
  243. }
  244. }
  245. }
  246. .task_time {
  247. margin-top: 4rpx;
  248. margin-bottom: 40rpx;
  249. color: #909399;
  250. font-size: 24rpx;
  251. .task-reject {
  252. color: #f56c6c;
  253. font-size: 24rpx;
  254. margin-left: 20rpx;
  255. }
  256. }
  257. }
  258. }
  259. </style>

备注


具体的页面模板以及更多模板存储在云盘里边


欢迎加群讨论技术,1群:677373950(满了,可以加,但通过不了),2群:656732739。有需要软件开发,或者学习软件技术的朋友可以和我联系~(Q:815170684)

评价

导出SQL脚本小程序

usingSystem; usingSystem.Collections.Generic; usingSystem.Linq; usingSystem.Text; usingSystem.Threading.Tasks; ...

微信小程序学习笔记

小程序是什么?小程序是一种不需要下载安装即可使用的应用,它实现了应用“触手可及”的梦想,用户扫一扫或者搜一下即可打...

小程序城市列表实现

小程序城市列表实现实现城市列表选择准备地址数据citydata.jsmodule.exports={ &quot;city&quot;:[ { &quot;title&quot;...

微信扫码---进入小程序指定页面(传参)

使用场景:商场的游戏机,用微信扫码获取机器id,进入到小程序指定页面,进行下单购买。微信公众平台中开发——开发设置—...

小程序html解析如:后台添加的文章详情

项目中遇到在微信小程序里需要显示音乐文章的内容,文章内容是通过接口读取的服 务器中的富文本内容,是html格式的,小程序...

微信小程序canvas的使用

画布。2.9.0 起支持一套新 Canvas 2D 接口(需指定 type 属性),同时支持同层渲染。Canvas 2D 示例代码html:&lt;canvastyp...

微信小程序设置页面导航条颜色

使用wx.setNavigationBarColor(Object object)即可参考代码:wx.setNavigationBarColor({ frontColor:&#39;#ffffff&#39;, ...

uni-app页面跳转与传值uni-app 小程序 本地存储传值的编码与解码传递中文参数

注意跳转的目标页面需要在page.json中申明哦,不然无法跳转哦,应该跳转的目标地址是一个页面,所以需要定义uni-app中页面...

小程序滚动浮窗案例

onPageScroll:function(e){var that=this;if (this.scrollEndTimer) {clearTimeout(this.scrollEndTimer);this.scrollEndTi...

uin小程序滚动浮窗案例

perfToX(){//悬浮按钮向右滑动 this.animation=uni.createAnimation({duration:300,timingFunction:&#39;ease&#39;}) thi...

uni-app弹窗小程序弹出层自定义组件弹窗解决滚动穿透

官方文档:https://uniapp.dcloud.net.cn/component/uniui/uni-popup.html [TOC]最简单的弹出一句话:需要什么东西在内容...

微信小程序发送验证码

先在js中定义方法post()的部分引入写好api开始引入js的方法获取验证码绑定async getUserBind() { var _this=this; if...

uni-app 微信小程序 上传图片文件uniappuni-file-picker 和数据一起上传图片上传图片的时候携带数据多图上传

[TOC]uni-app中上传图片可以使用方法uni.uploadFileuni.uploadFile官方文档:https://uniapp.dcloud.net.cn/api/request/ne...

uni-app 微信小程序 实现图片预览

基本用法:在uniapp中,我们可以使用uni.previewImage()API对图片进行预览,具体使用方法如下: uni.previewImage({ ur...

uni-app 怎么编译到微信开发者工具运行到微信小程序

在uni-app中填写自己的微信小程序的 AppID在manifest.json中找到微信小程序配置,填写好AppId 在 HBuilderX 中,配置“...

uni-app 组件编译到微信小程序后没有样式文件wxss

组件编译到微信小程序没有生成WXSS文件,H5与APP可以正常显示,小程序不行! 解决:不需要引用,去除页面中的import这一引...