uniapp使用记录(二)--内置组件、引入echarts、组件样式不协调问题、使用uview-plus组件库、使用(自定义)table表格、修改组件样式

265 阅读5分钟

第一次尝试写作,开始记录自己的学习笔记和实习心得,加油!

1. 各类组件的使用

1.1 下拉框uni-data-select

下拉的数据是maojrList数组,要符合官方规定的格式,不然显示不出来。 如下格式valuetext

 range: [
        { value: 0, text: "篮球" },
        { value: 1, text: "足球" },
        { value: 2, text: "游泳" },
        ]
<uni-data-select v-model="myInfo.MajIdTag" :localdata="maojrList"
style="width:400rpx"></uni-data-select>

后续更新:

label 用来显示, key 为值,使用 map 映射为:

<uni-data-checkbox :localdata="localdata" :map="{text:'label',value:'key'}"></uni-data-checkbox >

如上,代码为: 将 text 属性映射到 原json的 label 属性上,将 value 属性映射到原json 的 key属性上

1.2 分段器uni-segmented-control

分段器样式类型,可选值:button(按钮类型),text(文字类型) 不同的类型对应的样式如下:

image.png

<template>
    <view>
        <uni-segmented-control :current="current" :values="items" @clickItem="onClickItem" styleType="button" activeColor="#4cd964"></uni-segmented-control>
        <view class="content">
            <view v-show="current === 0">
                选项卡1的内容
            </view>
            <view v-show="current === 1">
                选项卡2的内容
            </view>
            <view v-show="current === 2">
                选项卡3的内容
            </view>
        </view>
    </view>
</template>
<script>
export default {
  data() {
    return {
        ...
        items: ['选项1', '选项2', '选项3'],
        current: 0
    };
  },
  
  methods: {
    ...
    onClickItem(e) {
      if (this.current != e.currentIndex) {
        this.current = e.currentIndex;
      }
    }
  }
};
</script>

1.3  scroll-view用法

讲一下常用的几个

@scroll  滚动时触发

 @scrolltoupper 滚动到顶部或左边,会触发 scrolltoupper 事件 @scrolltolower   滚动到底部或右边,会触发 scrolltolower 事件

1.纵向滚动

设置scroll-y="true"  开启纵向滚动功能

<view>
<scroll-view :scroll-top="scrollTop" 
scroll-y="true" class="scroll-Y"
@scrolltoupper="upper"	
@scrolltolower="lower" @scroll="scroll">
<view id="demo1" class="scroll-view-item uni-bg-red">A</view>
<view id="demo2" class="scroll-view-item uni-bg-green">B</view>
<view id="demo3" class="scroll-view-item uni-bg-blue">C</view>
</scroll-view>
	</view>

2.横向滚动

设置scroll-x="true"  开启横向滚动功能

<view>
		<scroll-view :scroll-top="scrollTop" scroll-x="true" class="scroll-Y" 
				 @scrolltoupper="upper"	@scrolltolower="lower" @scroll="scroll">
					<view id="demo1" class="scroll-view-item uni-bg-red">A</view>
					<view id="demo2" class="scroll-view-item uni-bg-green">B</view>
					<view id="demo3" class="scroll-view-item uni-bg-blue">C</view>
				</scroll-view>
	</view>

注意:scroll-view本身的display:flex不生效、如果想实现display:flex功能,则可以给scroll-view加上white-space: nowrap,给内容容器加上display:inline-block

image.png

3.触底事件

@scrolltolower 滚动到底部或右边,会触发 scrolltolower 事件

<template>
	<view>
		<scroll-view  scroll-y="true" style="height: 500rpx;" @scrolltolower="onReachScollBottom">
		
		</scroll-view>
	</view>
</template>
<script>
	export default {
		data() {
			return {
			
			}
		},
		methods: {
			onReachScollBottom(){
				uni.showToast({
					title:"触发了触底事件",
					duration:1500,
					icon:"none"
				})
			}
		}
	}
</script>
 
<style>
 
</style>

4.下拉刷新 refresher-enabled = "true" 开启自定义下拉刷新

refresher-triggered ="true" 设置当前下拉刷新状态,true 表示下拉刷新已经被触发,false 表示下 拉刷新未被触发

@refresherrefresh 自定义下拉刷新被触发

 
<template>
	<view>
		<scroll-view scroll-y="true" style="height: 500rpx;" refresher-enabled="true" :refresher-triggered="refresh" @refresherrefresh="onRefresh">
		
		</scroll-view>
	</view>
