speList.vue 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. <template>
  2. <view class="spe-list-item" @click="handleClick">
  3. <!-- 左侧搜索图标 -->
  4. <!-- <up-icon name="search" size="50rpx" color="#ccc" class="search-icon" /> -->
  5. <img class="w-34 h-34 search-icon" src="https://ta.zycpzs.cn/oss-file/smart-trace/szyy/images-plt/plant/searchGrey.png" mode="widthFix" alt="" />
  6. <!-- 中间文本区域(间隔30rpx) -->
  7. <view class="text-container">
  8. <!-- 使用 view + text 显示高亮文本 -->
  9. <view class="text-content">
  10. <text v-for="(part, index) in textParts" :key="index" :style="part.isHighlight ? highlightStyle : {}">
  11. {{ part.text }}
  12. </text>
  13. </view>
  14. </view>
  15. <!-- 右侧勾选图标(根据check状态显示) -->
  16. <!-- <up-icon v-if="check" name="checkmark" size="45rpx" color="#37A954" class="check-icon" /> -->
  17. <img v-if="check === '1'" class="w-30 h-30" src="https://ta.zycpzs.cn/oss-file/smart-trace/szyy/images-plt/plant/chooseSuccessfully.png" mode="widthFix" alt="" />
  18. </view>
  19. </template>
  20. <script setup lang="ts">
  21. import { computed } from 'vue';
  22. const props = defineProps({
  23. // 显示的完整文本
  24. text: {
  25. type: String,
  26. required: true,
  27. },
  28. // 搜索文本,用于高亮匹配部分
  29. searchText: {
  30. type: String,
  31. default: '',
  32. },
  33. // 高亮颜色
  34. highlightColor: {
  35. type: String,
  36. default: '#37A954',
  37. },
  38. // 是否选中状态(字符串格式:0-未选中,1-选中)
  39. check: {
  40. type: String,
  41. default: '0',
  42. },
  43. });
  44. const emit = defineEmits<{
  45. // 更新check状态的事件
  46. 'update:check': [check: string];
  47. // 点击事件
  48. click: [];
  49. }>();
  50. // 高亮样式
  51. const highlightStyle = computed(() => ({
  52. color: props.highlightColor,
  53. fontWeight: 'bold',
  54. }));
  55. // 将文本分割为高亮和非高亮部分
  56. const textParts = computed(() => {
  57. if (!props.searchText || !props.text) {
  58. return [{ text: props.text || '', isHighlight: false }];
  59. }
  60. // 创建正则表达式进行匹配(不区分大小写)
  61. const regex = new RegExp(`(${props.searchText.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi');
  62. const parts = props.text.split(regex);
  63. // 过滤空字符串并标记高亮部分
  64. return parts
  65. .filter((part) => part !== '')
  66. .map((part) => ({
  67. text: part,
  68. isHighlight: part.toLowerCase() === props.searchText.toLowerCase(),
  69. }));
  70. });
  71. // 处理点击事件
  72. const handleClick = () => {
  73. const newValue = props.check === '1' ? '0' : '1';
  74. emit('update:check', newValue);
  75. emit('click');
  76. };
  77. </script>
  78. <style lang="scss" scoped>
  79. .spe-list-item {
  80. display: flex;
  81. align-items: center;
  82. padding: 20rpx 24rpx;
  83. background-color: #fff;
  84. margin-bottom: 16rpx;
  85. transition: all 0.2s ease;
  86. }
  87. .search-icon {
  88. flex-shrink: 0;
  89. margin-right: 25rpx;
  90. }
  91. .text-container {
  92. flex: 1;
  93. overflow: hidden;
  94. }
  95. .text-content {
  96. font-size: 28rpx;
  97. color: #333;
  98. line-height: 1.5;
  99. display: flex;
  100. flex-wrap: wrap;
  101. }
  102. .check-icon {
  103. flex-shrink: 0;
  104. margin-left: 20rpx;
  105. }
  106. .search_icon {
  107. width: 38rpx;
  108. height: 38rpx;
  109. }
  110. </style>