This commit is contained in:
2024-09-10 10:49:08 +08:00
parent b5fd06b800
commit dd4f5938da
6391 changed files with 722800 additions and 0 deletions

View File

@@ -0,0 +1,134 @@
<!--
Jeepay 门店选择 / 应用选择
@author terrfly
@site https://www.jeequan.com
@date 2022/12/06 12:55
-->
<template>
<!-- 选择门店 -->
<JeepayPopupListSelect
ref="jeepayRedPopupListSelectByBizinfos"
:reqTableDataFunc="reqTableDataByBizsFunc"
:searchInputName="getSearchInputName()"
:fields="getField()"
/>
</template>
<script setup>
import { reactive, ref } from 'vue'
import { reqLoad, API_URL_MCH_STORE_LIST, API_URL_MCH_APP_LIST } from '@/http/apiManager.js'
// 定义组件参数
const props = defineProps({
configMode: { type: String, default: ''}, // 搜索时仅展示商户号
// 是否多选框, 默认单选。
isCheckbox: { type: Boolean, default: false },
// 自动关闭, 点击确定, 自动关闭
autoClose: { type: Boolean, default: true },
// 业务类型: 默认门店
bizType: { type: String, default: 'store' },
// 是否支持选择 【 全部门店 、 全部应用 】
isShowAllBiz: { type: Boolean, default: false },
// 特殊参数处理
params:{type:Object,default:()=>({})}
})
const jeepayRedPopupListSelectByBizinfos = ref()
function getField(){
if(props.bizType == 'store'){
return { key: 'storeId', left: 'storeName', right: 'storeId' }
}
if(props.bizType == 'mchApp'){
return { key: 'appId', left: 'appName', right: 'appId' }
}
}
function getSearchInputName(){
if(props.bizType == 'store'){
return "storeName"
}
if(props.bizType == 'mchApp'){
return "appName"
}
}
function reqTableDataByBizsFunc(params) {
Object.assign(params,props.params)
console.log(params);
let apiResult = null;
if(props.bizType == 'store'){
apiResult = reqLoad.list(API_URL_MCH_STORE_LIST, params)
}
if(props.bizType == 'mchApp'){
apiResult = reqLoad.list(API_URL_MCH_APP_LIST, params)
}
return apiResult.then((apiRes) => {
return processApiResBizData(params, apiRes)
})
}
// 选择门店
function open (defaultVal){
console.log(defaultVal,'defaultValdefaultVal')
return jeepayRedPopupListSelectByBizinfos.value.open(defaultVal).then((selected) => {
// 自动关闭
if(props.autoClose){
close()
}
return selected;
})
}
function close(){
jeepayRedPopupListSelectByBizinfos.value.close() //自行关闭
}
function processApiResBizData(params, apiRes){
// 第一页 拼接全部门店 (index = 0 )
if(params.pageNumber == 1 && props.isShowAllBiz){
if(props.bizType == 'store'){
apiRes.bizData.records.unshift({storeName: '全部门店', storeId: ''})
}
if(props.bizType == 'mchApp'){
apiRes.bizData.records.unshift({appName: '全部应用', appId: ''})
}
}
return apiRes
}
// 将表格事件暴露出去 https://www.jianshu.com/p/39d14c25c987
defineExpose({ open, close })
</script>
<style>
</style>

View File