</template>
 
 
<script>
	export default {
		data() {
			return {
				colorList:["blue","red","yellow"],
				refresh: false
			}
		},
		methods: {
			onRefresh() {
				this.refresh= true;
				uni.showToast({
					title:"触发了下拉刷新",
					duration:1500,
					icon:"none"
				})
				// 这里不能直接让refresh直接为false,否则可能会发生下拉加载无法复位的情况
				setTimeout(() => {
					this.refresh = false;
				}, 500)
			}
		}
	}
</script>
 

1.4 uni-app中 lin-select下拉菜单

参考地址

2. uniapp中使用echarts

首先给出地址,可以直接去插件市场下载插件

2.1 第一步 下载插件:

image.png

image.png

然后安装到uniapp对应的项目就可以。

2.2 第二步 在项目中安装echarts:

npm install echarts

然后在文件中直接使用即可

uniapp+vue3,折线图完整代码如下:(慢慢看,终将有所收获)

<template>
	<view class="echarts-container">
		<view style="width:680rpx; height:360rpx">
                <l-echart ref="chartRef"></l-echart>
            </view>
	</view>
</template>

<script setup>
	import * as echarts from 'echarts' // 引入ECharts库
	import {onBeforeUnmount,ref,onMounted} from 'vue'
	// echarts实例
	const chartRef = ref(null)
	const option = {
		title: {
			text: '我的历程',
			// fontSize: 12,
			textStyle: {
				fontSize: 15,
				fontWeight: "bolder"
			},
		},
		tooltip: {
			trigger: 'axis',
		},
		legend: {
			// data: ['申请次数', '考核通过范围数'], //分类文字说明,
			data: ['Email', 'Union Ads', 'Video Ads', 'Direct', 'Search Engine'],
		},
		grid: {
			left: '3%',
			right: '4%',
			bottom: '3%',
			// top: '20%',
			containLabel: true,
		},
		toolbox: {
			feature: {
				saveAsImage: {},
			},
		},
		xAxis: {
			type: 'category',
			boundaryGap: false,
			// data: xAxis.value,
			data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
		},
		yAxis: {
			type: 'value',
		},
		// series: seriesArr.value,
		series: [{
			name: 'Email',
			type: 'line',
			stack: 'Total',
			data: [120, 132, 101, 134, 90, 230, 210]
		}],
	};	
	onMounted(() => {
		// 组件能被调用必须是组件的节点已经被渲染到页面上
		setTimeout(async () => {
			if (!chartRef.value) return
			const myChart = await chartRef.value.init(echarts)
			myChart.setOption(option)
		}, 300)
	})
	onBeforeUnmount(() => {
		console.log('onBeforeUnmount');
	});
</script>

<style lang="scss" scoped>
	.echarts-container {
		margin-top: 20rpx;
		width: 100%;
		height: 400rpx;

		background-color: $var-bg-color-white;
		border-radius: 10rpx;
	}
</style>

其他配置和echart一致。

ps: 如果遇到,使用 vite + vue3 非微信小程序可能会遇到echarts文件缺少wx判断导致无法使用或缺少tooltip

image.png

方式一:可以在echarts.min.js文件开头增加以下内容,参考插件内的echart.min.js的做法

复制代码// 某些echarts版本下 uniapp app 需要global,不然会报__ECHARTS__DEFAULT__RENDERER__
let global = null
let wx = uni

方式二:在vite.config.jsdefine设置环境

复制代码//  或者在`vite.config.js`的`define`设置环境
import { defineConfig } from 'vite';
import uni from '@dcloudio/vite-plugin-uni';

const define = {}
if(!["mp-weixin", "h5", "web"].includes(process.env.UNI_PLATFORM)) {
    define['global'] =  null
    define['wx'] =  'uni'
}
export default defineConfig({
    plugins: [uni()],
    define
});

我用的方法二可行。

小程序echarts显示问题 配置如下代码

	// #ifdef VUE3
	// #ifdef MP
	// 由于vue3 使用vite 不支持umd格式的包,小程序依然可以使用,但需要使用require
	const echarts = require("../../../uni_modules/lime-echart/static/echarts.min");


	// #endif

	// #ifndef MP
	// 由于 vue3 使用vite 不支持umd格式的包,故引入npm的包
	import * as echarts from 'echarts';
	// #endif
	// #endif

