Files
t/uni_modules/zetank-personalpage/pages/personalpage/personalpage.vue
T
root 4f5893f87a fix: 修复首页空白/失效外链/云函数越权,补齐缺失页面与种子数据
## 阻断性缺陷
- list.vue 是 0 字节空文件、slist.vue 与 search/search.vue 从未存在,
  而前者是 tabBar 首页、后者是 tabBar「搜索」页 —— 开屏即白屏。
  按 .nvue 原型与详情页契约重建三页(CSS 渐变主视觉、分类筛选、搜索历史/热搜/联想)。
- parse-image-url.js 对空封面调 undefined.startsWith 直接抛错,列表页整页崩。
- 云函数目录缺 uni-cms-articles / uni-cms-categories / uni-cms-unlock-record
  schema 与 schema.ext.js,线上内容渲染与解锁逻辑无配置可用。

## 越权与数据一致性
- uni-cms-articles:del/update/add 全部无鉴权,未登录即可删任意文章、
  改他人文章作者与阅读量。补 login + 作者归属校验,作者与计数改为服务端取值。
- comments.likeComment/relikeComment:直接采信客户端传入的 user_id,
  可冒名点赞刷计数。改为以令牌为准,并纳入事务。
- comments.updateComment:对数组取 .author_id,权限判断恒失败;
  字段名 updateTime 与 ip_location 类型与 schema 不符。
- comments.deleteComment:`!root_id === 0` 优先级错误导致计数恒不减;
  且误更新 uni-cms-articles、按不存在的 type 字段删点赞明细产生孤儿数据。
- cms-articles-like/collect:查重条件混入本次请求时间戳,防重永远失效,
  可无限重复刷计数;补唯一索引并事务化。
- cms-vote:读-改-写票数导致并发丢票,记录与统计非原子;改为事务 + 原子自增。
- cms-articles-log:忽略传入 user_id 直接返回全表,泄露全站浏览记录。
- article_info:get() 使用未定义变量必崩;读接口全部无鉴权。
- user-info:公开资料接口可查任意用户 last_login_ip。

## 资源与数据
- 全项目清空失效的签名外链(expire_at 均为 2025-03,必然 403),
  改为本地生成资源:6 套文章模板、8 个编辑器图标、2 张文章配图。
- 新增分类 / 模板 / 礼物 / 热搜词种子数据,并在 db_init.json 登记,
  同时补上点赞、收藏、投票、浏览日志的唯一索引。

## 功能
- 草稿箱:预览页拆出「发布」与「存为草稿」,作品列表按状态筛选并显示徽标。
  原实现有 4 个 tab 但只有 1 个有内容,且 article_status 在 UI 上无体现。
- 编辑中断恢复:接上原本空实现的「编辑草稿」回调,区分新建与编辑已有文章。

## 工具
- tools/audit-project.js:编码 / 页面路由 / 云调用 / 云函数鉴权 / 敏感信息检查
- tools/check-vue.js:SFC 脚本语法(词法扫描处理 import·export 与条件编译)
- tools/verify.js:一键验证;两个检查器各带自测,防止"永远通过"
- tools/gen-*.py:模板与图标资源生成脚本
2026-09-11 17:48:27 +08:00

