flex嵌套,以及:nth-of-type(3)伪类使用

flex嵌套

弹性盒子也能创建一些颇为复杂的布局。设置一个元素为 flex 项,那么他同样成为一个 flex 容器,它的孩子(直接子节点)也表现为弹性盒子。看一下 复杂弹性盒子.html在线浏览)。

article:nth-of-type(3) {
  flex: 3 200px;
  display: flex;
  flex-flow: column;
}

代码分析

  1. 选择器 article:nth-of-type(3)

    • 这个选择器用于选择文档中第三个<article>元素。:nth-of-type(n)伪类选择器用于选择同类型元素中的第n个元素。

    • 例如,如果有多个<article>元素,这个选择器会应用样式到第三个<article>元素。

  2. flex: 3 200px;

    • 这是一个简写属性,用于设置弹性容器内项目的弹性增长因子、缩小因子和基础大小。

    • 3 是增长因子,表示如果有额外的空间,这个项目将比其他项目多增长3倍。

    • 200px 是基础大小,表示项目在没有额外空间或需要缩小时的基础尺寸。

  3. display: flex;

    • <article>元素设置为弹性容器,使其子元素成为弹性项目。

    • 弹性布局(Flexbox)是一种一维布局模型,允许更高效地排列和对齐容器中的项目。

  4. flex-flow: column;

    • 这是flex-directionflex-wrap的简写属性。

    • column 指定弹性项目将垂直排列(从上到下)。

相关概念

  • Flexbox:是一种CSS布局模型,旨在为用户界面设计提供更高效的布局方式。它允许容器内的项目在不同的屏幕尺寸和设备上自动调整和排列。

  • 伪类选择器:nth-of-type(n)是CSS中的一种伪类选择器,用于选择特定类型的元素。它可以用于复杂的选择器组合,以实现更精确的样式应用。

示例代码

假设有以下HTML结构:

<article>First Article</article>
<article>Second Article</article>
<article>Third Article</article>
<article>Fourth Article</article>

应用上述CSS后,第三个<article>元素将会被设置为弹性容器,并且其子元素将垂直排列。

文档链接