3. 小程序和H5样式不协调问题

而在修改微信小程序的样式的时候,遇到不生效问题,H5却很听话。
其实uniapp有个参数配置,需要开启小程序的样式穿透才行。
那么在Vue3里该如何配置呢? image.png 从这里不难看出,是表单的样式修改,没有生效,导致表单的高度过高,从而往下推了。

image.png 解决方法:添加下面这段代码

image.png

1、解除微信样式隔离

<script>
  export default {
    options: { styleIsolation: 'shared' },
  }
</script>

2、:v-deep的元素需要一个父class

.custo-clsss ::v-deep {
    .u-button {
    }
}

二者缺一不可。

4. 原生微信小程序/uniapp使用空格占位符无效解决方法

直接用双大括号,括起来

image.png

Page({
  data:{
    myText: '&ensp;&ensp;&ensp;&ensp;爱吃炸排骨&ensp;'
  },
  onLoad: function() {

  }
})

5.uniapp+vue3使用uview-plus

5.1 首先插件安装

点击安装插件:

image.png

image.png

image.png

image.png

5.2 安装依赖,直接用npm 安装

npm i sass@1.63.2 -D  
npm i sass-loader @10.4.1 -D  
npm i dayjs  
npm i clipboard

image.png

import uviewPlus from '@/uni_modules/uview-plus'
 
app.use(uviewPlus)
  1. 在uni.scss中配置样式: image.png
@import "@/uni_modules/uview-plus/index.scss";
  1. 在App.vue中配置样式:

image.png

@import "@/uni_modules/uview-plus/index.scss";

3.在pages.json配置easycom

image.png

"easycom": {
		"autoscan": true,
		"custom": {
			"^u--(.*)": "@/uni_modules/uview-plus/components/u-$1/u-$1.vue",
			"^up-(.*)": "@/uni_modules/uview-plus/components/u-$1/u-$1.vue",
			"^u-([^-].*)": "@/uni_modules/uview-plus/components/u-$1/u-$1.vue"
		}
	},

5.3 使用组件

image.png

6.uniapp 中使用table表格

uniapp中使用table表格是真的麻烦,以下是我记录的踩坑经历

6.1 使用up-parse

uview-plus的up-parse组件直接解析原生的table,这样解析之后,在微信小程序中可以正常显示,不会有格式错乱问题。但是也存在问题,像表格点击事件之类的,就无法解析。

up-parse介绍: 该组件一般用于富文本解析场景,比如解析文章内容,商品详情,带原生HTML标签的各类字符串等,此组件和uni-app官方的rich-text组件功能有重合之处,但是也有不同的地方。

相同点:

  • 二者都能解析HTML字符串

不同点:

  • 对于轻量、简单的字符串,rich-text性能更好
  • 对于复杂的字符串,使用parse组件效果更好,有更多的自定义属性和效果

总结:如果是简单的场景,比如一段简单的文字和图片内容,可以优先使用rich-text组件,在文章内容,商品详情等复杂的文本详情,可以优先使用parse组件。

使用效果如下:

image.png 完整可执行代码如下:

<template>
	<!-- 定义背景视图 -->
	<view class="bg">
		<!-- 定义学生信息视图 -->
		<view class="studentInfo">
			<!-- 使用u-parse组件解析并显示HTML内容 -->
			<u-parse :content="content" :tag-style="tagStyle"></u-parse>
		</view>
		<!-- 添加一个填充视图以调整布局 -->
		<view class="fill"></view>
	</view>
</template>