@@ -0,0 +1,355 @@
<!--
组件作用 弹层 列表支持 单选 多选
使用方法
<JeepayPopupListSelect ref="jeepayPopupListSelect" :reqTableDataFunc="reqTableDataFunc" :fields="{ key: 'articleId', left: 'articleId', right: 'title'}"/>
jeepayPopupListSelect.value.open().then((selected) => {
console.log(selected);
jeepayPopupListSelect.value.close() //自行关闭
})
@author terrfly
@site https://www.jeequan.com
@date 2022/11/26 16:24
-->
<template>
<uni-popup ref="popupRef" type="bottom" @maskClick="close" @change="change" mask-background-color="rgba(0,0,0,.5)" :safe-area="false">
<view class="card-wrapper">
<view class="selected-title" v-if="title">
{{ title }}
</view>
<view v-if="props.searchInputName" class="input-search">
<uni-easyinput
v-model="vdata.searchData[props.searchInputName]"
prefixIcon="search"
:inputBorder="false"
:clearable="false"
:styles="{
backgroundColor: 'transparent',
}"
type="text"
placeholder="搜索"
placeholderStyle=" color: rgba(0,0,0,0.85);font-size: 30rpx;"
/>
<view class="search-button" @tap="searchFunc">搜索</view>
</view>
<!-- 数据渲染 -->
<JTableList ref="jeepayTableListRef" :reqTableDataFunc="reqTableDataFuncWrapper" :searchData="vdata.searchData" :initData="false" height='406rpx'>
<template #tableBody="{ record }">
<view class="store" @tap="selectFunc(record)">
<template v-if="isCheckbox">
<view class="more-selected" :class="{ 'more-disabled': record.hasDirector, 'more-active': hasSelected(record) }">
<image :src="record.hasDirector ? '/static/iconImg/icon-disable.svg' : '/static/iconImg/icon-check.svg'" mode="scaleToFill" />
</view>
</template>
<view v-else :class="{ 'store-dot-def': true, 'active-dot': hasSelected(record) }"></view>
<slot name="content" :record="record">
<view class="store-inner-slot">
<view class="left">
<text>{{ record[props.fields.left] }}</text>
</view>
<view class="right">{{ record[props.fields.right] }}</view>
</view>
</slot>
</view>
</template>
</JTableList>
<!-- <button v-if="vdata.hasNext" @tap="jeepayTableListRef.addNext()">下一页</button> -->
<view class="footer-wrapper">
<view class="footer-main">
<view class="footer-button">
<view class="flex-center" hover-class="touch-button" @tap="close">取消</view>
<view @tap="confirmFunc" class="confirm flex-center" hover-class="touch-button">确认</view>
</view>
</view>
</view>
</view>
</uni-popup>
</template>
<script setup>
import { inject, nextTick, reactive, ref, render, watch } from 'vue'
const jeepayTableListRef = ref()
// 定义组件参数
const props = defineProps({
// 请求业务数据, 参数可自行控制。
reqTableDataFunc: { type: Function, default: () => {} },
// 搜索输入框的name 不传入则不显示搜索。
searchInputName: { type: String },
// 约定的字段 , 若不合适请通过插槽自行插入。
fields: { type: Object, default: { key: 'id', left: 'left', right: 'right' } },
// 是否多选框, 默认单选。
isCheckbox: { type: Boolean, default: false },
// 标题有则显示无则隐藏
title: [String, Number],
})
let changePageMetaOverflowFunc = inject('changePageMetaOverflowFunc')
const emits = defineEmits(['confirm'])
const popupRef = ref()
const vdata = reactive({
searchData: {}, //当前页的搜索条件
hasNext: false, // 是否包含下一页数据
selectedList: [], // 选择的值
promiseObject: {},
})
// 点击搜索
function searchFunc() {
jeepayTableListRef.value.refTable(true)
}
/** reqTableDataFunc 处理函数 */
function reqTableDataFuncWrapper(params) {
return props.reqTableDataFunc(params).then(({ bizData }) => {
vdata.hasNext = bizData.hasNext // 是否包含下一页
return Promise.resolve({ bizData })
})
}
// 是否选中
function hasSelected(record) {
return vdata.selectedList.filter((r) => r[props.fields.key] == record[props.fields.key]).length > 0
}
/** 选择函数 **/
function selectFunc(record) {
// 判断是否已存在
if (hasSelected(record)) {
// 多选需删除
if (props.isCheckbox) {
vdata.selectedList.splice(
vdata.selectedList.findIndex((r) => r[props.fields.key] == record[props.fields.key]),
1
)
}
// 单选无需操作
return false
}
// 多选直接添加
if (props.isCheckbox) {
if (record.hasDirector) return //如果被其他店长绑定 禁止选中
return vdata.selectedList.push(record)
} else {
// 单选
return (vdata.selectedList = [record])
}
}
// 点击确定事件
function confirmFunc() {
// 多选
if (props.isCheckbox) {
emits('confirm', vdata.selectedList)
return vdata.promiseObject.resolve(vdata.selectedList)
}
// 单选 仅返回第一个即可。
emits('confirm', vdata.selectedList.length > 0 ? vdata.selectedList[0] : null)
vdata.promiseObject.resolve(vdata.selectedList.length > 0 ? vdata.selectedList[0] : null)
}
// 显示弹层, 并且返回一个promise
// promise.then(selected)
// 注意: 此Promise 只会回调一次, 如需要验证是否选中正确, 需要使用@confirm事件。
// 如果对拿到的值不做校验,获取到然后关闭。 那么可以直接使用.then() 然后立马关闭弹层。
function open(defaultVal) {
// 清空数据
vdata.selectedList = []
vdata.searchData[props.searchInputName] = ''
// 默认选中。
if (defaultVal) {
if (Array.isArray(defaultVal)) {
vdata.selectedList = defaultVal
} else {
vdata.selectedList = [defaultVal]
}
}
popupRef.value.open()
nextTick(() => {
jeepayTableListRef.value.refTable(true)
uni.hideTabBar() // 可能报错, 在nextTick中 不影响其他业务。
})
return new Promise((resolve, reject) => {
vdata.promiseObject.resolve = resolve
vdata.promiseObject.reject = reject
})
}
// 关闭弹层
function close() {
popupRef.value.close()
uni.showTabBar()
}
const change = (e) => {
if (changePageMetaOverflowFunc) {
changePageMetaOverflowFunc(!e.show)
}
}
// 将表格事件暴露出去 https://www.jianshu.com/p/39d14c25c987
defineExpose({ open, close })
</script>
<style lang="scss" scoped>
.card-wrapper {
border-radius: 32rpx 32rpx 0 0;
background-color: #fff;
overflow: hidden;
min-height: 70vh;
max-height: 80vh;
overflow-y: auto;
.selected-title {
height: 110rpx;
line-height: 110rpx;
text-align: center;
font-size: 30rpx;
font-weight: 500;
border-bottom: 1rpx solid #ededed;
}
.input-search {
display: flex;
align-items: center;
padding-left: 10rpx;
margin: 30rpx;
border-radius: 10rpx;
background-color: #f7f7f7;
.search-button {
padding: 24rpx 30rpx;
font-size: 32rpx;
font-weight: 500;
color: #2980fd;
}
}
.store {
position: relative;
display: flex;
justify-content: flex-start;
align-items: center;
padding: 0 40rpx;
height: 120rpx;
font-size: 30rpx;
.more-selected {
width: 36rpx;
height: 36rpx;
border-radius: 6rpx;
margin-right: 20rpx;
border: 2rpx solid rgba(217, 217, 217, 1);
image {
width: 100%;
height: 100%;
}
}
.more-disabled {
background-color: #f7f7f7;
}
.more-active {
background-color: #2980fd;
}
.store-dot-def {
position: relative;
margin-right: 20rpx;
width: 36rpx;
height: 36rpx;
background-color: #d7d8d9;
border-radius: 50%;
&::after {
content: '';
display: block;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 50%;
height: 50%;
border-radius: 50%;
background-color: #fff;
}
}
.active-dot {
background-color: #2980fd;
}
.store-inner-slot {
display: flex;
flex-direction: row;
justify-content: space-between;
width: 100%;
.left {
display: flex;
align-items: center;
}
.right {
color: #999999;
}
}
}
.all-store::after {
content: '';
display: block;
position: absolute;
bottom: 0;
left: 40rpx;
right: 40rpx;
height: 1rpx;
background-color: #ededed;
}
.footer-wrapper {
height: 186rpx;
.footer-main {
position: fixed;
left: 0;
right: 0;
bottom: env(safe-area-inset-bottom);
border-top: 1rpx solid #ededed;
.tips {
margin: 20rpx;
text-align: center;
font-size: 27rpx;
color: #a6a6a6;
}
.footer-button {
padding: 0 30rpx;
margin-top: 30rpx;
padding-bottom: 30rpx;
display: flex;
justify-content: space-between;
view {
width: 330rpx;
height: 110rpx;
font-size: 33rpx;
font-weight: 500;
color: rgba(0, 0, 0, 0.5);
border-radius: 20rpx;
background-color: #f7f7f7;
}
.confirm {
color: #fff;
background: $jeepay-bg-primary;
}
}
}
}
}
</style>