774 lines
22 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view>
<z-paging ref="paging" :fixed="true" @scroll="scroll" @query="queryData" :hide-empty-view="true">
<image class="info-cover" @tap="fnMainBgPic"
src="https://qnycdn.mymoyu.top/static/17b0292c-8a63-4b7b-a6a6-724f416a9958.jpg"
mode="scaleToFill"></image>
<!-- 用户头像关注 -->
<view class="u-flex-wrap"
style="padding-top: 18rpx;padding-bottom: 18rpx;position: relative;align-items: center;display: flex;flex-direction: row;justify-content: flex-end;">
<view class="info-avatar" >
<cloud-image width="135rpx" height="135rpx" border-radius="50%"
v-if="userinfo.avatar_file"
:src="userinfo.avatar_file.url">
</cloud-image>
</view>
<view style="margin-right: 50rpx;" v-if="uid === userInfo._id">
<u-tag v-if='showedit' text="编辑信息" mode="dark" shape="" bg-color="#f5991e" @click="UserEdit" />
<view v-if='!showedit' style="height: 45rpx;"></view>
</view>
<view style="margin-right: 50rpx;" v-else>
<u-tag v-if='showedit' :text="!isFollow?'关注':'取消关注'"
@click="toFollow()"
mode="dark" shape="" :bg-color="!isFollow?'#6699ff':'#ffcc66'" />
<view v-if='!showedit' style="height: 45rpx;"></view>
</view>
</view>
<!-- 用户名 -->
<view style="display: flex;align-items: center;margin-left: 50rpx;margin-top: 20rpx;"
v-if="userinfo.length!=0">
<text
style="font-size: 32rpx;color: #111111;font-weight: bold;margin-right: 10rpx;">{{userinfo.nickname}}</text>
<u-icon v-if="userinfo.gender === 0" :name="userinfo.gender===1?'man':'woman'" :color="userinfo.gender===1?'#4baed5':'#f5991e'"
size="30"></u-icon>
</view>
<!-- 单位职务 -->
<view class="u-flex">
<view style="display: flex;align-items: center;margin-left: 50rpx;margin-top: 20rpx;"
v-if="userinfo.length!=0">
<u-icon name="map-fill" size="32" color="#4baed5"></u-icon>
<text style="font-size: 24rpx;color: #555555;margin-left: 10rpx;">{{userinfo.city}}</text>
</view>
</view>
<!-- 简介-->
<view style="font-size: 24rpx;color: #555555;margin:20rpx 50rpx;" v-if="userinfo.length!=0">
<u-tag v-if='membertype!=""' :text="membertype" mode="dark" shape="circle" bg-color="#4baed5" />
<text style="margin-right: 20rpx;">{{!Information?'暂无简介':Information}}</text>
</view>
<view v-if="isFixed" style="height: 90rpx;line-height: 90rpx;background-color: white;margin-bottom: 18rpx;">
</view>
<view id="tabbar" :class="isFixed?'tabbar-fixed':''"
style="border-bottom:18rpx #f8f8f8 solid ;align-items: stretch;height: 90rpx;line-height: 90rpx;background-color: white;margin-bottom: 18rpx; display: flex;flex-direction: row;justify-content: space-around;">
<view style="font-size: 32rpx;font-weight: bold;text-align: center;width: 128rpx;"
:class="current == 0?'tabbarsh':'notabbarsh'" @tap="fnBarClick(0)">动态</view>
<view style="font-size: 32rpx;font-weight: bold;text-align: center;width: 128rpx;"
:class="current == 1?'tabbarsh':'notabbarsh'" @tap="fnBarClick(1)">他的收藏</view>
</view>
<!-- 导航显示内容 -->
<view v-if='current === 0'>
<unicloud-db ref='udb' v-slot:default="{ pagination, hasMore, loading, error, options }"
orderby="last_view_time desc" @error="onqueryerror" :page-size="10"
@onPullDownRefresh="onPullDownRefresh" @load="listLoad" :collection="colList">
<!-- 基于 uni-list 的页面布局 field="user_id.nickname"-->
<!-- #ifdef APP-NVUE -->
<list class="uni-list" :border="false" >
<!-- #endif -->
<!-- #ifndef APP-NVUE -->
<scroll-view scroll-y class="uni-list" refresher-enabled
:refresher-triggered="loadType=== 'refresh'"
@refresherrefresh="refresh" @scrolltolower="loadMore">
<!-- #endif -->
<!-- #ifdef APP-NVUE -->
<refresh-box :loading="loading" @refresh="refresh"></refresh-box>
<!-- #endif -->
<!-- 列表渲染 -->
<template v-for="item in listData">
<view class="" v-if="item.article_status === 1">
<not-cover v-if="item.thumbnail && item.thumbnail.length === 0"
:data="getNewItem(item)"></not-cover>
<right-small-cover v-else-if="item.thumbnail && item.thumbnail.length === 1"
:data="getNewItem(item)"></right-small-cover>
<three-cover v-else-if="item.thumbnail && item.thumbnail.length === 3"
:data="getNewItem(item)"></three-cover>
</view>
</template>
<!-- 加载状态:上拉加载更多,加载中,没有更多数据了,加载错误 -->
<!-- #ifdef APP-PLUS -->
<uni-list-item>
<template v-slot:body>
<!-- #endif -->
<uni-load-state @networkResume="refresh"
:state="{ data: listData, pagination, hasMore, loading, error }"
@loadMore="loadMore">
</uni-load-state>
<!-- #ifdef APP-PLUS -->
</template>
</uni-list-item>
<!-- #endif -->
<!-- #ifndef APP-NVUE -->
</scroll-view>
<!-- #endif -->
<!-- #ifdef APP-NVUE -->
</list>
<!-- #endif -->
</unicloud-db>
</view>
<view v-if='current === 1'>
<unicloud-db ref='udb1' v-slot:default="{ pagination, hasMore, loading, error, options }"
orderby="last_view_time desc" @error="onqueryerror" :page-size="10"
@onPullDownRefresh="onPullDownRefresh" @load="listLoad1" :collection="colList1">
<!-- 基于 uni-list 的页面布局 field="user_id.nickname"-->
<!-- #ifdef APP-NVUE -->
<list class="uni-list" :border="false" :style="{ height: listHeight }">
<!-- #endif -->
<!-- #ifndef APP-NVUE -->
<scroll-view scroll-y class="uni-list" refresher-enabled @scrolltolower="loadMore1">
<!-- #endif -->
<!-- #ifdef APP-NVUE -->
<refresh-box :loading="loading" @refresh="refresh1"></refresh-box>
<!-- #endif -->
<!-- 列表渲染 -->
<template v-for="item in listData1">
<view class="" v-if="item.article_status === 1">
<not-cover v-if="item.thumbnail && item.thumbnail.length === 0"
:data="getNewItem(item)"></not-cover>
<right-small-cover v-else-if="item.thumbnail && item.thumbnail.length === 1"
:data="getNewItem(item)"></right-small-cover>
<three-cover v-else-if="item.thumbnail && item.thumbnail.length === 3"
:data="getNewItem(item)"></three-cover>
</view>
</template>
<!-- 加载状态:上拉加载更多,加载中,没有更多数据了,加载错误 -->
<!-- #ifdef APP-PLUS -->
<uni-list-item>
<template v-slot:body>
<!-- #endif -->
<uni-load-state @networkResume="refresh1"
:state="{ data: listData1, pagination, hasMore, loading, error }"
@loadMore="loadMore1">
</uni-load-state>
<!-- #ifdef APP-PLUS -->
</template>
</uni-list-item>
<!-- #endif -->
<!-- #ifndef APP-NVUE -->
</scroll-view>
<!-- #endif -->
<!-- #ifdef APP-NVUE -->
</list>
<!-- #endif -->
</unicloud-db>
</view>
</z-paging>
</view>
</template>
<script>
import statusBar from "@/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-status-bar";
import translatePublishTime from "@/uni_modules/uni-cms-article/common/publish-time";
import refreshBox from "@/uni_modules/uni-cms-article/components/refresh-box/refreshBox.nvue";
import notCover from "@/uni_modules/uni-cms-article/components/list-template/not-cover.vue";
import rightSmallCover from "@/uni_modules/uni-cms-article/components/list-template/right-small-cover.vue";
import threeCover from "@/uni_modules/uni-cms-article/components/list-template/three-cover.vue";
import {
parseImageUrl
} from "@/uni_modules/uni-cms-article/common/parse-image-url";
import cloudImage from "@/components/cloud-image.vue"
const db = uniCloud.database();
const articleDBName = 'uni-cms-articles'
const userDBName = 'uni-id-users'
const uniIdCo = uniCloud.importObject("uni-id-co")
import {
store,
mutations
} from '@/pages3/uni_modules/uni-id-pages/common/store.js';
export default {
components: {
statusBar,
refreshBox,
notCover,
rightSmallCover,
threeCover,
cloudImage
},
computed: {
userInfo() {
return store.userInfo
},
realNameStatus() {
if (!this.userInfo.realNameAuth) {
return 0
}
return this.userInfo.realNameAuth.authStatus
},
// 根据当前语言返回不同的搜索框占位符
inputPlaceholder(e) {
if (uni.getStorageSync('CURRENT_LANG') == "en") {
return 'Please enter the search content' // 英文
} else {
return '请输入搜索内容' // 中文
}
},
// 连表查询,返回两个集合的查询结果
colList() {
return [
db.collection(articleDBName).where(this.articleWhere).field(
'thumbnail,article_status,title,publish_date,user_id,excerpt').getTemp(), // 文章集合
db.collection(userDBName).field('_id,nickname').getTemp() // 用户集合
];
},
colList1() {
return [
db.collection("cms-articles-collect")
.where(this.collectWhere)
.getTemp(),
db.collection(articleDBName)
.field('_id,thumbnail,title,publish_date,user_id, excerpt, article_status')
.getTemp(),
db.collection(userDBName)
.field('_id,nickname')
.getTemp()
];
},
articleWhere() {
return this.uid ? {
user_id: this.uid
} : {
user_id: '__empty__'
}
},
collectWhere() {
return this.uid ? {
user_id: this.uid
} : {
user_id: '__empty__'
}
}
},
data() {
return {
tags_v: [],
tags: [
],
isFollow:false,
showRefresh: false, // 是否显示刷新按钮
listHeight: 0, // 列表高度
mpButtonLeftPlaceholderSize: 0, // 小程序左侧icon占位大小
mpButtonPlaceholderSize: 87, // 小程序导航栏按钮占位大小
navBarHeight: 44, // 导航栏高度
refreshStatus: 0, // 刷新状态 0: 未刷新 1: 刷新中 2: 刷新完成
listData: [], // 列表数据
listData1: [],
loadType: null,
historyList: [],
uid: '',
userinfo: {
nickname: 'zetank',
gender: 1,
city: '广州',
good: {}
},
where_flag: false,
Information: '本人性格热情开朗,待人友好,为人诚实谦虚。工作勤奋,认真负责,能吃苦耐劳,尽职 尽责,有耐心。具有亲和力,平易近人,善于与人沟通',
membertype: '',
showedit: true, //信息编辑按钮
// 是否固定导航
isFixed: false,
// 距离顶部达到导航距离
topNum: 0,
// 选中
current: 0,
// 导航距离顶部
tabbarTop: 0,
clickRefresh: false,
// 刷新间隔
timeOutUserInfo: 0,
// 激活顶部导航关联页状态
status: {
publish: true,
praise: false,
},
}
},
async onLoad(option) {
// 等待0.3秒页面渲染,$nextTick使用不能准确
setTimeout(() => {
this.getInfo(option);
this.getIsFollow(option);
uni.hideLoading()
// 获取导航条距顶部高度
this.setTabbarTop();
}, 300);
},
created() {
},
async onReady() {
},
methods: {
async getIsFollow(option) {
console.log(this.userInfo)
console.log(option)
const res = await uniCloud.importObject("follow").getIsFollow({
uid: this.userInfo._id,
fid: option.uid
})
console.log(res)
if (res.code === 200) this.isFollow = res.isFollow;
else {
console.log("关注检测异常")
}
},
async toFollow() {
console.log(this.isFollow)
try {
if (this.isFollow === false) {
const res = await uniCloud.importObject("follow").follow({
uid: this.userInfo._id,
fid: this.uid
});
if (res.code === 200) {
console.log(res);
this.isFollow = true;
} else {
console.log(res.msg);
}
}
else if (this.isFollow === true) {
const res = await uniCloud.importObject("follow").reFollow({
uid: this.userInfo._id,
fid: this.uid
});
if (res.code === 200) {
if (res.code === 200) {
console.log(res);
this.isFollow = false;
}
} else {
console.log(res.msg)
}
}
}catch(e) {
console.log(e.message)
}
},
checkUrlProtocol(url) {
try {
const protocolSeparatorIndex = url.indexOf('://');
if (protocolSeparatorIndex === -1) {
return 'invalid';
}
const protocol = url.substring(0, protocolSeparatorIndex).toLowerCase();
if (protocol === 'http' || protocol === 'https') {
return 'http/https';
} else if (protocol === 'cloud') {
return 'cloud';
} else {
return 'other';
}
} catch (error) {
return 'invalid';
}
},
async getInfo(option) {
this.uid = option.uid;
if (this.uid) { // ID 不为空,则发起查询
console.log(this.uid);
this.where_flag = true;
const res = await uniCloud.importObject("user-info").get_user_info({
uid: this.uid
});
if (res) console.log(res);
if (res.code === 200 ) {
this.userinfo = res.data;
this.gender = res.data.gender;
// last_login_ip 属于隐私字段,公开资料接口已不再返回。
// 个人主页不展示登录地点,留空即可。
this.userinfo.city = '';
this.userinfo.nickname = res.data.nickname;
this.userinfo.avatar_file = res.data.avatar_file;
this.userinfo._id = res.data._id;
this.Information = res.data.personal_profile;
this.$refs.udb.loadData()
}
} else {
uni.showToast({
icon: 'none',
title: 'id 不能为空'
})
}
},
bt(t) {
console.log(t);
},
getNewItem(item) {
if (!item.excerpt) {
item.excerpt = "";
} else if (item.excerpt.length > 50) {
item.excerpt = item.excerpt.slice(0, 50) + " ... ...";
}
return item;
},
async listLoad(data) {
if (data.length !== 0) {
const listData = data.map(item => {
if (typeof item.thumbnail === 'string') {
item.thumbnail = [item.thumbnail]
}
return item
})
// 处理腾讯云文件链接
for (const article of listData) {
const parseImages = await parseImageUrl(article.thumbnail)
article.thumbnail = parseImages ? parseImages.map(image => image.src) : []
}
this.listData = this.loadType === 'loadMore' ? this.listData.concat(listData) : listData
this.loadType = null
} else {
this.listData = this.loadType === 'loadMore' ? this.listData.concat([]) :[];
this.loadType = null
}
},
async listLoad1(data) {
console.log(data)
if(data.lenght !== 0) {
const listData1 = data.map(item => {
if (typeof item.article_id.thumbnail === 'string') {
item.article_id[0].thumbnail = [item.article_id[0].thumbnail]
}
item.article_id[0].user_id = item.user_id[0];
console.log(item);
item.article_id[0].last_view_time = new Date(item.last_view_time).getTime();
return item.article_id[0];
})
console.log(listData1);
// 处理腾讯云文件链接
for (const article of listData1) {
const parseImages = await parseImageUrl(article.thumbnail)
article.thumbnail = parseImages ? parseImages.map(image => image.src) : []
}
this.listData1 = this.loadType === 'loadMore' ? this.listData1.concat(listData1) : listData1
this.loadType = null
} else {
this.listData1 = this.loadType === 'loadMore' ? this.listData1.concat([]) : []
this.loadType = null;
}
},
// 初始化导航栏大小
initNavBarSize() {
// 获取小程序导航栏按钮信息
// #ifdef MP-TOUTIAO
let menuButtonInfo = tt.getCustomButtonBoundingClientRect()
menuButtonInfo.width = menuButtonInfo.capsule.width // 小程序按钮区域中使用的按钮宽度
this.mpButtonLeftPlaceholderSize = menuButtonInfo.leftIcon.width + 10
// #endif
// #ifndef MP-TOUTIAO
let menuButtonInfo = uni.getMenuButtonBoundingClientRect()
// #endif
// 计算小程序导航栏按钮占位大小
this.mpButtonPlaceholderSize = menuButtonInfo.width + 10
// 获取系统信息,判断是否为 iOS 系统,设置导航栏高度
this.navBarHeight = uni.getSystemInfoSync().system.toLowerCase().includes('ios') ? 44 : 48
},
// 格式化时间戳
publishTime(timestamp) {
return translatePublishTime(timestamp)
},
// 点击搜索框
searchClick(e) {
uni.hideKeyboard();
uni.navigateTo({
url: '/uni_modules/uni-cms-article/pages/search/search'
});
},
// 重试
retry() {
this.refresh()
},
// 刷新
refresh() {
this.loadType = 'refresh'
this.$refs.udb.loadData({
clear: true
}, () => {
uni.stopPullDownRefresh()
// #ifdef APP-NVUE
this.showRefresh = false
// #endif
})
},
refresh1() {
this.loadType = 'refresh'
this.$refs.udb1.loadData({
clear: true
}, () => {
uni.stopPullDownRefresh()
// #ifdef APP-NVUE
this.showRefresh = false
// #endif
})
},
// 加载更多
loadMore() {
this.loadType = 'loadMore'
this.$refs.udb.loadMore()
},
loadMore1() {
this.loadType = 'loadMore'
this.$refs.udb1.loadMore()
},
// 查询出错
onqueryerror(e) {
console.error(e);
},
// #ifdef H5
// 下拉刷新
onPullDownRefresh() {
this.refresh()
},
// #endif
change(currentPage, type) {
this.page.currentPage = currentPage;
console.log("点击了" + type + ",当前页:" + currentPage);
this.data_clear();
},
async getHistoryList() {
// 云对象方法返回 Promise,必须先 await 才能取到 { code, data }
const res = await uniCloud.importObject("cms-articles-log").getHistoryList({
user_id: this.userinfo._id
});
return (res && res.data) || [];
},
async getHistory() {
return uniCloud.importObject("cms-articles-log").getHistory(this.userinfo._id);
},
// 滚动事件 (需在up配置onScroll:true才生效)
scroll(e) {
this.topNum = e.detail.scrollTop
if (e.detail.scrollTop >= this.tabbarTop) {
this.isFixed = true // 显示悬浮菜单
} else {
this.isFixed = false // 隐藏悬浮菜单
}
},
// 修改用户背景封面图
fnMainBgPic() {
},
//编辑信息
UserEdit() {
uni.navigateTo({
url:"/pages2/setting/setting"
})
},
/// 顶部导航选项点击
fnBarClick(current) {
// console.log(current);
// 是否当前项点击
if (this.current == current) {
this.timeOutUserInfo += 1;
// 是否为刷新值和连续点击2次
// console.log('timeOutUserInfo',this.timeOutUserInfo);
if (!this.clickRefresh && this.timeOutUserInfo >= 2) {
// 刷新值开
// console.log('点击了两下');
this.clickRefresh = true;
// 获取新数据
// 定时器重置
this.timeOutUserInfo = setTimeout(() => {
// 清除定时器
// console.log('5秒后清除定时器');
clearTimeout(this.timeOutUserInfo)
// 连续触发记录重置
this.timeOutUserInfo = 0;
// 5秒后刷新值关
this.clickRefresh = false;
}, 5000);
}
} else {
// 改变顶部导航选中
this.current = current;
// 首次选中激活顶部导航关联页状态
if (!this.status.praise && this.current == 1) this.status.praise = true;
// 获取新数据
// 清除定时器
clearTimeout(this.timeOutUserInfo)
// 连续触发记录重置
this.timeOutUserInfo = 0;
// 刷新值关
this.clickRefresh = false;
}
// 滚动上滑
this.$refs.paging.scrollToY(this.tabbarTop);
// console.log("滚动上滑");
},
// 设置nav到顶部的距离 (滚动条为0, 菜单顶部的数据加载完毕获取到的数值是最精确的)
setTabbarTop() {
let view = uni.createSelectorQuery().in(this).select('#tabbar');
view.boundingClientRect(data => {
// 到屏幕顶部的距离
this.tabbarTop = data.top
}).exec();
},
queryData() {
// this.$refs.paging.reload();
this.$refs.paging.complete([])
}
}
}
</script>
<style lang="scss" scoped>
.info-cover {
display: block;
width: 100%;
height: 260rpx;
}
.info-avatar {
position: absolute;
left: 0;
top: -56rpx;
margin-left: 50rpx;
}
.tabbarsh {
color: #4baed5;
border-bottom: 4rpx #4baed5 solid;
}
.notabbarsh {
color: #555555;
}
.tabbar-fixed {
position: fixed;
left: 0;
right: 0;
/* #ifdef H5 */
top: 0rpx;
/* #endif */
/* #ifndef H5 */
top: 0;
/* #endif */
z-index: 300;
background: #FFFFFF;
margin-bottom: 0;
border-bottom: 2rpx #EEEEEE solid;
}
/* #ifndef APP-NVUE */
.pages view {
display: flex;
box-sizing: border-box;
flex-direction: column;
}
/* #endif */
.pages {
background-color: #FFFFFF;
}
.refresh {
text-align: center;
}
.nav-box {
background-color: #FFFFFF;
position: fixed;
top: 0;
left: 0;
right: 0;
/* #ifndef APP-PLUS */
z-index: 9;
/* #endif */
}
.pages .nav {
display: flex;
align-items: center;
flex-direction: row;
}
.uni-search-box {
flex: 1;
padding: 0 10px;
}
.uni-search-box :deep(.uni-searchbar) {
padding: 0;
}
.uni-search-box :deep(.uni-searchbar__box) {
height: 32px;
flex-direction: row;
}
.cover-search-bar {
position: absolute;
left: 0;
right: 0;
bottom: 0;
top: 0;
/* #ifndef APP-NVUE */
z-index: 999;
/* #endif */
}
.pages .uni-list :deep(.uni-list-item__container) {
flex-direction: row;
width: 100%;
}
.pages .uni-list :deep(.uni-list-item) {
align-items: flex-start;
}
.pages .uni-list :deep(.uni-load-more) {
display: flex;
}
.pages .uni-list :deep(.uni-list--border:after) {
background-color: #f5f5f5;
}
</style>