<script setup>
	// 包含学生信息和成绩的HTML内容
	const content = ref(`
				<table width="100%" cellspacing="0" cellpadding="5">
					<tr>
						<!-- 班级信息,合并两列 -->
						<td align="center" colspan="2">班级</td>
						<td align="center">三年四班</td>
					</tr>
					<tr>
						<!-- 姓名信息,合并两列 -->
						<td align="center" colspan="2">姓名</td>
						<td align="center">张三</td>
					</tr>
					<tr>
						<!-- 学号信息,合并两列 -->
						<td align="center" colspan="2">学号</td>
						<td align="center">123456</td>
					</tr>
					<tr>
						<!-- 考号信息,合并两列 -->
						<td align="center" colspan="2">考号</td>
						<td align="center">456789</td>
					</tr>
					<tr>
						<!-- 总分标题,合并五行 -->
						<td align="center" rowspan="5">总分</td>
						<!-- 班级排名 -->
						<td align="center">班名</td>
						<td align="center">1</td>
					</tr>
					<tr>
						<!-- 学校排名 -->
						<td align="center">校名</td>
						<td align="center">1</td>
					</tr>
					<tr>
						<!-- 县级排名 -->
						<td align="center">县名</td>
						<td align="center">1</td>
					</tr>
					<tr>
						<!-- 市级排名 -->
						<td align="center">市名</td>
						<td align="center">9</td>
					</tr>
					<tr>
						<!-- 联考排名 -->
						<td align="center">联名</td>
						<td align="center">74</td>
					</tr>
					<tr>
						<!-- 语文科目标题,合并六行 -->
						<td align="center" rowspan="6">语文</td>
						<!-- 原始分数 -->
						<td align="center">原始分数</td>
						<td align="center">109.5</td>
					</tr>
					<tr>
						<!-- 语文班级排名 -->
						<td align="center">班名</td>
						<td align="center">3</td>
					</tr>
					<tr>
						<!-- 语文学校排名 -->
						<td align="center">校名</td>
						<td align="center">6</td>
					</tr>
					<tr>
						<!-- 语文县级排名 -->
						<td align="center">县名</td>
						<td align="center">12</td>
					</tr>
					<tr>
						<!-- 语文市级排名 -->
						<td align="center">市名</td>
						<td align="center">126</td>
					</tr>
					<tr>
						<!-- 语文联考排名 -->
						<td align="center">联名</td>
						<td align="center">2203</td>
					</tr>
				</table>`);
	// 定义HTML标签样式
	const tagStyle = ref({
		table: 'box-sizing: border-box; border-top: 1px solid #dfe2e5; border-left: 1px solid #dfe2e5;',
		th: 'border-right: 1px solid #dfe2e5; border-bottom: 1px solid #dfe2e5;',
		td: 'border-right: 1px solid #dfe2e5; border-bottom: 1px solid #dfe2e5;',
		li: 'margin: 5px 0;'
	});
</script>
<script>
	export default {
		options: {
			styleIsolation: 'shared'
		},
	}
</script>
<style lang="scss">
	/* 移除 scoped 改为全局样式 */
	.bg {
		width: 100%;
		height: auto;
		background: #F7F9FD;
		position: absolute;
		top: 0;

		.studentInfo {
			width: 690rpx;
			background: #FFFFFF;
			box-shadow: 0rpx 4rpx 8rpx 0rpx rgba(68, 105, 249, 0.15);
			border-radius: 20rpx;
			margin: 36rpx 0 0 15rpx;
			padding: 20rpx 15rpx 15rpx 15rpx;

			/* 直接使用类名选择器 */
			._table {
				border-top: 1rpx solid #dfe2e5;
				border-right: 1rpx solid #dfe2e5;
			}

			/* 替换 ::deep() 为普通选择器 */
			._td,
			._th {
				border-left: 1rpx solid #dfe2e5;
				border-bottom: 1rpx solid #dfe2e5;
			}
		}

		.fill {
			height: 80rpx;
		}
	}

	/* 修改全局样式 */
	.u-line {
		margin: 0 auto !important;
	}
</style>

6.2 使用原生table

网页端是没有问题的,但是原生微信小程序不支持table标签,直接格式出现问题,排除此方法,

6.3 参考网上封装的table表格

效果如下:

image.png

<template>
	<view class='table'>
  <!-- 左侧固定 -->
  <view class='table_left_column'>
    <view class='left_col_item'>排班</view>
    <view class='left_col_item' :style="{height: timeHeight1 + 'px'}">上午</view>
    <view class='left_col_item' :style="{height: timeHeight2 + 'px'}">下午</view>
    <view class='left_col_item' :style="{height: timeHeight3 + 'px'}">晚上</view>
  </view>
  <!-- 右侧表格滚动 -->
  <view class="table_right_scroll_box">
    <view v-for="(item, index) in list" :key="index" :class="'table_tr_item tableRow' + index">
      <view v-for="(ditem, dindex) in item.data" :key="dindex">
        <view v-if="index == 0" class='tr_th tr_td'> 
          <view class="">{{ditem.date}}</view>
          <view class="">{{ditem.day}}</view>
        </view>
        <view v-else class='tr_td'>
          <view v-for="(uitem, uindex) in ditem.userList" :key="uindex" class="tr_td_row">
            {{uitem.name}}
          </view>
        </view>
      </view>
    </view>
  </view>
