messageList.vue 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. <template>
  2. <view class="msg_list_content">
  3. <uni-collapse>
  4. <uni-collapse-item title-border="show" :border="true" :show-animation="anime" :open="open">
  5. <template v-slot:title>
  6. <uni-section :title="title" type="line" titleFontSize="1.3rem">
  7. <template v-slot:right>
  8. <uni-badge :text="unReadNum" style="margin-right: 6rem;" v-if="unReadNum!==undefined&&unReadNum>0"></uni-badge>
  9. <button @click.stop="clickReadButton" class="read_button" v-if="unReadNum!==undefined" :disabled="unReadNum===0?true:false">一键阅读</button>
  10. </template>
  11. </uni-section>
  12. </template>
  13. <View style="height: 69.5vh;">
  14. <z-paging :fixed="false" @query="queryData" :value="list" :default-page-size="pSize"
  15. :default-page-no="pageNo" ref="paging">
  16. <template #top>
  17. <view v-if="props.segments" class="segmented_control_container">
  18. <uni-segmented-control :current="current" :values="segmentKeys" @clickItem="onClickItem"
  19. styleType="text" activeColor="#409eff"></uni-segmented-control>
  20. </view>
  21. </template>
  22. <view @click="handleToDetail(message)" v-for="(message, index) in list" :key="index"
  23. :class="message.isread == 'Y' || message.if_read ? ' ' : 'message_container_unread'"
  24. class="message_container">
  25. <uni-card :is-full="true" padding="5px 10px">
  26. <template v-slot:title>
  27. <uni-row>
  28. <view class="message_top_container">
  29. <text class="message_user">
  30. {{ message.name }}
  31. </text>
  32. </view>
  33. </uni-row>
  34. <uni-row>
  35. <view class="message_mid_container">
  36. <uni-col :xs="18" :sm="20">
  37. <view class="message_title hidden_over">
  38. {{ message.title }}
  39. </view>
  40. </uni-col>
  41. <uni-col :xs="6" :sm="4">
  42. <view class="message_time">
  43. {{ formatDate(message.sendtime) }}
  44. </view>
  45. </uni-col>
  46. </view>
  47. </uni-row>
  48. </template>
  49. <view v-if="message.content" class="message_bottom_container">
  50. <text class="message_content hidden_over">
  51. {{ message.content }}
  52. </text>
  53. </view>
  54. </uni-card>
  55. </view>
  56. </z-paging>
  57. </View>
  58. </uni-collapse-item>
  59. </uni-collapse>
  60. </view>
  61. </template>
  62. <script setup lang="ts">
  63. import { onMounted, ref } from 'vue';
  64. const props = defineProps({
  65. anime: { type: Boolean, default: false }, // 是否开启动画
  66. open: { type: Boolean, default: false }, // 是否默认打开
  67. title: { type: String, required: true }, // 标题
  68. segments: { type: Array, default: undefined }, // 分段器数据
  69. // list: { type: Array, required: true }, // 消息数据
  70. pSize: { type: Number, default: 10 }, // 分页大小
  71. pageNo: { type: Number, default: 1 }, // 默认页
  72. defaultCurrent: {type: Number, default: 0}, // 默认选中项
  73. unReadNum: { type: Number, default: undefined }, // 未读消息数
  74. })
  75. const emits = defineEmits([
  76. 'clickSegment', // 点击分段器
  77. 'clickItem', // 点击内容项
  78. 'scrollToBottom', // 到达底部
  79. 'readMsg',//消息已读
  80. ])
  81. // 分段器 键值
  82. const segmentKeys = ref({})
  83. const segmentValues = ref({})
  84. onMounted(() => {
  85. if (props.segments !== undefined) {
  86. segmentKeys.value = Object.keys(props.segments)
  87. segmentValues.value = Object.values(props.segments)
  88. }
  89. })
  90. function clickReadButton() {
  91. console.log('clickReadButton');
  92. emits('readMsg')
  93. }
  94. const paging = ref(null)
  95. const totalPage=ref(0)
  96. // 数据列表
  97. const list = ref([])
  98. // 加载完成 更新数据
  99. function complete(dataList, total, pageNo) {
  100. totalPage.value = Math.ceil(total / props.pSize)
  101. if (pageNo <= totalPage.value) {
  102. list.value.push(...dataList);
  103. }
  104. // 第一页直接加载数据
  105. if (pageNo === 1) {
  106. list.value=dataList
  107. paging.value.complete(dataList)
  108. return
  109. }
  110. // 防止重复获取最后一次信息
  111. if (props.pSize*pageNo < total) {
  112. paging.value.complete(dataList)
  113. } else {
  114. paging.value.complete([])
  115. }
  116. }
  117. function reload() {
  118. paging.value.reload()
  119. }
  120. // 点击分段器
  121. const current = ref(props.defaultCurrent)
  122. function onClickItem({ currentIndex }) {
  123. current.value = currentIndex
  124. // 重新加载数据 pageNo恢复为默认值
  125. reload();
  126. }
  127. // 刷新
  128. function queryData(pageNo, pSize, queryType) {
  129. switch (queryType) {
  130. case 0: // 下拉刷新
  131. case 1: // 初始加载
  132. reloadData()
  133. break
  134. case 3: // 上拉加载
  135. scrollQuery(pageNo, pSize)
  136. break
  137. default: // 默认刷新
  138. reloadData()
  139. break
  140. }
  141. }
  142. // 刷新数据
  143. function reloadData() {
  144. const params = {
  145. pSize: props.pSize,
  146. pageNo: props.pageNo,
  147. type: '',
  148. segmentValue: segmentValues.value[current.value]
  149. }
  150. emits('clickSegment', params, complete)
  151. }
  152. // 上拉加载
  153. function scrollQuery(pageNo, pSize) {
  154. const params = {
  155. pSize,
  156. pageNo,
  157. type: '',
  158. segmentValue: segmentValues.value[current.value]
  159. }
  160. emits('scrollToBottom', params, complete)
  161. }
  162. // 跳转详情
  163. function handleToDetail(message) {
  164. emits('clickItem', message)
  165. }
  166. // 格式化时间
  167. function formatDate(now) {
  168. const [date, time] = now.split(" ")
  169. if (isInTimeRange(now)) {
  170. return time
  171. } else {
  172. return date
  173. }
  174. }
  175. //判断时间是否在今天内
  176. function isInTimeRange(inputDate) {
  177. const inputTime = new Date(inputDate).getTime();
  178. // 获取当前时间戳
  179. const now = new Date();
  180. const year = now.getFullYear();
  181. const month = now.getMonth();
  182. const day = now.getDate();
  183. // 构建当天的起始时间和结束时间的时间戳
  184. const startTime = new Date(year, month, day, 0, 0, 0).getTime();
  185. const endTime = new Date(year, month, day, 23, 59, 59).getTime();
  186. // 判断当前时间是否在范围内
  187. return inputTime >= startTime && inputTime <= endTime;
  188. }
  189. defineExpose({
  190. reload,
  191. });
  192. </script>
  193. <style lang="scss">
  194. .hidden_over {
  195. white-space: nowrap; // 不换行
  196. overflow: hidden; // 超出内容隐藏
  197. text-overflow: ellipsis; // 超出部分显示省略号
  198. display: inline-block;
  199. max-width: 100%;
  200. }
  201. .msg_list_content {
  202. .read_button {
  203. position: absolute;
  204. top: 12px;
  205. right: 10px;
  206. height: 28px;
  207. line-height: 28px;
  208. font-size: 14px;
  209. background-color: #007aff;
  210. color: #fff;
  211. }
  212. .read_button[disabled] {
  213. background-color: #f5f5f5;
  214. color: #666;
  215. opacity: 0.5;
  216. }
  217. .message_container {
  218. border-left: #7b7b7b .4rem solid;
  219. .message_top_container {
  220. padding: 10px 10px 10px;
  221. .message_user {
  222. color: #333;
  223. font-size: 0.875rem;
  224. }
  225. }
  226. .message_mid_container {
  227. // padding-top: 10px;
  228. padding-left: 10px;
  229. height: 1.8rem;
  230. .message_title {
  231. font-size: 1.1rem;
  232. color: #333;
  233. }
  234. .message_time {
  235. color: #888;
  236. text-align: right;
  237. font-size: 0.8rem;
  238. line-height: 1.8rem;
  239. }
  240. }
  241. .message_bottom_container {
  242. .message_content {
  243. font-size: 1rem;
  244. color: #666;
  245. }
  246. }
  247. }
  248. .message_container_unread {
  249. // 未读样式
  250. border-left-color: #0f6cbd;
  251. .message_top_container {
  252. .message_user {
  253. font-weight: bold;
  254. }
  255. }
  256. .message_mid_container {
  257. .message_title {
  258. color: #0f6cbd;
  259. font-weight: bold;
  260. }
  261. }
  262. }
  263. }
  264. </style>