<template> <view class="content"> <view class="content_box"> <view class="u-page__item content_box_tit"> <u-navbar :is-back="false" title="" :fixed="true" title="发现" :safeAreaInsetTop="true" :height="54" :background="background"> <view class="left_icon u-nav-slot"> <u-icon @click="goToBack()" name="arrow-left" color="#fff" size="28"></u-icon> <u-icon @click="goToHome()" name="home-fill" color="#fff" size="28"></u-icon> </view> </u-navbar> </view> <view class="my_lawyer"> <view class="my_lawyer_box"> <view class="list_l"> <image :src="List[0].tx" mode=""></image> </view> <view class="list_r"> <view class=""> <text>{{List[0].name}}</text> <text>{{List[0].year}}</text> </view> <view class=""> <text>{{List[0].sc}}</text> </view> </view> </view> </view> </view> </view> </template> <script> import bg1 from &#39;@/static/home/bg.png&#39;; import my1 from &#39;@/static/my/bg.png&#39;; import NavHeader from &#39;@/pages/components/NavHeader.vue&#39;; export default { components: { NavHeader }, data() { return { List: [{ tx: bg1, year: &#39;执业10年&#39;, name: &#39;罗毅-律师&#39;, sc: &#39;擅长领域:地产、婚姻、金融&#39; }], bg1, keyword: &#39;&#39;, background: { background: `url(${my1})`, // 还可以设置背景图size属性 backgroundSize: &#39;cover&#39;, backgroundSize: &#39;100% 100%&#39;, backgroundRepeat: &#39;no-repeat&#39;, height: &#39;370rpx&#39;, // backgroundImage: &#39;linear-gradient(45deg, rgb(28, 187, 180), rgb(141, 198, 63))&#39; }, inputStyle: { margin: &#39; 0 0 0 48rpx&#39;, opacity: &#39;0.6&#39;, color: &#39;#FFFFFF&#39;, fontWeight: &#39;500&#39;, } }; }, methods: { goToBack() { console.log("返回按钮"); uni.navigateBack({ delta: 1 }) }, goToHome() { console.log("返回主页"); uni.switchTab({ url: &#39;/pages/index/index&#39; }) }, goIntroduction() { console.log("简介"); } }, onLoad() { console.log(this.$u); } }; </script> <style scoped lang="scss"> .content_box_tit ::v-deep .u-navbar-fixed { // z-index: 999!important; // 根据需要调整 // z-index: -1 !important; } .left_tit { display: flex; } .content { .content_box { width: 100vw; .content_box_tit { width: 100vw; .left_icon { color: red; margin: -9px 20rpx 0; padding: 6px 10px 6px 19px; background: #545464; border-radius: 18px; border: 1px solid #545464; opacity: 0.4; width: 81px; height: 32px; display: flex; justify-content: space-between; align-items: center; } } .my_lawyer { .my_lawyer_box { width: 702rpx; height: 160rpx; background: pink; .list_l { width: 112rpx; height: 112rpx; image { width: 100%; height: 100%; border-radius: 50%; } } .list_r { display: flex; margin-left: 20rpx; flex-direction: column; view:nth-of-type(1) { text { font-weight: 400; font-size: 15px; color: #333333; } } view:nth-of-type(2) { text { margin-top: 16rpx; font-weight: 400; font-size: 12px; color: #999999; } } } } } } } </style>为啥my_lawyer部分的样式在页面显示不出来给了index:999也不行
07-17
<template> <view class="content"> <!-- 预警信息 --> <view class="alarmInformation"> <view class="title"> <text>预警信息</text> </view> <view class="alarmDetail"> <view class="alarmDetailItem"> <text>报警型:</text> <text>{{detailData.alarmtype}}</text> </view> <view class="alarmDetailItem"> <text>风险等级:</text> <text>{{detailData.risklevel}}</text> </view> <view class="alarmDetailItem"> <text>报警次数:</text> <text>{{detailData.alarmcount}}</text> </view> <view class="alarmDetailItem"> <text>持续时间:</text> <text>{{detailData.duration}}</text> </view> <view class="alarmDetailItem"> <text>报警时间:</text> <text>{{detailData.firsttime}}至{{detailData.lasttime}}</text> </view> <view class="alarmDetailItem"> <text>开始位置:</text> <text>{{detailData.firstlocation}}</text> </view> <view class="alarmDetailItem"> <text>结束位置:</text> <text>{{detailData.lastlocation}}</text> </view> <view class="alarmDetailItem"> <text>报警车速:</text> <text>{{startspeed}}</text> </view> <view class="alarmDetailItem" v-if="detailData.powerprocessed == &#39;3OL4M8GZ&#39;"> <text>热值:</text> <input style="border: 1px solid #ddd;width:88%;border-radius: 4px;padding:5px;" placeholder-style="color:#999;font-size:22upx" placeholder="请输入热值" v-model="detailData.calorific"></input> </view> <view > <text style="font-weight: 700;font-size: 30upx;">原因分析:</text> <textarea style="border: 1px solid #ddd;width:92%;padding:10px;border-radius: 4px;" auto-height=&#39;true&#39; name="measure" v-model="detailData.remarks" placeholder-style="color:#999;font-size:28upx" placeholder="请输入原因分析..." /> </view> <view> <text style="font-weight: 700;font-size: 30upx;">整改措施:</text> <textarea style="border: 1px solid #ddd;width:92%;padding:10px;border-radius: 4px;" auto-height=&#39;true&#39; name="measure" v-model="detailData.measures" placeholder-style="color:#999;font-size:28upx" placeholder="请输入整改措施..." /> </view> <view> <text style="font-weight: 700;font-size: 30upx;">处理说明:</text> <textarea style="border: 1px solid #ddd;width:92%;padding:10px;border-radius: 4px;" auto-height=&#39;true&#39; name="measure" v-model="detailData.instructions" placeholder-style="color:#999;font-size:28upx" placeholder="请输入处理说明..." /> </view> <view style="margin-top: 28rpx;"><text style="font-size: 34rpx;font-weight: bold;">处理附件:</text></view> <view style="display: flex;width: 580rpx;flex-wrap: wrap;"> <view v-for="(photo, index) in detailData.penaltyfjList" :key="index" class="loop-img-box"> <image style="margin-right: 10px;" class="img-list" :src="photo" @tap="previewPhoto(detailData.penaltyfjList, index)" mode="aspectFill"></image> <view v-if="num > 0" class="q-image-remover" :data-idx="index" @click="btnDeleteImg(index)"> <image class="delete-img" src="@/static/delete_1.jpg" mode="aspectFill"></image> </view> </view> <image class="img-list" @tap="chooth(num)" src="@/static/jiazhao.png" mode="aspectFill" v-if="detailData.penaltyfjList.length < num"></image> </view> </view> </view> <view class="footer_btn" > <view class="dispose_btn" @click="<strong>btnQd</strong>()"> 确定 </view> </view> <!-- 忽略提示框 --> <!-- <uni-popup ref="popupDialog" type="dialog"> <uni-popup-dialog title="通知" content="确定要忽略?" :before-close="true" @confirm="dialogHuLveConfirm" @close="dialogClose" /> </uni-popup> --> </view> </template> <script charset="utf-8" src="https://map.qq.com/api/gljs?v=1.exp&key=NCVBZ-PXCKW-O2KRT-3SN3X-JLFM3-NNB5G"></script> <script> // import { getUserInfo } from &#39;@/request/api.js&#39; import request from &#39;@/http/request.js&#39; export default { data() { return { photoData:[], num:9, Arr:[], detailData: { penaltyfjList:[] }, status: &#39;&#39;, remark: &#39;&#39;, formDisposeData: {}, disposeId: &#39;&#39;, picList: [], videoList: [], showMap: false, latitude: &#39;&#39;, longitude: &#39;&#39;, points: [], polyline: [], markers: [], mapContext: null, nextPointIndex: 1, //下一个坐标点的索引 duratioinTime: 1000, //相邻两点动画持续时长默认1秒 showPlay: true, //默认显示播放按钮 pl: [], mapScale: 17, startspeed: &#39;&#39;, firstgeopoint: &#39;&#39;, car: &#39;&#39;, photoArray:[], File:[], scId:[], cysstatus:"", lx:"", formDisposeData1:{}, showEmpty: false, isForwarding: false, //正在快进中 isBacking: false, //正在快退中 isEnding: false, //播放结束 pointCount: 10 ,//快进的点位数 lx:&#39;&#39;, ryid:"", } }, async onLoad(option) { uni.showLoading({ title: &#39;加载中&#39; }) var my = this this.mapContext = uni.createMapContext(&#39;mymap&#39;, this) this.disposeId = option.ddid this.lx = option.lx ? option.lx : &#39;&#39; await my.loadDetail(option.ddid) var user = uni.getStorageSync(&#39;user&#39;) console.log(user) my.ryid = user[0].id }, methods: { btnJxcs(){ }, async btnQd(){ var my = this; var formDisposeData = {} if(my.lx !==&#39;&#39; && my.detailData.powerprocessed ==&#39;3OL4M8GY&#39;){ if(my.lx ==&#39;cl&#39;){ formDisposeData.id = my.disposeId formDisposeData.ryid = my.ryid formDisposeData.remarks =my.detailData.remarks formDisposeData.powerresults = &#39;3T4000CQ&#39; formDisposeData.penaltyfj = my.scId.join(&#39;,&#39;) formDisposeData.measures=my.detailData.measures, formDisposeData.instructions=my.detailData.instructions, request.vsportal(&#39;XcxJgAction.addJgdcl&#39;, formDisposeData).then(function(res) { if (res.status) { uni.showToast({ title: "处理成功!", icon: "success", }) uni.$emit(&#39;refreshPreviousPage&#39;, { data: &#39;dispose&#39; }); setTimeout(function() { uni.navigateBack({ url: "/pages/prewarning/index" }); }, 500); } }) }else if(my.lx ==&#39;xg&#39;){ formDisposeData.id = my.disposeId formDisposeData.ryid = my.ryid formDisposeData.remarks =my.detailData.remarks formDisposeData.penaltyfj = my.scId.join(&#39;,&#39;) formDisposeData.measures=my.detailData.measures formDisposeData.instructions=my.detailData.instructions request.vsportal(&#39;XcxJgAction.editWarn&#39;, formDisposeData).then(function(res) { if (res.status) { uni.showToast({ title: "处理成功!", icon: "success", }) uni.$emit(&#39;refreshPreviousPage&#39;, { data: &#39;dispose&#39; }); setTimeout(function() { uni.navigateBack({ url: "/pages/prewarning/index" }); }, 500); } }) }else if(my.lx ==&#39;jcbj&#39;){ formDisposeData.id = my.disposeId formDisposeData.ryid = my.ryid formDisposeData.powerresults = &#39;3T4000CP&#39; formDisposeData.remarks = my.detailData.remarks formDisposeData.penaltyfj = my.scId.join(&#39;,&#39;) formDisposeData.measures=my.detailData.measures, formDisposeData.instructions=my.detailData.instructions, request.vsportal(&#39;XcxJgAction.addJgdcl&#39;, formDisposeData).then(function(res) { if (res.status) { uni.showToast({ title: "处理成功!", icon: "success", }) uni.$emit(&#39;refreshPreviousPage&#39;, { data: &#39;dispose&#39; }); setTimeout(function() { uni.navigateBack({ url: "/pages/prewarning/index" }); }, 500); } }) } } await request.vsportal(&#39;XlAction.editysabn&#39;, { measures:my.detailData.measures, remarks:my.detailData.remarks, instructions:my.detailData.instructions, calorific:my.detailData.calorific ? my.detailData.calorific :&#39;&#39;, id:my.disposeId, penaltyfj:my.scId.join(&#39;,&#39;) }).then(function(res) { uni.navigateBack() }) }, chooth(num) { console.log(this.detailData) this.Arr = [] var number = this.num - this.detailData.penaltyfjList.length var my = this var array = [] my.photoArray = [] my.File = [] uni.chooseImage({ count: number, //默认9 sizeType: [&#39;original&#39;, &#39;compressed&#39;], //可以指定是原图还是压缩图,默认二者都有 success: function (res) { //图片数组 console.log(res,&#39;11&#39;) uni.showLoading({ title: &#39;上传中...&#39;, mask: true }) let tempFilePath = res.tempFilePaths let Arr1 = [] for (var i = 0; i < res.tempFilePaths.length; i++) { my.detailData.penaltyfjList.push(res.tempFilePaths[i]) Arr1.push(res.tempFilePaths[i]) } setTimeout(function () { my.tpsc(Arr1) }, 600) } }) }, //图片上传 tpsc(tps) { var url = request.HttpHost + &#39;/portal.php?resid=fileUpload.uploader&#39; this.digui(0, tps, url) }, //异步递归 digui(index, arr, url) { if (index == arr.length) { uni.hideLoading() // console.log(this.scId); // console.log(this.typeimg); //this.$emit(&#39;tijiaoImg&#39;, this.scId, this.typeimg) return } var my = this //console.log(&#39;上传图片filePath===&#39;,arr[index]) uni.uploadFile({ url: url, filePath: arr[index], name: &#39;file&#39;, success: (uploadFileRes) => { //console.log("上传success=====",uploadFileRes) var res = JSON.parse(uploadFileRes.data) this.scId.push(res.data.id) console.log(this.scId) index++ // console.log(index); my.digui(index, arr, url) }, fail: (res) => { console.log("上传fail=====",res) } }) }, // 预览图片 previewPhoto(arr, index) { uni.previewImage({ current: index, //预览图片的下标 urls: arr //预览图片的地址,必须要数组形式,如果不是数组形式就转换成数组形式就可以 // loop:true, }) // this.$forceUpdate()this }, // 删除照片 btnDeleteImg(index) { // console.log(this.scId); var my = this my.detailData.penaltyfjList.splice(index, 1) my.scId.splice(index, 1) }, zpurl(zp) { let zpurl = new Array(zp.length); for (let i = 0; i < zp.length; i++) { zpurl[i] = request.imageUrl(zp[i]); } return zpurl; }, async loadDetail(id) { var my = this; await request.vsportal(&#39;XcxJgAction.warnDetail&#39;, { id: id }).then(function(res) { uni.hideLoading() if (res.status) { my.detailData = res.data[0] if(!my.detailData.calorific) my.detailData.calorific = &#39;0&#39; if(my.detailData.penaltyfj && my.detailData.penaltyfj !==&#39;&#39;)my.scId = my.detailData.penaltyfj.split(&#39;,&#39;) if(my.detailData.penaltyfj && my.detailData.penaltyfj !==&#39;&#39;){ var arr = my.detailData.penaltyfj.split(&#39;,&#39;) my.detailData.penaltyfjList = my.zpurl(arr) }else{ my.detailData.penaltyfjList = [] } if(my.detailData.firsttime)my.detailData.firsttime = my.formatDate(my.detailData.firsttime) if(my.detailData.lasttime)my.detailData.lasttime = my.formatDate(my.detailData.lasttime) if (res.data[0].firstlocation.indexOf(&#39;[]&#39;) != -1) { my.detailData.firstlocation = &#39;&#39; } if (res.data[0].lastlocation.indexOf(&#39;[]&#39;) != -1) { my.detailData.lastlocation = &#39;&#39; } my.startspeed = my.detailData.startspeed != "" ? my.detailData.startspeed + &#39;km/h&#39; : "0km/h" } }); }, formatDate(value) { if (value == undefined) { return; } // let date = new Date(value * 1000); let date = new Date(value); //时间戳为10位需*1000,时间戳为13位的话不需乘1000 let y = date.getFullYear(); let MM = date.getMonth() + 1; MM = MM < 10 ? (&#39;0&#39; + MM) : MM; //月补0 let d = date.getDate(); d = d < 10 ? (&#39;0&#39; + d) : d; //天补0 let h = date.getHours(); h = h < 10 ? (&#39;0&#39; + h) : h; //小时补0 let m = date.getMinutes(); m = m < 10 ? (&#39;0&#39; + m) : m; //分钟补0 let s = date.getSeconds(); s = s < 10 ? (&#39;0&#39; + s) : s; //秒补0 console.log(y + &#39;-&#39; + MM + &#39;-&#39; + d + &#39; &#39; + h + &#39;:&#39; + m + ":" + s) return y + &#39;-&#39; + MM + &#39;-&#39; + d + &#39; &#39; + h + &#39;:&#39; + m + ":" + s; //年月日时分秒 }, splitString(fileList) { var my = this; //my.picList.push("http://n.sinaimg.cn/ent/4_img/upload/1f0ce517/251/w1024h827/20210413/a255-knqqqmv1931923.jpg") for (var i = 0; i < fileList.length; i++) { console.log(fileList[i].fileurl) var file = fileList[i].fileurl if (file.includes("png") || file.includes("jpg")) { my.picList.push(file); } else if (file.includes("mp4")) { my.videoList.push({ path: file, id: &#39;myVideo&#39; + i }) } } }, } } </script> <style lang="scss"> .loop-img-box { position: relative; width: 160rpx !important; height: 110rpx !important; margin-right: 10px; margin-bottom: 7px; } .img-list { display: block; position: relative; padding: 15rpx ; width: 160rpx !important; height: 110rpx !important; //padding-right: 15rpx; /* vertical-align: bottom; */ } .q-image-remover { width: 48rpx; height: 48rpx; } .delete-img { width: 48rpx; height: 48rpx; position: absolute; top:-4px; right: -16px; // padding: 10rpx; } .img { width: 140rpx; height: 110rpx; padding: 15rpx; } .popup-content2 { background-color: #fff; width: 686upx; border-radius: 28upx; padding: 50upx 38upx; box-sizing: border-box; .reason { display: flex; flex-direction: column; text { font-size: 34upx; font-weight: bold; } text:nth-child(2) { display: inline-block; width: 172upx; height: 60upx; line-height: 60upx; color: #FFF; border-radius: 40upx; font-size: 28upx; text-align: center; background-color: #2257FF; font-weight: normal; margin-top: 30upx; } } .btn { display: flex; justify-content: space-around; margin-top: 54upx; view { width: 252upx; height: 80upx; border-radius: 40upx; border: 1px solid #2257FF; line-height: 80upx; text-align: center; color: #2257FF; } .submit { background-color: #2257FF; color: #fff; } } } .popup-save { @include flex; align-items: center; justify-content: center; padding: 15px; height: 50px; background-color: #fff; } // 分界线 .boundary { width: 100%; height: 24upx; background-color: #ddd; } .content { width: 100%; box-sizing: border-box; padding-bottom: 80upx; .jgdDisposeInformation { padding: 0 32upx; .title { margin-top: 20upx; text { font-size: 34upx; color: #333333; font-weight: 900; } } .remark { padding: 20upx 0; view { display: flex; text { display: inline-block; width: 150upx; } text:nth-child(2) { display: inline-block; width: 450upx; } } } } .orderInfomation { padding: 0 32upx; .title { margin-top: 20upx; text { font-size: 34upx; color: #333333; font-weight: 900; } } .oderDetail { padding: 20upx 0; view { font-size: 32upx; color: #333333; font-weight: 400; line-height: 50upx; } .WaybillNumber, .name, .commonCarrier, .car { display: flex; justify-content: start; text:nth-child(1) { display: inline-block; width: 160upx; font-size: 30upx; font-weight: 700; } text:nth-child(2) { display: inline-block; width: auto; font-weight: 500; font-size: 30upx; } image { display: flex; width: 40upx; height: 40upx; justify-content: center; margin-left: 15upx; margin-top: 4upx; margin-right: 20upx; } } } } .alarmInformation { margin-top: 20upx; padding: 0 32upx; .title { text { font-size: 34upx; color: #333333; font-weight: 900; } } .alarmDetail { padding: 20upx 0; view { font-size: 32upx; color: #333333; font-family: PingFang SC; font-weight: 400; line-height: 50upx; } .alarmDetailItem { display: flex; justify-content: start; text:nth-child(1) { display: inline-block; width: 160upx; font-weight: 700; font-size: 30upx; } text:nth-child(2) { display: inline-block; width: 520upx; font-weight: 500; font-size: 30upx; } } } } .alarmAnnex { margin-top: 20upx; padding: 0 32upx; .title { text { font-size: 34upx; color: #333333; font-weight: 900; } } .annexDetail { padding: 20upx 0; image { display: inline-block; width: 100%; height: 516upx; } } .annexDetail_video { width: 100%; height: 516upx; margin-top: 48upx; } .annexDetail_map { position: relative; .map { margin-top: 20upx; width: 100%; height: 416upx; } image { width: 100upx; height: 100upx; position: absolute; top: 75%; left: 35%; z-index: 2; } } .empty { width: 500upx; height: 300upx; margin-left: 50%; margin-top: 35%; transform: translate(-50%, -50%); image { display: block; width: 100%; } text { display: block; width: 100%; text-align: center; margin: 0 auto; font-size: 28upx; color: #333333; } } .page-section { width: 100%; height: 300upx; } } .footer_btn { display: flex; flex-direction: column; margin-top: 86upx; padding: 0 32upx; view { height: 80upx; background-color: #2257FF; border-radius: 40upx; line-height: 80upx; text-align: center; color: #fff; } .overlook { background-color: #fff; color: #2257FF; border: 1px solid #2257FF; margin-top: 30upx; } } .map_button { justify-content: space-between; flex-direction: row; image:nth-child(1) { width: 80upx; height: 80upx; position: absolute; top: 90%; left: 30%; transform: translate(-50%, -50%); z-index: 55; } image:nth-child(2) { width: 80upx; height: 80upx; position: absolute; top: 90%; left: 50%; transform: translate(-50%, -50%); z-index: 55; } image:nth-child(3) { width: 80upx; height: 80upx; position: absolute; top: 90%; left: 70%; transform: translate(-50%, -50%); z-index: 55; } } } </style>哪里出问题了
最新发布
08-26
<template> <q-page :key="$route.fullPath"> <!--表头--> <q-banner class="q-py-sm q-px-xs"> <q-breadcrumbs> <q-breadcrumbs-el v-for="item in breadcrumbs" :key="item" :label="item" icon="widgets" /> </q-breadcrumbs> </q-banner> <div class="row q-py-xs q-px-xs items-center"> <div class="col-2"> <q-select dense outlined v-model="scriptListContext.currentView" :options="scriptListContext.views" option-label="name" option-value="id" emit-value map-options @update:model-value="changedView" fit :label="t(&#39;Views&#39;)" /> </div> <div class="q-mx-sm"> <q-btn v-if="scriptListContext.currentView == scriptListContext.recordType?.id" color="brown-5" :label="t(&#39;Customise View&#39;)" @click="customiseView" /> <q-btn v-else color="brown-5" :label="t(&#39;Edit View&#39;)" @click="editView" /> </div> <div><actions-bar-component v-model:script-list-context="scriptListContext" :actives="scriptListContext.buttons" :data="null"></actions-bar-component></div> </div> <q-card flat class="q-pl-xs q-pb-xs q-br-sm q-pt-sm"> <q-card-actions class="bg-grey-3" align="left" vertical> <q-btn color="grey" flat dense size="xs" :icon="expanded ? &#39;keyboard_arrow_up&#39; : &#39;keyboard_arrow_down&#39;" @click="expanded = !expanded"></q-btn> </q-card-actions> <q-slide-transition> <div v-show="expanded"> <div class="q-gutter-xs q-pa-sm"> <q-btn color="primary" @click="handleSearch" :label="t(&#39;Search&#39;)" /> <q-btn color="primary" @click="resetSearch" :label="t(&#39;Reset&#39;)" /> </div> <q-card-section v-show="search.searchAvailableFilters.length > 0" class="q-gutter-x-md items-center example-break-row"> <div class="row items-start example-container q-gutter-xs"> <template v-for="availableFilter in search.searchAvailableFilters" :key="availableFilter.id"> <template v-if="availableFilter.field.fieldViewType == 0"> <q-checkbox v-model="queryParams[availableFilter.fieldCustomId]" :label="availableFilter.field.name" left-label></q-checkbox> </template> <template v-else-if="availableFilter.field.fieldViewType == 7"> <q-input v-model="queryParamsTemp[availableFilter.fieldCustomId]" :label="availableFilter.field.name" @update:model-value=" (val) => { updateFilter(availableFilter.field, val); } " dense ></q-input> </template> <template v-else-if="availableFilter.field.fieldViewType == 2"> <q-input filled v-model="queryParamsTemp[availableFilter.fieldCustomId + &#39;_from&#39;]" :label="availableFilter.field.name" dense @update:model-value=" (val) => { updateFilterDate(availableFilter, &#39;from&#39;, val); } " > <template v-slot:append> <q-icon name="event" class="cursor-pointer"> <q-popup-proxy cover transition-show="scale" transition-hide="scale"> <q-date v-model="queryParamsTemp[availableFilter.fieldCustomId + &#39;_from&#39;]" mask="YYYY-MM-DD" @update:model-value=" (val, reason, details) => { updateFilterDate(availableFilter, &#39;from&#39;, val, reason, details); } " > <div class="row items-center justify-end"> <q-btn v-close-popup label="Close" color="primary" flat></q-btn> </div> </q-date> </q-popup-proxy> </q-icon> </template> </q-input> <span>至</span> <q-input filled v-model="queryParamsTemp[availableFilter.fieldCustomId + &#39;_to&#39;]" :label="availableFilter.field.name" dense @update:model-value=" (val) => { updateFilterDate(availableFilter, &#39;to&#39;, val); } " > <template v-slot:append> <q-icon name="event" class="cursor-pointer"> <q-popup-proxy cover transition-show="scale" transition-hide="scale"> <q-date v-model="queryParamsTemp[availableFilter.fieldCustomId + &#39;_to&#39;]" mask="YYYY-MM-DD" @update:model-value=" (val, reason, details) => { updateFilterDate(availableFilter, &#39;to&#39;, val, reason, details); } " > <div class="row items-center justify-end"> <q-btn v-close-popup label="Close" color="primary" flat></q-btn> </div> </q-date> </q-popup-proxy> </q-icon> </template> </q-input> </template> <template v-else-if="availableFilter.field.fieldViewType == 13"> <q-select v-model="queryParams[availableFilter.fieldCustomId]" :options="fieldOptions[availableFilter.fieldCustomId]" :label="availableFilter.field.name" use-input :option-value="availableFilter.field.fieldListOrRecordTypeIsList ? &#39;value&#39; : &#39;id&#39;" option-label="name" emit-value map-options @filter=" (val, update, abort) => { filterFn(availableFilter.field, val, update, abort); } " @filter-abort="abortFilterFn" @update:model-value="updateModelValue" :loading="optionLoading" dense clearable ></q-select> </template> </template> </div> </q-card-section> </div> </q-slide-transition> <q-card-section class="q-pl-xs q-pr-md q-pb-xs"> <q-table class="my-sticky-header-last-column-table" row-key="id" separator="cell" :rows="scriptListContext.items" :columns="columns" dense v-model:pagination="scriptListContext.pagination" :rows-per-page-options="pageOptions" :loading="loading" @request="onRequest" > <template v-slot:top="props"> <q-checkbox v-model="showInactives" :label="t(&#39;ShowInactives&#39;)"></q-checkbox> <q-space></q-space> <q-btn color="primary" icon-right="archive" :label="t(&#39;ExportToExcel&#39;)" no-caps @click="exportTable"></q-btn> <q-btn flat round dense :icon="props.inFullscreen ? &#39;fullscreen_exit&#39; : &#39;fullscreen&#39;" @click="props.toggleFullscreen" class="q-ml-md"></q-btn> </template> <template v-slot:body="props"> <q-tr :props="props"> <q-td v-for="col in columns" :key="col.name" :props="props"> <div> {{ props.row.value }} <div v-if="col.name == &#39;index&#39;">{{ props.rowIndex + 1 }}</div> <template v-else-if="col.name == &#39;actions&#39;"> <actions-bar-component v-model:script-list-context="scriptListContext" :actives="scriptListContext.buttonsRow" :data="props.row"></actions-bar-component> </template> <q-checkbox v-else-if="col.fieldModel?.fieldViewType == fieldViewTypeEnum.CheckBox" v-model="props.row[col.fieldModel.customId]" dense disable></q-checkbox> <template v-else-if="col.fieldModel?.fieldViewType == fieldViewTypeEnum.ListOrRecord"> {{ props.row[col.name] }} </template> <template v-else> {{ props.row[col.name] }} </template> </div> </q-td> </q-tr> </template> </q-table> </q-card-section> </q-card> </q-page> </template> <script setup lang="ts"> import { fetchListResult } from "src/api/customization/search"; import ActionsBarComponent from "src/components/ViewContent/ActionsBarComponent.vue"; import useTableList from "src/composables/useTableList"; import { IActive } from "src/interfaces/IActive"; import { IField } from "src/interfaces/IField"; import { Iparams } from "src/interfaces/Iparams"; import { Icolumn } from "src/interfaces/Icolumn"; import { IScriptListContext } from "src/interfaces/IScriptListContext"; import { formateList } from "src/modules/common-functions/datetimeOpration"; import { exportExcel } from "src/modules/common-functions/excelOpration"; import { onMounted, ref, watch } from "vue"; import { useRoute, useRouter } from "vue-router"; import { useI18n } from "vue-i18n"; import { toRecordTypePage } from "src/utils/routeRedirection"; import { fieldViewTypeEnum } from "src/enums/fieldViewTypeEnum"; import { operatorType } from "src/enums/operatorType"; import { getAction } from "src/api/manage"; import { addLoadingTotal, getLoadingTotal, loadingOne, setQuasar } from "src/modules/common-functions/loadingStatus"; import { listPage } from "src/modules/listPageCS"; const { t } = useI18n(); const route = useRoute(); const router = useRouter(); const showInactives = ref(true); const breadcrumbs: string[] = String(route.name || "").split(","); const optionLoading = ref(false); const expanded = ref(true); const fieldOptions: Record<string, any> = ref({}); const queryParamsTemp: Record<string, any> = ref({}); //初始化查询参数 const queryParas = ref<Iparams>({ RecordTypeId: "", IsInActive: showInactives.value, SkipCount: 0, MaxResultCount: 1000, Filter: "", }); //行按钮 const defaultRowActives: Array<IActive> = [ { id: "btn-view", name: "view", label: "查看", displayAS: 0, function: "", showInView: false, showInEdit: false, location: "row", isStandard: true, }, { id: "btn-edit", name: "edit", label: "编辑", displayAS: 0, function: "", showInView: false, showInEdit: false, location: "row", isStandard: true, }, { id: "btn-delete", name: "delete", label: "删除", displayAS: 0, function: "", showInView: false, showInEdit: false, location: "row", isStandard: true, }, ]; //主表按钮 const defaultActives: Array<IActive> = [ { id: "btn-new", name: "new", label: "新建", displayAS: 0, function: "handleCreate", showInView: false, showInEdit: false, location: "main", isStandard: true, }, ]; //上下文对象 const scriptListContext = ref<IScriptListContext>({ items: [], recordType: { id: route.query.id as string }, fieldOptions: {}, title: "", views: [], currentView: "", fields: [], colsApi: "", rowsApi: "/master-currency/paged", pagination: { sortBy: "", descending: false, page: 1, rowsPerPage: 100, rowsNumber: 0, }, buttons: defaultActives, buttonsRow: defaultRowActives, addButton: (button: IActive) => addButton(button), removeButton: (buttonId: string) => removeButton(buttonId), }); //列属性 const columns = ref<Icolumn[]>([ { name: "index", label: "序号", field: "index", align: "center" as const, headerStyle: "width: 60px", sortable: false, }, { name: "curName", required: true, label: "币别名称", field: "curName", align: "left" as const, sortable: true, }, { name: "isoCode", align: "center" as const, label: "货币ISO代码", field: "isoCode", sortable: true, }, { name: "formatSymbol", label: "显示符号", field: "formatSymbol", sortable: true, }, { name: "isInActive", label: "禁用", field: "isInActive", sortable: true, }, { name: "actions", label: "操作", field: "actions", align: "center" as const, headerStyle: "width: 100px", sortable: false, }, ]); const _listPage = new listPage(scriptListContext as Ref<IScriptListContext>); // 加载数据 onMounted(async () => { await _listPage.pageInit(); getTableData(); }); watch( () => scriptListContext.value.items, (newValue, oldValue) => { formateList(newValue, columns.value); }, { deep: true } ); const addButton = function (button: IActive) { if (button.location?.toLowerCase() == "row") { scriptListContext.value.buttonsRow.push(button); } else { scriptListContext.value.buttons.push(button); } }; const removeButton = function (buttonId: string) { const rb = scriptListContext.value.buttonsRow.find((item: IActive) => item.id == buttonId); if (rb) { scriptListContext.value.buttonsRow.splice(scriptListContext.value.buttonsRow.indexOf(rb), 1); } const btn = scriptListContext.value.buttons.find((item: IActive) => item.id == buttonId); if (btn) { scriptListContext.value.buttons.splice(scriptListContext.value.buttons.indexOf(btn), 1); } }; const { $q, queryParams, pageOptions, loading, onRequest, //服务器端分页 search, getTableData, //初始化加载 handleSearch, //search按钮 resetSearch, //reset按钮 } = useTableList(scriptListContext as Ref<IScriptListContext>, t); setQuasar($q); /** ========== export excel ============== */ const exportTable = async () => { const exportData = await getExportData(); exportExcel(exportData, columns.value); }; const getExportData = async () => { const params: Iparams = { Sorting: scriptListContext.value.pagination.sortBy, Descending: scriptListContext.value.pagination.descending, SkipCount: 0, MaxResultCount: 300, RecordTypeId: "", IsInActive: false, Filter: "", }; const filterParams = { Filter: JSON.stringify(queryParams.value), }; if (!scriptListContext.value.pagination.rowsNumber) return []; const totalPage = scriptListContext.value.pagination.rowsNumber / params.MaxResultCount; addLoadingTotal(totalPage); let exportData: Array<any> = []; for (let i = 0; i < totalPage; i++) { const allParams = Object.assign({}, params, filterParams); await getAction(scriptListContext.value.rowsApi, allParams).then((res) => { exportData = exportData.concat(res.items); params.SkipCount += params.MaxResultCount; loadingOne(); }); } addLoadingTotal(-1 * getLoadingTotal()); return exportData; }; /** ============= 过滤条件 ================ */ const getFieldOptions = async (field: IField, query: Iparams) => { optionLoading.value = true; await fetchListResult(field.fieldListOrRecordTypeId, query) .then((response) => { fieldOptions.value[field.customId] = response.items; }) .catch((res) => { console.log("error res:", res); }) .finally(() => { optionLoading.value = false; }); }; const filterFn = async (field: IField, val: string, update: any, abort: any) => { const queryFilter: any | object = {}; queryFilter["keywords"] = `opt_${operatorType.Like} ${val}`; // &#39;opt_6 &#39; + val queryParas.value.SkipCount = 0; queryParas.value.MaxResultCount = 100; queryParas.value.Filter = JSON.stringify(queryFilter); if (!val) { update(async () => { await getFieldOptions(field, queryParas.value); }); return; } update(async () => { await getFieldOptions(field, queryParas.value); }); }; const abortFilterFn = () => { // console.log(&#39;delayed filter aborted&#39;) }; const updateModelValue = (val: any) => { // console.log(&#39;updateModelValue&#39;, val) }; const updateFilterDate = (availableFilter: any, direction: string, val: any, reason = "", details: object = {}) => { var values = [queryParamsTemp.value[availableFilter.fieldCustomId + "_from"], queryParamsTemp.value[availableFilter.fieldCustomId + "_to"]]; queryParams.value[availableFilter.fieldCustomId] = "opt_11" + " " + JSON.stringify(values); }; const updateFilter = (field: IField, val: any) => { queryParams.value[field.customId] = "opt_6" + " " + val; }; const changedView = (val: string) => { toRecordTypePage(router, scriptListContext.value.recordType?.customId as string, "list", "", val); }; /** ============= 视图定义 ================ */ const editView = () => { toRecordTypePage(router, "search", "edit", scriptListContext.value.currentView, "3a0eb999-3fa6-d262-4b4e-f85331d1ca7d", undefined, "_blank"); }; const customiseView = () => { toRecordTypePage(router, "search", "create", scriptListContext.value.currentView, "3a0eb999-3fa6-d262-4b4e-f85331d1ca7d", { copy: "T" }, "_blank"); }; </script> <style lang="sass"> .example-break-row .flex-break flex: 1 0 100% !important height: 0 !important .my-sticky-header-last-column-table /* height or max-height is important */ height: 70vh table border-bottom: 1px solid rgba(0, 0, 0, 0.12); /* specifying max-width so the example can highlight the sticky column on any browser window */ // max-width: 600px td:last-child /* bg color is important for td; just specify one */ background-color: #eeeeee tr th position: sticky /* higher than z-index for td below */ z-index: 2 /* bg color is important; just specify one */ background: #eeeeee /* this will be the loading indicator */ thead tr:last-child th /* height of all previous header rows */ top: 48px /* highest z-index */ z-index: 3 thead tr:first-child th top: 0 z-index: 1 tr:last-child th:last-child /* highest z-index */ z-index: 3 td:last-child z-index: 1 td:last-child, th:last-child position: sticky right: 0 /* prevent scrolling behind sticky top row on focus */ tbody /* height of all previous header rows */ scroll-margin-top: 48px tbody tr:nth-child(even) background-color:#fafafa a &:link, &:visited color: blue text-decoration: none &:hover color: purple &:active color: blue .text-orignblue color: red !important .horizontal-items display: flex flex-wrap: nowrap justify-content: space-between align-items: center > q-item margin-right: 10px &:last-child margin-right: 0 // 如果需要为 q-item 添加更多样式,可以在这里继续嵌套 // 例如: // &:hover // background-color: lightgray </style> 一句一句给我解释
07-31
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值