</view>
</template>

<script setup>
	import { ref, onMounted } from "vue";


 // 动态计算左侧行高(根据右侧内容高度)
const timeHeight1 = ref(0);
const timeHeight2 = ref(0);
const timeHeight3 = ref(0);
   let  list= ref([
      {
        time: '排班',
        data: [{
            date: '周一',
            day: '04/25',
            userList: []
          },
          {
            date: '周二',
            day: '04/26',
            userList: []
          },
          {
            date: '周三',
            day: '04/27',
            userList: []
          },
          {
            date: '周四',
            day: '04/28',
            userList: []
          },
          {
            date: '周五',
            day: '04/29',
            userList: []
          },
          {
            date: '周六',
            day: '04/30',
            userList: []
          },
          {
            date: '周日',
            day: '05/01',
            userList: []
          }
        ]
      },
    {
      time: '上午',
      data: [{
          date: '周一',
          day: '00/00',
          userList: [{
              code: '000',
              name: '值班人'
            },
            {
              code: '000',
              name: '值班人'
            },
            {
              code: '000',
              name: '值班人'
            }
          ]
        },
        {
          date: '周二',
          day: '00/00',
          userList: [{
              code: '000',
              name: '值班人'
            },
            {
              code: '000',
              name: '值班人'
            }
          ]
        },
        {
          date: '周三',
          day: '00/00',
          userList: [{
              code: '000',
              name: '值班人'
            },
            {
              code: '000',
              name: '值班人'
            }
          ]
        },
        {
          date: '周四',
          day: '00/00',
          userList: [{
              code: '000',
              name: '值班人'
            },
            {
              code: '000',
              name: '值班人'
            }
          ]
        },
        {
          date: '周五',
          day: '00/00',
          userList: [{
              code: '000',
              name: '值班人'
            },
            {
              code: '000',
              name: '值班人'
            },
            {
              code: '000',
              name: '值班人'
            }
          ]
        },
        {
          date: '周六',
          day: '00/00',
          userList: [{
              code: '000',
              name: '值班人'
            },
            {
              code: '000',
              name: '值班人'
            },
            {
              code: '000',
              name: '值班人'
            }
          ]
        },
        {
          date: '周日',
          day: '00/00',
          teacher: []
        }
      ]
    },
    {
      time: '下午',
      data: [{
          date: '周一',
          day: '00/00',
          userList: [{
              code: '000',
              name: '值班人'
            },
            {
              code: '000',
              name: '值班人'
            },
            {
              code: '000',
              name: '值班人'
            }
          ]
        },
        {
          date: '周二',
          day: '00/00',
          userList: [{
              code: '000',
              name: '值班人'
            },
            {
              code: '000',
              name: '值班人'
            }
          ]
        },
        {
          date: '周三',
          day: '00/00',
          userList: [{
              code: '000',
              name: '值班人'
            },
            {
              code: '000',
              name: '值班人'
            }
          ]
        },
        {
          date: '周四',
          day: '00/00',
          userList: [{
              code: '000',
              name: '值班人'
            },
            {
              code: '000',
              name: '值班人'
            }
          ]
        },
        {
          date: '周五',
          day: '00/00',
          userList: [{
              code: '000',
              name: '值班人'
            },
            {
              code: '000',
              name: '值班人'
            },
            {
              code: '000',
              name: '值班人'
            }
          ]
        },
        {
          date: '周六',
          day: '00/00',
          userList: [{
              code: '000',
              name: '值班人'
            },
            {
              code: '000',
              name: '值班人'
            },
            {
              code: '000',
              name: '值班人'
            }
          ]
        },
        {
          date: '周日',
          day: '00/00',
          userList: [{
            code: '000',
            name: '值班人'
          }]
        }
      ]
    },
    {
      time: '晚上',
      data: [{
          date: '周一',
          day: '00/00',
          userList: [{
              code: '000',
              name: '值班人'
            },
            {
              code: '000',
              name: '值班人'
            }
          ]
        },
        {
          date: '周二',
          day: '00/00',
          userList: [{
              code: '000',
              name: '值班人'
            },
            {
              code: '000',
              name: '值班人'
            }
          ]
        },
        {
          date: '周三',
          day: '00/00',
          userList: [{
            code: '000',
            name: '值班人'
          }]
        },
        {
          date: '周四',
          day: '00/00',
          userList: []
        },
        {
          date: '周五',
          day: '00/00',
          userList: [{
            code: '000',
            name: '值班人'
          }]
        },
        {
          date: '周六',
          day: '00/00',
          userList: [{
            code: '000',
            name: '值班人' 
          }]
        },
        {
          date: '周日',
          day: '00/00',
          userList: []
        }
      ]
    }
  ]);
// 封装高度计算函数
const calculateHeights = () => {
  setTimeout(() => {
    nextTick(() => {
      const query = uni.createSelectorQuery().in(this);
      
      query.select('.tableRow1').boundingClientRect(rect => {
        timeHeight1.value = rect ? rect.height - 1 : 0;
      }).exec();
      
      query.select('.tableRow2').boundingClientRect(rect => {
        timeHeight2.value = rect ? rect.height - 1 : 0;
      }).exec();
      
      query.select('.tableRow3').boundingClientRect(rect => {
        timeHeight3.value = rect ? rect.height - 1 : 0;
      }).exec();
    });
  }, 300); // 延迟确保渲染完成
};

// 生命周期钩子
onMounted(() => {
  calculateHeights();
});

</script>
<script>
	export default {
		options: {
			styleIsolation: 'shared'
		},
	}
</script>
<style lang="scss">

 
.table {
  display: flex;
  background: white;
  border: 1rpx solid rgba(218, 217, 217, 1);
  border-bottom: 0;
}
 
.table_left_column {
  width: 100rpx;
  height: auto;
  display: flex;
  flex-direction: column;
}
 
.left_col_item {
  width: 100rpx;
  min-height: 90rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  border-bottom: 1rpx solid #e5e5e5;
  color: #000;
  font-weight: bolder;
}
 
.table_right_scroll_box {
  width: 1400rpx;
  height: auto;
  white-space: nowrap;
  overflow-x: scroll;
  border-left: 1rpx solid #e5e5e5;
  font-weight: normal;
}
 
.table_tr_item {
  width: 1400rpx;
  display: flex;
  flex-direction: row;
}
 
.tr_th {
  background: rgba(241, 252, 255, 1);
}
 
.tr_th view:last-child {
  font-size: 25rpx;
}
 
.tr_td {
  display: flex;
  align-items: center;
  flex-direction: column;
  justify-content: center;
  width: 200rpx;
  min-height: 90rpx;
  border: 1rpx solid rgba(218, 217, 217, 1);
  border-top: 0;
  border-left: 0;
}
 
.tr_td_row {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  min-height: 60rpx;
  color: rgba(55, 134, 244, 0.8);
  flex-basis: auto;
  flex-grow: 1;
  -webkit-flex-grow: 1;
  word-wrap: break-word;
  word-break: break-all;
  white-space: pre-line;
  border-bottom: 1rpx solid rgba(218, 217, 217, 1);
}
 
.tr_td_row:last-child {
  border-bottom: none;
}
</style>

6.4 我的最终解决方案

使用view封装table表格,支持跨行跨列,嵌套下拉框等

  1. 实现效果如下:

image.png

完整代码如下:

<template>
	<view class="table-container">
		<!-- 表头 -->
		<view class="table-row header-row">
			<view class="table-cell title" @click="testClick">评分项</view>
			<view class="table-cell title1">评分操作</view>
		</view>

		<!-- 表格内容 -->
		<template v-for="(group, gIndex) in standResult" :key="gIndex">
			<view class="table-row">
				<!-- 分组标题单元格(跨行) -->
				<view class="table-cell group-title" :style="{ height: group.arr.length * rowHeight + 'rpx' }">
					{{ group.StandGName }}
				</view>

				<!-- 评分项列表 -->
				<view class="table-cell items-column">
					<view class="item-row" v-for="(item, index) in group.arr" :key="item.StanderId">
						{{ index + 1 }}.{{ item.StanderName }}
					</view>
				</view>

				<!-- 评分选择器 -->
				<view class="table-cell items-column">
					<view class="item-row" v-for="(item, index) in group.arr" :key="item.StanderId">
						<uni-data-select v-model="item.value" :localdata="transformToOptions(item.StandPriceLimit)" />
					</view>
				</view>

			</view>
		</template>
	</view>
</template>

<script setup>
	import {
		ref
	} from 'vue'

	const rowHeight = 120 // 每行基础高度


	function testClick() {
		console.log('change', value.value)
	}
	let standResult = ref([{
			"index": 1,
			"StandGName": "工作能力",
			"arr": [{
					"StanderId": 28,
					"StanderName": "工作量",
					"StanderDes": "仅考虑完成工作数量。职责内工作、上级交办工作及自主性工作完成的总量。",
					"StandPriceLimit": "2,4,5,8,10",
					"StandExp": null,
					"FKStandGId": 22,
					"StandGName": "工作能力",
					"RatioNum": 0,
					"CompIdTag": 27,
					"CompName": "工作量",
					"ComProjectCode": 1,
					"ControlDrop": null,
					"ControlDropList": [],
					"arr": [],
					"value": "",
					"tag": 1
				},

				{
					"StanderId": 32,
					"StanderName": "应变力",
					"StanderDes": "针对客观变化,采取措施(行动)的主动性、有效性及工作中对上级的依赖程度",
					"StandPriceLimit": "2,4,5,8,10",
					"StandExp": null,
					"FKStandGId": 22,
					"StandGName": "工作能力",
					"RatioNum": 0,
					"CompIdTag": 31,
					"CompName": "应变力",
					"ComProjectCode": 1,
					"ControlDrop": null,
					"ControlDropList": [],
					"arr": [],
					"value": ""
				},




				{
					"StanderId": 40,
					"StanderName": "品德言行",
					"StanderDes": "是否做到诚实守信,言行具有正能量、良好的信誉",
					"StandPriceLimit": "2,4,5,8,10",
					"StandExp": null,
					"FKStandGId": 23,
					"StandGName": "工作态度",
					"RatioNum": 0,
					"CompIdTag": 39,
					"CompName": "品德言行",
					"ComProjectCode": 1,
					"ControlDrop": null,
					"ControlDropList": [],
					"arr": [],
					"value": ""
				}
			]
		},
		{
			"index": 2,
			"StandGName": "扣分项",
			"arr": [{
					"StanderId": 41,
					"StanderName": "违纪批评",
					"StanderDes": "有违反劳动纪律、违反安全操作规程被书面通报批评者,不得参加评优,扣10分 ",
					"StandPriceLimit": "10",
					"StandExp": null,
					"FKStandGId": 25,
					"StandGName": "扣分项",
					"RatioNum": 0,
					"CompIdTag": 40,
					"CompName": "违纪批评",
					"ComProjectCode": 2,
					"ControlDrop": null,
					"ControlDropList": [],
					"arr": [],
					"value": "",
					"tag": 2
				},

				{
					"StanderId": 43,
					"StanderName": "住宿情况",
					"StanderDes": "宿舍脏乱差,被警示后仍不整改的,扣2分",
					"StandPriceLimit": "2",
					"StandExp": null,
					"FKStandGId": 25,
					"StandGName": "扣分项",
					"RatioNum": 0,
					"CompIdTag": 42,
					"CompName": "住宿情况",
					"ComProjectCode": 2,
					"ControlDrop": null,
					"ControlDropList": [],
					"arr": [],
					"value": ""
				},
				{
					"StanderId": 44,
					"StanderName": "其他情况",
					"StanderDes": "造谣生事,散播谣言,挑拨离间,导致同事之间或公司受损失者,扣5分",
					"StandPriceLimit": "5",
					"StandExp": null,
					"FKStandGId": 25,
					"StandGName": "扣分项",
					"RatioNum": 0,
					"CompIdTag": 43,
					"CompName": "其他情况",
					"ComProjectCode": 2,
					"ControlDrop": null,
					"ControlDropList": [],
					"arr": [],
					"value": ""
				}
			]
		},
		{
			"index": 3,
			"StandGName": "加分项",
			"arr": [{
					"StanderId": 45,
					"StanderName": "技能考试",
					"StanderDes": "技能考试成绩在本部门同专业里排名第一5分,第二3分,第三1分",
					"StandPriceLimit": "5,3,1",
					"StandExp": null,
					"FKStandGId": 24,
					"StandGName": "加分项",
					"RatioNum": 0,
					"CompIdTag": 44,
					"CompName": "技能考试",
					"ComProjectCode": 3,
					"ControlDrop": null,
					"ControlDropList": [],
					"arr": [],
					"value": "",
					"tag": 3
				},
				{
					"StanderId": 46,
					"StanderName": "技能竞赛",
					"StanderDes": "公司及以上级别技能竞赛金奖10分,银奖8分,铜奖5分",
					"StandPriceLimit": "10,8,5",
					"StandExp": null,
					"FKStandGId": 24,
					"StandGName": "加分项",
					"RatioNum": 0,
					"CompIdTag": 45,
					"CompName": "技能竞赛",
					"ComProjectCode": 3,
					"ControlDrop": null,
					"ControlDropList": [],
					"arr": [],
					"value": ""
				},

				{
					"StanderId": 50,
					"StanderName": "获得表彰",
					"StanderDes": "获得公司及政府部门、客户单位发文表彰的加10分(不能重复加分)",
					"StandPriceLimit": "10",
					"StandExp": null,
					"FKStandGId": 24,
					"StandGName": "加分项",
					"RatioNum": 0,
					"CompIdTag": 49,
					"CompName": "获得表彰",
					"ComProjectCode": 3,
					"ControlDrop": null,
					"ControlDropList": [],
					"arr": [],
					"value": ""
				}
			]
		}
	])
	const transformToOptions = (priceLimit) => {
		const values = priceLimit.split(',')
		return values.map((val, idx) => ({
			value: idx + 1,
			text: ['极差', '较差', '一般', '良好', '优秀'][idx] || `等级${idx + 1}`,
			score: val
		}))
	}
</script>

<style lang="scss" scoped>
	// 表格容器样式,设置宽度为100%,并添加边框
	.table-container {
		width: 100%;
		border: 4rpx solid #ebeef5;
		border-collapse: collapse; // 确保边框合并
	}

	// 表格行样式,使用flex布局,并为每一行添加底部边框
	.table-row {
		display: flex;
		border-bottom: 2rpx solid #ebeef5;

		// 针对表头行的特殊样式,设置背景颜色和字体加粗
		&.header-row {
			background-color: #f5f7fa;
			font-weight: bold;
		}
	}

	// 表格标题样式,设置flex3,文本居中,高度和行高等于60rpx,并添加左侧边框
	.title {
		flex: 3;
		text-align: center;
		height: 60rpx;
		line-height: 60rpx;
		border-left: 2rpx solid #fff;
	}

	// 第二个表格标题样式,设置flex1.5,文本居中,高度和行高等于60rpx
	.title1 {
		flex: 1.5;
		text-align: center;
		height: 60rpx;
		line-height: 60rpx;
	}

	// 表格单元格样式,添加右侧边框,并移除内边距
	.table-cell {
		// flex: 1; // 如果需要每个单元格等宽,可以取消注释
		border-right: 2rpx solid #ebeef5;
		padding: 0;

		// 移除最后一个单元格的右侧边框
		&:last-child {
			border-right: none;
		}

		// 分组标题单元格样式,设置为等宽,使用flex布局,并添加背景颜色和边框
		&.group-title {
			flex: 1;
			display: flex;
			align-items: center;
			justify-content: center;
			background-color: #fff;
			position: relative;
			border: 2rpx solid #f0f0f0;

			// 添加伪元素,用于在分组标题右侧绘制一条2rpx的边框
			&::after {
				content: "";
				position: absolute;
				right: 0;
				top: 0;
				bottom: 0;
				width: 2rpx;
				background-color: #ebeef5;
			}
		}

		// 项目列单元格样式,设置为等宽,使用flex布局,并移除内边距
		&.items-column {
			flex: 1;
			display: flex;
			flex-direction: column;
			padding: 0;
		}
	}

	// 项目行样式,设置最小高度为120rpx,使用flex布局,并添加底部边框和背景颜色
	.item-row {
		min-height: 120rpx;
		display: flex;
		align-items: center;
		padding: 0 12rpx;
		border-bottom: 2rpx solid #f0f0f0;
		background-color: #fff;

		// 移除最后一行的底部边框
		&:last-child {
			border-bottom: none;
		}
	}

	// /* 适配选择器样式,确保uni-data-select组件的样式符合表格整体设计 */
	// :deep(.uni-data-select) {
	// 	width: 100%;
	// 	margin: 8rpx 0;
	// }
</style>

7.修改组件样式

修改前的样式

image.png

修改方法如下:

image.png

	::v-deep .uni-table-checkbox .checkbox__inner.checkbox--indeterminate {
		color: #ffffff !important;
		background-color: #007aff !important;
	}

	::v-deep .uni-table-checkbox .checkbox__inner.is-checked {
		color: #ffffff !important;
		background-color: #007aff !important;
	}