Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 23e4407459 | |||
| 53a1442cf7 | |||
| 6cc53db443 | |||
| 7f97467f82 | |||
| d6e1c83f88 | |||
| b69b5dbf31 | |||
|
|
27a8d6894e | ||
|
|
acad1cd067 | ||
|
|
c0f03ef9aa | ||
|
|
db05de04a5 | ||
|
|
5e6646b574 | ||
|
|
5a655ba09e | ||
|
|
656793dae2 | ||
|
|
413222a5f0 | ||
|
|
e928fdfa2a | ||
|
|
7fe5d028e4 | ||
|
|
f01bc839f7 | ||
|
|
994cf8bf2b | ||
|
|
c2135c6119 | ||
|
|
2f1523d4e9 | ||
|
|
56b115a695 | ||
|
|
cc97b6acca | ||
|
|
30bf53abf9 | ||
|
|
490c513f48 | ||
|
|
4f65b08c06 | ||
|
|
fd0c452a76 | ||
|
|
b4a0393d2d |
93
App.vue
93
App.vue
@@ -3,11 +3,24 @@
|
|||||||
App.vue本身不是页面,这里不能编写视图元素,也就是没有<template>
|
App.vue本身不是页面,这里不能编写视图元素,也就是没有<template>
|
||||||
-->
|
-->
|
||||||
<script setup>
|
<script setup>
|
||||||
import {
|
import { onLaunch } from '@dcloudio/uni-app';
|
||||||
onLaunch
|
import { getVersion } from '@/http/api/index.js'
|
||||||
} from '@dcloudio/uni-app';
|
import appConfig from '@/config/appConfig.js';
|
||||||
import { getFindBySource } from '@/http/yskApi/version.js'
|
import { provide,onMounted } from 'vue';
|
||||||
|
import WebsocketUtil from '@/commons/utils/websocket.js'
|
||||||
|
|
||||||
|
const websocketUtil = new WebsocketUtil(appConfig.wss, 5000); // 创建 WebSocket 工具类实例
|
||||||
|
provide('websocketUtil', websocketUtil); // 提供给所有子组件
|
||||||
|
onMounted(() => {
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
onLaunch(() => {
|
onLaunch(() => {
|
||||||
|
// 非开发工具移除 console.log console.info
|
||||||
|
if (uni.getSystemInfoSync().platform !== "devtools") {
|
||||||
|
console.log = () => {};
|
||||||
|
console.info = () => {};
|
||||||
|
}
|
||||||
let that = this
|
let that = this
|
||||||
uni.hideTabBar()
|
uni.hideTabBar()
|
||||||
// #ifdef MP-WEIXIN
|
// #ifdef MP-WEIXIN
|
||||||
@@ -24,7 +37,8 @@ App.vue本身不是页面,这里不能编写视图元素,也就是没有<tem
|
|||||||
// 新版本下载失败
|
// 新版本下载失败
|
||||||
})
|
})
|
||||||
// #endif
|
// #endif
|
||||||
|
// console.log("getSystemSetting==",uni.getSystemInfoSync())
|
||||||
|
// console.log("getSystemSetting==",uni.getSystemSetting())
|
||||||
|
|
||||||
|
|
||||||
//#ifdef APP-PLUS
|
//#ifdef APP-PLUS
|
||||||
@@ -32,7 +46,8 @@ App.vue本身不是页面,这里不能编写视图元素,也就是没有<tem
|
|||||||
plus.runtime.getProperty(plus.runtime.appid, widgetInfo => {
|
plus.runtime.getProperty(plus.runtime.appid, widgetInfo => {
|
||||||
//请求后台接口 解析数据 对比版本
|
//请求后台接口 解析数据 对比版本
|
||||||
console.log("widgetInfo==",widgetInfo)
|
console.log("widgetInfo==",widgetInfo)
|
||||||
getFindBySource({source:'APP'}).then(res => {
|
let type = uni.getSystemInfoSync().platform == 'ios' ? 2 : 1
|
||||||
|
getVersion({source:'manager_app',type: type}).then(res => {
|
||||||
console.log("selectNewApp==",res)
|
console.log("selectNewApp==",res)
|
||||||
console.log("version===",res.url && widgetInfo.version < res.version)
|
console.log("version===",res.url && widgetInfo.version < res.version)
|
||||||
if (res.url && widgetInfo.version < res.version) {
|
if (res.url && widgetInfo.version < res.version) {
|
||||||
@@ -53,8 +68,7 @@ App.vue本身不是页面,这里不能编写视图元素,也就是没有<tem
|
|||||||
success: res => {
|
success: res => {
|
||||||
if (res.confirm) {
|
if (res.confirm) {
|
||||||
uni.showLoading('下载中...');
|
uni.showLoading('下载中...');
|
||||||
if (uni.getSystemInfoSync().platform ==
|
if (uni.getSystemInfoSync().platform == 'android') {
|
||||||
'android') {
|
|
||||||
uni.downloadFile({
|
uni.downloadFile({
|
||||||
url: downloadLink,
|
url: downloadLink,
|
||||||
success: downloadResult => {
|
success: downloadResult => {
|
||||||
@@ -63,24 +77,16 @@ App.vue本身不是页面,这里不能编写视图元素,也就是没有<tem
|
|||||||
entry.getParent(_oldFile=>{
|
entry.getParent(_oldFile=>{
|
||||||
entry.moveTo(_oldFile,'.apk',newFilePath=>{
|
entry.moveTo(_oldFile,'.apk',newFilePath=>{
|
||||||
console.log('newFilePath',newFilePath.fullPath)
|
console.log('newFilePath',newFilePath.fullPath)
|
||||||
plus.runtime
|
plus.runtime.install(newFilePath.fullPath, { force: false },
|
||||||
.install(newFilePath.fullPath, { force: false },
|
d => {
|
||||||
d => {
|
console .log( 'install success...' );
|
||||||
console
|
plus.runtime .restart();
|
||||||
.log(
|
},
|
||||||
'install success...'
|
e => {
|
||||||
);
|
console.log(e)
|
||||||
plus.runtime
|
console .error( 'install fail...' );
|
||||||
.restart();
|
}
|
||||||
},
|
);
|
||||||
e => {
|
|
||||||
console.log(e)
|
|
||||||
console
|
|
||||||
.error(
|
|
||||||
'install fail...'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -88,10 +94,8 @@ App.vue本身不是页面,这里不能编写视图元素,也就是没有<tem
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (uni.getSystemInfoSync().platform ==
|
if (uni.getSystemInfoSync().platform == 'ios') {
|
||||||
'ios') {
|
plus.runtime.openURL(downloadLink, function( res) {});
|
||||||
plus.runtime.openURL(downloadLink, function(
|
|
||||||
res) {});
|
|
||||||
}
|
}
|
||||||
} else if (res.cancel) {
|
} else if (res.cancel) {
|
||||||
console.log('取消');
|
console.log('取消');
|
||||||
@@ -107,34 +111,23 @@ App.vue本身不是页面,这里不能编写视图元素,也就是没有<tem
|
|||||||
success: res => {
|
success: res => {
|
||||||
if (res.confirm) {
|
if (res.confirm) {
|
||||||
uni.showLoading('下载中...');
|
uni.showLoading('下载中...');
|
||||||
if (uni.getSystemInfoSync().platform ==
|
if (uni.getSystemInfoSync().platform == 'android') {
|
||||||
'android') {
|
|
||||||
uni.downloadFile({
|
uni.downloadFile({
|
||||||
url: downloadLink,
|
url: downloadLink,
|
||||||
success: downloadResult => {
|
success: downloadResult => {
|
||||||
if (downloadResult
|
if (downloadResult.statusCode == 200) {
|
||||||
.statusCode ===
|
|
||||||
200) {
|
|
||||||
plus.io.resolveLocalFileSystemURL(downloadResult.tempFilePath, entry => {
|
plus.io.resolveLocalFileSystemURL(downloadResult.tempFilePath, entry => {
|
||||||
entry.getParent(_oldFile=>{
|
entry.getParent(_oldFile=>{
|
||||||
entry.moveTo(_oldFile,'.apk',newFilePath=>{
|
entry.moveTo(_oldFile,'.apk',newFilePath=>{
|
||||||
console.log('newFilePath',newFilePath.fullPath)
|
console.log('newFilePath',newFilePath.fullPath)
|
||||||
plus.runtime
|
plus.runtime.install(newFilePath.fullPath, { force: false },
|
||||||
.install(newFilePath.fullPath, { force: false },
|
|
||||||
d => {
|
d => {
|
||||||
console
|
console.log('install success...');
|
||||||
.log(
|
plus.runtime.restart();
|
||||||
'install success...'
|
|
||||||
);
|
|
||||||
plus.runtime
|
|
||||||
.restart();
|
|
||||||
},
|
},
|
||||||
e => {
|
e => {
|
||||||
console.log(e)
|
console.log(e)
|
||||||
console
|
console.error('install fail...');
|
||||||
.error(
|
|
||||||
'install fail...'
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
@@ -145,10 +138,8 @@ App.vue本身不是页面,这里不能编写视图元素,也就是没有<tem
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (uni.getSystemInfoSync().platform ==
|
if (uni.getSystemInfoSync().platform == 'ios') {
|
||||||
'ios') {
|
plus.runtime.openURL(downloadLink, function( res) {});
|
||||||
plus.runtime.openURL(downloadLink, function(
|
|
||||||
res) {});
|
|
||||||
}
|
}
|
||||||
} else if (res.cancel) {
|
} else if (res.cancel) {
|
||||||
console.log('取消');
|
console.log('取消');
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
{
|
|
||||||
"version" : "1",
|
|
||||||
"prompt" : "template",
|
|
||||||
"title" : "服务协议和隐私政策",
|
|
||||||
"message" : " 请你务必审慎阅读、充分理解“服务协议”和“隐私政策”各条款,包括但不限于:为了更好的向你提供服务,我们需要收集你的设备标识、操作日志等信息用于分析、优化应用性能。<br/> 你可阅读<a href=\"static/service.html\">《服务协议》</a>和<a href=\"static/privacy.html\">《隐私政策》</a>了解详细信息。如果你同意,请点击下面按钮开始接受我们的服务。",
|
|
||||||
"buttonAccept" : "同意并接受",
|
|
||||||
"buttonRefuse" : "暂不同意",
|
|
||||||
"second" : {
|
|
||||||
"title" : "确认提示",
|
|
||||||
"message" : " 进入应用前,你需先同意<a href=\"static/service.html\">《服务协议》</a>和<a href=\"static/privacy.html\">《隐私政策》</a>,否则将退出应用。",
|
|
||||||
"buttonAccept" : "同意并继续",
|
|
||||||
"buttonRefuse" : "退出应用"
|
|
||||||
},
|
|
||||||
"styles" : {
|
|
||||||
"backgroundColor" : "#FFFFFF",
|
|
||||||
"borderRadius" : "5px",
|
|
||||||
"title" : {
|
|
||||||
"color" : "#262626"
|
|
||||||
},
|
|
||||||
"buttonAccept" : {
|
|
||||||
"color" : "#3981FF"
|
|
||||||
},
|
|
||||||
"buttonRefuse" : {
|
|
||||||
"color" : "#A6A6A6"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
export const ColorMain= '#318AFE';
|
|
||||||
export const ColorRed= '#F02C45';
|
|
||||||
|
|
||||||
|
|
||||||
export default{
|
|
||||||
ColorMain,ColorRed
|
|
||||||
}
|
|
||||||
@@ -1,74 +1,12 @@
|
|||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
export const $types = [{
|
|
||||||
title: "计量商品",
|
|
||||||
desc: '单价购买',
|
|
||||||
value: 'normal'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "多规格",
|
|
||||||
desc: '多种不同规格',
|
|
||||||
value: 'sku'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "套餐组合",
|
|
||||||
desc: '选择多种组合',
|
|
||||||
value: 'group'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "称重商品",
|
|
||||||
desc: '按重量售卖',
|
|
||||||
value: 'weight'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "时价商品",
|
|
||||||
desc: '收银端可更改价格',
|
|
||||||
value: 'currentPrice'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
// 商品默认sku
|
// 商品默认sku
|
||||||
export const $defaultSku = {
|
export const $defaultSku = {
|
||||||
|
originPrice: '',
|
||||||
|
costPrice: '',
|
||||||
salePrice: '',
|
salePrice: '',
|
||||||
memberPrice: '',
|
memberPrice: '',
|
||||||
costPrice: '',
|
suitNum: '',
|
||||||
originPrice: '',
|
|
||||||
// stockNumber: '',
|
|
||||||
firstShared: '',
|
|
||||||
suit: 1,
|
|
||||||
barCode: `${uni.getStorageSync("shopId")}${dayjs().valueOf()}`,
|
barCode: `${uni.getStorageSync("shopId")}${dayjs().valueOf()}`,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 库存记录筛选类型
|
|
||||||
export const $invoicingType = [{
|
|
||||||
text: '全部',
|
|
||||||
value: ''
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: '供应商入库',
|
|
||||||
value: 'purveyor'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: '供应商退货',
|
|
||||||
value: 'reject'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: '其他入库',
|
|
||||||
value: 'purchase'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: '其他出库',
|
|
||||||
value: 'other-out'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
// 页面常用数据
|
|
||||||
export const $pageData = {
|
|
||||||
query: {
|
|
||||||
page: 0,
|
|
||||||
size: 10
|
|
||||||
},
|
|
||||||
totalElements: 0,
|
|
||||||
list: [],
|
|
||||||
hasAjax: false,
|
|
||||||
}
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
export default {
|
|
||||||
status: [
|
|
||||||
{
|
|
||||||
key: 'unpaid',
|
|
||||||
label: '待支付'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'unsend',
|
|
||||||
label: '待发货'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'closed',
|
|
||||||
label: '订单完成'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'send',
|
|
||||||
label: '已发'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'refunding',
|
|
||||||
label: '申请退单'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'refund',
|
|
||||||
label: '退单'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'cancelled',
|
|
||||||
label: '取消订单'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'merge',
|
|
||||||
label: '合台'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'pending',
|
|
||||||
label: '挂单'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'activate',
|
|
||||||
label: '激活'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'paying',
|
|
||||||
label: '支付中'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
sendType: [
|
|
||||||
{
|
|
||||||
key: 'post',
|
|
||||||
label: '快递'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'takeaway',
|
|
||||||
label: '外卖'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'takeself',
|
|
||||||
label: '自提'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'table',
|
|
||||||
label: '堂食'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
orderType: [
|
|
||||||
{
|
|
||||||
key: 'cash',
|
|
||||||
label: '收银'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'miniapp',
|
|
||||||
label: '小程序'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'offline',
|
|
||||||
label: '线下'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'return',
|
|
||||||
label: '退单'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
export const $status = {
|
|
||||||
pending: {
|
|
||||||
label: "挂单中",
|
|
||||||
type: "#E6A23C",
|
|
||||||
},
|
|
||||||
using: {
|
|
||||||
label: "开台中",
|
|
||||||
type: "#fa5555",
|
|
||||||
},
|
|
||||||
paying: {
|
|
||||||
label: "结算中",
|
|
||||||
type: "#E6A23C",
|
|
||||||
},
|
|
||||||
idle: {
|
|
||||||
label: "空闲",
|
|
||||||
type: "#3F9EFF",
|
|
||||||
},
|
|
||||||
subscribe: {
|
|
||||||
label: "预定",
|
|
||||||
type: "rgb(34, 191, 100)",
|
|
||||||
},
|
|
||||||
closed: {
|
|
||||||
label: "关台",
|
|
||||||
type: "rgb(221,221,221)",
|
|
||||||
},
|
|
||||||
// opening: {
|
|
||||||
// label: "开台中",
|
|
||||||
// type: "#67C23A",
|
|
||||||
// },
|
|
||||||
cleaning: {
|
|
||||||
label: "待清台",
|
|
||||||
type: "#FAAD14",
|
|
||||||
},
|
|
||||||
unbind: {
|
|
||||||
label: "未绑定",
|
|
||||||
type: "rgb(221,221,221)",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -28,3 +28,10 @@ export function getThisMonthTimestamps() {
|
|||||||
return { start, end ,label:'本月'};
|
return { start, end ,label:'本月'};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取上个月的开始和结束时间
|
||||||
|
export function getThisLastMonthTimestamps() {
|
||||||
|
const start = dayjs().subtract(1, 'month').startOf('month').format('YYYY-MM-DD HH:mm:ss');
|
||||||
|
const end = dayjs().subtract(1, 'month').endOf('month').format('YYYY-MM-DD HH:mm:ss');
|
||||||
|
return { start, end ,label:'上月'};
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
/**
|
|
||||||
* @desc 函数防抖
|
|
||||||
* @param func 目标函数
|
|
||||||
* @param wait 延迟执行毫秒数
|
|
||||||
* @param immediate true - 立即执行, false - 延迟执行
|
|
||||||
*/
|
|
||||||
export const debounce = function(func, wait = 1000, immediate = true) {
|
|
||||||
let timer;
|
|
||||||
return function() {
|
|
||||||
let context = this,
|
|
||||||
args = arguments;
|
|
||||||
if (timer) clearTimeout(timer);
|
|
||||||
if (immediate) {
|
|
||||||
let callNow = !timer;
|
|
||||||
timer = setTimeout(() => {
|
|
||||||
timer = null;
|
|
||||||
}, wait);
|
|
||||||
if (callNow) func.apply(context, args);
|
|
||||||
} else {
|
|
||||||
timer = setTimeout(() => {
|
|
||||||
func.apply(context, args);
|
|
||||||
}, wait)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
261
commons/utils/dict.js
Normal file
261
commons/utils/dict.js
Normal file
@@ -0,0 +1,261 @@
|
|||||||
|
export default {
|
||||||
|
orderStatus: [{
|
||||||
|
label: "待支付",
|
||||||
|
type: "unpaid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "制作中",
|
||||||
|
type: "in_production"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "待取餐",
|
||||||
|
type: "wait_out"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "订单完成",
|
||||||
|
type: "done"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "申请退单",
|
||||||
|
type: "refunding"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "退单",
|
||||||
|
type: "refund"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "部分退单",
|
||||||
|
type: "part_refund"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "取消订单",
|
||||||
|
type: "cancelled"
|
||||||
|
},
|
||||||
|
],
|
||||||
|
orderType: [{
|
||||||
|
label: "收银",
|
||||||
|
type: "cash"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "小程序",
|
||||||
|
type: "miniapp"
|
||||||
|
},
|
||||||
|
],
|
||||||
|
dineMode: [{
|
||||||
|
label: "堂食",
|
||||||
|
type: "dine-in"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "外带",
|
||||||
|
type: "take-out"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "外卖",
|
||||||
|
type: "take-away"
|
||||||
|
},
|
||||||
|
],
|
||||||
|
payType: [{
|
||||||
|
label: "主扫",
|
||||||
|
type: "main_scan"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "被扫",
|
||||||
|
type: "back_scan"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "微信小程序",
|
||||||
|
type: "wechat_mini"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "支付宝小程序",
|
||||||
|
type: "alipay_mini"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "会员支付",
|
||||||
|
type: "vip_pay"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "现金支付",
|
||||||
|
type: "cash_pay"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "挂账支付",
|
||||||
|
type: "credit_pay"
|
||||||
|
},
|
||||||
|
],
|
||||||
|
bizCodes: [{
|
||||||
|
label: "现金充值",
|
||||||
|
type: "cashIn"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "微信小程序充值",
|
||||||
|
type: "wechatIn"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "支付宝小程序充值",
|
||||||
|
type: "alipayIn"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "充值奖励",
|
||||||
|
type: "awardIn"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "充值退款",
|
||||||
|
type: "rechargeRefund"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "订单消费",
|
||||||
|
type: "orderPay"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "订单退款",
|
||||||
|
type: "orderRefund"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "管理员充值",
|
||||||
|
type: "adminIn"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "管理员消费",
|
||||||
|
type: "adminOut"
|
||||||
|
},
|
||||||
|
],
|
||||||
|
platformType: [{
|
||||||
|
label: '微信小程序',
|
||||||
|
type: 'WX'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '支付宝小程序',
|
||||||
|
type: 'ALI'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '收银机客户端',
|
||||||
|
type: 'PC'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'PC管理端',
|
||||||
|
type: 'WEB'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'APP管理端',
|
||||||
|
type: 'APP'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '收款码',
|
||||||
|
type: 'H5'
|
||||||
|
},
|
||||||
|
],
|
||||||
|
tableStatus: {
|
||||||
|
unbound: {
|
||||||
|
label: "未绑定",
|
||||||
|
type: "#909090"
|
||||||
|
},
|
||||||
|
idle: {
|
||||||
|
label: "空闲",
|
||||||
|
type: "#3F9EFF"
|
||||||
|
},
|
||||||
|
ordering: {
|
||||||
|
label: "点餐中",
|
||||||
|
type: "#46AEA4"
|
||||||
|
},
|
||||||
|
unsettled: {
|
||||||
|
label: "未结账",
|
||||||
|
type: "#DD3F41"
|
||||||
|
},
|
||||||
|
paying: {
|
||||||
|
label: "支付中",
|
||||||
|
type: "#909090"
|
||||||
|
},
|
||||||
|
settled: {
|
||||||
|
label: "待清台",
|
||||||
|
type: "#FF9500"
|
||||||
|
},
|
||||||
|
closed: {
|
||||||
|
label: "关台",
|
||||||
|
type: "#DDDDDD"
|
||||||
|
},
|
||||||
|
subscribe: {
|
||||||
|
label: "预定",
|
||||||
|
type: "#58B22C"
|
||||||
|
},
|
||||||
|
},
|
||||||
|
invoicingType: [{
|
||||||
|
label: '全部',
|
||||||
|
type: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '手动入库',
|
||||||
|
type: 'manual-in'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '手动出库',
|
||||||
|
type: 'manual-out'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '盘盈入库',
|
||||||
|
type: 'win-in'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '盘亏出库',
|
||||||
|
type: 'loss-out'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '订单退款入库',
|
||||||
|
type: 'other-out'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '订单消费出库',
|
||||||
|
type: 'order-out'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '损耗出库',
|
||||||
|
type: 'damage-out'
|
||||||
|
},
|
||||||
|
],
|
||||||
|
invoicingType: [{
|
||||||
|
label: '全部',
|
||||||
|
type: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '手动入库',
|
||||||
|
type: 'manual-in'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '手动出库',
|
||||||
|
type: 'manual-out'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '盘盈入库',
|
||||||
|
type: 'win-in'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '盘亏出库',
|
||||||
|
type: 'loss-out'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '订单退款入库',
|
||||||
|
type: 'other-out'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '订单消费出库',
|
||||||
|
type: 'order-out'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '损耗出库',
|
||||||
|
type: 'damage-out'
|
||||||
|
},
|
||||||
|
],
|
||||||
|
refundType: [{
|
||||||
|
label: '现金退款',
|
||||||
|
type: 'cash'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '原路退回',
|
||||||
|
type: 'payBack'
|
||||||
|
},
|
||||||
|
],
|
||||||
|
getDiceName(val, key) {
|
||||||
|
let item = this[key].find(v => v.type == val)
|
||||||
|
return item ? item.label : ''
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
/**
|
|
||||||
* 获取url链接参数
|
|
||||||
* @param {Object} url
|
|
||||||
* @param {Object} name
|
|
||||||
*/
|
|
||||||
export function getQueryString(url, name) {
|
|
||||||
var reg = new RegExp('(^|&|/?)' + name + '=([^&|/?]*)(&|/?|$)', 'i')
|
|
||||||
var r = url.substr(1).match(reg)
|
|
||||||
if (r != null) {
|
|
||||||
return r[2]
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
export function canComputedPackFee(v) {
|
export function canComputedPackFee(v) {
|
||||||
return v.pack && v.status != 'return' && v.status != 'refund' && v.status != 'refunding'
|
return v.pack && v.status != 'return' && v.status != 'refund' && v.status != 'part_refund'
|
||||||
}
|
}
|
||||||
export function returnCanComputedGoodsArr(arr) {
|
export function returnCanComputedGoodsArr(arr) {
|
||||||
return arr.filter(v => canComputedPackFee(v))
|
return arr.filter(v => canComputedPackFee(v))
|
||||||
@@ -17,17 +17,30 @@ export function canTuicai(orderInfo, item) {
|
|||||||
return orderInfo.status == 'unpaid' && orderInfo.useType != 'dine-in-before' && item.status != 'return'
|
return orderInfo.status == 'unpaid' && orderInfo.useType != 'dine-in-before' && item.status != 'return'
|
||||||
}
|
}
|
||||||
export function canTuiKuan(orderInfo, item) {
|
export function canTuiKuan(orderInfo, item) {
|
||||||
return orderInfo.status == 'closed' && item.status != 'return' && item.status != 'refund' && item.status !=
|
if( item ){
|
||||||
'refunding'
|
return (orderInfo.status == 'done' || orderInfo.status == 'part_refund')
|
||||||
|
&& item.status != 'return' && item.status != 'refund' && item.status != 'refunding'
|
||||||
|
&& (item.returnNum < item.num)
|
||||||
|
} else {
|
||||||
|
let data = false;
|
||||||
|
uni.$utils.objToArrary(orderInfo.detailMap).some((v,i)=>{
|
||||||
|
if( orderInfo.refundAmount < orderInfo.payAmount || (orderInfo.status == 'done' || orderInfo.status == 'part_refund' ) && v.status != 'return' && v.status != 'refund' && v.status != 'refunding' && (v.returnNum+v.refundNum < v.num) ){
|
||||||
|
data = true
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
export function isTuiCai(item) {
|
export function isTuiCai(item) {
|
||||||
return item.status == 'return'
|
return item.status == 'return' || item.status == 'part_refund'
|
||||||
}
|
}
|
||||||
export function isTui(item) {
|
export function isTui(item) {
|
||||||
return item.status == 'return' || item.status == 'refund' || item.status == 'refunding'
|
return item.status == 'return' || item.status == 'refund' || item.status == 'part_refund'
|
||||||
}
|
}
|
||||||
export function isGift(item) {
|
export function isGift(item) {
|
||||||
return !isTui(item) && item.gift
|
return !isTui(item) && item.isGift == 1
|
||||||
}
|
}
|
||||||
export function numSum(arr) {
|
export function numSum(arr) {
|
||||||
const sum = arr.reduce((a, b) => {
|
const sum = arr.reduce((a, b) => {
|
||||||
@@ -35,3 +48,14 @@ export function numSum(arr) {
|
|||||||
}, 0)
|
}, 0)
|
||||||
return (sum / 100).toFixed(2)
|
return (sum / 100).toFixed(2)
|
||||||
}
|
}
|
||||||
|
export function mathFloorPrice(price,item) {
|
||||||
|
if( item ){
|
||||||
|
if( item.productType == 'weight' || item.type == 'weight'){
|
||||||
|
return (Math.floor(price * 100)/100).toFixed(2)
|
||||||
|
} else {
|
||||||
|
return parseFloat(price).toFixed(2)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return parseFloat(price).toFixed(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,3 @@
|
|||||||
import {
|
|
||||||
$hasPermission
|
|
||||||
} from '@/http/yskApi/shop.js'
|
|
||||||
import infoBox from '@/commons/utils/infoBox.js'
|
import infoBox from '@/commons/utils/infoBox.js'
|
||||||
|
|
||||||
const $PermissionObj = {
|
const $PermissionObj = {
|
||||||
@@ -147,17 +144,18 @@ export async function hasPermission(params) {
|
|||||||
if (!params) {
|
if (!params) {
|
||||||
return infoBox.showToast('未找到相关权限,请检查代码或在权限配置文件commons/utils/hasPermission.js文件进行修改或增加')
|
return infoBox.showToast('未找到相关权限,请检查代码或在权限配置文件commons/utils/hasPermission.js文件进行修改或增加')
|
||||||
}
|
}
|
||||||
const option = Object.assign({
|
// const option = Object.assign({
|
||||||
tips: true,
|
// tips: true,
|
||||||
key: '',
|
// key: '',
|
||||||
text: ''
|
// text: ''
|
||||||
}, params)
|
// }, params)
|
||||||
const res = await $hasPermission({
|
// const res = await $hasPermission({
|
||||||
code: params.key
|
// code: params.key
|
||||||
})
|
// })
|
||||||
if (!res && option.tips) {
|
// if (!res && option.tips) {
|
||||||
infoBox.showToast('您没有' + params.text + '权限!')
|
// infoBox.showToast('您没有' + params.text + '权限!')
|
||||||
}
|
// }
|
||||||
return res
|
// return res
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
194
commons/utils/index.js
Normal file
194
commons/utils/index.js
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
|
||||||
|
export const utils = {
|
||||||
|
ColorMain: '#318AFE',
|
||||||
|
ColorRed: '#F02C45',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 限制只让输入数字
|
||||||
|
* @param {Object} e
|
||||||
|
*/
|
||||||
|
isNumber (e) {
|
||||||
|
return e.replace(/[^\d]/g, '')
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 限制金额输入格式
|
||||||
|
* @param {Object} e
|
||||||
|
*/
|
||||||
|
isMoney (e) {
|
||||||
|
return e.toString().replace(/[^0-9.]/g, '').replace(/^\./g, "").replace(".", "$#$").replace(/\./g, "").replace("$#$", ".").replace(/^(\-)*(\d+)\.(\d{0,2}).*$/, "$1$2.$3")
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断菜品使用价格
|
||||||
|
* @param {Object} e
|
||||||
|
*/
|
||||||
|
isGoodsPrice(item,user) {
|
||||||
|
let isVip = uni.getStorageSync("shopInfo").isMemberPrice&&user.id&&user.isVip
|
||||||
|
|
||||||
|
let memberPrice = item.memberPrice ? item.memberPrice : item.price;
|
||||||
|
let price = isVip ? memberPrice : item.price;
|
||||||
|
price = item.discountSaleAmount ? item.discountSaleAmount : price
|
||||||
|
return price;
|
||||||
|
},
|
||||||
|
|
||||||
|
inputReg(value,key,regName){
|
||||||
|
//判断regList对象是否存在属性 避免报错
|
||||||
|
// utils.hasOwnProperty.call(utils,regName)&&(form[key]=utils[regName](value))
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 金额保留两位小数
|
||||||
|
* @param {Object} e
|
||||||
|
*/
|
||||||
|
toFixed (price,item) {
|
||||||
|
if( item ){
|
||||||
|
if( item.productType == 'weight' || item.type == 'weight'){
|
||||||
|
return (Math.floor(price * 100)/100).toFixed(2)
|
||||||
|
} else {
|
||||||
|
return parseFloat(price).toFixed(2)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return parseFloat(price).toFixed(2)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 金额向下取整
|
||||||
|
* @param {Object} e
|
||||||
|
*/
|
||||||
|
formatPrice (e) {
|
||||||
|
return (Math.floor(n*100)/100).toFixed(2)
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息提示框
|
||||||
|
*/
|
||||||
|
showToast(title, duration = 1.5, extObject) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
uni.showToast(Object.assign({ title: title, icon: 'none', mask: false, duration: (duration * 1000) }, extObject))
|
||||||
|
setTimeout(resolve, (duration * 1000));
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保留小数n位,不进行四舍五入
|
||||||
|
* num你传递过来的数字,
|
||||||
|
* decimal你保留的几位,默认保留小数后两位
|
||||||
|
*/
|
||||||
|
formatDecimal (num, decimal = 2) {
|
||||||
|
num = num.toString()
|
||||||
|
const index = num.indexOf('.')
|
||||||
|
if (index !== -1) {
|
||||||
|
num = num.substring(0, decimal + index + 1)
|
||||||
|
} else {
|
||||||
|
num = num.substring(0)
|
||||||
|
}
|
||||||
|
//截取后保留两位小数
|
||||||
|
return parseFloat(num).toFixed(decimal)
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分转元
|
||||||
|
* amount - 金额
|
||||||
|
* parseFloat - 是否转换为数字格式,
|
||||||
|
* 默认String
|
||||||
|
*/
|
||||||
|
cert2Dollar(amount, needParseFloat = false) {
|
||||||
|
if (needParseFloat) { // parseFlot
|
||||||
|
return formatDecimal(amount / 100)
|
||||||
|
}
|
||||||
|
return formatDecimal(amount / 100)
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @desc 函数防抖
|
||||||
|
* @param func 目标函数
|
||||||
|
* @param wait 延迟执行毫秒数
|
||||||
|
* @param immediate true - 立即执行, false - 延迟执行
|
||||||
|
*/
|
||||||
|
debounce (func, wait = 1000, immediate = true) {
|
||||||
|
let timer;
|
||||||
|
return function() {
|
||||||
|
let context = this,
|
||||||
|
args = arguments;
|
||||||
|
if (timer) clearTimeout(timer);
|
||||||
|
if (immediate) {
|
||||||
|
let callNow = !timer;
|
||||||
|
timer = setTimeout(() => {
|
||||||
|
timer = null;
|
||||||
|
}, wait);
|
||||||
|
if (callNow) func.apply(context, args);
|
||||||
|
} else {
|
||||||
|
timer = setTimeout(() => {
|
||||||
|
func.apply(context, args);
|
||||||
|
}, wait)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @desc 函数节流
|
||||||
|
* @param func 函数
|
||||||
|
* @param wait 延迟执行毫秒数
|
||||||
|
* @param type 1 使用表时间戳,在时间段开始的时候触发 2 使用表定时器,在时间段结束的时候触发
|
||||||
|
*/
|
||||||
|
throttle (func, wait = 1000, type = 1) {
|
||||||
|
let previous = 0;
|
||||||
|
let timeout;
|
||||||
|
return function() {
|
||||||
|
let context = this;
|
||||||
|
let args = arguments;
|
||||||
|
if (type === 1) {
|
||||||
|
let now = Date.now();
|
||||||
|
|
||||||
|
if (now - previous > wait) {
|
||||||
|
func.apply(context, args);
|
||||||
|
previous = now;
|
||||||
|
}
|
||||||
|
} else if (type === 2) {
|
||||||
|
if (!timeout) {
|
||||||
|
timeout = setTimeout(() => {
|
||||||
|
timeout = null;
|
||||||
|
func.apply(context, args)
|
||||||
|
}, wait)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对象转数组
|
||||||
|
* @param {Object} e
|
||||||
|
*/
|
||||||
|
objToArrary (obj) {
|
||||||
|
|
||||||
|
if (Object.values(obj) && Array.isArray(Object.values(obj)[0])){
|
||||||
|
// 是数组
|
||||||
|
let arr = []
|
||||||
|
Object.values(obj).forEach(item=>{
|
||||||
|
arr = [...arr,...item]
|
||||||
|
})
|
||||||
|
return arr
|
||||||
|
} else {
|
||||||
|
// 不是数组
|
||||||
|
return Object.keys(obj).map(key => obj[key])
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取url链接参数
|
||||||
|
* @param {Object} url
|
||||||
|
* @param {Object} name
|
||||||
|
*/
|
||||||
|
getQueryString(url, name) {
|
||||||
|
var reg = new RegExp('(^|&|/?)' + name + '=([^&|/?]*)(&|/?|$)', 'i')
|
||||||
|
var r = url.substr(1).match(reg)
|
||||||
|
if (r != null) {
|
||||||
|
return r[2]
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,143 +0,0 @@
|
|||||||
import { $getBaiduToken } from '@/http/apiManager.js';
|
|
||||||
const audioTeam = [];
|
|
||||||
let audioStartSwitch = false;
|
|
||||||
const getAudioUrl = 'https://tsn.baidu.com/text2audio';
|
|
||||||
|
|
||||||
export default function openVoice(objs) { // 传入需转为语音的文本内容
|
|
||||||
let lineUp = false;
|
|
||||||
let returnAudio = false;
|
|
||||||
if (typeof(objs) !== 'string') {
|
|
||||||
if (objs && objs.lineUp === true) {
|
|
||||||
lineUp = true;
|
|
||||||
}
|
|
||||||
if (objs && objs.returnAudio === true) {
|
|
||||||
returnAudio = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(returnAudio) {
|
|
||||||
return new Promise((resolve, reject)=>{
|
|
||||||
openVoiceFc(objs, returnAudio).then(res=>{
|
|
||||||
resolve(res);
|
|
||||||
}).catch(err=>{
|
|
||||||
reject(err)
|
|
||||||
});
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!audioStartSwitch || lineUp) {
|
|
||||||
audioStartSwitch = true;
|
|
||||||
openVoiceFc(objs);
|
|
||||||
} else {
|
|
||||||
audioTeam.push(objs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function openVoiceFc(objs, returnAudio) {
|
|
||||||
if(returnAudio) {
|
|
||||||
return new Promise((resolve, reject)=>{
|
|
||||||
$getBaiduToken().then(({bizData}) => {
|
|
||||||
if (bizData) {
|
|
||||||
resolve(tts(objs, bizData, returnAudio));
|
|
||||||
} else {
|
|
||||||
reject('获取语音tok接口为空');
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}else{
|
|
||||||
$getBaiduToken().then(({bizData}) => {
|
|
||||||
if (bizData) {
|
|
||||||
tts(objs, bizData);
|
|
||||||
} else {
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function tts(objs, tok, returnAudio) {
|
|
||||||
if(typeof(objs)=='string')
|
|
||||||
objs = {voiceSet: {tex: objs}};
|
|
||||||
const data = {
|
|
||||||
tok,
|
|
||||||
cuid: tok,
|
|
||||||
ctp: 1,
|
|
||||||
lan: 'zh',
|
|
||||||
...objs.voiceSet
|
|
||||||
}
|
|
||||||
if(returnAudio)
|
|
||||||
return btts( data, objs.audioSet, objs.audioCallback, objs.lineUp, returnAudio);
|
|
||||||
btts( data, objs.audioSet, objs.audioCallback, objs.lineUp, returnAudio);
|
|
||||||
}
|
|
||||||
|
|
||||||
function setAudioSet(options, audio) {
|
|
||||||
if (options) {
|
|
||||||
audio.volume = options.volume || 1;
|
|
||||||
audio.startTime = options.startTime || 0;
|
|
||||||
audio.loop = options.loop || false;
|
|
||||||
audio.obeyMuteSwitch = options.obeyMuteSwitch && typeof(options.obeyMuteSwitch) == 'boolean' ? options.obeyMuteSwitch :
|
|
||||||
true; //支持微信小程序、百度小程序、头条小程序
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function btts(param, options, audioCallback, lineUp, returnAudio) {
|
|
||||||
let audio = uni.createInnerAudioContext();
|
|
||||||
setAudioSet(options, audio);
|
|
||||||
// 序列化参数列表
|
|
||||||
let fd = [];
|
|
||||||
for (let k in param) {
|
|
||||||
fd.push(k + '=' + encodeURIComponent(encodeURIComponent(param[k])));
|
|
||||||
}
|
|
||||||
audio.src = `${getAudioUrl}?${fd.join('&')}`;
|
|
||||||
|
|
||||||
if(returnAudio) {
|
|
||||||
audio.onEnded(() => {
|
|
||||||
audio.destroy(); //销毁音频实例
|
|
||||||
audio = null;
|
|
||||||
})
|
|
||||||
audio.onError((e)=>{
|
|
||||||
if (audioCallback && audioCallback.onError && typeof(audioCallback.onError) == 'function') audioCallback.onError(e);
|
|
||||||
audio.destroy(); //销毁音频实例
|
|
||||||
audio = null;
|
|
||||||
})
|
|
||||||
return audio;
|
|
||||||
}
|
|
||||||
audio.onPlay(() => {
|
|
||||||
if (audioCallback && audioCallback.onPlay && typeof(audioCallback.onPlay) == 'function') audioCallback.onPlay();
|
|
||||||
})
|
|
||||||
audio.onPause(()=>{
|
|
||||||
if (audioCallback && audioCallback.onPause && typeof(audioCallback.onPause) == 'function') audioCallback.onPause();
|
|
||||||
})
|
|
||||||
audio.onWaiting(()=>{
|
|
||||||
if (audioCallback && audioCallback.onWaiting && typeof(audioCallback.onWaiting) == 'function') audioCallback.onWaiting();
|
|
||||||
})
|
|
||||||
audio.onStop(()=>{
|
|
||||||
if (audioCallback && audioCallback.onStop && typeof(audioCallback.onStop) == 'function') audioCallback.onStop();
|
|
||||||
})
|
|
||||||
audio.onTimeUpdate(()=>{
|
|
||||||
if (audioCallback && audioCallback.onTimeUpdate && typeof(audioCallback.onTimeUpdate) == 'function') audioCallback.onTimeUpdate();
|
|
||||||
})
|
|
||||||
audio.onSeeking(()=>{
|
|
||||||
if (audioCallback && audioCallback.onSeeking && typeof(audioCallback.onSeeking) == 'function') audioCallback.onSeeking();
|
|
||||||
})
|
|
||||||
audio.onSeeked(()=>{
|
|
||||||
if (audioCallback && audioCallback.onSeeked && typeof(audioCallback.onSeeked) == 'function') audioCallback.onSeeked();
|
|
||||||
})
|
|
||||||
audio.onEnded(() => {
|
|
||||||
audio.destroy(); //销毁音频实例
|
|
||||||
audio = null;
|
|
||||||
if (audioCallback && audioCallback.onEnded && typeof(audioCallback.onEnded) == 'function') audioCallback.onEnded();
|
|
||||||
if (lineUp !== false) {
|
|
||||||
if (audioTeam.length > 0) {
|
|
||||||
openVoiceFc(audioTeam[0]);
|
|
||||||
audioTeam.splice(0, 1);
|
|
||||||
} else {
|
|
||||||
audioStartSwitch = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
audio.onError((e)=>{
|
|
||||||
if (audioCallback && audioCallback.onError && typeof(audioCallback.onError) == 'function') audioCallback.onError(e);
|
|
||||||
audio.destroy(); //销毁音频实例
|
|
||||||
audio = null;
|
|
||||||
})
|
|
||||||
audio.play();
|
|
||||||
}
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
import storageManage from '@/commons/utils/storageManage.js'
|
|
||||||
import dayjs from 'dayjs'
|
|
||||||
import baiduyy from './QS-baiduyy.js'; // 百度语音合成
|
|
||||||
|
|
||||||
// #ifdef MP-WEIXIN
|
|
||||||
import wxTextToSpeach from './wxTextToSpeach.js'; // 微信小程序插件语音合成
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
|
|
||||||
const model = {
|
|
||||||
// 监听推送通知
|
|
||||||
addPushMsgEventListener: function(){
|
|
||||||
|
|
||||||
console.log("监听推送")
|
|
||||||
|
|
||||||
// #ifdef APP-PLUS
|
|
||||||
// unipush1.0监听消息
|
|
||||||
if(plus && plus.push) {
|
|
||||||
plus.push.addEventListener('receive', model.handlePush)
|
|
||||||
}
|
|
||||||
// #endif
|
|
||||||
// unipush2.0监听消息
|
|
||||||
model.uniPushListener2()
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
// uniPush2.0 接收推送消息
|
|
||||||
uniPushListener2: function() {
|
|
||||||
uni.onPushMessage((res) => {
|
|
||||||
console.log("uniPush2.0 收到推送消息:", res.data) //监听推送消息
|
|
||||||
model.handlePush(res.data)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
// 语音播报
|
|
||||||
handlePush: function(message) {
|
|
||||||
|
|
||||||
// 没有token信息
|
|
||||||
if(!storageManage.token()){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 信息不存在
|
|
||||||
if(!message || !message.content) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const content = JSON.parse(message.content)
|
|
||||||
console.log("消息内容:", content)
|
|
||||||
|
|
||||||
// 支付成功
|
|
||||||
if (content && content.type == 'paySuccess') {
|
|
||||||
// 在过期时间之内, 则调起语音播报。
|
|
||||||
if( dayjs(content.expiredTime).isAfter(dayjs()) ){
|
|
||||||
console.log('执行消息播报');
|
|
||||||
// #ifdef MP-WEIXIN
|
|
||||||
wxTextToSpeach(content.msg)
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
// #ifndef MP-WEIXIN
|
|
||||||
baiduyy(content.msg)
|
|
||||||
// #endif
|
|
||||||
uni.vibrateLong({});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export default model
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
import {
|
|
||||||
$pushInfoRegister
|
|
||||||
} from '@/http/apiManager.js'
|
|
||||||
import storageManage from '@/commons/utils/storageManage.js'
|
|
||||||
// 默认导出 方法 注册 push连接
|
|
||||||
export default async function() {
|
|
||||||
let cid1 = undefined // unipush1.0 客户端CID
|
|
||||||
let cid2 = undefined // unipush2.0 客户端CID
|
|
||||||
let orgCid = undefined // 原始cid如果获取的cid和新的cid不相同赋值原始cid后端会根据原始cid更新
|
|
||||||
let cidType = undefined //传递类型 是 app 还是 微信
|
|
||||||
// #ifdef APP-PLUS
|
|
||||||
cidType = 'app_plus'
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
// #ifdef MP-WEIXIN
|
|
||||||
cidType = 'mp_weixin'
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
// #ifdef APP-PLUS
|
|
||||||
if (!plus) {
|
|
||||||
cid1 = plus.push.getClientInfo().clientid
|
|
||||||
}
|
|
||||||
// #endif
|
|
||||||
const data = await uni.getPushClientId()
|
|
||||||
console.log('客户端推送标识:', data.cid)
|
|
||||||
cid2 = data.cid
|
|
||||||
// 如果不存 cid 本地存储 写入 cid
|
|
||||||
if (!storageManage.uniPush2Cid()) {
|
|
||||||
storageManage.uniPush2Cid(data.cid)
|
|
||||||
} else if (cid2 !== storageManage.uniPush2Cid()) { // 否则进行 cid 对比 判断 是否相等 不相等 赋值 orgCid
|
|
||||||
orgCid = storageManage.uniPush2Cid() //赋值原始cid
|
|
||||||
storageManage.uniPush2Cid(data.cid) //重新写入 cid
|
|
||||||
}
|
|
||||||
if (cid1) {
|
|
||||||
pushInfoRegister(cid1)
|
|
||||||
} else {
|
|
||||||
pushInfoRegister(cid1, cid2, orgCid, cidType)
|
|
||||||
}
|
|
||||||
|
|
||||||
function pushInfoRegister(cid1 = '', cid2 = '', org = '', cidType = '') {
|
|
||||||
$pushInfoRegister({
|
|
||||||
cid1,
|
|
||||||
cid2,
|
|
||||||
orgCid: org,
|
|
||||||
cidType
|
|
||||||
}).then(res => {
|
|
||||||
orgCid = '' //重置 数据
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
import { $mchConfig } from "@/http/apiManager"
|
|
||||||
import storageManage from '@/commons/utils/storageManage.js'
|
|
||||||
let num = 0 //计算错误此时 超过5次错误 不在出触发
|
|
||||||
const plugin = requirePlugin("WechatSI")
|
|
||||||
const pushMsgArr = [] //维护一个消息队列
|
|
||||||
let backgroundAudioManager = undefined //获取背景音频实例
|
|
||||||
let audioMp3 = ''
|
|
||||||
console.log('执行创建 语音播报逻辑');
|
|
||||||
// 获取配置项 判断是否 开启 小程序 语音推送
|
|
||||||
export function getPushStatus () {
|
|
||||||
if (!storageManage.token()) return //未登录 不播放
|
|
||||||
$mchConfig('orderConfig').then(({ bizData = [] }) => {
|
|
||||||
const weChat = bizData.find(v => v.configKey == "weChatVoice")
|
|
||||||
if (weChat && weChat?.configVal == 1) {
|
|
||||||
createBgMusice()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// getPushStatus()
|
|
||||||
// 创建 背景音乐
|
|
||||||
function createBgMusice (file) {
|
|
||||||
backgroundAudioManager = wx.getBackgroundAudioManager()
|
|
||||||
backgroundAudioManager.title = '订单通知'
|
|
||||||
if (!audioMp3) {
|
|
||||||
createFile()
|
|
||||||
} else {
|
|
||||||
backgroundAudioManager.src = audioMp3
|
|
||||||
}
|
|
||||||
|
|
||||||
// 监听 音频播放失败事件
|
|
||||||
backgroundAudioManager.onError(function (res) {
|
|
||||||
console.log('音频播放失败', res, num);
|
|
||||||
if (num >= 5) return
|
|
||||||
createFile()
|
|
||||||
num++
|
|
||||||
})
|
|
||||||
// 监听 音频播放结束事件
|
|
||||||
onBgMusiceEnd()
|
|
||||||
}
|
|
||||||
// 监听bei背景音乐播放状态
|
|
||||||
export function onBgMusiceEnd () {
|
|
||||||
backgroundAudioManager.onEnded(() => {
|
|
||||||
if (pushMsgArr.length > 0) return broadcast(pushMsgArr.pop()) //如果有消息 则继续播放
|
|
||||||
backgroundAudioManager.src = audioMp3 //否则播放默认背景音乐
|
|
||||||
})
|
|
||||||
}
|
|
||||||
export function startOrEndMusice (flag) {
|
|
||||||
if (!flag && !!backgroundAudioManager) return backgroundAudioManager.stop() //关闭背景音乐 地址指向空即可
|
|
||||||
if (!backgroundAudioManager) return createBgMusice() // 如果一开始是关闭状态 则创建背景音乐实例
|
|
||||||
backgroundAudioManager.src = audioMp3 // 否则重新赋值背景音地址即可
|
|
||||||
}
|
|
||||||
export default function (message) {
|
|
||||||
if (!backgroundAudioManager) return
|
|
||||||
pushMsgArr.unshift(message) //将消息添加到消息队列头部 背景音乐播放结束后 会对消息队列 进行校验 如果消息队列有消息 会进行播放 否则继续循环背景音乐
|
|
||||||
}
|
|
||||||
// 播放订单
|
|
||||||
function broadcast (msg) {
|
|
||||||
plugin.textToSpeech({
|
|
||||||
lang: "zh_CN",
|
|
||||||
tts: true,
|
|
||||||
content: msg,
|
|
||||||
success: function (res) {
|
|
||||||
backgroundAudioManager.src = res.filename;
|
|
||||||
onBgMusiceEnd()
|
|
||||||
},
|
|
||||||
fail: function (res) {
|
|
||||||
console.log("fail tts", res)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建文件
|
|
||||||
export function createFile (file) {
|
|
||||||
const fs = wx.getFileSystemManager()
|
|
||||||
fs.copyFile({
|
|
||||||
srcPath: `static/noiseless.mp3`,
|
|
||||||
destPath: `${wx.env.USER_DATA_PATH}/noiseless.mp3`,
|
|
||||||
success (res) {
|
|
||||||
console.log(res, `${wx.env.USER_DATA_PATH}/noiseless.mp3`)
|
|
||||||
audioMp3 = `${wx.env.USER_DATA_PATH}/noiseless.mp3`
|
|
||||||
backgroundAudioManager.src = audioMp3
|
|
||||||
},
|
|
||||||
fail (res) {
|
|
||||||
console.error(res)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
创建 云空间 上传云函数 云函数 url化 运营平台 配置云函数地址
|
|
||||||
|
|
||||||
打包时 勾选云push 2.0 push1.0 仅支持 app 推送
|
|
||||||
|
|
||||||
注意配置 百度语音相关参数
|
|
||||||
|
|
||||||
使用push2.0 请将 static\noiseless.mp3 文件 配置到运营平台 系统 配置 通知配置 push2.0 uniPush语音播报音频文件(小程序播报必填) 下
|
|
||||||
|
|
||||||
注意:扩展库依赖3张opendb表:opendb-tempdata,opendb-device,uni-id-device。公测版uniCloud,执行扩展库会自动创建。如果你使用的是uniCloud正式版需要自己创建这3张表。
|
|
||||||
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
export const objToArrary = (obj,keyNewName) => {
|
|
||||||
return Object.entries(obj).map(([key, value]) => ({
|
|
||||||
key,
|
|
||||||
[keyNewName]:key,
|
|
||||||
...value,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
import {
|
|
||||||
getCurrentInstance,
|
import { getCurrentInstance } from 'vue';
|
||||||
} from 'vue';
|
|
||||||
export async function getElRect(elClass, instance,option) {
|
export async function getElRect(elClass, instance,option) {
|
||||||
instance = instance ? instance : getCurrentInstance();
|
instance = instance ? instance : getCurrentInstance();
|
||||||
const query = uni.createSelectorQuery().in(instance.proxy);
|
const query = uni.createSelectorQuery().in(instance.proxy);
|
||||||
|
|||||||
@@ -18,15 +18,10 @@ const appCache = {
|
|||||||
const model = {
|
const model = {
|
||||||
|
|
||||||
setLogin(res){
|
setLogin(res){
|
||||||
const user=res.user.user
|
uni.setStorageSync('shopInfo',res.shopInfo)
|
||||||
uni.setStorageSync('logoutHandle',false)
|
|
||||||
uni.setStorageSync('shopId', res.shopId)
|
|
||||||
uni.setStorageSync('shopName',res.shopName)
|
|
||||||
uni.setStorageSync('logo',res.logo)
|
|
||||||
uni.setStorageSync('loginType',res.loginType)
|
uni.setStorageSync('loginType',res.loginType)
|
||||||
uni.setStorageSync('shopUserId',user.id)
|
if(res.loginType=='1'){
|
||||||
if(res.loginType=='staff'){
|
// uni.setStorageSync('merchantName',user.createBy||user.updateBy)
|
||||||
uni.setStorageSync('merchantName',user.createBy||user.updateBy)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 退出清空所有的缓存数据。 (不包含 环境相关)
|
// 退出清空所有的缓存数据。 (不包含 环境相关)
|
||||||
@@ -51,14 +46,14 @@ const model = {
|
|||||||
|
|
||||||
if (val) {
|
if (val) {
|
||||||
// 有值,为放置
|
// 有值,为放置
|
||||||
appCache.tokenVal = val
|
appCache.tokenVal = val.tokenValue
|
||||||
uni.setStorageSync(appConfig.tokenKey, val)
|
uni.setStorageSync(appConfig.tokenKey, val)
|
||||||
} else {
|
} else {
|
||||||
// 否则为获取
|
// 否则为获取
|
||||||
|
|
||||||
if (!appCache.tokenVal) {
|
if (!appCache.tokenVal) {
|
||||||
//缓存取不到,获取应用本地信息
|
//缓存取不到,获取应用本地信息
|
||||||
appCache.tokenVal = uni.getStorageSync(appConfig.tokenKey)
|
appCache.tokenVal = uni.getStorageSync(appConfig.tokenKey).tokenValue
|
||||||
}
|
}
|
||||||
return appCache.tokenVal
|
return appCache.tokenVal
|
||||||
}
|
}
|
||||||
@@ -254,6 +249,7 @@ const model = {
|
|||||||
if (envMode) {
|
if (envMode) {
|
||||||
uni.setStorageSync(appConfig.storeEnvEnumKey, envMode) // 改变存储
|
uni.setStorageSync(appConfig.storeEnvEnumKey, envMode) // 改变存储
|
||||||
}
|
}
|
||||||
|
|
||||||
return uni.getStorageSync(appConfig.storeEnvEnumKey)
|
return uni.getStorageSync(appConfig.storeEnvEnumKey)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
/**
|
|
||||||
* @desc 函数节流
|
|
||||||
* @param func 函数
|
|
||||||
* @param wait 延迟执行毫秒数
|
|
||||||
* @param type 1 使用表时间戳,在时间段开始的时候触发 2 使用表定时器,在时间段结束的时候触发
|
|
||||||
*/
|
|
||||||
export const throttle = (func, wait = 1000, type = 1) => {
|
|
||||||
let previous = 0;
|
|
||||||
let timeout;
|
|
||||||
return function() {
|
|
||||||
let context = this;
|
|
||||||
let args = arguments;
|
|
||||||
if (type === 1) {
|
|
||||||
let now = Date.now();
|
|
||||||
|
|
||||||
if (now - previous > wait) {
|
|
||||||
func.apply(context, args);
|
|
||||||
previous = now;
|
|
||||||
}
|
|
||||||
} else if (type === 2) {
|
|
||||||
if (!timeout) {
|
|
||||||
timeout = setTimeout(() => {
|
|
||||||
timeout = null;
|
|
||||||
func.apply(context, args)
|
|
||||||
}, wait)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -6,7 +6,6 @@
|
|||||||
* @date 2022/11/22 10:38
|
* @date 2022/11/22 10:38
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { $parseQrCodeUrl } from '@/http/apiManager.js'
|
|
||||||
|
|
||||||
const model = {
|
const model = {
|
||||||
|
|
||||||
@@ -23,9 +22,9 @@ const model = {
|
|||||||
|
|
||||||
// 解析 码牌
|
// 解析 码牌
|
||||||
parseQrc: (originQrVal) => {
|
parseQrc: (originQrVal) => {
|
||||||
return $parseQrCodeUrl(originQrVal).then( ({bizData}) => {
|
// return $parseQrCodeUrl(originQrVal).then( ({bizData}) => {
|
||||||
return model.returnFunc(model.QR_TYPE_QRC, bizData, originQrVal)
|
// return model.returnFunc(model.QR_TYPE_QRC, bizData, originQrVal)
|
||||||
})
|
// })
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { $versionDetection } from '@/http/apiManager.js';
|
|
||||||
import appConfig from '@/config/appConfig.js'
|
import appConfig from '@/config/appConfig.js'
|
||||||
|
|
||||||
// app更新
|
// app更新
|
||||||
@@ -8,38 +7,38 @@ function appPlusUpdate(sign){
|
|||||||
plus.runtime.getProperty(plus.runtime.appid, function(inf) {
|
plus.runtime.getProperty(plus.runtime.appid, function(inf) {
|
||||||
|
|
||||||
// 调起接口查询
|
// 调起接口查询
|
||||||
$versionDetection({versionNumber: inf.versionCode})
|
// $versionDetection({versionNumber: inf.versionCode})
|
||||||
.then(({ bizData }) => {
|
// .then(({ bizData }) => {
|
||||||
|
|
||||||
//返回data为空或者版本号一致
|
// //返回data为空或者版本号一致
|
||||||
if (!bizData || Object.keys(bizData).length == 0 || !bizData.versionSerialNumber || bizData.versionSerialNumber == inf.versionCode) {
|
// if (!bizData || Object.keys(bizData).length == 0 || !bizData.versionSerialNumber || bizData.versionSerialNumber == inf.versionCode) {
|
||||||
if(sign === 'checked') {
|
// if(sign === 'checked') {
|
||||||
uni.showToast({
|
// uni.showToast({
|
||||||
title: '已是最新版本'
|
// title: '已是最新版本'
|
||||||
})
|
// })
|
||||||
}
|
// }
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
// 是否强制更新
|
// // 是否强制更新
|
||||||
let isForceUpdate = bizData.forceUpdate == 1
|
// let isForceUpdate = bizData.forceUpdate == 1
|
||||||
uni.showModal({
|
// uni.showModal({
|
||||||
title: '发现新版本:' + bizData.versionName,
|
// title: '发现新版本:' + bizData.versionName,
|
||||||
showCancel: !isForceUpdate ,
|
// showCancel: !isForceUpdate ,
|
||||||
content: bizData.versionDesc,
|
// content: bizData.versionDesc,
|
||||||
confirmText: '立即更新',
|
// confirmText: '立即更新',
|
||||||
confirmColor: '#108EE9',
|
// confirmColor: '#108EE9',
|
||||||
success: function(r) {
|
// success: function(r) {
|
||||||
if (r.confirm) {
|
// if (r.confirm) {
|
||||||
downLoad(bizData.downloadUrl);
|
// downLoad(bizData.downloadUrl);
|
||||||
}else{
|
// }else{
|
||||||
// 强制更新也需要更新
|
// // 强制更新也需要更新
|
||||||
if(isForceUpdate){
|
// if(isForceUpdate){
|
||||||
downLoad(bizData.downloadUrl);
|
// downLoad(bizData.downloadUrl);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
});
|
// });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
150
commons/utils/websocket.js
Normal file
150
commons/utils/websocket.js
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
|
||||||
|
import { reactive, ref } from 'vue';
|
||||||
|
// WebSocket 工具类,封装了 WebSocket 的连接、发送、接收、心跳、重连和关闭等操作
|
||||||
|
class WebsocketUtil {
|
||||||
|
|
||||||
|
// 构造函数,初始化 WebSocket 连接
|
||||||
|
constructor(url, time, params) {
|
||||||
|
this.url = url; // WebSocket 服务器的 URL
|
||||||
|
this.params = params; // WebSocket 服务器的 URL
|
||||||
|
this.time = time; // 心跳发送的间隔时间(秒)
|
||||||
|
this.socketTask = null; // WebSocket 任务对象
|
||||||
|
this.isOpen = false; // WebSocket 连接是否打开
|
||||||
|
this.reconnectTimeout = null; // 重连定时器
|
||||||
|
this.heartbeatInterval = null; // 心跳定时器
|
||||||
|
this.messageCallbacks = []; // 存储外部注册的消息回调函数的数组
|
||||||
|
this.messageCallbacks = []; // 存储外部注册的消息回调函数的数组
|
||||||
|
|
||||||
|
// 初始化 WebSocket 连接
|
||||||
|
this.initializeWebSocket();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化 WebSocket 连接
|
||||||
|
initializeWebSocket() {
|
||||||
|
if( this.isOpen){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.socketTask = uni.connectSocket({
|
||||||
|
url: this.url,
|
||||||
|
success: () => {
|
||||||
|
console.log('WebSocket连接成功');
|
||||||
|
return this.socketTask;
|
||||||
|
},
|
||||||
|
fail: (error) => {
|
||||||
|
console.error('WebSocket连接失败', error);
|
||||||
|
uni.$emit('is-socket-open', true)
|
||||||
|
this.reconnect();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.socketTask.onOpen((res) => {
|
||||||
|
console.log('WebSocket连接正常!==',res);
|
||||||
|
this.isOpen = true;
|
||||||
|
// 连接成功后启动心跳和消息监听
|
||||||
|
this.startHeartbeat();
|
||||||
|
this.listenForMessages();
|
||||||
|
uni.$emit('is-socket-open', true)
|
||||||
|
|
||||||
|
});
|
||||||
|
this.socketTask.onError((res) => {
|
||||||
|
console.log('WebSocket连接失败!==',res);
|
||||||
|
uni.$emit('is-socket-open', false)
|
||||||
|
this.reconnect();
|
||||||
|
});
|
||||||
|
// 注意:这里的 onClose 监听器应该放在 uni.connectSocket 调用之后
|
||||||
|
this.socketTask.onClose((result) => {
|
||||||
|
this.isOpen = false;
|
||||||
|
// if( this.isOpen ){
|
||||||
|
this.reconnect();
|
||||||
|
// }
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 启动心跳检测
|
||||||
|
startHeartbeat() {
|
||||||
|
if (this.heartbeatInterval) {
|
||||||
|
clearInterval(this.heartbeatInterval);
|
||||||
|
}
|
||||||
|
this.heartbeatInterval = setInterval(() => {
|
||||||
|
if (this.isOpen) {
|
||||||
|
this.send(JSON.stringify({"type": "ping_interval","set": "onboc"}));
|
||||||
|
}
|
||||||
|
}, this.time);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送消息
|
||||||
|
send(data,type) {
|
||||||
|
if (this.socketTask && this.isOpen) {
|
||||||
|
this.socketTask.send({
|
||||||
|
data: data,
|
||||||
|
success: (res) => {
|
||||||
|
// console.log('消息发送成功', res);
|
||||||
|
},
|
||||||
|
fail: (error) => {
|
||||||
|
console.error('消息发送失败', error);
|
||||||
|
this.reconnect(); // 这里可能需要根据实际情况判断是否重连
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 监听 WebSocket 消息
|
||||||
|
listenForMessages() {
|
||||||
|
if (this.socketTask) {
|
||||||
|
this.socketTask.onMessage((res) =>{
|
||||||
|
const { data } = res;
|
||||||
|
this.messageCallbacks.forEach(callback => callback(data.toString())); // 假设 data 是字符串或可转换为字符串
|
||||||
|
});
|
||||||
|
// this.send("WebSocket连接正常");
|
||||||
|
} else {
|
||||||
|
console.error('WebSocket 连接尚未建立,无法监听消息');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重连 WebSocket
|
||||||
|
reconnect() {
|
||||||
|
if (this.reconnectTimeout) {
|
||||||
|
clearTimeout(this.reconnectTimeout);
|
||||||
|
}
|
||||||
|
this.reconnectTimeout = setTimeout(() => {
|
||||||
|
this.initializeWebSocket();
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭 WebSocket 连接
|
||||||
|
closeSocket() {
|
||||||
|
if (this.socketTask) {
|
||||||
|
uni.closeSocket({
|
||||||
|
success: () => {
|
||||||
|
console.log('WebSocket连接已关闭');
|
||||||
|
this.isOpen = false;
|
||||||
|
},
|
||||||
|
fail: (error) => {
|
||||||
|
console.error('关闭WebSocket连接失败', error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.socketTask = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 外部注册消息回调函数
|
||||||
|
onMessage(callback) {
|
||||||
|
this.messageCallbacks.push(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 外部注销消息回调函数
|
||||||
|
offMessage(callback) {
|
||||||
|
this.messageCallbacks = []
|
||||||
|
}
|
||||||
|
|
||||||
|
// 销毁 WebSocket 连接,清理资源
|
||||||
|
destroy() {
|
||||||
|
this.closeSocket();
|
||||||
|
clearInterval(this.heartbeatInterval);
|
||||||
|
clearTimeout(this.reconnectTimeout);
|
||||||
|
this.messageCallbacks = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default WebsocketUtil;
|
||||||
@@ -1,133 +0,0 @@
|
|||||||
<template>
|
|
||||||
<uni-popup ref="refPopup" type="center" @change='change' :safe-area="false">
|
|
||||||
<view class="popup-wrapper">
|
|
||||||
<view class="title">用户服务协议与隐私政策</view>
|
|
||||||
<view class="content">
|
|
||||||
如需登录,请先认真阅读并同意{{ $appName }}
|
|
||||||
<text class="info" @tap="go.to(service)">《用户服务协议》</text>
|
|
||||||
与<text class="info" @tap="toPrivacy">《隐私政策》</text>。
|
|
||||||
</view>
|
|
||||||
<view class="but-wrapper">
|
|
||||||
<view class="but-item" hover-class="touch-button" @tap="disagreeClose">拒绝</view>
|
|
||||||
<button class="but-item agree" id="agree-btn" open-type="agreePrivacyAuthorization"
|
|
||||||
@agreeprivacyauthorization="handAgree">同意</button>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</uni-popup>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { reactive, ref, onMounted } from 'vue'
|
|
||||||
import go from '@/commons/utils/go.js'
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
service: { type: String },
|
|
||||||
privacy: { type: String }
|
|
||||||
})
|
|
||||||
const refPopup = ref(null)
|
|
||||||
const emits = defineEmits(['agree'])
|
|
||||||
const open = () => {
|
|
||||||
getPrivacy()
|
|
||||||
refPopup.value.open()
|
|
||||||
}
|
|
||||||
const vdata = reactive({})
|
|
||||||
const close = () => refPopup.value.close()
|
|
||||||
const toPrivacy = () => {
|
|
||||||
// #ifdef APP-PLUS
|
|
||||||
if (props.privacy) return go.to(props.privacy)
|
|
||||||
// #endif
|
|
||||||
// 打开小程序隐私政策
|
|
||||||
// #ifdef MP-WEIXIN
|
|
||||||
wx.openPrivacyContract(
|
|
||||||
{
|
|
||||||
fail: () => {
|
|
||||||
uni.showToast({
|
|
||||||
title: '打开失败请稍后重试', // 打开失败
|
|
||||||
icon: 'none'
|
|
||||||
})
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
}
|
|
||||||
function disagreeClose () {
|
|
||||||
close()
|
|
||||||
}
|
|
||||||
// 获取微信你用户是否同意过隐私政策
|
|
||||||
const getPrivacy = () => {
|
|
||||||
wx.getPrivacySetting({
|
|
||||||
success: (r) => {
|
|
||||||
Object.assign(vdata, r)
|
|
||||||
if (vdata.needAuthorization) {
|
|
||||||
wx.onNeedPrivacyAuthorization(res => {
|
|
||||||
vdata.resolve = res
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
const handAgree = () => {
|
|
||||||
if (vdata.needAuthorization) {
|
|
||||||
vdata.resolve({ buttonId: 'agree-btn', event: 'agree' })
|
|
||||||
}
|
|
||||||
emits('agree')
|
|
||||||
close()
|
|
||||||
}
|
|
||||||
defineExpose({ open, close })
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.popup-wrapper {
|
|
||||||
width: 600rpx;
|
|
||||||
border-radius: 20rpx;
|
|
||||||
background: #FFF;
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
.title {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
padding: 30rpx 0 50rpx;
|
|
||||||
text-align: center;
|
|
||||||
color: rgba(0, 0, 0, 0.50);
|
|
||||||
font-size: 28rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content {
|
|
||||||
padding-bottom: 70rpx;
|
|
||||||
margin: 0 auto;
|
|
||||||
width: 500rpx;
|
|
||||||
color: #000;
|
|
||||||
font-size: 28rpx;
|
|
||||||
line-height: 1.5;
|
|
||||||
|
|
||||||
.info {
|
|
||||||
color: $v-color-t21;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.but-wrapper {
|
|
||||||
display: flex;
|
|
||||||
|
|
||||||
.but-item {
|
|
||||||
flex: 1;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
height: 110rpx;
|
|
||||||
color: rgba(0, 0, 0, 0.70);
|
|
||||||
font-size: 32rpx;
|
|
||||||
font-weight: 400;
|
|
||||||
border-radius: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.agree {
|
|
||||||
background: $jeepay-bg-primary;
|
|
||||||
color: #fff;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
@@ -1,185 +0,0 @@
|
|||||||
<template>
|
|
||||||
<!-- 修改应用弹窗 -->
|
|
||||||
<uni-popup ref="popup" type="bottom" mask-background-color="rgba(0,0,0,.5)" :safe-area="false" @maskClick="emits('cancel')">
|
|
||||||
<view class="card-wrapper">
|
|
||||||
<view class="input-search">
|
|
||||||
<uni-easyinput
|
|
||||||
v-model="vadta.searchInfo"
|
|
||||||
prefixIcon="search"
|
|
||||||
:inputBorder="false"
|
|
||||||
:clearable="false"
|
|
||||||
:styles="styles"
|
|
||||||
type="text"
|
|
||||||
placeholder="搜索门店名称、ID"
|
|
||||||
placeholderStyle=" color: rgba(0,0,0,0.85);font-size: 30rpx;"
|
|
||||||
/>
|
|
||||||
<view class="search-button">搜索</view>
|
|
||||||
</view>
|
|
||||||
<!-- 循环开始部分 -->
|
|
||||||
<view class="store">
|
|
||||||
<view class="left">
|
|
||||||
<view class="store-dot"></view>
|
|
||||||
<view class="app-info">
|
|
||||||
<view class="app-name">应用名称</view>
|
|
||||||
<view class="app-code">62a55637e4b07ea5b8717ca3</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 循环结束部分 -->
|
|
||||||
<view class="footer-wrapper">
|
|
||||||
<view class="footer-main">
|
|
||||||
<view class="tips" v-if="tips">{{ tips }}</view>
|
|
||||||
<view class="footer-button">
|
|
||||||
<view class="flex-center" hover-class="touch-button" @tap="close">取消</view>
|
|
||||||
<view class="confirm flex-center" hover-class="touch-button">确认</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</uni-popup>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { onMounted, reactive, ref } from 'vue'
|
|
||||||
const emits = defineEmits(['cancel', 'confirm'])
|
|
||||||
const props = defineProps({
|
|
||||||
isAll: { type: Boolean, default: false }, //是否展示全部门店 默认false
|
|
||||||
tips: { type: String }, //提示信息 传入则展示
|
|
||||||
})
|
|
||||||
const styles = reactive({
|
|
||||||
backgroundColor: '#f7f7f7',
|
|
||||||
height: '90rpx',
|
|
||||||
borderRadius: '10rpx',
|
|
||||||
color: '#000',
|
|
||||||
})
|
|
||||||
const vadta = reactive({
|
|
||||||
searchInfo: '',
|
|
||||||
})
|
|
||||||
const popup = ref(null)
|
|
||||||
const open = (val) => {
|
|
||||||
popup.value.open()
|
|
||||||
}
|
|
||||||
const close = () => {
|
|
||||||
emits('cancel')
|
|
||||||
popup.value.close()
|
|
||||||
}
|
|
||||||
const confirm = () => {}
|
|
||||||
onMounted(() => {
|
|
||||||
open()
|
|
||||||
})
|
|
||||||
defineExpose({ open })
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.card-wrapper {
|
|
||||||
border-radius: 32rpx 32rpx 0 0;
|
|
||||||
background-color: #fff;
|
|
||||||
overflow: hidden;
|
|
||||||
min-height: 70vh;
|
|
||||||
.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;
|
|
||||||
align-items: center;
|
|
||||||
padding: 0 40rpx;
|
|
||||||
height: 170rpx;
|
|
||||||
font-size: 30rpx;
|
|
||||||
.left {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
.store-dot {
|
|
||||||
align-self: start;
|
|
||||||
position: relative;
|
|
||||||
top: 2rpx;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.app-info {
|
|
||||||
.app-code {
|
|
||||||
margin-top: 15rpx;
|
|
||||||
font-size: 26rpx;
|
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.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>
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
<template>
|
|
||||||
<!-- 单元格布局 -->
|
|
||||||
<view
|
|
||||||
class="cell-main"
|
|
||||||
:hover-class="isTouch ? 'touch-hover' : ''"
|
|
||||||
:style="{ '--border-width': borderWidth, marginTop: mT + 'rpx', '--m-rl': mRL + 'rpx', backgroundColor: bgColor }"
|
|
||||||
>
|
|
||||||
<view class="title" :style="{ color: color }"> {{ title }} </view>
|
|
||||||
<slot name="right">
|
|
||||||
<image src="/static/iconImg/icon-arrow-right.svg" mode="scaleToFill" />
|
|
||||||
</slot>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
const props = defineProps({
|
|
||||||
title: { type: String }, //标题
|
|
||||||
mT: { type: Number }, //上边距
|
|
||||||
mRL: { type: Number }, //左右两侧边距
|
|
||||||
bgColor: { type: String }, //背景颜色
|
|
||||||
color: { type: String }, //标题字体颜色
|
|
||||||
borderWidth: { type: String, default: '100vw' }, //边框距离左侧距离 默认100vw 没有边框
|
|
||||||
isTouch: { type: Boolean, default: true }, //是否有触摸反馈
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.cell-main {
|
|
||||||
position: relative;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
margin-left: var(--m-rl);
|
|
||||||
margin-right: var(--m-rl);
|
|
||||||
height: 120rpx;
|
|
||||||
.title {
|
|
||||||
margin-left: 40rpx;
|
|
||||||
font-size: 32rpx;
|
|
||||||
font-weight: 400;
|
|
||||||
}
|
|
||||||
image {
|
|
||||||
width: 120rpx;
|
|
||||||
height: 120rpx;
|
|
||||||
}
|
|
||||||
background-color: #fff;
|
|
||||||
&::after {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
right: 0;
|
|
||||||
z-index: 10;
|
|
||||||
width: calc(100vw - var(--border-width));
|
|
||||||
height: 1rpx;
|
|
||||||
background-color: #ededed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
<template>
|
|
||||||
<template v-if="subTitle">
|
|
||||||
<view class="details-wrapper" style="align-items: flex-start; padding-top: 40rpx">
|
|
||||||
<view class="details-title">{{ title }}</view>
|
|
||||||
<view>
|
|
||||||
<view class="sub-title">
|
|
||||||
<view class="details-info single-text-beyond"> {{ subTitle }}</view>
|
|
||||||
<image src="/static/iconImg/icon-arrow-small.svg" mode="scaleToFill" />
|
|
||||||
</view>
|
|
||||||
<view class="sub-info details-info single-text-beyond">{{ info }}</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<view class="details-wrapper">
|
|
||||||
<view class="details-title">{{ title }}</view>
|
|
||||||
<view class="details-info single-text-beyond">{{ info }}</view>
|
|
||||||
<image src="/static/iconImg/icon-arrow-right.svg" mode="scaleToFill" />
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
const props = defineProps({
|
|
||||||
title: { type: String }, //标题
|
|
||||||
info: [String, Number], //内容
|
|
||||||
subTitle: { type: String }, //副标题
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.details-wrapper {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding-left: 40rpx;
|
|
||||||
min-height: 120rpx;
|
|
||||||
font-size: 30rpx;
|
|
||||||
background-color: #fff;
|
|
||||||
.details-title {
|
|
||||||
width: 200rpx;
|
|
||||||
color: #4c4c4c;
|
|
||||||
}
|
|
||||||
.details-info {
|
|
||||||
flex: 1;
|
|
||||||
width: 334rpx;
|
|
||||||
}
|
|
||||||
image {
|
|
||||||
width: 108rpx;
|
|
||||||
height: 120rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.sub-title {
|
|
||||||
display: flex;
|
|
||||||
image {
|
|
||||||
width: 108rpx;
|
|
||||||
height: 40rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.sub-info {
|
|
||||||
margin-top: 20rpx;
|
|
||||||
font-size: 30rpx;
|
|
||||||
color: #a1a1a1;
|
|
||||||
padding-bottom: 40rpx;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
<template>
|
|
||||||
<!-- 详情页 带开关卡片布局 -->
|
|
||||||
<view class="s-wrapper">
|
|
||||||
<view class="s-title">
|
|
||||||
<text>{{ title }}</text>
|
|
||||||
<slot name="titleRight" />
|
|
||||||
</view>
|
|
||||||
<view class="s-tips">{{ subTitle }}</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
const props = defineProps({
|
|
||||||
title: { type: String }, //标题
|
|
||||||
subTitle: { type: String }, //提示信息
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.s-wrapper {
|
|
||||||
padding: 40rpx;
|
|
||||||
margin: 30rpx 35rpx;
|
|
||||||
border-radius: $J-b-r32;
|
|
||||||
background-color: #fff;
|
|
||||||
.s-title {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
font-size: 30rpx;
|
|
||||||
color: #4d4d4d;
|
|
||||||
}
|
|
||||||
.s-tips {
|
|
||||||
font-size: 25rpx;
|
|
||||||
color: #808080;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,164 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view class="k-wrapper">
|
|
||||||
<view class="k-store-name">
|
|
||||||
<view class="k-store-title flex-center">收款门店:</view>
|
|
||||||
<view class="flex-center" @tap="emits('selectedStore')"> {{ storeName || '选择门店' }} <image src="/static/iconImg/icon-arrow-black.svg" mode="scaleToFill" /></view>
|
|
||||||
</view>
|
|
||||||
<view class="k-main">
|
|
||||||
<block v-for="(v, i) in keyList" :key="i">
|
|
||||||
<view :class="[v.clsName]" hover-class="touch-number" hover-stay-time="150" v-if="v.type == 'number'" @tap="boardDown(v.value)">{{ v.value }}</view>
|
|
||||||
<view :class="[v.clsName]" hover-class="touch-number" hover-stay-time="150" v-if="v.type == 'image'" @tap="boardDown(v.value)">
|
|
||||||
<image :src="v.imgUrl" mode="scaleToFill" />
|
|
||||||
</view>
|
|
||||||
<view :class="[v.clsName]" hover-class="touch-button" hover-stay-time="150" v-if="v.type == 'button'" @tap="boardDown(v.value)">
|
|
||||||
<image :src="v.imgUrl" mode="scaleToFill" />
|
|
||||||
<text>{{ v.text }}</text>
|
|
||||||
</view>
|
|
||||||
</block>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { reactive, ref } from 'vue'
|
|
||||||
const emits = defineEmits(['boardDown', 'selectedStore',"update:value"])
|
|
||||||
/***
|
|
||||||
* 键盘渲染集合
|
|
||||||
* boardDown 回调事件 回调参数 value
|
|
||||||
* selectedStore 回调事件 选择门店 回调参数 无
|
|
||||||
* storeName 门店名称
|
|
||||||
* */
|
|
||||||
const props = defineProps({
|
|
||||||
storeName: { type: String }, //门店名称
|
|
||||||
|
|
||||||
point: { type: Number, default: 2 }, //限制小数点后几位 默认两位
|
|
||||||
maxLength: { type: Number, default: 10 }, //最大输入长度 包含小数点
|
|
||||||
value:{type:[String,Number],default:'0'}
|
|
||||||
})
|
|
||||||
const keyList = reactive([
|
|
||||||
{ type: 'number', clsName: 'k-number', value: '1' },
|
|
||||||
{ type: 'number', clsName: 'k-number', value: '2' },
|
|
||||||
{ type: 'number', clsName: 'k-number', value: '3' },
|
|
||||||
{ type: 'number', clsName: 'k-number', value: '4' },
|
|
||||||
{ type: 'number', clsName: 'k-number', value: '5' },
|
|
||||||
{ type: 'number', clsName: 'k-number', value: '6' },
|
|
||||||
{ type: 'number', clsName: 'k-number', value: '7' },
|
|
||||||
{ type: 'number', clsName: 'k-number', value: '8' },
|
|
||||||
{ type: 'number', clsName: 'k-number', value: '9' },
|
|
||||||
{ type: 'number', clsName: 'k-number', value: '.' },
|
|
||||||
{ type: 'number', clsName: 'k-number k-zero', value: '0' },
|
|
||||||
{ type: 'image', clsName: 'k-number', value: 'deleted', imgUrl: '/static/iconImg/icon-delete.svg' },
|
|
||||||
{ type: 'button', clsName: 'k-button', value: 'scan', imgUrl: '/static/iconImg/icon-scan.svg', text: '扫一扫' },
|
|
||||||
{ type: 'button', clsName: 'k-button k-button-code', value: 'code', imgUrl: '/static/iconImg/icon-code.svg', text: '聚合码' },
|
|
||||||
])
|
|
||||||
|
|
||||||
const deletedNumber = () => {
|
|
||||||
emits('update:value', props.value.toString().slice(0, props.value.length - 1))
|
|
||||||
}
|
|
||||||
const boardDown = (val) => {
|
|
||||||
// 如果 点击 扫一扫 或聚合码 直接回调事件
|
|
||||||
if (val == 'scan' || val == 'code') return emits('boardDown', val)
|
|
||||||
// 点击删除 调用函数
|
|
||||||
if (val == 'deleted') return deletedNumber()
|
|
||||||
// 如果值已经是0并且按下不是小数点 直接替换值
|
|
||||||
if (props.value.toString().length == 1 && props.value == 0 && val != '.') return emits('update:value', val)
|
|
||||||
// 只能包含一个小数点
|
|
||||||
if (props.value.toString().includes('.') && val == '.') return
|
|
||||||
// 限制小数点位数
|
|
||||||
if (props.value.toString().includes('.') && props.value.split('.')[1].length >= props.point) return
|
|
||||||
// 长度只有 一位 并且按下结果是小数点 直接 return
|
|
||||||
if (props.value.toString().length == 1 && props.value == 0 && val != '.') return
|
|
||||||
// 如果 清空后直接按下小数点 直接 return
|
|
||||||
if ((props.value === '' || props.value == undefined) && val == '.') return emits('update:value', '0' + val)
|
|
||||||
// 超出最大输入长度 直接 return
|
|
||||||
if (props.value.toString().length >= props.maxLength) return
|
|
||||||
// 回调结果
|
|
||||||
emits('update:value', props.value + val)
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.k-wrapper {
|
|
||||||
padding: 0 10rpx;
|
|
||||||
border-radius: 72rpx 72rpx 0 0;
|
|
||||||
border-top: 1rps solid rgba($color: #000000, $alpha: 0.1);
|
|
||||||
box-shadow: 0 -30rpx 80rpx -20rpx rgba(0, 0, 0, 0.05);
|
|
||||||
.k-store-name {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
height: 110rpx;
|
|
||||||
margin: 10rpx 0;
|
|
||||||
padding: 0 60rpx;
|
|
||||||
view {
|
|
||||||
flex-grow: 0;
|
|
||||||
height: 100%;
|
|
||||||
font-size: 30rpx;
|
|
||||||
font-weight: 500;
|
|
||||||
image {
|
|
||||||
width: 40rpx;
|
|
||||||
height: 40rpx;
|
|
||||||
transform: rotate(180deg);
|
|
||||||
margin-left: 10rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.k-store-title {
|
|
||||||
white-space: nowrap;
|
|
||||||
font-size: 30rpx;
|
|
||||||
font-weight: 400;
|
|
||||||
color: $J-color-t4d;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.k-main {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(3, 200rpx);
|
|
||||||
grid-template-rows: repeat(5, 120rpx);
|
|
||||||
grid-gap: 10rpx 20rpx;
|
|
||||||
padding: 0 50rpx;
|
|
||||||
font-size: 60rpx;
|
|
||||||
border-radius: 30rpx 30rpx 0 0;
|
|
||||||
overflow: hidden;
|
|
||||||
.k-number {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
border-radius: 10rpx;
|
|
||||||
image {
|
|
||||||
width: 60rpx;
|
|
||||||
height: 60rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.k-button {
|
|
||||||
grid-column: 1 / span 2;
|
|
||||||
grid-row: 5 / span 2;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
margin-top: 20rpx;
|
|
||||||
width: 315rpx;
|
|
||||||
height: 110rpx;
|
|
||||||
background: $jeepay-bg-primary;
|
|
||||||
font-size: 26rpx;
|
|
||||||
border-radius: 10rpx;
|
|
||||||
color: #fff;
|
|
||||||
image {
|
|
||||||
width: 40rpx;
|
|
||||||
height: 40rpx;
|
|
||||||
margin-right: 10rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.k-button-code {
|
|
||||||
transform: translateX(335rpx);
|
|
||||||
background: linear-gradient(270deg, rgba(72, 192, 255, 1) 0%, rgba(51, 157, 255, 1) 100%);
|
|
||||||
}
|
|
||||||
.touch-number {
|
|
||||||
border-radius: 80rpx;
|
|
||||||
background-color: #e9eaeb;
|
|
||||||
}
|
|
||||||
.touch-button {
|
|
||||||
opacity: 0.5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="p-wrapper">
|
<view class="p-wrapper">
|
||||||
<input class="p-input" type="number" v-model="info" :focus="vdata.isFoucs" :maxlength="num" @input="inputChange" />
|
<input class="p-input" type="number" v-model="info" :focus="vdata.isFoucs" :maxlength="num" @input="inputChange" />
|
||||||
<view class="p-main" :style="{ margin: margin }">
|
<view class="p-main" :style="{ margin: margin }">
|
||||||
<div class="p-number flex-center" v-for="v in num" :key="v" :class="{ 'p-active': v <= info.length }"></div>
|
<div class="p-number flex-center" v-for="v in num" :key="v" :class="{ 'p-active': v <= info.length }"></div>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
|||||||
@@ -1,53 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view class="search-wrapper" :style="{ paddingTop: pTop + 'rpx', backgroundColor: bgColor }">
|
|
||||||
<view class="search-main" @tap="emits('click')">
|
|
||||||
<image src="/static/iconImg/icon-search.svg" mode="scaleToFill" />
|
|
||||||
<input type="text" :placeholder="place" placeholder-style="color: rgba(0,0,0,0.35);" :style="{ fontSize: size + 'rpx' }" disabled />
|
|
||||||
</view>
|
|
||||||
<slot name="right" />
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
const props = defineProps({
|
|
||||||
place: { type: String }, //提示语
|
|
||||||
pTop: { type: Number }, //距离上边距离 使用padding 为了有背景色
|
|
||||||
bgColor: { type: String }, //背景色
|
|
||||||
size: { type: Number, default: 27 }, //搜素框文字大小
|
|
||||||
})
|
|
||||||
const emits = defineEmits(['click'])
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.search-wrapper {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
height: 110rpx;
|
|
||||||
background-color: $J-bg-ff;
|
|
||||||
padding: 0 30rpx;
|
|
||||||
.search-main {
|
|
||||||
flex: 1;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
height: 70rpx;
|
|
||||||
background-color: $J-bg-f5;
|
|
||||||
border-radius: $J-b-r12;
|
|
||||||
image {
|
|
||||||
padding: 0 22rpx;
|
|
||||||
width: 26rpx;
|
|
||||||
height: 26rpx;
|
|
||||||
}
|
|
||||||
input {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
.search-text {
|
|
||||||
padding: 0 30rpx;
|
|
||||||
font-size: 32rpx;
|
|
||||||
font-weight: 500;
|
|
||||||
color: $J-color-t29;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
<template>
|
|
||||||
<uni-popup ref="popup" type="bottom" mask-background-color="rgba(0,0,0,.5)" @change="change" :safe-area="false">
|
|
||||||
<view class="tips-wrapper">
|
|
||||||
<view class="tips-text flex-center" v-if="title">{{ title }}</view>
|
|
||||||
<scroll-view scroll-y class="list-wrap">
|
|
||||||
<block v-for="v in list" :key="v[value]">
|
|
||||||
<view
|
|
||||||
class="single-text flex-center"
|
|
||||||
hover-class="u-cell-hover"
|
|
||||||
hover-stay-time="150"
|
|
||||||
:style="{ color: v[value] == selected ? activeColor : v.color }"
|
|
||||||
@tap="confirm(v)"
|
|
||||||
>
|
|
||||||
{{ v[label] }}
|
|
||||||
</view>
|
|
||||||
</block>
|
|
||||||
</scroll-view>
|
|
||||||
<view class="line"></view>
|
|
||||||
<view class="tips-text tips-cancel flex-center" hover-class="u-cell-hover" hover-stay-time="150" @tap="popup.close()">取消</view>
|
|
||||||
</view>
|
|
||||||
</uni-popup>
|
|
||||||
|
|
||||||
<JeepayPopupConfirm ref="jeepayPopupConfirm" />
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { reactive, ref, inject } from 'vue';
|
|
||||||
const emits = defineEmits(['confirm']);
|
|
||||||
const props = defineProps({
|
|
||||||
title: { type: String }, //标题 传入展示 不传则隐藏
|
|
||||||
activeColor: { type: String, default: '#2980FD' }, //选中后文字颜色
|
|
||||||
textColor: { type: String }, //列表文字颜色
|
|
||||||
textSize: { type: String }, //列表文字大小
|
|
||||||
titleColor: { type: String }, //标题文字颜色
|
|
||||||
titleSize: { type: String }, //标题文字大小
|
|
||||||
list: { type: Array }, //渲染单选列表集合
|
|
||||||
label: { type: String, default: 'label' }, //展示文字的键名 可传值复写
|
|
||||||
value: { type: String, default: 'value' } //展示文字的key 可传值复写
|
|
||||||
});
|
|
||||||
const selected = ref(undefined);
|
|
||||||
const popup = ref(null);
|
|
||||||
|
|
||||||
const jeepayPopupConfirm = ref();
|
|
||||||
|
|
||||||
// 打开弹窗 val 选中数据的key
|
|
||||||
const open = (val) => {
|
|
||||||
selected.value = val;
|
|
||||||
popup.value.open();
|
|
||||||
};
|
|
||||||
const confirm = (listItem) => {
|
|
||||||
popup.value.close();
|
|
||||||
|
|
||||||
// 包含回调函数
|
|
||||||
if (listItem.fun) {
|
|
||||||
// 包含确认弹层。
|
|
||||||
if (listItem.confirmText) {
|
|
||||||
jeepayPopupConfirm.value
|
|
||||||
.open(listItem.confirmText)
|
|
||||||
.then(() => {
|
|
||||||
listItem.fun();
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
popup.value.open();
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
listItem.fun();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
1;
|
|
||||||
emits('confirm', listItem);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let changePageMetaOverflowFunc = inject('changePageMetaOverflowFunc');
|
|
||||||
const change = (e) => {
|
|
||||||
if (changePageMetaOverflowFunc) {
|
|
||||||
changePageMetaOverflowFunc(!e.show);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const close = () => popup.value.close();
|
|
||||||
defineExpose({ open, close });
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.list-wrap {
|
|
||||||
max-height: 60vh;
|
|
||||||
}
|
|
||||||
.tips-wrapper {
|
|
||||||
// overflow: hidden;
|
|
||||||
border-radius: 32rpx 32rpx 0 0;
|
|
||||||
padding-top: 20rpx;
|
|
||||||
padding-bottom: 60rpx;
|
|
||||||
background-color: #fff;
|
|
||||||
.tips-text {
|
|
||||||
text-align: center;
|
|
||||||
height: 90rpx;
|
|
||||||
font-size: 30rpx;
|
|
||||||
border-bottom: 1rpx solid rgba(0, 0, 0, 0.07);
|
|
||||||
}
|
|
||||||
.single-text {
|
|
||||||
height: 120rpx;
|
|
||||||
}
|
|
||||||
.line {
|
|
||||||
height: 20rpx;
|
|
||||||
background-color: rgba(0, 0, 0, 0.07);
|
|
||||||
}
|
|
||||||
.tips-cancel {
|
|
||||||
height: 110rpx;
|
|
||||||
color: $J-color-t80;
|
|
||||||
font-size: 33rpx;
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
.u-cell-hover {
|
|
||||||
background-color: #f8f9fa;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
<template>
|
|
||||||
<switch :checked="flag" :disabled="disabled" color="#238FFC" :style="{ transform: 'scale(' + scale + ')', margin: margin }" @change="change" @tap="emits('click')" />
|
|
||||||
<JeepayPopupConfirm ref="jeepayPopupConfirmRef" />
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref, watchEffect } from 'vue'
|
|
||||||
const props = defineProps({
|
|
||||||
scale: { type: Number, default: 0.8 }, //控制开关大小 倍数 默认.8
|
|
||||||
margin: { type: String, default: '0' }, // 控制开关外边距默认0
|
|
||||||
tips: { type: String }, //修改提示语不传使用 默认tips弹出层提示语
|
|
||||||
bol: { type: Boolean }, //开关状态
|
|
||||||
index: { type: Number, default: 0 }, // 列表渲染索引值
|
|
||||||
confirmTips: { type: Boolean, default: true }, //是否需要提示弹窗默认 需要
|
|
||||||
disabled: { type: Boolean, default: false }, // 是否禁用 默认否
|
|
||||||
})
|
|
||||||
const emits = defineEmits(['confirm', 'cancel', 'click'])
|
|
||||||
const flag = ref()
|
|
||||||
|
|
||||||
watchEffect(() => {
|
|
||||||
flag.value = props.bol
|
|
||||||
})
|
|
||||||
|
|
||||||
const jeepayPopupConfirmRef = ref() //提示弹窗
|
|
||||||
|
|
||||||
const change = (e) => {
|
|
||||||
flag.value = e.detail.value
|
|
||||||
if (!props.confirmTips) return confirm()
|
|
||||||
jeepayPopupConfirmRef.value
|
|
||||||
.open(props.tips || '确定修改状态?')
|
|
||||||
.then(() => {
|
|
||||||
confirm()
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
flag.value = !flag.value
|
|
||||||
emits('cancel', flag.value)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const confirm = () => {
|
|
||||||
emits('confirm', flag.value)
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped></style>
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view class="manage-main" :style="{ '--border-width': borderWidth }">
|
|
||||||
<view class="manage-title" :style="{ fontSize: titleSize, color: titleColor }">
|
|
||||||
{{ title }}
|
|
||||||
<slot name="right"></slot>
|
|
||||||
</view>
|
|
||||||
<view class="manage-info" :style="{ width: tipsWidth + 'rpx', fontSize: titleSize, color: titleColor }">{{ tips }}</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
const props = defineProps({
|
|
||||||
title: { type: String }, //标题
|
|
||||||
tips: { type: String }, //提示信息
|
|
||||||
tipsWidth: { type: Number }, // 提示信息宽度 默认500rpx
|
|
||||||
titleSize: { type: Number }, //标题字体大小
|
|
||||||
tipsSize: { type: Number }, //提示信息字体大小
|
|
||||||
titleColor: { type: String }, //标题文字颜色
|
|
||||||
tipsColor: { type: String }, //提示信息文字颜色
|
|
||||||
borderWidth: { type: String, default: '40rpx' }, //边框距离左侧距离 默认80rpx
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.manage-main {
|
|
||||||
position: relative;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
padding: 0 40rpx;
|
|
||||||
height: 198rpx;
|
|
||||||
background-color: #fff;
|
|
||||||
&::after {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
right: 0;
|
|
||||||
z-index: 10;
|
|
||||||
width: calc(100vw - var(--border-width));
|
|
||||||
height: 1rpx;
|
|
||||||
background-color: #ededed;
|
|
||||||
}
|
|
||||||
.manage-title {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
color: #4d4d4d;
|
|
||||||
}
|
|
||||||
.manage-info {
|
|
||||||
margin-top: 12rpx;
|
|
||||||
width: 500rpx;
|
|
||||||
font-size: 25rpx;
|
|
||||||
color: #999999;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
<template>
|
|
||||||
<scroll-view
|
|
||||||
class="table-list"
|
|
||||||
scroll-y
|
|
||||||
:style="{ '--height': height }"
|
|
||||||
@scrolltolower="addNext"
|
|
||||||
@refresherrefresh="openRefresh"
|
|
||||||
:refresher-enabled="refresh"
|
|
||||||
:refresher-triggered="vdata.isRefresh"
|
|
||||||
>
|
|
||||||
<template v-for="(record, i) in vdata.allData" :key="i">
|
|
||||||
<slot name="tableBody" :record="record" :index="i" />
|
|
||||||
</template>
|
|
||||||
<view class="list-null" v-if="!vdata.apiResData.hasNext && showListNull">暂无更多数据</view>
|
|
||||||
</scroll-view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref, reactive, onMounted } from 'vue';
|
|
||||||
import { onPullDownRefresh, onReachBottom } from '@dcloudio/uni-app';
|
|
||||||
|
|
||||||
// 定义传入属性
|
|
||||||
const props = defineProps({
|
|
||||||
reqTableDataFunc: { type: Function, default: () => {} },
|
|
||||||
searchData: { type: Object, default: () => {} }, // 搜索条件参数
|
|
||||||
pageSize: { type: Number, default: 10 }, // 默认每页条数
|
|
||||||
initData: { type: Boolean, default: true }, // 初始化列表数据, 默认true
|
|
||||||
showListNull: { type: Boolean, default: true }, //是否显示缺省 默认显示
|
|
||||||
height: { type: String, default: '88rpx' }, // 高度 这里的高度 为 外部使用高度 scroll-view 高度 为 100vh - 传入高度
|
|
||||||
refresh: { type: Boolean, default: false } //是否开启下拉刷新 默认不开启
|
|
||||||
});
|
|
||||||
|
|
||||||
const vdata = reactive({
|
|
||||||
allData: [], // app与web不同, app是每次查询到数据会拼接到后面
|
|
||||||
|
|
||||||
// 接口返回的数据
|
|
||||||
apiResData: { total: 0, records: [] },
|
|
||||||
|
|
||||||
// 分页参数
|
|
||||||
iPage: { pageNumber: 1, pageSize: props.pageSize },
|
|
||||||
|
|
||||||
// 下拉刷新开启状态
|
|
||||||
isRefresh: false
|
|
||||||
});
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
//初始化表数据
|
|
||||||
props.initData ? refTable(true) : undefined;
|
|
||||||
});
|
|
||||||
|
|
||||||
// 查询表格数据
|
|
||||||
function refTable(isToFirst = false) {
|
|
||||||
if (isToFirst) {
|
|
||||||
// 重新搜索, 第一页。
|
|
||||||
vdata.iPage.pageNumber = 1;
|
|
||||||
vdata.allData = []; //清空数据
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新检索数据
|
|
||||||
return props.reqTableDataFunc(Object.assign({}, vdata.iPage, props.searchData)).then(({ bizData }) => {
|
|
||||||
Object.assign(vdata.apiResData, bizData); // 列表数据更新
|
|
||||||
|
|
||||||
if (bizData.records) {
|
|
||||||
bizData.records.forEach((r) => vdata.allData.push(r));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 追加下一页数据 **/
|
|
||||||
function addNext() {
|
|
||||||
// console.log('加载下一页')
|
|
||||||
// 包含下一页
|
|
||||||
if (vdata.apiResData.hasNext) {
|
|
||||||
vdata.iPage.pageNumber++;
|
|
||||||
refTable(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 下拉刷新
|
|
||||||
const openRefresh = () => {
|
|
||||||
vdata.isRefresh = true;
|
|
||||||
refTable(true).then(() => {
|
|
||||||
setTimeout(() => {
|
|
||||||
vdata.isRefresh = false;
|
|
||||||
}, 300);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// 将表格事件暴露出去 https://www.jianshu.com/p/39d14c25c987
|
|
||||||
defineExpose({ refTable, addNext });
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.table-list {
|
|
||||||
height: calc(75vh - var(--height));
|
|
||||||
}
|
|
||||||
.list-null {
|
|
||||||
position: relative;
|
|
||||||
height: 110rpx;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
padding-bottom: 70rpx;
|
|
||||||
gap: 20rpx;
|
|
||||||
font-size: 26rpx;
|
|
||||||
color: #a6a6a6;
|
|
||||||
&::after,
|
|
||||||
&::before {
|
|
||||||
content: '';
|
|
||||||
display: block;
|
|
||||||
width: 30%;
|
|
||||||
height: 2rpx;
|
|
||||||
background-color: #ededed;
|
|
||||||
transform: translateY(-50%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
<template>
|
|
||||||
<uni-popup ref="popup" type="bottom" mask-background-color="rgba(0,0,0,.5)" @change='change' :safe-area="false" @maskClick="emits('cancel')">
|
|
||||||
<!-- 通用提示弹窗 用于提示用户 数据含义 -->
|
|
||||||
<view class="card-wrapper">
|
|
||||||
<view class="card-title flex-center">{{ title }}</view>
|
|
||||||
<slot />
|
|
||||||
<view class="card-button flex-center" hover-class="touch-hover" @tap="confirm"> {{ buttonText }}</view>
|
|
||||||
</view>
|
|
||||||
</uni-popup>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { onMounted, reactive, ref,inject } from 'vue'
|
|
||||||
const emits = defineEmits(['cancel'])
|
|
||||||
const props = defineProps({
|
|
||||||
title: { type: String }, //标题
|
|
||||||
buttonText: { type: String }, //按钮文字
|
|
||||||
})
|
|
||||||
const popup = ref(null)
|
|
||||||
|
|
||||||
const open = (val) => {
|
|
||||||
popup.value.open()
|
|
||||||
}
|
|
||||||
const confirm = () => {
|
|
||||||
emits('cancel')
|
|
||||||
popup.value.close()
|
|
||||||
}
|
|
||||||
let changePageMetaOverflowFunc = inject('changePageMetaOverflowFunc')
|
|
||||||
const change = (e)=>{
|
|
||||||
if(changePageMetaOverflowFunc){
|
|
||||||
changePageMetaOverflowFunc(!e.show)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
defineExpose({ open })
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.card-wrapper {
|
|
||||||
border-radius: 32rpx 32rpx 0 0;
|
|
||||||
background-color: #fff;
|
|
||||||
padding-bottom: 60rpx;
|
|
||||||
max-height: 70vh;
|
|
||||||
.card-title {
|
|
||||||
margin-bottom: 20rpx;
|
|
||||||
height: 110rpx;
|
|
||||||
font-size: 30rpx;
|
|
||||||
font-weight: 400;
|
|
||||||
border-bottom: 1rpx solid rgba(0, 0, 0, 0.07);
|
|
||||||
}
|
|
||||||
.card-button {
|
|
||||||
margin-top: 20rpx;
|
|
||||||
height: 110rpx;
|
|
||||||
font-size: 32rpx;
|
|
||||||
color: #2980fd;
|
|
||||||
border-top: 20rpx solid #f7f7f7;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
<template>
|
|
||||||
<!-- 单张广告 -->
|
|
||||||
<view class="ad-wrapper" v-if="list.length == 1">
|
|
||||||
<image :src="list[0].imgUrl" mode="aspectFill" @tap='toH5(list[0].linkUrl)' />
|
|
||||||
</view>
|
|
||||||
<!-- 多张广告 -->
|
|
||||||
<view class="ads-wrapper" v-else>
|
|
||||||
<block v-for="(v, i) in list" :key="i">
|
|
||||||
<view>
|
|
||||||
<image :src="v.imgUrl" mode="aspectFill" @tap='toH5(v.linkUrl)' />
|
|
||||||
</view>
|
|
||||||
</block>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
const props = defineProps({
|
|
||||||
list: { type: Array, default: [] }
|
|
||||||
})
|
|
||||||
const toH5 = (url) => {
|
|
||||||
if (!url) return
|
|
||||||
uni.navigateTo({
|
|
||||||
url: '/pages/adH5/adH5?url=' + url
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.ad-wrapper {
|
|
||||||
margin: 40rpx;
|
|
||||||
|
|
||||||
max-height: 680rpx;
|
|
||||||
border-radius: 30rpx;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ads-wrapper {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
margin: 30rpx;
|
|
||||||
|
|
||||||
view {
|
|
||||||
width: calc(50% - 20rpx);
|
|
||||||
max-height: 400rpx;
|
|
||||||
border-radius: 30rpx;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
image {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,237 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view class="start" v-if="show">
|
|
||||||
<view class="skip" :style="skipPositionStyle" @click="onSkip">跳过 {{ time2 }}</view>
|
|
||||||
<swiper class="swiper" :interval="interval" :autoplay="list.length > 1" @change="onChangeSwiper">
|
|
||||||
<swiper-item v-for="(item, index) in list" :key="index">
|
|
||||||
<view class="swiper-item" :style="bgStyle">
|
|
||||||
<image class="image" :src="item.imgUrl" mode="aspectFill" @tap="toAdH5(item)"></image>
|
|
||||||
<view class="after" :style="afterStyle"></view>
|
|
||||||
</view>
|
|
||||||
</swiper-item>
|
|
||||||
<!-- autoplay -->
|
|
||||||
</swiper>
|
|
||||||
<view class="swiper-dot" v-if="list.length > 1">
|
|
||||||
<view class="view" :style="index === current ? currentStyle : ''" :class="{ active: index === current }"
|
|
||||||
v-for="(item, index) in list" :key="index" />
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
props: {
|
|
||||||
list: {
|
|
||||||
type: Array,
|
|
||||||
default() {
|
|
||||||
return []
|
|
||||||
},
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
hasTabbar: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
hasNavbar: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
interval: {
|
|
||||||
type: Number,
|
|
||||||
default: 3000,
|
|
||||||
},
|
|
||||||
time: {
|
|
||||||
type: Number,
|
|
||||||
default: 3,
|
|
||||||
},
|
|
||||||
url: {
|
|
||||||
type: String,
|
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
bgColor: {
|
|
||||||
type: String,
|
|
||||||
default: '#fff',
|
|
||||||
},
|
|
||||||
afterColor: {
|
|
||||||
type: String,
|
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
currentColor: {
|
|
||||||
type: String,
|
|
||||||
default: '#BB1219',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
current: 0,
|
|
||||||
show: true,
|
|
||||||
timer: null,
|
|
||||||
time2: this.time,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
time2(val) {
|
|
||||||
if (val <= 0) {
|
|
||||||
this.onSkip()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
bgStyle() {
|
|
||||||
return this.obj2strStyle({
|
|
||||||
'background-color': this.bgColor,
|
|
||||||
})
|
|
||||||
},
|
|
||||||
afterStyle() {
|
|
||||||
return this.obj2strStyle({
|
|
||||||
'background-color': this.afterColor,
|
|
||||||
})
|
|
||||||
},
|
|
||||||
currentStyle() {
|
|
||||||
return this.obj2strStyle({
|
|
||||||
'background-color': this.currentColor,
|
|
||||||
})
|
|
||||||
},
|
|
||||||
skipPositionStyle() {
|
|
||||||
const { statusBarHeight } = uni.getSystemInfoSync()
|
|
||||||
if (!this.hasNavbar) {
|
|
||||||
return this.obj2strStyle({
|
|
||||||
top: `${statusBarHeight * 2 + 88 + 30}rpx`,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return this.obj2strStyle({
|
|
||||||
top: '30rpx',
|
|
||||||
})
|
|
||||||
},
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.$emit('openInt', this.onStart)
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
if (this.hasTabbar) {
|
|
||||||
uni.hideTabBar()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
onStart() {
|
|
||||||
this.timer = setInterval(() => {
|
|
||||||
this.time2--
|
|
||||||
}, 1000)
|
|
||||||
},
|
|
||||||
onPause() {
|
|
||||||
clearInterval(this.timer)
|
|
||||||
},
|
|
||||||
obj2strStyle(obj) {
|
|
||||||
let style = ''
|
|
||||||
for (let key in obj) {
|
|
||||||
style += `${key}:${obj[key]};`
|
|
||||||
}
|
|
||||||
return style
|
|
||||||
},
|
|
||||||
onSkip() {
|
|
||||||
const { url, hasTabbar, timer } = this
|
|
||||||
clearTimeout(timer)
|
|
||||||
this.show = false
|
|
||||||
if (hasTabbar) {
|
|
||||||
uni.showTabBar()
|
|
||||||
}
|
|
||||||
if (url) {
|
|
||||||
uni.reLaunch({
|
|
||||||
url: url,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onChangeSwiper(e) {
|
|
||||||
this.current = e.detail.current
|
|
||||||
},
|
|
||||||
toAdH5(ite) {
|
|
||||||
if (!ite.linkUrl) return
|
|
||||||
clearInterval(this.timer)
|
|
||||||
uni.navigateTo({
|
|
||||||
url: '/pages/adH5/adH5?url=' + ite.linkUrl,
|
|
||||||
})
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
/* $nav-height: 44px; */
|
|
||||||
.start {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
z-index: 9999;
|
|
||||||
}
|
|
||||||
|
|
||||||
.skip {
|
|
||||||
position: absolute;
|
|
||||||
z-index: 2;
|
|
||||||
background-color: rgba(0, 0, 0, 0.1);
|
|
||||||
color: #fff;
|
|
||||||
right: 30rpx;
|
|
||||||
font-size: 28rpx;
|
|
||||||
width: 133rpx;
|
|
||||||
height: 60rpx;
|
|
||||||
border-radius: 44rpx;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.swiper {
|
|
||||||
height: 100vh;
|
|
||||||
width: 100vw;
|
|
||||||
}
|
|
||||||
|
|
||||||
.swiper-item {
|
|
||||||
height: 100vh;
|
|
||||||
width: 100vw;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
overflow: hidden;
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.swiper-item .after {
|
|
||||||
width: 100vw;
|
|
||||||
height: 500rpx;
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
bottom: 0;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.swiper-item .image {
|
|
||||||
height: 100vh;
|
|
||||||
width: 100vw;
|
|
||||||
display: block;
|
|
||||||
position: relative;
|
|
||||||
z-index: 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.swiper-dot {
|
|
||||||
position: absolute;
|
|
||||||
width: 100vw;
|
|
||||||
left: 0;
|
|
||||||
bottom: 100rpx;
|
|
||||||
z-index: 3;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.swiper-dot .view {
|
|
||||||
width: 16rpx;
|
|
||||||
height: 16rpx;
|
|
||||||
border-radius: 100%;
|
|
||||||
background-color: rgba(0, 0, 0, 0.2);
|
|
||||||
margin: 0 12rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.swiper-dot .view.active {
|
|
||||||
width: 30rpx;
|
|
||||||
border-radius: 24rpx;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
<!--
|
|
||||||
背景模板
|
|
||||||
|
|
||||||
使用方式:
|
|
||||||
|
|
||||||
A. 背景图片的通用外部view ( APP不支持背景图片的变量动态替换, 所以只能业务页面来写入背景图片的地址。 )
|
|
||||||
<JeepayBackground :bgImgView="true">页面内容</JeepayBackground>
|
|
||||||
<style scoped>
|
|
||||||
/deep/ .bg-img-view { background: url('/static/indexImg/user-bg.svg'); }
|
|
||||||
</style>
|
|
||||||
|
|
||||||
B. 背景是自定义颜色的外部view ( 默认蓝色渐变 )
|
|
||||||
<JeepayBackground :bgColorStyle="{}">页面内容</JeepayBackground>
|
|
||||||
|
|
||||||
@author terrfly
|
|
||||||
@site https://www.jeequan.com
|
|
||||||
@date 2022/11/19 08:08
|
|
||||||
-->
|
|
||||||
<template>
|
|
||||||
|
|
||||||
<!-- 微信小程序: <page-meta>: 只能是页面内的第一个节点,且不能被 wx:if 或 wx:for 动态变更
|
|
||||||
uniapp: 打包到小程序, 会添加 <jeepay-background>标签, 导致该问题。 无奈 小程序不可使用: <page-meta> 标签, 实现方式为: page-wrapper height方式。
|
|
||||||
-->
|
|
||||||
<!-- <page-meta :pageStyle="'overflow:' + (vdata.pageMetaOverflow ? 'visible' : 'hidden')"></page-meta> -->
|
|
||||||
<!-- #ifdef APP-PLUS-->
|
|
||||||
<page-meta :pageStyle="'overflow:' + (vdata.pageMetaOverflow ? 'visible' : 'hidden')"></page-meta>
|
|
||||||
<!-- #endif -->
|
|
||||||
<!-- page-wrapper 包裹 -->
|
|
||||||
<view class="page-wrapper" :style="{overflow:vdata.pageMetaOverflow ? 'visible' : 'hidden', height:vdata.pageMetaOverflow ? 'auto' : '90vh'}">
|
|
||||||
|
|
||||||
<!-- 背景图片view -->
|
|
||||||
<view class="bg-img-view" :style="vdata.bgImgStyle">
|
|
||||||
|
|
||||||
<!-- 背景颜色view -->
|
|
||||||
<view class="bg-color-view" :style="vdata.bgColorStyle" style="border-radius:0;background-color: #318AFE!important;">
|
|
||||||
<view class="bgbottomStyle">
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<!-- 解决定位层级问题 -->
|
|
||||||
<view class="bg-main">
|
|
||||||
<slot></slot>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { reactive, ref, onMounted, provide, computed } from 'vue'
|
|
||||||
|
|
||||||
// 选择是图片风格 还是 背景颜色风格。
|
|
||||||
const props = defineProps({
|
|
||||||
// 背景图片
|
|
||||||
bgImgView: { type: Boolean }, // APP 不支持背景图片的动态替换。。。
|
|
||||||
|
|
||||||
// 背景颜色style
|
|
||||||
bgColorStyle: { type: Object },
|
|
||||||
// 禁止滚动穿透
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
function changePageMetaOverflowFunc(v){
|
|
||||||
vdata.pageMetaOverflow = v
|
|
||||||
}
|
|
||||||
provide('changePageMetaOverflowFunc', changePageMetaOverflowFunc)
|
|
||||||
|
|
||||||
|
|
||||||
const vdata = reactive({
|
|
||||||
|
|
||||||
bgImgStyle : { }, // 注意: style变量需要全部替换, 不可使用Object.assign修改里面的值, 否则 APP不生效!
|
|
||||||
bgColorStyle : { },
|
|
||||||
pageMetaOverflow: true
|
|
||||||
})
|
|
||||||
provide('pageMetaOverflow',computed(()=>vdata.pageMetaOverflow))
|
|
||||||
onMounted(() => {
|
|
||||||
|
|
||||||
// 包含背景图片
|
|
||||||
if(props.bgImgView){
|
|
||||||
vdata.bgImgStyle = {
|
|
||||||
position: "absolute",
|
|
||||||
top: 0,
|
|
||||||
left: 0,
|
|
||||||
right: 0,
|
|
||||||
backgroundRepeat: 'no-repeat'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// 包含背景色
|
|
||||||
if(props.bgColorStyle){
|
|
||||||
let defStyle = { // 默认颜色
|
|
||||||
position: "absolute",
|
|
||||||
top: 0,
|
|
||||||
left: 0,
|
|
||||||
right: 0,
|
|
||||||
height: '550rpx',
|
|
||||||
borderRadius: '0 0 32rpx 32rpx',
|
|
||||||
// background: 'linear-gradient(270deg, rgba(72, 192, 255, 1) 0%, rgba(51, 157, 255, 1) 100%)',
|
|
||||||
}
|
|
||||||
vdata.bgColorStyle = Object.assign(defStyle, props.bgColorStyle)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
<style scoped lang="scss">
|
|
||||||
.bg-main{
|
|
||||||
position: relative;
|
|
||||||
z-index: 10;
|
|
||||||
}
|
|
||||||
.bgbottomStyle{
|
|
||||||
position: absolute;
|
|
||||||
bottom: -2rpx;
|
|
||||||
left: 0;
|
|
||||||
|
|
||||||
width: 750rpx;
|
|
||||||
height: 74rpx;
|
|
||||||
background: linear-gradient( 180deg, rgba(195,215,235,0) 0%, #F9F9F9 100%);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
<template>
|
|
||||||
<swiper
|
|
||||||
class="swiper"
|
|
||||||
circular
|
|
||||||
:indicator-dots="true"
|
|
||||||
autoplay
|
|
||||||
:interval="interval * 1000"
|
|
||||||
:duration="500"
|
|
||||||
>
|
|
||||||
<block v-for="(v, i) in list" :key="i">
|
|
||||||
<swiper-item>
|
|
||||||
<image :src="v.imgUrl" mode="aspectFill" @tap="toH5(v.linkUrl)" />
|
|
||||||
</swiper-item>
|
|
||||||
</block>
|
|
||||||
</swiper>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
const props = defineProps({
|
|
||||||
list: { type: Array, default: [] },
|
|
||||||
interval: { type: [String, Number] },
|
|
||||||
});
|
|
||||||
const toH5 = (url) => {
|
|
||||||
if (!url) return;
|
|
||||||
uni.navigateTo({
|
|
||||||
url: '/pages/adH5/adH5?url=' + url,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.uni-margin-wrap {
|
|
||||||
width: 690rpx;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.swiper {
|
|
||||||
margin: 40rpx;
|
|
||||||
height: 300rpx;
|
|
||||||
border-radius: 30rpx;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.swiper-item {
|
|
||||||
display: block;
|
|
||||||
|
|
||||||
height: 300rpx;
|
|
||||||
line-height: 300rpx;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
image {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,143 +0,0 @@
|
|||||||
<!--
|
|
||||||
Jeepay 门店选择 / 应用选择
|
|
||||||
|
|
||||||
@author terrfly
|
|
||||||
@site https://www.jeequan.com
|
|
||||||
@date 2022/12/06 12:55
|
|
||||||
-->
|
|
||||||
<template>
|
|
||||||
<!-- 选择门店 -->
|
|
||||||
<JeepayPopupListSelect
|
|
||||||
ref="jeepayPopupListSelectByBizinfos"
|
|
||||||
:reqTableDataFunc="reqTableDataByBizsFunc"
|
|
||||||
:searchInputName="getSearchInputName()"
|
|
||||||
:fields="getField()"
|
|
||||||
:isCheckbox="props.isCheckbox"
|
|
||||||
:addUse="props.addUse"
|
|
||||||
@confirm="confirm"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { reactive, ref } from 'vue';
|
|
||||||
import { reqLoad, API_URL_MCH_STORE_LIST, API_URL_MCH_APP_LIST, API_URL_MCH_ISV_LIST } from '@/http/apiManager.js';
|
|
||||||
|
|
||||||
// 定义组件参数
|
|
||||||
const props = defineProps({
|
|
||||||
configMode: '',
|
|
||||||
// 是否多选框, 默认单选。
|
|
||||||
isCheckbox: { type: Boolean, default: false },
|
|
||||||
|
|
||||||
// 自动关闭, 点击确定, 自动关闭
|
|
||||||
autoClose: { type: Boolean, default: true },
|
|
||||||
|
|
||||||
// 业务类型: 默认门店
|
|
||||||
bizType: { type: String, default: 'store' },
|
|
||||||
range: { type: String, default: 0 },
|
|
||||||
ifCode: { type: String, default: '' },
|
|
||||||
|
|
||||||
// 是否支持选择 【 全部门店 、 全部应用 】
|
|
||||||
isShowAllBiz: { type: Boolean, default: false },
|
|
||||||
// 特殊参数处理
|
|
||||||
params: { type: Object, default: () => ({}) },
|
|
||||||
addUse: { type: Boolean, default: false }
|
|
||||||
});
|
|
||||||
|
|
||||||
const jeepayPopupListSelectByBizinfos = ref();
|
|
||||||
const emits = defineEmits(['confirm']);
|
|
||||||
function confirm(data) {
|
|
||||||
console.log(data);
|
|
||||||
emits('confirmData', data);
|
|
||||||
}
|
|
||||||
console.log(props.isCheckbox);
|
|
||||||
function getField() {
|
|
||||||
if (props.bizType == 'store') {
|
|
||||||
return { key: 'storeId', left: 'storeName', right: 'storeId' };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (props.bizType == 'mchApp') {
|
|
||||||
return { key: 'appId', left: 'appName', right: 'appId' };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (props.bizType == 'isvApp') {
|
|
||||||
return { key: 'isvNo', left: 'isvName', right: 'isvNo' };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSearchInputName() {
|
|
||||||
if (props.bizType == 'store') {
|
|
||||||
return 'storeName';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (props.bizType == 'mchApp') {
|
|
||||||
return 'appName';
|
|
||||||
}
|
|
||||||
if (props.bizType == 'isvApp') {
|
|
||||||
return 'isvName';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (props.bizType == 'isvApp') {
|
|
||||||
params.ifCode = props.ifCode;
|
|
||||||
params.range = props.range;
|
|
||||||
apiResult = reqLoad.list(API_URL_MCH_ISV_LIST, params);
|
|
||||||
}
|
|
||||||
return apiResult.then((apiRes) => {
|
|
||||||
return processApiResBizData(params, apiRes);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 选择门店
|
|
||||||
function open(defaultVal) {
|
|
||||||
console.log(defaultVal, 'defaultValdefaultVal');
|
|
||||||
return jeepayPopupListSelectByBizinfos.value.open(defaultVal).then((selected) => {
|
|
||||||
// 自动关闭
|
|
||||||
if (props.autoClose) {
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
|
|
||||||
return selected;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function close() {
|
|
||||||
jeepayPopupListSelectByBizinfos.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: '' });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (props.bizType == 'isvApp') {
|
|
||||||
apiRes.bizData.records.unshift({ appName: '全部渠道', appId: '' });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return apiRes;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 将表格事件暴露出去 https://www.jianshu.com/p/39d14c25c987
|
|
||||||
defineExpose({ open, close });
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style></style>
|
|
||||||
@@ -1,144 +0,0 @@
|
|||||||
<!--
|
|
||||||
通用的选择某项业务, 一般用作修改页。
|
|
||||||
目前支持: 门店 和 应用
|
|
||||||
@author terrfly
|
|
||||||
@site https://www.jeepay.vip
|
|
||||||
@date 2022/12/08 14:18
|
|
||||||
-->
|
|
||||||
<template>
|
|
||||||
<view class="details-wrapper" style="align-items: flex-start; padding-top: 40rpx">
|
|
||||||
<view v-if="props.hasTitle" class="details-title">
|
|
||||||
<slot name="title">{{ bizTypeMap[props.bizType].title }}</slot>
|
|
||||||
</view>
|
|
||||||
<view @tap="show">
|
|
||||||
<view class="sub-title">
|
|
||||||
<view class="details-info single-text-beyond">
|
|
||||||
<text :class="{ 'text-gray': vdata.selectedRow[bizTypeMap[props.bizType].nameKey] ? false : true }">
|
|
||||||
{{ vdata.selectedRow[bizTypeMap[props.bizType].nameKey] || bizTypeMap[props.bizType].nameDef }}
|
|
||||||
</text>
|
|
||||||
</view>
|
|
||||||
<image src="/static/iconImg/icon-arrow-small.svg" mode="scaleToFill" v-if="isIcon" />
|
|
||||||
</view>
|
|
||||||
<view class="sub-info details-info single-text-beyond">{{ vdata.selectedRow[bizTypeMap[props.bizType].id] }}</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view>
|
|
||||||
<JeepayBizinfoSelect ref="jeepayBizinfoSelectRef" :bizType="props.bizType" :isCheckbox="false" :range="props.range" :ifCode="props.ifCode" :addUse="props.addUse" />
|
|
||||||
<JeepayIncomingBizinfoSelect ref="jeepayIncomingBizinfoSelectRef" :bizType="props.bizType" :range="props.range" :ifCode="props.ifCode" />
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref, reactive, nextTick, watch, onMounted } from 'vue';
|
|
||||||
|
|
||||||
const jeepayBizinfoSelectRef = ref();
|
|
||||||
const jeepayIncomingBizinfoSelectRef = ref();
|
|
||||||
|
|
||||||
const bizTypeMap = {
|
|
||||||
store: { title: '选择门店', nameKey: 'storeName', nameDef: '请选择门店', id: 'storeId' },
|
|
||||||
mchApp: { title: '选择应用', nameKey: 'appName', nameDef: '请选择应用', id: 'appId' },
|
|
||||||
isvApp: { title: '选择渠道', nameKey: 'isvName', nameDef: '请选择渠道', id: 'isvNo' },
|
|
||||||
incomingApp: { title: '发起进件', nameKey: 'name', nameDef: '请选择场景', id: 'range' }
|
|
||||||
};
|
|
||||||
|
|
||||||
// emit 父组件使用: v-model:value="val" 进行双向绑定。
|
|
||||||
const emits = defineEmits(['update:value', 'update:showName', 'change']);
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
// 是否包含 标题部分
|
|
||||||
hasTitle: { type: Boolean, default: true },
|
|
||||||
|
|
||||||
//绑定的值, 双向绑定
|
|
||||||
value: { type: [String, Number] },
|
|
||||||
|
|
||||||
// 仅仅用作修改的回显
|
|
||||||
showName: { type: [String, Number] },
|
|
||||||
|
|
||||||
// 业务类型: 默认门店
|
|
||||||
bizType: { type: String, default: 'store' },
|
|
||||||
range: { type: String, default: 0 },
|
|
||||||
ifCode: { type: String, default: '' },
|
|
||||||
isIcon: { type: Boolean, default: true },
|
|
||||||
addUse: { type: Boolean, default: false }
|
|
||||||
});
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
if (props.value) {
|
|
||||||
vdata.selectedRow[bizTypeMap[props.bizType].id] = props.value;
|
|
||||||
}
|
|
||||||
if (props.showName) {
|
|
||||||
vdata.selectedRow[bizTypeMap[props.bizType].nameKey] = props.showName;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 切换时
|
|
||||||
watch(
|
|
||||||
() => props.value,
|
|
||||||
(newVal, oldVal) => {
|
|
||||||
vdata.selectedRow[bizTypeMap[props.bizType].id] = newVal;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// 切换时
|
|
||||||
watch(
|
|
||||||
() => props.showName,
|
|
||||||
(newVal, oldVal) => {
|
|
||||||
vdata.selectedRow[bizTypeMap[props.bizType].nameKey] = newVal;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const vdata = reactive({
|
|
||||||
// 当前选择行
|
|
||||||
selectedRow: {}
|
|
||||||
});
|
|
||||||
|
|
||||||
function show() {
|
|
||||||
jeepayBizinfoSelectRef.value.open().then((selectedRow) => {
|
|
||||||
vdata.selectedRow = selectedRow || {};
|
|
||||||
|
|
||||||
emits('update:value', vdata.selectedRow[bizTypeMap[props.bizType].id]);
|
|
||||||
emits('update:showName', vdata.selectedRow[bizTypeMap[props.bizType].nameKey]);
|
|
||||||
emits('change', vdata.selectedRow[bizTypeMap[props.bizType].id]);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.details-wrapper {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
font-size: 32rpx;
|
|
||||||
background-color: #fff;
|
|
||||||
.details-title {
|
|
||||||
width: 180rpx;
|
|
||||||
color: #4c4c4c;
|
|
||||||
}
|
|
||||||
.details-info {
|
|
||||||
flex-grow: 1;
|
|
||||||
width: 405rpx;
|
|
||||||
}
|
|
||||||
image {
|
|
||||||
width: 108rpx;
|
|
||||||
height: 100rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sub-title {
|
|
||||||
flex: 1;
|
|
||||||
display: flex;
|
|
||||||
image {
|
|
||||||
width: 108rpx;
|
|
||||||
height: 40rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.sub-info {
|
|
||||||
margin-top: 20rpx;
|
|
||||||
font-size: 30rpx;
|
|
||||||
color: #a1a1a1;
|
|
||||||
padding-bottom: 20rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-gray {
|
|
||||||
color: #b3b3b3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
<!--
|
|
||||||
组件功能: 卡片布局
|
|
||||||
标题, 副标题, 和编辑按钮及插槽。
|
|
||||||
注意: 不包含 中间的内容
|
|
||||||
@author terrfly
|
|
||||||
@site https://www.jeequan.com
|
|
||||||
@date 2022/12/06 08:06
|
|
||||||
-->
|
|
||||||
<template>
|
|
||||||
<view class="c-card-wrapper" :style="props.viewStyle">
|
|
||||||
|
|
||||||
<view v-if="props.title" class="card-title" :class="{'border-none':!isTitleBorder}" @tap="emits('clickTitle')">
|
|
||||||
<view class="c-card-title"> {{ props.title }} <view><slot name="titleRight"/> </view> </view>
|
|
||||||
<view class="sub-title" v-if="props.subtitle">{{ props.subtitle }}</view>
|
|
||||||
</view>
|
|
||||||
<!-- 默认插槽位置 -->
|
|
||||||
<slot></slot>
|
|
||||||
|
|
||||||
<!-- 编辑区域 -->
|
|
||||||
<slot name="editContent">
|
|
||||||
<view v-if="props.editText" class="card-edit flex-center" hover-class="touch-hover" @tap="emits('editTap')">
|
|
||||||
<image src="/pageDevice/static/devIconImg/icon-edit.svg" mode="scaleToFill" /> {{ props.editText }}
|
|
||||||
</view>
|
|
||||||
</slot>
|
|
||||||
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { reactive, ref, onMounted, watch } from 'vue'
|
|
||||||
|
|
||||||
const emits = defineEmits(['editTap','clickTitle'])
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
|
|
||||||
viewStyle: { type: [String, Object] }, // 样式透传, 小程序不支持再组件上加style(不生效)
|
|
||||||
|
|
||||||
title: { type: String }, //标题文字 传值则显示
|
|
||||||
|
|
||||||
subtitle: { type: String }, //副标题
|
|
||||||
|
|
||||||
editText: { type: String }, // 编辑文本, 若存在请通过 editTap 事件接收点击事件。
|
|
||||||
isTitleBorder:{type:Boolean, default:true} //是否存在标题下边框
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.c-card-wrapper {
|
|
||||||
margin: 0 35rpx;
|
|
||||||
border-radius: 32rpx;
|
|
||||||
background-color: #fff;
|
|
||||||
overflow: hidden;
|
|
||||||
.card-title {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
padding: 30rpx 40rpx;
|
|
||||||
min-height: 42rpx;
|
|
||||||
font-size: 32rpx;
|
|
||||||
font-weight: 500;
|
|
||||||
border-bottom: 1rpx solid #ededed;
|
|
||||||
.c-card-title{
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
.sub-title {
|
|
||||||
margin-top: 15rpx;
|
|
||||||
font-size: 25rpx;
|
|
||||||
color: #808080;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.card-edit {
|
|
||||||
height: 110rpx;
|
|
||||||
border-top: 1rpx solid #ededed;
|
|
||||||
color: #2980fd;
|
|
||||||
font-size: 33rpx;
|
|
||||||
font-weight: 400;
|
|
||||||
image {
|
|
||||||
width: 44rpx;
|
|
||||||
height: 44rpx;
|
|
||||||
margin-right: 10rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.border-none{
|
|
||||||
border: none !important;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
<!--
|
|
||||||
组件功能: 解决原生组件,双向绑定问题。
|
|
||||||
@author terrfly
|
|
||||||
@site https://www.jeequan.com
|
|
||||||
@date 2022/11/18 14:32
|
|
||||||
-->
|
|
||||||
<template>
|
|
||||||
<view class="select-box" @click="changeFunc">
|
|
||||||
<button class="agree-item" id="agree-btn" open-type="agreePrivacyAuthorization"
|
|
||||||
@agreeprivacyauthorization="handAgree">
|
|
||||||
<image v-if="props.checked" class="select-img" src="@/static/login/selected.svg"></image>
|
|
||||||
<image v-else class="select-img" src="@/static/login/select.svg"></image>
|
|
||||||
</button>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { reactive, ref, onMounted } from 'vue'
|
|
||||||
|
|
||||||
// emit 父组件使用: v-model="val" 进行双向绑定。
|
|
||||||
const emit = defineEmits(['update:checked'])
|
|
||||||
onMounted(() => {
|
|
||||||
// #ifdef MP-WEIXIN
|
|
||||||
getPrivacy()
|
|
||||||
// #endif
|
|
||||||
})
|
|
||||||
// 定义组件参数
|
|
||||||
const props = defineProps({
|
|
||||||
|
|
||||||
checked: { type: Boolean, default: false },
|
|
||||||
|
|
||||||
})
|
|
||||||
const vdata = reactive({})
|
|
||||||
function changeFunc () {
|
|
||||||
emit('update:checked', !props.checked)
|
|
||||||
}
|
|
||||||
// 获取微信你用户是否同意过隐私政策
|
|
||||||
const getPrivacy = () => {
|
|
||||||
wx.getPrivacySetting({
|
|
||||||
success: (r) => {
|
|
||||||
Object.assign(vdata, r)
|
|
||||||
if (vdata.needAuthorization) {
|
|
||||||
wx.onNeedPrivacyAuthorization(res => {
|
|
||||||
vdata.resolve = res
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
const handAgree = () => {
|
|
||||||
// #ifdef MP-WEIXIN
|
|
||||||
if (vdata.needAuthorization) {
|
|
||||||
vdata.resolve({ buttonId: 'agree-btn', event: 'agree' })
|
|
||||||
}
|
|
||||||
// #endif
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style scoped lang="scss">
|
|
||||||
.select-box {
|
|
||||||
display: inline;
|
|
||||||
|
|
||||||
.select-img {
|
|
||||||
width: 46rpx;
|
|
||||||
height: 46rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.agree-item {
|
|
||||||
padding: 0;
|
|
||||||
padding-left: 0;
|
|
||||||
padding-right: 0;
|
|
||||||
padding-top: 0;
|
|
||||||
padding-bottom: 0;
|
|
||||||
line-height: 0;
|
|
||||||
width: 46rpx;
|
|
||||||
height: 46rpx;
|
|
||||||
border-radius: 0;
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,159 +0,0 @@
|
|||||||
<!--
|
|
||||||
组件功能: 自定义导航栏包裹 , 基于: uni-nav-bar 的封装。
|
|
||||||
1. pages.json : "navigationStyle": "custom"
|
|
||||||
2. 页面引入该组件。
|
|
||||||
3. 如果背景透明并且需要下滑变默认背景色。 需要在页面实现: onPageScroll函数(可以空函数), 否则该组件无法正常监听。
|
|
||||||
|
|
||||||
|
|
||||||
示例:
|
|
||||||
|
|
||||||
背景通铺效果
|
|
||||||
<JeepayCustomNavbar :transparent="true" bgDefaultColor='#b6a3a3' title="背景通铺效果" backCtrl="back" ></JeepayCustomNavbar>
|
|
||||||
import { onPageScroll } from '@dcloudio/uni-app'
|
|
||||||
onPageScroll(() => {})
|
|
||||||
|
|
||||||
纯色导航条
|
|
||||||
<JeepayCustomNavbar :transparent="false" bgDefaultColor='#ffaa7f' title="纯色导航条" backCtrl="back"></JeepayCustomNavbar>
|
|
||||||
|
|
||||||
自定义左上角 效果
|
|
||||||
<JeepayCustomNavbar :transparent="true" bgDefaultColor='#ff557f' title="自定义左上角" backCtrl="back">
|
|
||||||
<view> 选择门店(自定义导航条内容) </view>
|
|
||||||
</JeepayCustomNavbar>
|
|
||||||
|
|
||||||
@author terrfly
|
|
||||||
@site https://www.jeequan.com
|
|
||||||
@date 2022/11/18 14:32
|
|
||||||
-->
|
|
||||||
<template>
|
|
||||||
<view>
|
|
||||||
<uni-nav-bar
|
|
||||||
fixed
|
|
||||||
:statusBar="true"
|
|
||||||
:border="false"
|
|
||||||
:height="props.height"
|
|
||||||
:backgroundColor="vdata.backgroundColor"
|
|
||||||
leftWidth="100%"
|
|
||||||
>
|
|
||||||
<!-- 使用左侧插槽 100%宽度 -->
|
|
||||||
<template #left>
|
|
||||||
<view class="left-slot-view">
|
|
||||||
<slot>
|
|
||||||
<view class="nav-bar-box">
|
|
||||||
<view>
|
|
||||||
<!-- 左侧按钮 -->
|
|
||||||
<uni-icons v-if="props.backCtrl" class="left-back" @click="backFunc" :type="props.backIcon" size="20" :color="props.textColor"></uni-icons>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 标题 -->
|
|
||||||
<view class="text" :style="{ color: props.textColor }"> {{props.title}} </view>
|
|
||||||
</view>
|
|
||||||
</slot>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
</uni-nav-bar>
|
|
||||||
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { onPageScroll } from '@dcloudio/uni-app'
|
|
||||||
import { reactive, ref, onMounted } from 'vue'
|
|
||||||
import ak from '@/commons/utils/ak.js'
|
|
||||||
|
|
||||||
// 定义组件参数
|
|
||||||
const props = defineProps({
|
|
||||||
|
|
||||||
// 标题
|
|
||||||
title: { type: String, default: '' },
|
|
||||||
|
|
||||||
// 文字颜色
|
|
||||||
textColor: { type: String, default: 'black' },
|
|
||||||
|
|
||||||
// 返回按钮类型
|
|
||||||
backIcon: { type: String, default: 'back' },
|
|
||||||
|
|
||||||
// 高度: 默认与uni-nav-bar 保持一致。
|
|
||||||
height: { type: Number, default: 44 },
|
|
||||||
|
|
||||||
// 默认背景色:
|
|
||||||
bgDefaultColor: { type: String, default: 'white' },
|
|
||||||
|
|
||||||
// 是否默认透明(此时可自定义背景), 当滑动时将切换为默认背景色。
|
|
||||||
transparent: { type: Boolean, default: false },
|
|
||||||
|
|
||||||
// 返回按钮的操作项: null-无返回按钮, back 返回上一页, pageUrl: '', 也可以是回调函数。
|
|
||||||
backCtrl: [ String, Function ],
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
// 只有透明色时 才需要监听
|
|
||||||
if(props.transparent){
|
|
||||||
|
|
||||||
onPageScroll((e) => { // 切换背景颜色 透明 or 主题色。
|
|
||||||
if(e.scrollTop > (props.height / 2.5) ){
|
|
||||||
vdata.backgroundColor = props.bgDefaultColor
|
|
||||||
}else{
|
|
||||||
vdata.backgroundColor = 'transparent'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 颜色
|
|
||||||
const vdata = reactive({
|
|
||||||
backgroundColor: 'transparent' // 默认透明色
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
// 当非透明色, 需要改为默认颜色
|
|
||||||
if(!props.transparent){
|
|
||||||
vdata.backgroundColor = props.bgDefaultColor + '';
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// 点击返回按钮,
|
|
||||||
function backFunc(){
|
|
||||||
|
|
||||||
if(!props.backCtrl){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(typeof props.backCtrl == 'function'){
|
|
||||||
return props.backCtrl()
|
|
||||||
}
|
|
||||||
|
|
||||||
if(props.backCtrl === 'back'){
|
|
||||||
return ak.go.back()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
<style scoped lang="scss">
|
|
||||||
.left-slot-view {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
line-height: 100%;
|
|
||||||
font-size: 33rpx;
|
|
||||||
font-weight: 500;
|
|
||||||
.nav-bar-box {
|
|
||||||
display: flex;
|
|
||||||
flex-grow: 1;
|
|
||||||
justify-content: space-between;
|
|
||||||
.left-back {
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
&::after {
|
|
||||||
content: "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
::v-deep.uni-navbar__header {
|
|
||||||
.uni-navbar__header-container,
|
|
||||||
.uni-navbar__header-btns-right {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
<!--
|
|
||||||
描述信息展示
|
|
||||||
通用信息
|
|
||||||
@author terrfly
|
|
||||||
@site https://www.jeequan.com
|
|
||||||
@date 2022/12/06 10:11
|
|
||||||
-->
|
|
||||||
<template>
|
|
||||||
|
|
||||||
<view class="c-desc-view">
|
|
||||||
<slot></slot>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
const props = defineProps({
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
|
|
||||||
.c-desc-view {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
</style>
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
<!--
|
|
||||||
描述信息展示
|
|
||||||
通用信息
|
|
||||||
@author terrfly
|
|
||||||
@site https://www.jeequan.com
|
|
||||||
@date 2022/12/06 10:11
|
|
||||||
-->
|
|
||||||
<template>
|
|
||||||
<view :class="{ 'c-desc-view-item': true, 'bottom-border': props.bottomBorder }">
|
|
||||||
<view class="title">
|
|
||||||
<slot name="title">{{ props.title }}</slot>
|
|
||||||
</view>
|
|
||||||
<view class="desc">
|
|
||||||
<slot name="desc">
|
|
||||||
<image v-if="props.descIsImg && props.desc" :src="props.desc" mode="scaleToFill" class="default-img" />
|
|
||||||
<template v-else>{{ props.desc }}</template>
|
|
||||||
</slot>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
const props = defineProps({
|
|
||||||
// 标题
|
|
||||||
title: { type: String },
|
|
||||||
|
|
||||||
// 描述
|
|
||||||
desc: { type: String },
|
|
||||||
|
|
||||||
// 描述是否是图片
|
|
||||||
descIsImg: { type: Boolean, default: false },
|
|
||||||
|
|
||||||
// 下边框
|
|
||||||
bottomBorder: { type: Boolean, default: false }
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.c-desc-view-item {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
padding: 20rpx 40rpx;
|
|
||||||
font-size: 30rpx;
|
|
||||||
font-weight: 400;
|
|
||||||
|
|
||||||
.title {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: flex-start;
|
|
||||||
width: 200rpx;
|
|
||||||
color: #808080;
|
|
||||||
}
|
|
||||||
.desc {
|
|
||||||
flex: 1;
|
|
||||||
text-align: right;
|
|
||||||
color: #000;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:first-child {
|
|
||||||
margin-top: 20rpx;
|
|
||||||
}
|
|
||||||
&:last-child {
|
|
||||||
margin-bottom: 20rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.default-img {
|
|
||||||
width: 150rpx;
|
|
||||||
height: 150rpx;
|
|
||||||
background-color: #f7f7f7;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.bottom-border {
|
|
||||||
padding-bottom: 40rpx;
|
|
||||||
border-bottom: 1rpx solid #ededed;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,151 +0,0 @@
|
|||||||
<!-- 待完成 -->
|
|
||||||
<template>
|
|
||||||
|
|
||||||
<view>
|
|
||||||
<slot></slot>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { reactive, ref, onMounted, provide, computed } from 'vue'
|
|
||||||
import infoBox from '@/commons/utils/infoBox.js'
|
|
||||||
|
|
||||||
|
|
||||||
// 定义组件参数
|
|
||||||
const props = defineProps({
|
|
||||||
|
|
||||||
// 验证规则
|
|
||||||
rules: { type: Object, default: () => { } },
|
|
||||||
|
|
||||||
// 用作表单验证
|
|
||||||
model: { type: Object, default: () => { } },
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
const vdata = reactive({
|
|
||||||
formNameList: [], // form 表单的已经注册的名字集合
|
|
||||||
|
|
||||||
errorListByText: [], // 错误信息集合 ( 需要显示的 )
|
|
||||||
errorListByToast: [], // 错误信息集合 ( alert 提示的 )
|
|
||||||
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
// 组件注册 和 取消
|
|
||||||
function itemSign(name){
|
|
||||||
|
|
||||||
if(vdata.formNameList.indexOf(name) < 0){
|
|
||||||
vdata.formNameList.push(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// 组件注册 和 取消
|
|
||||||
function unItemSign(name){
|
|
||||||
if(vdata.formNameList.indexOf(name) >= 0){
|
|
||||||
vdata.formNameList.splice(vdata.formNameList.indexOf(name), 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// { type: String, required: true, message: '', showToastError: false, validator: (rule, value) => {} }
|
|
||||||
|
|
||||||
// showTextError : 是否显示文本错误, 默认为true
|
|
||||||
// showToastError: 是否alert信息, 默认为:false
|
|
||||||
|
|
||||||
// 错误条目数据结构: {name, value, rule, errorMsg}
|
|
||||||
// 注意: errorMsg 跟 rule里的 message不是一回事, errorMsg 可能是 回调函数自定义。
|
|
||||||
function pushError(name, value, errorMsg, rule){
|
|
||||||
|
|
||||||
// 明确是 false, 则不加入文本错误信息, 未定义等都是true(默认值)
|
|
||||||
if(rule.showTextError === false){
|
|
||||||
}else{
|
|
||||||
vdata.errorListByText.push({name, value, rule, errorMsg})
|
|
||||||
}
|
|
||||||
|
|
||||||
// alert 默认为 false
|
|
||||||
if(rule.showToastError === true){
|
|
||||||
vdata.errorListByToast.push({name, value, rule, errorMsg})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function validateFormItem(name){
|
|
||||||
|
|
||||||
// 不存在
|
|
||||||
if(!name || !props.rules[name] ){
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// model的值
|
|
||||||
const value = props.model[name]
|
|
||||||
|
|
||||||
props.rules[name].forEach( rule => {
|
|
||||||
|
|
||||||
// 必填 && 验证失败
|
|
||||||
if(rule.required && (value == null || value == '' || typeof value == 'undefined')){
|
|
||||||
pushError(name, value, rule.message, rule)
|
|
||||||
|
|
||||||
}else{ // 非必填 || 必填验证通过
|
|
||||||
|
|
||||||
if(rule.validator){ // 包含验证自定义函数, 暂时先不支持promise
|
|
||||||
|
|
||||||
let validatorResult = rule.validator(rule, value)
|
|
||||||
if( validatorResult == true){ // 验证通过
|
|
||||||
|
|
||||||
}else{ // 验证失败
|
|
||||||
pushError(name, value, validatorResult, rule)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 表单验证 , 返回Promise
|
|
||||||
function validate(){
|
|
||||||
|
|
||||||
// 清空错误信息
|
|
||||||
vdata.errorListByText = []
|
|
||||||
vdata.errorListByToast = []
|
|
||||||
|
|
||||||
vdata.formNameList.forEach(name => validateFormItem(name) )
|
|
||||||
|
|
||||||
if(vdata.errorListByToast && vdata.errorListByToast.length > 0){
|
|
||||||
infoBox.showToast(vdata.errorListByToast[0].errorMsg)
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(vdata.formNameList);
|
|
||||||
console.log(vdata.errorListByText);
|
|
||||||
console.log(vdata.errorListByToast);
|
|
||||||
|
|
||||||
if(vdata.errorListByText.length <= 0 && vdata.errorListByToast.length <= 0){
|
|
||||||
alert('成功')
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 向下注册的组件
|
|
||||||
const provideModel = {
|
|
||||||
itemSign: itemSign,
|
|
||||||
unItemSign: unItemSign,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
provide('jeepayForm', computed( ()=> provideModel ) )
|
|
||||||
|
|
||||||
// provideModel 写入: errorListByText 监听不到。
|
|
||||||
provide('jeepayErrorListByText', computed( ()=> vdata.errorListByText ) )
|
|
||||||
|
|
||||||
defineExpose({ validate })
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
</style>
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view>
|
|
||||||
{{props.label}} : <slot></slot>
|
|
||||||
|
|
||||||
<view v-if="props.showErrorText && vdata.errorMsg">{{ vdata.errorMsg }}</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { reactive, ref, onMounted, onUnmounted, provide, computed, inject, watch } from 'vue'
|
|
||||||
|
|
||||||
|
|
||||||
const jeepayFormInject = inject("jeepayForm")
|
|
||||||
const jeepayForm = jeepayFormInject.value
|
|
||||||
|
|
||||||
const jeepayErrorListByTextInject = inject("jeepayErrorListByText")
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
jeepayForm.itemSign(props.name)
|
|
||||||
})
|
|
||||||
|
|
||||||
onUnmounted(() => {
|
|
||||||
|
|
||||||
jeepayForm.unItemSign(props.name)
|
|
||||||
})
|
|
||||||
|
|
||||||
// 定义组件参数
|
|
||||||
const props = defineProps({
|
|
||||||
|
|
||||||
name: { type: String },
|
|
||||||
|
|
||||||
label: { type: String },
|
|
||||||
|
|
||||||
// 是否显示 错误信息占位
|
|
||||||
showErrorText: { type: Boolean, default: true },
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
const vdata = reactive({
|
|
||||||
|
|
||||||
errorMsg: null, // 错误提示信息
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
// 关于本条的数据
|
|
||||||
function changeItemErrorMsg(itemErrorListByText){
|
|
||||||
|
|
||||||
vdata.errorMsg = null;
|
|
||||||
if(itemErrorListByText && itemErrorListByText.length > 0){
|
|
||||||
vdata.errorMsg = itemErrorListByText[0].errorMsg
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
watch(() => jeepayErrorListByTextInject.value, (newVal, oldVal) => {
|
|
||||||
|
|
||||||
if(!newVal){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
changeItemErrorMsg(newVal.filter(r=> r.name == props.name))
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// 错误信息的传递
|
|
||||||
provide('jeepayFormItemErrorMsg', computed( ()=> vdata.errorMsg ) )
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
</style>
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
<template>
|
|
||||||
<uni-easyinput
|
|
||||||
v-model="props.value" :type="props.type"
|
|
||||||
:placeholder="vdata.errorMsg || props.placeholder"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { reactive, ref, onMounted, onUnmounted, provide, computed, inject, watch } from 'vue'
|
|
||||||
|
|
||||||
const jeepayFormItemErrorMsgInject = inject("jeepayFormItemErrorMsg")
|
|
||||||
|
|
||||||
|
|
||||||
// 定义组件参数
|
|
||||||
const props = defineProps({
|
|
||||||
|
|
||||||
placeholder: { type: String },
|
|
||||||
|
|
||||||
label: { type: String },
|
|
||||||
|
|
||||||
type: { type: String },
|
|
||||||
|
|
||||||
// 双向绑定
|
|
||||||
value: { type: [String, Number] }
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
const vdata = reactive({
|
|
||||||
|
|
||||||
errorMsg: null, // 错误提示信息
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
watch(() => jeepayFormItemErrorMsgInject.value, (newVal, oldVal) => {
|
|
||||||
vdata.errorMsg = newVal
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
</style>
|
|
||||||
@@ -1,91 +0,0 @@
|
|||||||
<!--
|
|
||||||
信息列表的预览页面, 比如 通知消息的前几条等。
|
|
||||||
通用信息
|
|
||||||
@author terrfly
|
|
||||||
@site https://www.jeequan.com
|
|
||||||
@date 2022/11/15 06:18
|
|
||||||
-->
|
|
||||||
<template>
|
|
||||||
<view class="notice-wrapper">
|
|
||||||
<view class="notice-title" v-if="props.tableTitle">
|
|
||||||
<view class="notice-news">{{ props.tableTitle }}</view>
|
|
||||||
<view class="notice-more flex-center" v-if="props.isShowMoreBtn" @tap="listviewClickFunc(true, null)">
|
|
||||||
更多<image src="/static/iconImg/icon-arrow-black.svg" mode="scaleToFill" /></view>
|
|
||||||
</view>
|
|
||||||
<block v-for="(v, i) in props.dataList" :key="i">
|
|
||||||
<view class="notice-main" hover-class="touch-hover" hover-stay-time="150" @tap="listviewClickFunc(false, v)">
|
|
||||||
<view class="notice-content single-text-beyond">{{ v[props.fields.title] }}</view>
|
|
||||||
<view class="notice-time">{{ v[props.fields.subtitle] }}</view>
|
|
||||||
</view>
|
|
||||||
</block>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
const props = defineProps({
|
|
||||||
|
|
||||||
//列表标题 传则展示 不传则移除
|
|
||||||
tableTitle: { type: String },
|
|
||||||
|
|
||||||
// 数据列表, 默认是按照: { title, subtitle }
|
|
||||||
dataList: { type: Array, default: () => [] },
|
|
||||||
|
|
||||||
// 约定的字段
|
|
||||||
fields: { type: Object, default: {title: 'title', subtitle: 'subtitle'} },
|
|
||||||
|
|
||||||
// 是否显示更多按钮
|
|
||||||
isShowMoreBtn: { type: Boolean, default: true },
|
|
||||||
|
|
||||||
})
|
|
||||||
// touchDown 列表点击回调 touchMore点击更多回调
|
|
||||||
const emits = defineEmits(["click"])
|
|
||||||
|
|
||||||
|
|
||||||
function listviewClickFunc (isClickMore, record) {
|
|
||||||
emits('click', isClickMore, record)
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.notice-wrapper {
|
|
||||||
width: 680rpx;
|
|
||||||
margin: 0 auto;
|
|
||||||
background-color: $J-bg-ff;
|
|
||||||
border-radius: $J-b-r32;
|
|
||||||
.notice-title {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
padding: 0 30rpx;
|
|
||||||
height: 102rpx;
|
|
||||||
border-bottom: 1rpx solid #ededed;
|
|
||||||
.notice-news {
|
|
||||||
font-size: 32rpx;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
.notice-more {
|
|
||||||
font-size: 32rpx;
|
|
||||||
color: $J-color-t80;
|
|
||||||
image {
|
|
||||||
width: 42rpx;
|
|
||||||
height: 42rpx;
|
|
||||||
transform: rotate(90deg);
|
|
||||||
margin-left: 5rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.notice-main {
|
|
||||||
padding: 30rpx;
|
|
||||||
height: 90rpx;
|
|
||||||
.notice-content {
|
|
||||||
margin-bottom: 16rpx;
|
|
||||||
font-size: 30rpx;
|
|
||||||
}
|
|
||||||
.notice-time {
|
|
||||||
font-size: 26rpx;
|
|
||||||
color: $J-color-ta6;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,131 +0,0 @@
|
|||||||
<!--
|
|
||||||
登录页专用文字上移样式,行高,宽度,密码框与通用样式不一致
|
|
||||||
autoComplete="new-password"
|
|
||||||
-->
|
|
||||||
<template>
|
|
||||||
<div class="jee-input">
|
|
||||||
<div class="jee-text-up">
|
|
||||||
<a-input
|
|
||||||
ref="inputRef"
|
|
||||||
:type="inputPassword"
|
|
||||||
:value="value"
|
|
||||||
:required="isGoogle"
|
|
||||||
:disabled="props.disabled"
|
|
||||||
autoComplete="new-password"
|
|
||||||
@change="onChange($event)"
|
|
||||||
/>
|
|
||||||
<label @click="inputRef.focus()">{{ placeholder }}</label>
|
|
||||||
</div>
|
|
||||||
<div v-if="isPassword == 'password'" class="eyes" @click="changeEyes">
|
|
||||||
<!-- 密码框的小眼睛 -->
|
|
||||||
<eye-outlined v-if="!eyes" />
|
|
||||||
<eye-invisible-outlined v-else />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { defineProps, ref } from 'vue'
|
|
||||||
|
|
||||||
// 定义input对象
|
|
||||||
const inputRef = ref()
|
|
||||||
|
|
||||||
// 定义父组件的传参和类型
|
|
||||||
const props = defineProps({
|
|
||||||
value: { type: String, default: null },
|
|
||||||
placeholder: { type: String, default: '' },
|
|
||||||
isPassword: { type: String, default: 'text' }, // 是否为密码框
|
|
||||||
isGoogle: { type: String, default: 'required' }, // 谷歌验证码是否必填
|
|
||||||
disabled: { type: Boolean, default: false } // 是否禁用
|
|
||||||
})
|
|
||||||
|
|
||||||
// nextTick(() => {
|
|
||||||
// // inputRef.value.focus()
|
|
||||||
// if(!props.value) {
|
|
||||||
// inputRef.value.blur()
|
|
||||||
// }
|
|
||||||
// // watch(() => props.value, () => {
|
|
||||||
|
|
||||||
// // })
|
|
||||||
// })
|
|
||||||
|
|
||||||
// 密码的显示与隐藏
|
|
||||||
let eyes = ref(true)
|
|
||||||
let inputPassword = ref(props.isPassword)
|
|
||||||
const changeEyes = () => {
|
|
||||||
eyes.value = !eyes.value
|
|
||||||
eyes.value
|
|
||||||
? (inputPassword.value = 'password')
|
|
||||||
: (inputPassword.value = 'text')
|
|
||||||
}
|
|
||||||
const emit = defineEmits(['update:value'])
|
|
||||||
const onChange = (e) => emit('update:value', e.target.value)
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped lang="less">
|
|
||||||
.jee-input {
|
|
||||||
position: relative;
|
|
||||||
.eyes {
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
z-index: 99;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 文字上移 效果
|
|
||||||
.jee-text-up {
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
input {
|
|
||||||
outline: 0;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
height: 40px;
|
|
||||||
max-width: 300px;
|
|
||||||
}
|
|
||||||
input::-webkit-input-placeholder {
|
|
||||||
color: transparent;
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
.placeShow::-webkit-input-placeholder {
|
|
||||||
color: #bfbfbf;
|
|
||||||
}
|
|
||||||
label {
|
|
||||||
margin-left: 6px;
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
bottom: 13px;
|
|
||||||
padding: 0px 5px;
|
|
||||||
color: #bfbfbf;
|
|
||||||
font-size: 13px;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
border-radius: 3px;
|
|
||||||
line-height: 1;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
cursor: initial;
|
|
||||||
}
|
|
||||||
|
|
||||||
input:focus + label,
|
|
||||||
input:active + label,
|
|
||||||
input:valid + label {
|
|
||||||
font-weight: normal;
|
|
||||||
font-size: 12px;
|
|
||||||
letter-spacing: 0.05em;
|
|
||||||
text-align: left;
|
|
||||||
color: var(--ant-primary-color);
|
|
||||||
background: #fff; // 更换背景色
|
|
||||||
transform: translateY(-22px);
|
|
||||||
}
|
|
||||||
|
|
||||||
input:not(:focus) + label {
|
|
||||||
color: #b0afb3;
|
|
||||||
background: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,110 +0,0 @@
|
|||||||
<!--
|
|
||||||
通用 确认弹层。
|
|
||||||
@author terrfly
|
|
||||||
@site https://www.jeequan.com
|
|
||||||
@date 2022/11/22 07:30
|
|
||||||
-->
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<uni-popup ref="popup" type="bottom" @maskClick="cancelFunc" mask-background-color="rgba(0,0,0,.5)" @change='change' :safe-area="false">
|
|
||||||
<view class="tips-wrapper">
|
|
||||||
<view class="tips-text" :style="{ textIndent: vdata.title.length > 20 ? '2em' : 0 }"> {{ vdata.title }} </view>
|
|
||||||
<view class="tips-text tips-confirm" hover-class="u-cell-hover" hover-stay-time="150" :style="{color: vdata.confirmColor }" @tap="confirmFunc">
|
|
||||||
{{ vdata.confirmText || "确认" }}
|
|
||||||
</view>
|
|
||||||
<view class="line"></view>
|
|
||||||
<view class="tips-text tips-cancel" hover-class="u-cell-hover" hover-stay-time="150" @tap="cancelFunc">
|
|
||||||
{{ vdata.cancelText || "取消" }}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</uni-popup>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref, reactive,inject } from "vue"
|
|
||||||
|
|
||||||
const popup = ref(null) //弹窗实例
|
|
||||||
const tips = ref("") // 提示语
|
|
||||||
|
|
||||||
const vdata = reactive({
|
|
||||||
title: '',
|
|
||||||
confirmText: '',
|
|
||||||
cancelText: '',
|
|
||||||
confirmColor: '',
|
|
||||||
promiseObject: { },
|
|
||||||
})
|
|
||||||
|
|
||||||
function confirmFunc(){
|
|
||||||
popup.value.close()
|
|
||||||
vdata.promiseObject.resolve()
|
|
||||||
}
|
|
||||||
|
|
||||||
function cancelFunc(){
|
|
||||||
popup.value.close()
|
|
||||||
vdata.promiseObject.reject()
|
|
||||||
}
|
|
||||||
function open (title, confirmTextOrExtObject , cancelText ) {
|
|
||||||
vdata.title = title
|
|
||||||
vdata.confirmText = typeof confirmTextOrExtObject == "string" ? confirmTextOrExtObject : ''
|
|
||||||
vdata.cancelText = cancelText
|
|
||||||
if(typeof confirmTextOrExtObject == "object" ) {
|
|
||||||
Object.assign(vdata,confirmTextOrExtObject)
|
|
||||||
}
|
|
||||||
popup.value.open()
|
|
||||||
|
|
||||||
return new Promise( (resolve, reject) => {
|
|
||||||
vdata.promiseObject.resolve = resolve
|
|
||||||
vdata.promiseObject.reject = reject
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
let changePageMetaOverflowFunc = inject('changePageMetaOverflowFunc')
|
|
||||||
const change = (e)=>{
|
|
||||||
if(changePageMetaOverflowFunc){
|
|
||||||
changePageMetaOverflowFunc(!e.show)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
defineExpose({ open })
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.tips-wrapper {
|
|
||||||
overflow: hidden;
|
|
||||||
border-radius: 32rpx 32rpx 0 0;
|
|
||||||
padding-bottom: 60rpx;
|
|
||||||
background-color: #fff;
|
|
||||||
.tips-text {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
text-align: center;
|
|
||||||
min-height: 110rpx;
|
|
||||||
|
|
||||||
line-height: 1.8;
|
|
||||||
padding: 30rpx;
|
|
||||||
box-sizing: border-box;
|
|
||||||
font-size: 30rpx;
|
|
||||||
}
|
|
||||||
.line {
|
|
||||||
height: 20rpx;
|
|
||||||
background-color: rgba(0, 0, 0, 0.07);
|
|
||||||
}
|
|
||||||
.tips-confirm {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
border-top: 1rpx solid rgba(0, 0, 0, 0.07);
|
|
||||||
color: #2980fd;
|
|
||||||
font-size: 33rpx;
|
|
||||||
}
|
|
||||||
.tips-cancel {
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
color: $J-color-t80;
|
|
||||||
font-size: 33rpx;
|
|
||||||
}
|
|
||||||
.u-cell-hover {
|
|
||||||
background-color: #f8f9fa;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,91 +0,0 @@
|
|||||||
<!--
|
|
||||||
组件作用: 单个输入框的弹层。
|
|
||||||
输入框的弹出框, uni必须使用的是: 组件方式, 无法直接JS调起。
|
|
||||||
// 要求, 输入空也可以点击确定。
|
|
||||||
示例:
|
|
||||||
|
|
||||||
A: 一般用法:
|
|
||||||
<JeepayPopupInput ref="ref" label="备注" :maxLength="3" v-model:value="vdata.payRemark" />
|
|
||||||
|
|
||||||
B: 自定义 校验规则
|
|
||||||
<JeepayPopupInput ref="ref" label="备注" :maxLength="3" v-model:value="vdata.payRemark" :rules="[ {required: true }, {pattern: '^(123)+$' } ]" />
|
|
||||||
|
|
||||||
@author terrfly
|
|
||||||
@site https://www.jeequan.com
|
|
||||||
@date 2022/11/17 10:46
|
|
||||||
-->
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<uni-popup ref="popupRef" type="dialog">
|
|
||||||
<uni-popup-dialog :before-close="true" mode="input" :title="`请输入${props.label}`" @confirm="confirmFunc" @close="popupRef.close()">
|
|
||||||
<template #default>
|
|
||||||
<uni-forms ref="formRef" :rules="vdata.rules" :modelValue="vdata.formData">
|
|
||||||
<uni-forms-item label="" name="singleInputVal">
|
|
||||||
<uni-easyinput :inputBorder="false" type="text" v-model="vdata.formData.singleInputVal" :placeholder="`最多输入${props.maxLength}个字`" :maxlength="props.maxLength" />
|
|
||||||
</uni-forms-item>
|
|
||||||
</uni-forms>
|
|
||||||
</template>
|
|
||||||
</uni-popup-dialog>
|
|
||||||
</uni-popup>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { reactive, ref, watch } from 'vue'
|
|
||||||
|
|
||||||
// 定义组件参数
|
|
||||||
const props = defineProps({
|
|
||||||
// 显示文本
|
|
||||||
label: { type: String, default: '' },
|
|
||||||
|
|
||||||
// 操作对象
|
|
||||||
value: [Number, String],
|
|
||||||
|
|
||||||
// 输入框最大位数
|
|
||||||
maxLength: { type: Number, default: 10 },
|
|
||||||
|
|
||||||
rules: { type: Array, default: () => [] },
|
|
||||||
})
|
|
||||||
|
|
||||||
// emit 父组件使用: v-model="val" 进行双向绑定。
|
|
||||||
const emit = defineEmits(['update:value'])
|
|
||||||
|
|
||||||
// 重置按钮,不能直接重置时间选择,需要通过watch监听,进行重置
|
|
||||||
watch(
|
|
||||||
() => props.value,
|
|
||||||
(newVal, oldVal) => {
|
|
||||||
vdata.formData.singleInputVal = newVal
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
const popupRef = ref()
|
|
||||||
const formRef = ref()
|
|
||||||
|
|
||||||
const vdata = reactive({
|
|
||||||
// 表单的值
|
|
||||||
formData: { singleInputVal: '' },
|
|
||||||
|
|
||||||
// 验证规则
|
|
||||||
rules: {
|
|
||||||
singleInputVal: { rules: props.rules },
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
// 点击确认按钮。
|
|
||||||
function confirmFunc() {
|
|
||||||
formRef.value.validate().then(() => {
|
|
||||||
emit('update:value', vdata.formData.singleInputVal)
|
|
||||||
popupRef.value.close()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 显示弹层
|
|
||||||
function open() {
|
|
||||||
vdata.formData.singleInputVal = props.value
|
|
||||||
popupRef.value.open()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 将表格事件暴露出去 https://www.jianshu.com/p/39d14c25c987
|
|
||||||
defineExpose({ open })
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped></style>
|
|
||||||
@@ -1,361 +0,0 @@
|
|||||||
<!--
|
|
||||||
组件作用: 弹层, 列表支持 单选, 多选。
|
|
||||||
|
|
||||||
使用方法:
|
|
||||||
|
|
||||||
<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)">
|
|
||||||
<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({
|
|
||||||
configMode: { type: String, default: '' }, // 搜索时仅展示商户号
|
|
||||||
// 请求业务数据, 参数可自行控制。
|
|
||||||
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();
|
|
||||||
|
|
||||||
console.log(props, 'propsprops');
|
|
||||||
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) {
|
|
||||||
console.log(111111111111111);
|
|
||||||
// 清空数据
|
|
||||||
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>
|
|
||||||
@@ -1,387 +0,0 @@
|
|||||||
<!--
|
|
||||||
组件作用: 弹层, 列表支持 单选, 多选。
|
|
||||||
|
|
||||||
使用方法:
|
|
||||||
|
|
||||||
<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 class="search-wrap" v-if="props.searchInputName">
|
|
||||||
<view 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>
|
|
||||||
<!-- <view class="add-btn" hover-class="touch-button" v-if="props.addUse" @tap="">新增应用</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> -->
|
|
||||||
<text class="tit">{{ record[props.fields.left] }}</text>
|
|
||||||
<text class="ino" v-if="record.intro">{{ record.intro }}</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({
|
|
||||||
configMode: { type: String, default: '' }, // 搜索时仅展示商户号
|
|
||||||
// 请求业务数据, 参数可自行控制。
|
|
||||||
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],
|
|
||||||
// 是否显示增加引用按钮
|
|
||||||
addUse: { type: Boolean, default: false }
|
|
||||||
});
|
|
||||||
let changePageMetaOverflowFunc = inject('changePageMetaOverflowFunc');
|
|
||||||
const emits = defineEmits(['confirm']);
|
|
||||||
|
|
||||||
const popupRef = ref();
|
|
||||||
|
|
||||||
console.log(props, 'propsprops');
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
.search-wrap {
|
|
||||||
padding: 30rpx;
|
|
||||||
display: flex;
|
|
||||||
.input-search {
|
|
||||||
flex: 1;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding-left: 10rpx;
|
|
||||||
border-radius: 10rpx;
|
|
||||||
background-color: #f7f7f7;
|
|
||||||
.search-button {
|
|
||||||
padding: 24rpx 30rpx;
|
|
||||||
font-size: 32rpx;
|
|
||||||
font-weight: 500;
|
|
||||||
color: #2980fd;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.add-btn {
|
|
||||||
border-radius: 10rpx;
|
|
||||||
color: #fff;
|
|
||||||
padding: 0 20upx;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
background: $jeepay-bg-primary;
|
|
||||||
margin-left: 30rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.store {
|
|
||||||
position: relative;
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-start;
|
|
||||||
align-items: center;
|
|
||||||
margin: 40rpx;
|
|
||||||
font-size: 30rpx;
|
|
||||||
background-color: #f5f5f5;
|
|
||||||
padding: 20rpx;
|
|
||||||
border-radius: 12rpx;
|
|
||||||
.more-selected {
|
|
||||||
flex-shrink: 0;
|
|
||||||
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;
|
|
||||||
flex-direction: column;
|
|
||||||
.ino {
|
|
||||||
color: #999;
|
|
||||||
padding-top: 12upx;
|
|
||||||
font-size: 24upx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.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;
|
|
||||||
background-color: #fff;
|
|
||||||
.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>
|
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
<!--
|
|
||||||
单选 view 一般用作: form表单内使用
|
|
||||||
@author terrfly
|
|
||||||
@site https://www.jeepay.vip
|
|
||||||
@date 2022/12/01 16:18
|
|
||||||
-->
|
|
||||||
<template>
|
|
||||||
<view>
|
|
||||||
<view @tap="show">
|
|
||||||
<!-- 插槽自定义内容 -->
|
|
||||||
<slot name="view" :record="vdata.checkedData">
|
|
||||||
<view class="selected-radio">
|
|
||||||
<view v-if="hasVal()" style="color: black">{{vdata.checkedData?.label}}</view>
|
|
||||||
<view v-else>{{props.label}}</view>
|
|
||||||
<image style="width: 30rpx;height: 30rpx" src="/static/right.svg" mode="scaleToFill" />
|
|
||||||
</view>
|
|
||||||
</slot>
|
|
||||||
</view>
|
|
||||||
<!-- popup 和 tap不能放置在同一个 view下。 -->
|
|
||||||
<view>
|
|
||||||
<JSinglePopup ref="popupRef" :list="props.list" @confirm="confirmFunc" />
|
|
||||||
</view>
|
|
||||||
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref, reactive, nextTick, watch, onMounted, inject } from "vue"
|
|
||||||
|
|
||||||
const popupRef = ref()
|
|
||||||
|
|
||||||
// emit 父组件使用: v-model:value="val" 进行双向绑定。
|
|
||||||
const emits = defineEmits(['update:value', 'change'])
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
|
|
||||||
//绑定的值, 双向绑定
|
|
||||||
value: { type: [String, Number] },
|
|
||||||
|
|
||||||
// 显示的名字
|
|
||||||
label: { type: [String, Number], default: "请选择" },
|
|
||||||
|
|
||||||
// 数组
|
|
||||||
list: { type: Array, default: () => [] },
|
|
||||||
|
|
||||||
// 是否多选框, 默认单选。
|
|
||||||
isCheckbox: { type: Boolean, default: false },
|
|
||||||
})
|
|
||||||
|
|
||||||
console.log(props.isCheckbox,'isCheckboxisCheckboxisCheckboxisCheckbox');
|
|
||||||
|
|
||||||
onMounted(()=>{
|
|
||||||
changePropsVal(props.value)
|
|
||||||
})
|
|
||||||
|
|
||||||
// 切换时
|
|
||||||
watch(() => props.value, (newVal, oldVal) => {
|
|
||||||
changePropsVal(newVal)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function changePropsVal(newVal){
|
|
||||||
let list = props.list.filter(r => r.value == newVal)
|
|
||||||
vdata.checkedData = list.length > 0 ? list[0] : { }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const vdata = reactive({
|
|
||||||
|
|
||||||
checkedData: { } // 当前选择的值
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
function show(){
|
|
||||||
popupRef.value.open(vdata.checkedData.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// 选择用户类型完毕
|
|
||||||
function confirmFunc(v){
|
|
||||||
vdata.checkedData = v
|
|
||||||
emits("update:value", v.value)
|
|
||||||
if(v.value!==1){
|
|
||||||
emits("change", v.value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function hasVal(){
|
|
||||||
return vdata.checkedData && vdata.checkedData.label ? true : false
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
|
|
||||||
|
|
||||||
.selected-radio {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
font-size: 32rpx;
|
|
||||||
color: #b3b3b3;
|
|
||||||
image {
|
|
||||||
width: 120rpx;
|
|
||||||
height: 120rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
</style>
|
|
||||||
@@ -1,134 +0,0 @@
|
|||||||
<!--
|
|
||||||
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>
|
|
||||||
@@ -1,355 +0,0 @@
|
|||||||
<!--
|
|
||||||
组件作用: 弹层, 列表支持 单选, 多选。
|
|
||||||
|
|
||||||
使用方法:
|
|
||||||
|
|
||||||
<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>
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
<!--
|
|
||||||
组件作用: 状态筛选器, 一般用作搜索栏右侧。
|
|
||||||
|
|
||||||
使用方法:
|
|
||||||
|
|
||||||
|
|
||||||
@author terrfly
|
|
||||||
@site https://www.jeequan.com
|
|
||||||
@date 2022/11/26 16:24
|
|
||||||
-->
|
|
||||||
|
|
||||||
<template>
|
|
||||||
|
|
||||||
<view>
|
|
||||||
<view class="code-state" @tap="statePopup.open(props.bizType)">
|
|
||||||
{{ props.list.find(i => {
|
|
||||||
return i.value == props.bizType
|
|
||||||
}).label }}
|
|
||||||
<image src="/pageDevice/static/devIconImg/icon-arrow-down.svg" mode="scaleToFill" />
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view>
|
|
||||||
<JSinglePopup :list="props.list" :title="props.title" ref="statePopup" @confirm="confirmState" />
|
|
||||||
</view>
|
|
||||||
|
|
||||||
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { reactive, ref } from 'vue'
|
|
||||||
|
|
||||||
|
|
||||||
const emits = defineEmits(['update:bizType', 'change'])
|
|
||||||
|
|
||||||
// 定义组件参数
|
|
||||||
const props = defineProps({
|
|
||||||
|
|
||||||
// 双向绑定
|
|
||||||
bizType: { type: [Number, String] },
|
|
||||||
// 搜索数据
|
|
||||||
list: { type: Array },
|
|
||||||
title: { type: String }
|
|
||||||
})
|
|
||||||
|
|
||||||
const vdata = reactive({
|
|
||||||
selected: {} // 当前选择对象
|
|
||||||
})
|
|
||||||
|
|
||||||
const statePopup = ref(null)
|
|
||||||
|
|
||||||
//按状态筛选
|
|
||||||
function confirmState(r){
|
|
||||||
vdata.selected = r || { }
|
|
||||||
emits('update:bizType', vdata.selected.value)
|
|
||||||
emits('change', vdata.selected)
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.code-state {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin-left: 40rpx;
|
|
||||||
font-size: 30rpx;
|
|
||||||
color: #222425;
|
|
||||||
image {
|
|
||||||
margin-left: 10rpx;
|
|
||||||
width: 40rpx;
|
|
||||||
height: 40rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
<!--
|
|
||||||
组件作用: 状态筛选器, 一般用作搜索栏右侧。
|
|
||||||
|
|
||||||
使用方法:
|
|
||||||
|
|
||||||
|
|
||||||
@author terrfly
|
|
||||||
@site https://www.jeequan.com
|
|
||||||
@date 2022/11/26 16:24
|
|
||||||
-->
|
|
||||||
|
|
||||||
<template>
|
|
||||||
|
|
||||||
<view>
|
|
||||||
<view class="code-state" @tap="statePopup.open(props.state)">
|
|
||||||
{{ vdata.selected.label || '全部状态' }}
|
|
||||||
<image src="/pageDevice/static/devIconImg/icon-arrow-down.svg" mode="scaleToFill" />
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view>
|
|
||||||
<JSinglePopup :list="stateList" title="按设备状态筛选" ref="statePopup" @confirm="confirmState" />
|
|
||||||
</view>
|
|
||||||
|
|
||||||
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { reactive, ref } from 'vue'
|
|
||||||
|
|
||||||
|
|
||||||
const emits = defineEmits(['update:state', 'change'])
|
|
||||||
|
|
||||||
// 定义组件参数
|
|
||||||
const props = defineProps({
|
|
||||||
|
|
||||||
// 双向绑定
|
|
||||||
state: { type: [Number, String] },
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
const vdata = reactive({
|
|
||||||
selected: {} , // 当前选择对象
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
const statePopup = ref(null)
|
|
||||||
|
|
||||||
|
|
||||||
const stateList = reactive([
|
|
||||||
{ label: '全部状态', value: '' },
|
|
||||||
{ label: '启用', value: '1' },
|
|
||||||
{ label: '禁用', value: '0' },
|
|
||||||
])
|
|
||||||
|
|
||||||
|
|
||||||
//按状态筛选
|
|
||||||
function confirmState(r){
|
|
||||||
vdata.selected = r || { }
|
|
||||||
emits('update:state', vdata.selected.value)
|
|
||||||
emits('change', vdata.selected.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.code-state {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin-left: 40rpx;
|
|
||||||
font-size: 30rpx;
|
|
||||||
color: #222425;
|
|
||||||
image {
|
|
||||||
margin-left: 10rpx;
|
|
||||||
width: 40rpx;
|
|
||||||
height: 40rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
<!--
|
|
||||||
Jeepay 通用状态切换按钮, 支持switch和badge两个格式, 根据权限进行判断
|
|
||||||
参考 jeepay-ui组件 。
|
|
||||||
@author terrfly
|
|
||||||
@site https://www.jeepay.vip
|
|
||||||
@date 2021/5/8 07:18
|
|
||||||
-->
|
|
||||||
<template>
|
|
||||||
<view>
|
|
||||||
<template v-if="props.showSwitchType" >
|
|
||||||
<switch v-if="vdata.isShowSwitchFlag" :checked="vdata.switchChecked" color="#238FFC" :style="{ transform: 'scale(' + scale + ')', margin: margin }" @change="changeFunc" />
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
|
|
||||||
<image v-if="vdata.switchChecked == 1" class="default-image" src="/pageDevice/static/devIconImg/icon-default.svg" mode="scaleToFill" />
|
|
||||||
<image v-if="vdata.switchChecked == 0" class="default-image" src="/pageDevice/static/devIconImg/icon-noDefault.svg" mode="scaleToFill" />
|
|
||||||
</template>
|
|
||||||
</view>
|
|
||||||
<JeepayPopupConfirm ref="jeepayPopupConfirmRef" />
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref, reactive, nextTick, watch, onMounted } from "vue"
|
|
||||||
const props = defineProps({
|
|
||||||
|
|
||||||
// 样式参数
|
|
||||||
scale: { type: Number, default: 0.8 }, //控制开关大小 倍数 默认.8
|
|
||||||
margin: { type: String, default: "0" }, // 控制开关外边距默认0
|
|
||||||
|
|
||||||
showSwitchType: { type: Boolean, default: false }, // 默认 badge
|
|
||||||
|
|
||||||
//开关状态, 0-关闭, 1-开启
|
|
||||||
state: { type: [Number,String], default: 1 },
|
|
||||||
|
|
||||||
// 是否显示二次确认
|
|
||||||
confirm: { type: Boolean, default: true },
|
|
||||||
|
|
||||||
confirmTitle: { type: String, default: '确定修改状态?' }, // 二次确认提示信息
|
|
||||||
|
|
||||||
// updateStateFunc回调事件. 需返回promise
|
|
||||||
updateStateFunc: { type: Function },
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
const jeepayPopupConfirmRef = ref() //提示弹窗
|
|
||||||
const emits = defineEmits(["update:state"])
|
|
||||||
|
|
||||||
onMounted(()=>{
|
|
||||||
vdata.switchChecked = props.state == 1
|
|
||||||
})
|
|
||||||
|
|
||||||
const vdata = reactive({
|
|
||||||
|
|
||||||
isShowSwitchFlag: true , // 用于重新加载组件
|
|
||||||
|
|
||||||
switchChecked: true, // 是否选中
|
|
||||||
})
|
|
||||||
|
|
||||||
// 监听 props属性
|
|
||||||
watch(() => props.state, function(o, n){
|
|
||||||
vdata.switchChecked = props.state == 1
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
function changeFunc(e){
|
|
||||||
|
|
||||||
let changeVal = e.detail.value
|
|
||||||
|
|
||||||
// 显示弹层
|
|
||||||
if(props.confirm){
|
|
||||||
jeepayPopupConfirmRef.value.open(props.confirmTitle).then(() => {
|
|
||||||
return propsUpdateStateFunc(changeVal ? 1 : 0)
|
|
||||||
}).then(() => {
|
|
||||||
emits("update:state", changeVal ? 1 : 0)
|
|
||||||
reloadSwitch(changeVal)
|
|
||||||
}).catch(() => {
|
|
||||||
reloadSwitch(!changeVal)
|
|
||||||
})
|
|
||||||
|
|
||||||
}else{ // 调起更新函数
|
|
||||||
|
|
||||||
propsUpdateStateFunc(changeVal ? 1 : 0).then(() => {
|
|
||||||
emits("update:state", changeVal ? 1 : 0)
|
|
||||||
reloadSwitch(changeVal)
|
|
||||||
}).catch(() => {
|
|
||||||
reloadSwitch(!changeVal)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// uniapp-switch 组件存在问题, 当用户出发了切换, 那么v-model:checked 绑定的元素不在生效了。
|
|
||||||
function reloadSwitch(changeVal){
|
|
||||||
|
|
||||||
vdata.switchChecked = changeVal
|
|
||||||
vdata.isShowSwitchFlag = false
|
|
||||||
nextTick(() => vdata.isShowSwitchFlag = true)
|
|
||||||
}
|
|
||||||
|
|
||||||
// props. default app 和小程序有出入,此函数用作兼容。
|
|
||||||
// APP default : () => { return (state) => {Promie.resole()} } (小层序认为 default即函数, )
|
|
||||||
function propsUpdateStateFunc(state){
|
|
||||||
|
|
||||||
if(props.updateStateFunc){
|
|
||||||
return props.updateStateFunc(state)
|
|
||||||
}
|
|
||||||
|
|
||||||
return Promise.resolve()
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
|
|
||||||
.default-image {
|
|
||||||
width: 50rpx;
|
|
||||||
height: 50rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
<!--
|
|
||||||
Jeepay 表格列表, 支持 下滑, 上滑刷新。
|
|
||||||
|
|
||||||
业务页面最好也监听下 触底函数, 否则H5无法监听到。
|
|
||||||
import { onReachBottom } from '@dcloudio/uni-app'
|
|
||||||
onReachBottom(() => { })
|
|
||||||
|
|
||||||
|
|
||||||
@author terrfly
|
|
||||||
@site https://www.jeequan.com
|
|
||||||
@date 2022/11/16 15:55
|
|
||||||
-->
|
|
||||||
<template>
|
|
||||||
<view>
|
|
||||||
<template v-for="(record, i) in vdata.allData" :key="i">
|
|
||||||
<slot name="tableBody" :record="record" :index="i" />
|
|
||||||
</template>
|
|
||||||
</view>
|
|
||||||
<view class="list-null" v-if="!vdata.apiResData.hasNext && showListNull">暂无更多数据</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref, reactive, onMounted } from 'vue';
|
|
||||||
import { onPullDownRefresh, onReachBottom } from '@dcloudio/uni-app';
|
|
||||||
|
|
||||||
// 定义传入属性
|
|
||||||
const props = defineProps({
|
|
||||||
reqTableDataFunc: { type: Function, default: () => {} },
|
|
||||||
searchData: { type: Object, default: () => {} }, // 搜索条件参数
|
|
||||||
pageSize: { type: Number, default: 10 }, // 默认每页条数
|
|
||||||
initData: { type: Boolean, default: true }, // 初始化列表数据, 默认true
|
|
||||||
showListNull: { type: Boolean, default: true } //是否显示缺省 默认显示
|
|
||||||
});
|
|
||||||
|
|
||||||
const vdata = reactive({
|
|
||||||
allData: [], // app与web不同, app是每次查询到数据会拼接到后面
|
|
||||||
|
|
||||||
// 接口返回的数据
|
|
||||||
apiResData: { total: 0, records: [] },
|
|
||||||
|
|
||||||
// 分页参数
|
|
||||||
iPage: { pageNumber: 1, pageSize: props.pageSize }
|
|
||||||
});
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
//初始化表数据
|
|
||||||
props.initData ? refTable(true) : undefined;
|
|
||||||
});
|
|
||||||
|
|
||||||
// 查询表格数据
|
|
||||||
function refTable(isToFirst = false) {
|
|
||||||
if (isToFirst) {
|
|
||||||
// 重新搜索, 第一页。
|
|
||||||
vdata.iPage.pageNumber = 1;
|
|
||||||
vdata.allData = []; //清空数据
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新检索数据
|
|
||||||
return props.reqTableDataFunc(Object.assign({}, vdata.iPage, props.searchData)).then(({ bizData }) => {
|
|
||||||
Object.assign(vdata.apiResData, bizData); // 列表数据更新
|
|
||||||
if (bizData.records) {
|
|
||||||
vdata.allData.push(...bizData.records); // 利用展开语法代替forEach
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 追加下一页数据 **/
|
|
||||||
function addNext() {
|
|
||||||
// 包含下一页
|
|
||||||
if (vdata.apiResData.hasNext) {
|
|
||||||
vdata.iPage.pageNumber++;
|
|
||||||
refTable(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 下拉刷新
|
|
||||||
onPullDownRefresh(() => {
|
|
||||||
refTable(true).then(() => {
|
|
||||||
uni.stopPullDownRefresh();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// 监听,触底事件。 查询下一页
|
|
||||||
onReachBottom(() => {
|
|
||||||
addNext();
|
|
||||||
});
|
|
||||||
|
|
||||||
// 将表格事件暴露出去 https://www.jianshu.com/p/39d14c25c987
|
|
||||||
defineExpose({ refTable, addNext });
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.list-null {
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
line-height: 110rpx;
|
|
||||||
text-align: center;
|
|
||||||
font-size: 26rpx;
|
|
||||||
color: #a6a6a6;
|
|
||||||
&::after,
|
|
||||||
&::before {
|
|
||||||
content: '';
|
|
||||||
display: block;
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
|
|
||||||
width: 30%;
|
|
||||||
height: 2rpx;
|
|
||||||
background-color: #ededed;
|
|
||||||
transform: translateY(-50%);
|
|
||||||
}
|
|
||||||
&::after {
|
|
||||||
left: 40rpx;
|
|
||||||
}
|
|
||||||
&::before {
|
|
||||||
right: 40rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
<!--
|
|
||||||
Jeepay 通用列表条目, 包含 头像, 主标题, 副标题
|
|
||||||
|
|
||||||
@author terrfly
|
|
||||||
@site https://www.jeequan.com
|
|
||||||
@date 2022/11/16 15:55
|
|
||||||
-->
|
|
||||||
<template>
|
|
||||||
<view :class="`list-item ${props.viewClass}`">
|
|
||||||
<image :style="props.logoStyle" v-if="props.logo" :src="props.logo" mode="scaleToFill" />
|
|
||||||
<view class="list-info">
|
|
||||||
<view class="list-title">
|
|
||||||
<view class="list-name">
|
|
||||||
<slot name="title">{{ props.title }} </slot>
|
|
||||||
</view>
|
|
||||||
<slot name="titleRight">
|
|
||||||
|
|
||||||
<!-- 直接写 typeof 页面报错。 -->
|
|
||||||
<template v-if="isShowState()" >
|
|
||||||
<view v-if="props.state == 1" class="state-dot state-dot-enable"></view>
|
|
||||||
<view v-else class="state-dot state-dot-disable"></view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template v-if="navListComputed">
|
|
||||||
<image style="width: 70rpx; height: 70rpx" src="/pageDevice/static/devIconImg/icon-more-white.svg" mode="scaleToFill" @tap="single.open()" />
|
|
||||||
</template>
|
|
||||||
</slot>
|
|
||||||
</view>
|
|
||||||
<view class="list-subtitle"><slot name="subtitle">{{ props.subtitle }} </slot></view>
|
|
||||||
</view>
|
|
||||||
<JSinglePopup ref="single" :list="navListComputed" activeColor="#FF5B4C" />
|
|
||||||
</view>
|
|
||||||
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
|
|
||||||
import {ref, reactive, onMounted, computed } from 'vue'
|
|
||||||
import ak from '@/commons/utils/ak.js'
|
|
||||||
|
|
||||||
// 弹层
|
|
||||||
const single = ref()
|
|
||||||
|
|
||||||
// 定义传入属性
|
|
||||||
const props = defineProps({
|
|
||||||
|
|
||||||
title: { type: [String, Number] }, // 标题
|
|
||||||
|
|
||||||
subtitle: { type: [String, Number] }, // 副标题
|
|
||||||
|
|
||||||
logo: { type: String }, // 图标
|
|
||||||
|
|
||||||
logoStyle: { type: Object } , // logo颜色背景图
|
|
||||||
|
|
||||||
moreBtnList: { type: Array }, //更多按钮
|
|
||||||
|
|
||||||
// 状态开启(蓝色),or 关闭(置灰) 【 注意:state 和 moreBtnList 二选一, 或者请使用插槽覆写 titleRight 】
|
|
||||||
state: { type: [Number, String] },
|
|
||||||
|
|
||||||
viewClass: { type: String, default: '' }, // 样式透传, 小程序不支持再组件上加class(不生效), 需要特殊定义,特殊传入。
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
function isShowState(){
|
|
||||||
return typeof(props.state) != 'undefined'
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// 计算属性
|
|
||||||
let navListComputed = computed(() => {
|
|
||||||
|
|
||||||
if(!props.moreBtnList){
|
|
||||||
return props.moreBtnList
|
|
||||||
}
|
|
||||||
return props.moreBtnList.filter(r => hasEnt(r.entId))
|
|
||||||
})
|
|
||||||
|
|
||||||
function hasEnt(entId){
|
|
||||||
|
|
||||||
// 不包含: 说明无需隐藏
|
|
||||||
if(!entId){
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return ak.ent.has(entId)
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
</style>
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view class="tag-wrapper" :class="[calcType()]" :style="styles">
|
|
||||||
<slot />
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { reactive } from 'vue'
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
type: { type: [String, Object], default: 'green' },
|
|
||||||
styles: { type: Object, default: () => ({}) },
|
|
||||||
})
|
|
||||||
|
|
||||||
const classList = ['purple', 'green', 'blue', 'green-rgba']
|
|
||||||
const calcType = () => {
|
|
||||||
try {
|
|
||||||
// 如果传入样式对象覆写样式
|
|
||||||
if (Object.keys(props.styles).length > 0) return ''
|
|
||||||
//如果预设样式类型中包含样式 使用预设样式类型
|
|
||||||
if (classList.includes(props.type)) return props.type
|
|
||||||
throw `预设样式类型中未包含此字段 请使使用style字段传入样式对象 自定义样式 注意样式名驼峰语法 目前预设样式字段有 ${classList.join(',')} `
|
|
||||||
} catch (err) {
|
|
||||||
console.error('error', err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.tag-wrapper {
|
|
||||||
display: inline-block;
|
|
||||||
margin-left: 15rpx;
|
|
||||||
padding: 0 15rpx;
|
|
||||||
height: 40rpx;
|
|
||||||
line-height: 40rpx;
|
|
||||||
border-radius: 6rpx;
|
|
||||||
text-align: center;
|
|
||||||
font-size: 23rpx;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
.purple {
|
|
||||||
background: linear-gradient(270deg, rgba(220, 61, 138, 1) 0%, rgba(187, 23, 92, 1) 100%);
|
|
||||||
}
|
|
||||||
.green {
|
|
||||||
background: linear-gradient(270deg, rgba(61, 220, 68, 1) 0%, rgba(23, 187, 118, 1) 100%);
|
|
||||||
}
|
|
||||||
.blue {
|
|
||||||
background: linear-gradient(270deg, rgba(35, 161, 252, 1) 0%, rgba(26, 102, 255, 1) 100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.green-rgba{
|
|
||||||
color: rgba(23, 188, 118, 1);
|
|
||||||
background: linear-gradient(270deg, rgba(61, 220, 68, 0.3) 0%, rgba(23, 187, 118, 0.3) 100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
@@ -1,167 +0,0 @@
|
|||||||
<!--
|
|
||||||
图片上传组件
|
|
||||||
@author terrfly
|
|
||||||
@site https://www.jeequan.com
|
|
||||||
@date 2022/11/30 18:18
|
|
||||||
-->
|
|
||||||
<template>
|
|
||||||
<view style="flex-grow: 1">
|
|
||||||
<!-- 图片内 带 x 号的模式。 -->
|
|
||||||
<template v-if="props.mode == 'img'">
|
|
||||||
<!-- 包含图片 -->
|
|
||||||
<template v-if="props.src">
|
|
||||||
<view class="image-wrapper">
|
|
||||||
<image v-if="!props.readonly" @tap="delImg" class="del-image" src="/static/iconImg/icon-x-white.svg" mode="scaleToFill" />
|
|
||||||
<image class="default-img" :src="props.src" @tap="preview"></image>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<!-- 不包含图片 -->
|
|
||||||
<view @tap="chooseImageAndUpload" style="flex-grow: 1; display: flex; justify-content: space-between; align-items: center">
|
|
||||||
<image
|
|
||||||
v-if="!props.readonly"
|
|
||||||
style="width: 150rpx; height: 150rpx; background-color: #f7f7f7; border-radius: 15rpx"
|
|
||||||
src="/static/iconImg/default-img.svg"
|
|
||||||
mode="scaleToFill"
|
|
||||||
/>
|
|
||||||
<image src="/pageDevice/static/devIconImg/icon-arrow-sex.svg" mode="scaleToFill" style="width: 120rpx; height: 120rpx" />
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<!-- 页面图片 加入 切换按钮 -->
|
|
||||||
<template v-if="props.mode == 'viewbtn'">
|
|
||||||
<image class="default-img" :src="props.src" @tap="preview" mode="aspectFill"></image>
|
|
||||||
|
|
||||||
<!-- 图片预览(手写非原生) -->
|
|
||||||
<enlarge v-if="vdata.showEnlarge" :imgs="props.src" :changeIsShow="!props.readonly" @chooseImg="chooseImageAndUpload" @enlargeClose="vdata.showEnlarge = false" />
|
|
||||||
</template>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref, reactive } from 'vue';
|
|
||||||
import http from '@/http/http.js';
|
|
||||||
import infoBox from '@/commons/utils/infoBox.js';
|
|
||||||
import enlarge from './enlarge.vue'; // 图片预览
|
|
||||||
import { API_URL_SINGLE_FILE_UPLOAD, $ossFilesForm } from '@/http/apiManager.js';
|
|
||||||
|
|
||||||
// emit 父组件使用: v-model:src="val" 进行双向绑定。
|
|
||||||
const emit = defineEmits(['update:src', 'change']);
|
|
||||||
|
|
||||||
// 定义 父组件传参
|
|
||||||
const props = defineProps({
|
|
||||||
src: { type: String, default: '' }, // 双向绑定 文件地址
|
|
||||||
bizType: { type: String, default: '' }, // 业务类型
|
|
||||||
imgSize: { type: Number, default: 5 }, // 上传图片大小限制 默认 5 M
|
|
||||||
|
|
||||||
// 两种模式: img - 图片包含删除按钮支持删除, viewbtn-图片内支预览按钮切换。
|
|
||||||
mode: { type: String, default: 'img' },
|
|
||||||
|
|
||||||
// 预览模式, 不支持切换图片。
|
|
||||||
readonly: { type: Boolean, default: false }
|
|
||||||
});
|
|
||||||
|
|
||||||
// 定义响应式数据
|
|
||||||
const vdata = reactive({
|
|
||||||
showEnlarge: false,
|
|
||||||
|
|
||||||
action: '', // 文件form表单请求地址
|
|
||||||
|
|
||||||
uploadForm: {
|
|
||||||
action: '', // 请求地址
|
|
||||||
header: {}, // 请求头
|
|
||||||
params: {} // 参数
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 预览图片
|
|
||||||
function preview() {
|
|
||||||
if (props.mode == 'img') {
|
|
||||||
// 原生图片预览
|
|
||||||
|
|
||||||
uni.previewImage({ urls: [props.src] });
|
|
||||||
} else {
|
|
||||||
// 组件模式
|
|
||||||
|
|
||||||
vdata.showEnlarge = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除图片
|
|
||||||
function delImg() {
|
|
||||||
emit('update:src', '');
|
|
||||||
emit('change', '');
|
|
||||||
}
|
|
||||||
|
|
||||||
// 选择图片 and 上传
|
|
||||||
function chooseImageAndUpload() {
|
|
||||||
// 最多选择一张图片 && 压缩图片 && 支持相册 和 相机
|
|
||||||
uni.chooseImage({ count: 1, sizeType: ['compressed'], sourceType: ['album', 'camera'] }).then((res) => {
|
|
||||||
let file = res.tempFiles[0];
|
|
||||||
|
|
||||||
// 预先检查
|
|
||||||
if (!beforeCheck(file)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查通过
|
|
||||||
|
|
||||||
$ossFilesForm(props.bizType, file).then(({ bizData }) => {
|
|
||||||
// 本地方式
|
|
||||||
if (bizData.formActionUrl === 'LOCAL_SINGLE_FILE_URL') {
|
|
||||||
return http.upload(API_URL_SINGLE_FILE_UPLOAD, { bizType: props.bizType }, file).then(({ bizData }) => {
|
|
||||||
emit('update:src', bizData);
|
|
||||||
emit('change', bizData);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// oss 直传
|
|
||||||
uni.uploadFile({ url: bizData.formActionUrl, filePath: file.path, name: 'file', formData: bizData.formParams }).then((ossRes) => {
|
|
||||||
if (ossRes.statusCode == 200) {
|
|
||||||
// 上传成功
|
|
||||||
emit('update:src', bizData.ossFileUrl);
|
|
||||||
emit('change', bizData.ossFileUrl);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
infoBox.showToast('oss服务响应异常');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function beforeCheck(file) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
defineExpose({
|
|
||||||
preview
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.default-img {
|
|
||||||
display: block;
|
|
||||||
width: 150rpx;
|
|
||||||
height: 150rpx;
|
|
||||||
background-color: #f7f7f7;
|
|
||||||
border-radius: 15rpx;
|
|
||||||
}
|
|
||||||
.image-wrapper {
|
|
||||||
position: relative;
|
|
||||||
width: 150rpx;
|
|
||||||
height: 150rpx;
|
|
||||||
margin-bottom: 20upx;
|
|
||||||
.del-image {
|
|
||||||
position: absolute;
|
|
||||||
top: -20rpx;
|
|
||||||
right: -20rpx;
|
|
||||||
z-index: 10;
|
|
||||||
width: 40rpx;
|
|
||||||
height: 40rpx;
|
|
||||||
border-radius: 50%;
|
|
||||||
background-color: tomato;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,143 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view class="previewImage" :style="{ 'background-color': 'rgba(0,0,0,' + opacity + ')' }" @tap.stop="close">
|
|
||||||
<movable-area class="marea" scale-area>
|
|
||||||
<movable-view
|
|
||||||
:id="'movable-view-' + i"
|
|
||||||
:key="'movable-view-' + i"
|
|
||||||
class="mview"
|
|
||||||
direction="all"
|
|
||||||
:out-of-bounds="false"
|
|
||||||
:inertia="true"
|
|
||||||
damping="90"
|
|
||||||
friction="2"
|
|
||||||
scale="true"
|
|
||||||
scale-min="1"
|
|
||||||
scale-max="4"
|
|
||||||
:scale-value="scale"
|
|
||||||
>
|
|
||||||
<image
|
|
||||||
:id="'image-' + i"
|
|
||||||
:key="'movable-view' + i"
|
|
||||||
class="image"
|
|
||||||
:src="imgs"
|
|
||||||
:data-index="i"
|
|
||||||
:data-src="img"
|
|
||||||
mode="widthFix"
|
|
||||||
/>
|
|
||||||
</movable-view>
|
|
||||||
</movable-area>
|
|
||||||
<view v-if="changeIsShow" class="change-img" @click="chooseImg">更换图片</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: "ksj-previewImage", //插件名称
|
|
||||||
props: {
|
|
||||||
imgs: {
|
|
||||||
//图片列表
|
|
||||||
type: String,
|
|
||||||
required: true,
|
|
||||||
default: "",
|
|
||||||
},
|
|
||||||
//透明度,0到1之间。
|
|
||||||
opacity: {
|
|
||||||
type: Number,
|
|
||||||
default: 1,
|
|
||||||
},
|
|
||||||
changeIsShow: { type: Boolean, default: true },
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
swiper: false, //是否禁用
|
|
||||||
show: false, //显示状态
|
|
||||||
index: 0, //当前页
|
|
||||||
deg: 0, //旋转角度
|
|
||||||
time: 0, //定时器
|
|
||||||
interval: 1000, //长按事件
|
|
||||||
scale: 1, //缩放比例
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
chooseImg() {
|
|
||||||
this.$emit("chooseImg")
|
|
||||||
},
|
|
||||||
|
|
||||||
//旋转
|
|
||||||
rotate(e) {
|
|
||||||
this.deg = this.deg == 270 ? 0 : this.deg + 90
|
|
||||||
},
|
|
||||||
close() {
|
|
||||||
this.$emit("enlargeClose")
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<!--使用scss,只在本组件生效-->
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.previewImage {
|
|
||||||
z-index: 25;
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
z-index: 999;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background-color: #000000;
|
|
||||||
user-select: none;
|
|
||||||
.marea {
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
position: fixed;
|
|
||||||
overflow: hidden;
|
|
||||||
.mview {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
width: 100%;
|
|
||||||
height: auto;
|
|
||||||
min-height: 100%;
|
|
||||||
.image {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.rotate {
|
|
||||||
position: absolute;
|
|
||||||
right: 10rpx;
|
|
||||||
width: 120rpx;
|
|
||||||
height: 56rpx;
|
|
||||||
bottom: 10rpx;
|
|
||||||
text-align: center;
|
|
||||||
padding: 10rpx;
|
|
||||||
.text {
|
|
||||||
background-color: rgba(0, 0, 0, 0.5);
|
|
||||||
color: #fff;
|
|
||||||
font-size: 30rpx;
|
|
||||||
border-radius: 20rpx;
|
|
||||||
border: 1rpx solid #f1f1f1;
|
|
||||||
padding: 6rpx 22rpx;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
.text:active {
|
|
||||||
background-color: rgba(100, 100, 100, 0.5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.change-img {
|
|
||||||
position: fixed;
|
|
||||||
width: 300rpx;
|
|
||||||
bottom: 5%;
|
|
||||||
left: 50%;
|
|
||||||
margin-left: -150rpx;
|
|
||||||
text-align: center;
|
|
||||||
z-index: 30;
|
|
||||||
color: #fff;
|
|
||||||
padding: 30rpx;
|
|
||||||
box-sizing: border-box;
|
|
||||||
background-color: #0041c4;
|
|
||||||
border-radius: 10rpx;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,135 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view v-show="isShow">
|
|
||||||
<view class="shade" @tap="hide"></view>
|
|
||||||
<view class="pop">
|
|
||||||
<view class="flex_col" style="margin-bottom: 20rpx;">
|
|
||||||
<view class="preview" :style="{'backgroundColor':pickerColor}"></view>
|
|
||||||
<view class="value">
|
|
||||||
<text v-if="pickerColor">颜色值:{{pickerColor}}</text>
|
|
||||||
</view>
|
|
||||||
<view class="ok" @tap="setColor">确定</view>
|
|
||||||
</view>
|
|
||||||
<view class="list flex_col" v-for="(item,index) in colorArr" :key="index">
|
|
||||||
<view v-for="(v,i) in item" :key="i"
|
|
||||||
:style="{'backgroundColor':v}"
|
|
||||||
:data-color="v"
|
|
||||||
:data-index="index"
|
|
||||||
:data-i="i"
|
|
||||||
:class="{'active':(index==pickerArr[0] && i==pickerArr[1])}"
|
|
||||||
@tap="picker"></view>
|
|
||||||
</view>
|
|
||||||
<view :style="{'height':(bottom+'px')}"></view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name:'picker-color',
|
|
||||||
props:{
|
|
||||||
isShow: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
bottom:{
|
|
||||||
type: Number,
|
|
||||||
default: 0,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
colorArr:[
|
|
||||||
['#000000','#111111','#222222','#333333','#444444','#666666','#999999','#CCCCCC','#EEEEEE','#FFFFFF'],
|
|
||||||
['#ff0000','#ff0033','#ff3399','#ff33cc','#cc00ff','#9900ff','#cc00cc','#cc0099','#cc3399','#cc0066'],
|
|
||||||
['#cc3300','#cc6600','#ff9933','#ff9966','#ff9999','#ff99cc','#ff99ff','#cc66ff','#9966ff','#cc33ff'],
|
|
||||||
['#663300','#996600','#996633','#cc9900','#a58800','#cccc00','#ffff66','#ffff99','#ffffcc','#ffcccc'],
|
|
||||||
['#336600','#669900','#009900','#009933','#00cc00','#66ff66','#339933','#339966','#009999','#33cccc'],
|
|
||||||
['#003366','#336699','#3366cc','#0099ff','#000099','#0000cc','#660066','#993366','#993333','#800000']
|
|
||||||
],
|
|
||||||
pickerColor:'',
|
|
||||||
pickerArr:[-1,-1]
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
picker(e) {
|
|
||||||
let data=e.currentTarget.dataset;
|
|
||||||
this.pickerColor=data.color;
|
|
||||||
this.pickerArr=[data.index,data.i];
|
|
||||||
},
|
|
||||||
hide(){
|
|
||||||
this.$emit("callback",'');
|
|
||||||
},
|
|
||||||
setColor(){
|
|
||||||
this.$emit("callback",this.pickerColor);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.shade{
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
background-color: rgba(0,0,0,0.5);
|
|
||||||
z-index: 99;
|
|
||||||
}
|
|
||||||
.pop{
|
|
||||||
position: fixed;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
background-color: #fff;
|
|
||||||
z-index: 100;
|
|
||||||
padding: 20upx 20upx 10upx 20upx;
|
|
||||||
font-size: 32upx;
|
|
||||||
}
|
|
||||||
.flex_col{
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
flex-wrap: nowrap;
|
|
||||||
justify-content: flex-start;
|
|
||||||
align-items: center;
|
|
||||||
align-content: center;
|
|
||||||
}
|
|
||||||
.list{
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
.list>view{
|
|
||||||
width: 60upx;
|
|
||||||
height: 60upx;
|
|
||||||
margin-bottom: 10upx;
|
|
||||||
box-sizing: border-box;
|
|
||||||
border-radius: 3px;
|
|
||||||
box-shadow: 0 0 2px #ccc;
|
|
||||||
}
|
|
||||||
.list .active{
|
|
||||||
box-shadow: 0 0 2px #09f;
|
|
||||||
transform:scale(1.05,1.05);
|
|
||||||
}
|
|
||||||
.preview{
|
|
||||||
width: 180upx;
|
|
||||||
height: 60upx;
|
|
||||||
}
|
|
||||||
.value{
|
|
||||||
margin: 0 40upx;
|
|
||||||
flex-grow: 1;
|
|
||||||
}
|
|
||||||
.ok{
|
|
||||||
width: 160upx;
|
|
||||||
height: 60upx;
|
|
||||||
line-height: 60upx;
|
|
||||||
text-align: center;
|
|
||||||
background-color: #ff9933;
|
|
||||||
color: #fff;
|
|
||||||
border-radius: 4px;
|
|
||||||
letter-spacing: 3px;
|
|
||||||
font-size: 32upx;
|
|
||||||
}
|
|
||||||
.ok:active{
|
|
||||||
background-color: rgb(255, 107, 34);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -44,24 +44,15 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import {
|
import { reactive, nextTick, ref,watch } from 'vue';
|
||||||
reactive,
|
|
||||||
nextTick,
|
|
||||||
ref,watch
|
|
||||||
} from 'vue';
|
|
||||||
import myModel from '@/components/my-components/my-model.vue'
|
import myModel from '@/components/my-components/my-model.vue'
|
||||||
import myButton from '@/components/my-components/my-button.vue'
|
import myButton from '@/components/my-components/my-button.vue'
|
||||||
import myTabs from '@/components/my-components/my-tabs.vue'
|
|
||||||
import infoBox from '@/commons/utils/infoBox.js'
|
import infoBox from '@/commons/utils/infoBox.js'
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
title: {
|
title: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ''
|
||||||
},
|
},
|
||||||
data: {
|
|
||||||
type: Array,
|
|
||||||
default: []
|
|
||||||
},
|
|
||||||
discount:{
|
discount:{
|
||||||
type: [Number,String],
|
type: [Number,String],
|
||||||
default:100
|
default:100
|
||||||
@@ -70,25 +61,24 @@
|
|||||||
type: [Number,String],
|
type: [Number,String],
|
||||||
default: 0
|
default: 0
|
||||||
},
|
},
|
||||||
nowPrice:{
|
|
||||||
type: [Number,String],
|
|
||||||
default: 0
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
function currentPriceInput(newval){
|
function currentPriceInput(newval){
|
||||||
form.discount=(newval*100/form.price)
|
form.discount = (newval*100/form.price).toFixed(2)
|
||||||
}
|
}
|
||||||
function discountInput(newval){
|
function discountInput(newval){
|
||||||
form.currentPrice=(form.price*newval/100).toFixed(2)
|
form.currentPrice= uni.$utils.isMoney(form.price*newval/100).toFixed(2)
|
||||||
}
|
}
|
||||||
function currentPriceChange(newval){
|
function currentPriceChange(newval){
|
||||||
if(newval<0){
|
if(newval<0){
|
||||||
form.currentPrice=0
|
form.currentPrice = '0.00'
|
||||||
form.discount=100
|
form.discount=100
|
||||||
return infoBox.showToast('实收金额不能小于0')
|
return infoBox.showToast('实收金额不能小于0')
|
||||||
}
|
}
|
||||||
if(newval>props.price){
|
console.log(props.price)
|
||||||
form.currentPrice=props.price
|
console.log(newval)
|
||||||
|
if(newval > props.price){
|
||||||
|
form.currentPrice = (uni.$utils.isMoney(props.price)*1).toFixed(2)
|
||||||
form.discount=0
|
form.discount=0
|
||||||
return infoBox.showToast('实收金额不能大于应付金额')
|
return infoBox.showToast('实收金额不能大于应付金额')
|
||||||
}
|
}
|
||||||
@@ -107,7 +97,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
const $form = {
|
const $form = {
|
||||||
price:props.price,
|
price: props.price,
|
||||||
currentPrice: props.price,
|
currentPrice: props.price,
|
||||||
discount: 100
|
discount: 100
|
||||||
}
|
}
|
||||||
@@ -115,8 +105,7 @@
|
|||||||
...$form
|
...$form
|
||||||
})
|
})
|
||||||
watch(()=>props.price,(newval)=>{
|
watch(()=>props.price,(newval)=>{
|
||||||
console.log(newval);
|
form.price = (newval*1).toFixed(2)
|
||||||
form.price=newval
|
|
||||||
form.currentPrice=newval
|
form.currentPrice=newval
|
||||||
})
|
})
|
||||||
function resetForm() {
|
function resetForm() {
|
||||||
@@ -129,9 +118,10 @@
|
|||||||
|
|
||||||
function open() {
|
function open() {
|
||||||
model.value.open()
|
model.value.open()
|
||||||
form.price=props.price
|
form.price= (props.price*1).toFixed(2)
|
||||||
form.discount=props.discount
|
form.discount=props.discount
|
||||||
form.currentPrice=(props.discount*props.price/100).toFixed(2)
|
form.currentPrice=(props.discount*props.price/100).toFixed(2)
|
||||||
|
console.log(form)
|
||||||
}
|
}
|
||||||
|
|
||||||
function close() {
|
function close() {
|
||||||
@@ -140,7 +130,6 @@
|
|||||||
const emits = defineEmits(['confirm'])
|
const emits = defineEmits(['confirm'])
|
||||||
|
|
||||||
function confirm() {
|
function confirm() {
|
||||||
console.log(form);
|
|
||||||
emits('confirm',{...form,currentPrice:Number(form.currentPrice).toFixed(2)})
|
emits('confirm',{...form,currentPrice:Number(form.currentPrice).toFixed(2)})
|
||||||
close()
|
close()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
|
|
||||||
</view>
|
</view>
|
||||||
<view class="u-p-30 u-flex u-flex-wrap gap-20 fastTime" v-if="props.isArea">
|
<view class="u-p-30 u-flex u-flex-wrap gap-20 fastTime" v-if="props.isArea">
|
||||||
<view class="item" v-for="(item,index) in fastTime" :key="index" @tap="changeTime(item.key)">
|
<view class="item" v-for="(item,index) in fastTime" :key="index" @tap="changeTime(item)">
|
||||||
{{item.title}}
|
{{item.label}}
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<picker-view :immediate-change="true" @pickend="pickend" :value="value" @change="bindChange"
|
<picker-view :immediate-change="true" @pickend="pickend" :value="value" @change="bindChange"
|
||||||
@@ -95,12 +95,10 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import { reactive, nextTick, ref } from 'vue';
|
||||||
|
import * as $time from '@/commons/utils/dayjs-time.js';
|
||||||
import myButton from "@/components/my-components/my-button.vue"
|
import myButton from "@/components/my-components/my-button.vue"
|
||||||
import {
|
|
||||||
reactive,
|
|
||||||
nextTick,
|
|
||||||
ref
|
|
||||||
} from 'vue';
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
selTime:{
|
selTime:{
|
||||||
type: [String,Number],
|
type: [String,Number],
|
||||||
@@ -178,24 +176,28 @@
|
|||||||
const seconds = new Array(60).fill(1).map((v, index) => {
|
const seconds = new Array(60).fill(1).map((v, index) => {
|
||||||
return index
|
return index
|
||||||
})
|
})
|
||||||
const fastTime = reactive([{
|
// const fastTime = reactive([{
|
||||||
title: '今日',
|
// title: '今日',
|
||||||
key: 'now'
|
// key: 'now'
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
title: '昨日',
|
// title: '昨日',
|
||||||
key: 'prve'
|
// key: 'prve'
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
title: '本月',
|
// title: '本月',
|
||||||
key: 'nowMonth'
|
// key: 'nowMonth'
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
title: '上月',
|
// title: '上月',
|
||||||
key: 'prveMonth'
|
// key: 'prveMonth'
|
||||||
}
|
// }
|
||||||
])
|
// ])
|
||||||
|
const today = $time.getTodayTimestamps();
|
||||||
|
const yesterday = $time.getYesterdayTimestamps();
|
||||||
|
const thisMonth = $time.getThisMonthTimestamps();
|
||||||
|
const thisLastMonth = $time.getThisLastMonthTimestamps()
|
||||||
|
const fastTime = reactive([today, yesterday, thisMonth, thisLastMonth])
|
||||||
|
|
||||||
|
|
||||||
function setPrveDay() {
|
function setPrveDay() {
|
||||||
@@ -230,84 +232,10 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeTime(key) {
|
function changeTime(e) {
|
||||||
const yearIndex = years.findIndex(v => v == nowDate.year)
|
console.log(e)
|
||||||
const prveyearIndex = years.findIndex(v => v == nowDate.year) - 1
|
const start = e.start
|
||||||
const nowMonthIndex = nowDate.month - 1
|
const end = e.end
|
||||||
const nowDayIndex = nowDate.day - 1
|
|
||||||
const dataMap = {
|
|
||||||
now: function() {
|
|
||||||
return {
|
|
||||||
start: {
|
|
||||||
year: yearIndex,
|
|
||||||
month: nowMonthIndex,
|
|
||||||
day: nowDayIndex
|
|
||||||
},
|
|
||||||
end: {
|
|
||||||
year: yearIndex,
|
|
||||||
month: nowMonthIndex,
|
|
||||||
day: nowDayIndex
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
prve: function() {
|
|
||||||
const oneDay = 1000 * 60 * 60 * 24
|
|
||||||
const date = new Date(new Date(nowDate.year, nowDate.month, nowDate.day, 0, 0, 0).getTime() -
|
|
||||||
oneDay)
|
|
||||||
return {
|
|
||||||
start: {
|
|
||||||
year: years.findIndex(v => v == date.getFullYear()),
|
|
||||||
month: date.getMonth() - 1 < 0 ? 11 : date.getMonth() - 1,
|
|
||||||
day: date.getDate() - 1
|
|
||||||
},
|
|
||||||
end: {
|
|
||||||
year: years.findIndex(v => v == date.getFullYear()),
|
|
||||||
month: date.getMonth() - 1 < 0 ? 11 : date.getMonth() - 1,
|
|
||||||
day: date.getDate() - 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
nowMonth: function() {
|
|
||||||
return {
|
|
||||||
start: {
|
|
||||||
year: yearIndex,
|
|
||||||
month: nowMonthIndex,
|
|
||||||
day: 0
|
|
||||||
},
|
|
||||||
end: {
|
|
||||||
year: yearIndex,
|
|
||||||
month: nowMonthIndex,
|
|
||||||
day: new Date(nowDate.year, nowDate.month, 0).getDate() - 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
prveMonth: function() {
|
|
||||||
const oneDay = 1000 * 60 * 60 * 24
|
|
||||||
const date = new Date(new Date(nowDate.year, nowDate.month - 1, 0, 0, 0).getTime() - oneDay)
|
|
||||||
console.log(date.getMonth());
|
|
||||||
return {
|
|
||||||
start: {
|
|
||||||
year: years.findIndex(v => v == date.getFullYear()),
|
|
||||||
month: date.getMonth(),
|
|
||||||
day: 0
|
|
||||||
},
|
|
||||||
end: {
|
|
||||||
year: years.findIndex(v => v == date.getFullYear()),
|
|
||||||
month: date.getMonth(),
|
|
||||||
day: date.getDate()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const data = dataMap[key]()
|
|
||||||
setDay(data.start, data.end)
|
|
||||||
changeDays(false, value.value)
|
|
||||||
changeDays(true, value1.value)
|
|
||||||
|
|
||||||
console.log(value1.value);
|
|
||||||
const start = returnDateString(value.value)
|
|
||||||
const end = returnDateString(value1.value)
|
|
||||||
|
|
||||||
emits('confirm', {
|
emits('confirm', {
|
||||||
text: `${start}——${end}`,
|
text: `${start}——${end}`,
|
||||||
start,
|
start,
|
||||||
@@ -390,7 +318,6 @@
|
|||||||
const month = arr[1] + 1
|
const month = arr[1] + 1
|
||||||
const day = arr[2] + 1
|
const day = arr[2] + 1
|
||||||
const hour = ('0' + (arr[3]||0)).slice(-2)
|
const hour = ('0' + (arr[3]||0)).slice(-2)
|
||||||
console.log(hour)
|
|
||||||
const min = ('0' + (arr[4]||0)).slice(-2)
|
const min = ('0' + (arr[4]||0)).slice(-2)
|
||||||
const sen = ('0' + (arr[5]||0)).slice(-2)
|
const sen = ('0' + (arr[5]||0)).slice(-2)
|
||||||
if (isObj) {
|
if (isObj) {
|
||||||
@@ -401,9 +328,7 @@
|
|||||||
|
|
||||||
|
|
||||||
function confirm(e) {
|
function confirm(e) {
|
||||||
console.log(value.value);
|
|
||||||
const start = returnDateString(value.value)
|
const start = returnDateString(value.value)
|
||||||
console.log(start);
|
|
||||||
const end = returnDateString(value1.value)
|
const end = returnDateString(value1.value)
|
||||||
if (!props.isArea) {
|
if (!props.isArea) {
|
||||||
emits('confirm', start)
|
emits('confirm', start)
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="model u-text-center" v-if="show" @tap="modelTap">
|
<view class="model u-text-center" v-if="show" @tap="modelTap">
|
||||||
<div @tap.stop="" class="box u-font-32 tranistion" :class="[returnBoxClass]" :style="[computeBoxStyle,computeStyle()]" >
|
<div @tap.stop="" class="box u-font-32 tranistion" :class="[returnBoxClass]" :style="[computeBoxStyle,computeStyle()]" >
|
||||||
<view class="u-relative">
|
<view class="u-relative" style="display: flex;align-items: center;justify-content: space-between;">
|
||||||
<view class=" color-333 font-bold">{{props.title||'提示'}}</view>
|
<view style=""></view>
|
||||||
|
<view class="color-333 font-bold up-line-1" style="width: 60%;">{{props.title||'提示'}}</view>
|
||||||
|
<view style=""></view>
|
||||||
<template v-if="showIcon">
|
<template v-if="showIcon">
|
||||||
<slot name="icon">
|
<slot name="icon">
|
||||||
<view class="close" @tap="close">
|
<view class="close" @tap="close">
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
default: 10
|
default: 10
|
||||||
},
|
},
|
||||||
totalElements: {
|
totalElements: {
|
||||||
type: Number,
|
type: String,
|
||||||
default: 0
|
default: 0
|
||||||
},
|
},
|
||||||
page: {
|
page: {
|
||||||
|
|||||||
@@ -48,7 +48,7 @@
|
|||||||
<view class="">{{item.name}}</view>
|
<view class="">{{item.name}}</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="u-flex-1 u-p-l-4 u-p-r-4 box-size-border">
|
<view class="u-flex-1 u-p-l-4 u-p-r-4 box-size-border">
|
||||||
{{item.typeEnum}}
|
{{item.type}}
|
||||||
</view>
|
</view>
|
||||||
<view class="u-flex-1">
|
<view class="u-flex-1">
|
||||||
¥{{ item.lowPrice }}
|
¥{{ item.lowPrice }}
|
||||||
@@ -80,15 +80,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import {
|
import { reactive, onMounted, ref, watch } from 'vue';
|
||||||
$tbProductList
|
|
||||||
} from '@/http/yskApi/goods.js';
|
|
||||||
import {
|
|
||||||
reactive,
|
|
||||||
onMounted,
|
|
||||||
ref,
|
|
||||||
watch
|
|
||||||
} from 'vue';
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
modelValue: {
|
modelValue: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
@@ -176,19 +168,19 @@
|
|||||||
getGoods()
|
getGoods()
|
||||||
function getGoods() {
|
function getGoods() {
|
||||||
const arr=selArr
|
const arr=selArr
|
||||||
$tbProductList(goods.query).then(res => {
|
// $tbProductList(goods.query).then(res => {
|
||||||
let selLen=0;
|
// let selLen=0;
|
||||||
goods.list = res.content.map(v => {
|
// goods.list = res.content.map(v => {
|
||||||
const checked=$selGoodsMap[v.id]?true:false
|
// const checked=$selGoodsMap[v.id]?true:false
|
||||||
selLen+=(checked?1:0)
|
// selLen+=(checked?1:0)
|
||||||
return {
|
// return {
|
||||||
...v,
|
// ...v,
|
||||||
checked
|
// checked
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
goods.allChecked = selLen==res.content.length?true:false
|
// goods.allChecked = selLen==res.content.length?true:false
|
||||||
goods.totalElements = res.totalElements
|
// goods.totalElements = res.totalElements
|
||||||
})
|
// })
|
||||||
}
|
}
|
||||||
|
|
||||||
function pageChange(page) {
|
function pageChange(page) {
|
||||||
|
|||||||
@@ -10,10 +10,8 @@
|
|||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
import {
|
import { ref } from 'vue'
|
||||||
ref
|
|
||||||
} from 'vue'
|
|
||||||
import color from '@/commons/color.js'
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
disabled: {
|
disabled: {
|
||||||
type: [Boolean],
|
type: [Boolean],
|
||||||
@@ -49,7 +47,7 @@
|
|||||||
width:${props.size}px;
|
width:${props.size}px;
|
||||||
height:${props.size}px;
|
height:${props.size}px;
|
||||||
border-color:${props.borderColor};
|
border-color:${props.borderColor};
|
||||||
border-color:${props.modelValue?color.ColorMain:props.borderColor};
|
border-color:${props.modelValue?uni.$utils.ColorMain:props.borderColor};
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
const emits = defineEmits(['update:modelValue', 'change'])
|
const emits = defineEmits(['update:modelValue', 'change'])
|
||||||
|
|||||||
@@ -1,345 +0,0 @@
|
|||||||
<template>
|
|
||||||
<up-popup customStyle="overflow: hidden;" :show="show" round="20" mode="bottom" @close="close" @open="open">
|
|
||||||
<view class="reportDamage">
|
|
||||||
<view class="reportDamage_head">
|
|
||||||
<view class="reportDamage_title">{{title}}</view>
|
|
||||||
<up-icon name="close-circle-fill" color="#333" size="25" @tap="close"></up-icon>
|
|
||||||
</view>
|
|
||||||
<view class="reportDamage_content">
|
|
||||||
<view class="reportDamage_cell">
|
|
||||||
<view class="cell_lable">
|
|
||||||
<up-image v-if="type=='product'" class="thumbnail" radius="10" :show-loading="true" :src="item.coverImg"></up-image>
|
|
||||||
<view>{{item.conName}}</view>
|
|
||||||
</view>
|
|
||||||
<view class="cell_value">
|
|
||||||
<up-icon name="minus-circle" color="#999" size="25" @tap="minus"></up-icon>
|
|
||||||
<view class="text">{{vdata.stockNumber}}</view>
|
|
||||||
<up-icon name="plus-circle-fill" color="#318AFE" size="25" @tap="plus"></up-icon>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="reportDamage_cell">
|
|
||||||
<view class="cell_lable">商品单位</view>
|
|
||||||
<view class="cell_value"><view>{{item.conUnit}}</view> <up-icon name="arrow-right" color="#999999" size="15"></up-icon></view>
|
|
||||||
</view>
|
|
||||||
<view class="reportDamage_cell">
|
|
||||||
<view class="cell_lable">报损图片</view>
|
|
||||||
<view class="cell_value file">
|
|
||||||
|
|
||||||
<view class="file_img" v-for="(item,index) in vdata.imgUrlList">
|
|
||||||
<up-image class="file_img_item" :show-loading="true" :src="item"></up-image>
|
|
||||||
<view class="del" @tap="del(index)">
|
|
||||||
<up-icon name="trash" color="#fff" size="25" @tap="plus"></up-icon>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="file" @tap="chooseAndUploadAvatar()">
|
|
||||||
<up-icon name="camera-fill" color="#E5E5E5" size="35"></up-icon>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="reportDamage_footer">
|
|
||||||
<view class="reportDamage_btn" @tap="affirm">确认</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</up-popup>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import {
|
|
||||||
computed,
|
|
||||||
ref,
|
|
||||||
reactive,
|
|
||||||
onMounted,
|
|
||||||
watch
|
|
||||||
} from 'vue';
|
|
||||||
import { $uploadFile } from '@/http/yskApi/file.js'
|
|
||||||
import { consumableBreakage , productBreakage} from '@/http/yskApi/breakage.js'
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
show:{
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
type:{
|
|
||||||
type: String,
|
|
||||||
default: ""
|
|
||||||
},
|
|
||||||
title:{
|
|
||||||
type: String,
|
|
||||||
default: ""
|
|
||||||
},
|
|
||||||
item:{
|
|
||||||
type: Object,
|
|
||||||
},
|
|
||||||
|
|
||||||
})
|
|
||||||
const emits = defineEmits(['close','open',"affirm"])
|
|
||||||
const vdata = reactive({
|
|
||||||
stockNumber: 1,
|
|
||||||
imgUrlList: [],
|
|
||||||
})
|
|
||||||
let show = ref(props.show)
|
|
||||||
let type = ref(props.type)
|
|
||||||
let itemData = ref(props.item)
|
|
||||||
watch(()=>props.show,(newval)=>{
|
|
||||||
show.value=newval
|
|
||||||
})
|
|
||||||
onMounted(() => {
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
function close() {
|
|
||||||
show.value = false;
|
|
||||||
vdata.imgUrlList = [];
|
|
||||||
vdata.stockNumber = 1;
|
|
||||||
emits('close')
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 打开报损弹窗
|
|
||||||
*/
|
|
||||||
function open() {
|
|
||||||
show.value = true;
|
|
||||||
emits('open')
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 报损数量减少
|
|
||||||
*/
|
|
||||||
function minus() {
|
|
||||||
if ( vdata.stockNumber <= 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
vdata.stockNumber--;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 报损数量增加
|
|
||||||
*/
|
|
||||||
function plus() {
|
|
||||||
vdata.stockNumber++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除报损图片
|
|
||||||
*/
|
|
||||||
function del ( index ) {
|
|
||||||
vdata.imgUrlList.splice(index,1)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 上传报损图片
|
|
||||||
*/
|
|
||||||
function chooseAndUploadAvatar () {
|
|
||||||
if ( vdata.imgUrlList.length >= 6 ) {
|
|
||||||
uni.showToast({
|
|
||||||
title:'最多只可以上传六张',
|
|
||||||
icon:'none'
|
|
||||||
})
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 选择图片
|
|
||||||
uni.chooseImage({
|
|
||||||
count: 1, // 默认为1,只选择一张图片
|
|
||||||
sizeType: ['original', 'compressed'], // 图片质量,原图或压缩
|
|
||||||
sourceType: ['album', 'camera'], // 图片来源,相册或相机
|
|
||||||
success: (res) => {
|
|
||||||
let file = res.tempFiles[0];
|
|
||||||
console.log(res)
|
|
||||||
$uploadFile(file).then(res => {
|
|
||||||
console.log(res);
|
|
||||||
vdata.imgUrlList.push(res.data[0])
|
|
||||||
|
|
||||||
}).catch(res=>{
|
|
||||||
console.log(res);
|
|
||||||
if(res.errMsg){
|
|
||||||
uni.showToast({
|
|
||||||
title:'图片大小超出限制',
|
|
||||||
icon:'error'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
},
|
|
||||||
fail: chooseImageError => {
|
|
||||||
// 选择图片失败处理逻辑
|
|
||||||
console.log('choose image fail:', chooseImageError);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 确认
|
|
||||||
*/
|
|
||||||
function affirm () {
|
|
||||||
// emits('affirm')
|
|
||||||
if (vdata.imgUrlList.length <= 0) {
|
|
||||||
uni.showToast({
|
|
||||||
title:'请上传报损图片',
|
|
||||||
icon:'none'
|
|
||||||
})
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let params = {
|
|
||||||
coverImg: vdata.imgUrlList,
|
|
||||||
}
|
|
||||||
//商品报损
|
|
||||||
if ( type.value == 'consumable') {
|
|
||||||
params.consId = itemData.value.conIn;
|
|
||||||
params.amount = vdata.stockNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
consumableBreakage(params).then((res) => {
|
|
||||||
show.value = false;
|
|
||||||
vdata.imgUrlList = [];
|
|
||||||
vdata.stockNumber = 1;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
defineExpose({
|
|
||||||
close,
|
|
||||||
open,
|
|
||||||
affirm
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
.mask {
|
|
||||||
background-color: rgba(51, 51, 51, .5);
|
|
||||||
}
|
|
||||||
::v-deep .u-popup__content{
|
|
||||||
// background-color: transparent;
|
|
||||||
|
|
||||||
}
|
|
||||||
.reportDamage{
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
.reportDamage_head{
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
padding: 32rpx;
|
|
||||||
box-sizing: border-box;
|
|
||||||
background: #F4F4F4;
|
|
||||||
.reportDamage_title{
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 32rpx;
|
|
||||||
color: #333333;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.reportDamage_content{
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
background-color: #fff;
|
|
||||||
|
|
||||||
.reportDamage_cell{
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
padding: 32rpx;
|
|
||||||
box-sizing: border-box;
|
|
||||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
|
||||||
font-weight: 500;
|
|
||||||
font-size: 28rpx;
|
|
||||||
color: #333333;
|
|
||||||
border-bottom: 2rpx solid #E5E5E5;
|
|
||||||
.cell_lable{
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
flex-shrink: 0;
|
|
||||||
.thumbnail{
|
|
||||||
width: 112rpx;
|
|
||||||
height: 112rpx;
|
|
||||||
margin-right: 24rpx;
|
|
||||||
}
|
|
||||||
::v-deep .u-image,.u-image__loading,.u-image__image{
|
|
||||||
width: 100%!important;
|
|
||||||
height: 100%!important;
|
|
||||||
}
|
|
||||||
::v-deep uni-image{
|
|
||||||
width: 112rpx!important;
|
|
||||||
height: 112rpx!important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.cell_value{
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: flex-end;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
.text{
|
|
||||||
margin-left: 20rpx;
|
|
||||||
margin-right: 20rpx;
|
|
||||||
}
|
|
||||||
.file{
|
|
||||||
padding: 30rpx;
|
|
||||||
border-radius: 8rpx 8rpx 8rpx 8rpx;
|
|
||||||
border: 2rpx solid #E5E5E5;
|
|
||||||
box-sizing: border-box;
|
|
||||||
margin-left: 20rpx;
|
|
||||||
}
|
|
||||||
.file_img{
|
|
||||||
width: 120rpx;
|
|
||||||
height: 120rpx;
|
|
||||||
margin-left: 20rpx;
|
|
||||||
margin-bottom: 20rpx;
|
|
||||||
position: relative;
|
|
||||||
border-radius: 10rpx;
|
|
||||||
overflow: hidden;
|
|
||||||
.del{
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
background-color: rgba(0, 0, 0, 0.2);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
.file_img_item{
|
|
||||||
width: 120rpx;
|
|
||||||
height: 120rpx;
|
|
||||||
|
|
||||||
}
|
|
||||||
::v-deep .u-image,.u-image__loading,.u-image__image{
|
|
||||||
width: 100%!important;
|
|
||||||
height: 100%!important;
|
|
||||||
}
|
|
||||||
::v-deep uni-image{
|
|
||||||
width: 120rpx!important;
|
|
||||||
height: 120rpx!important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.cell_value.file{
|
|
||||||
// flex-direction: row-reverse;
|
|
||||||
// justify-content: flex-start;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.reportDamage_cell:last-child{
|
|
||||||
border-bottom: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.reportDamage_footer{
|
|
||||||
background-color: #fff;
|
|
||||||
padding: 32rpx;
|
|
||||||
padding-bottom: 68rpx;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
.reportDamage_btn{
|
|
||||||
width: 100%;
|
|
||||||
height: 80rpx;
|
|
||||||
line-height: 80rpx;
|
|
||||||
text-align: center;
|
|
||||||
background: #318AFE;
|
|
||||||
border-radius: 40rpx 40rpx 40rpx 40rpx;
|
|
||||||
font-weight: 500;
|
|
||||||
font-size: 32rpx;
|
|
||||||
color: #FFFFFF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
<view class="">{{item.name}}</view>
|
<view class="">{{item.name}}</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="u-flex-1 u-p-l-4 u-p-r-4 box-size-border">
|
<view class="u-flex-1 u-p-l-4 u-p-r-4 box-size-border">
|
||||||
{{item.typeEnum}}
|
{{item.type}}
|
||||||
</view>
|
</view>
|
||||||
<view class="u-flex-1">
|
<view class="u-flex-1">
|
||||||
¥{{ item.lowPrice }}
|
¥{{ item.lowPrice }}
|
||||||
|
|||||||
@@ -4,13 +4,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import {
|
import { ref, watch } from 'vue';
|
||||||
$uploadFile
|
import { uploadFile } from '@/http/api/index.js'
|
||||||
} from '@/http/yskApi/file.js'
|
|
||||||
import {
|
|
||||||
ref,
|
|
||||||
watch
|
|
||||||
} from 'vue';
|
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
modelValue: {
|
modelValue: {
|
||||||
@@ -49,7 +44,7 @@
|
|||||||
// #ifndef H5
|
// #ifndef H5
|
||||||
file= par
|
file= par
|
||||||
// #endif
|
// #endif
|
||||||
return $uploadFile(file)
|
return uploadFile(file)
|
||||||
}
|
}
|
||||||
|
|
||||||
function afterRead(e) {
|
function afterRead(e) {
|
||||||
@@ -62,7 +57,7 @@
|
|||||||
console.log(res);
|
console.log(res);
|
||||||
images.value.push({
|
images.value.push({
|
||||||
url: e.file[i].url,
|
url: e.file[i].url,
|
||||||
serveUrl: res.data[0]
|
serveUrl: res
|
||||||
})
|
})
|
||||||
}).catch(res => {
|
}).catch(res => {
|
||||||
console.log(res);
|
console.log(res);
|
||||||
@@ -82,7 +77,7 @@
|
|||||||
console.log(res);
|
console.log(res);
|
||||||
images.value.push({
|
images.value.push({
|
||||||
url: e.file.url,
|
url: e.file.url,
|
||||||
serveUrl: res.data[0]
|
serveUrl: res
|
||||||
})
|
})
|
||||||
}).catch(res => {
|
}).catch(res => {
|
||||||
console.log(res);
|
console.log(res);
|
||||||
|
|||||||
@@ -5,9 +5,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import {
|
import { uploadFile } from '@/http/api/index.js'
|
||||||
$uploadFile
|
|
||||||
} from '@/http/yskApi/file.js'
|
|
||||||
import {
|
import {
|
||||||
reactive,
|
reactive,
|
||||||
ref,
|
ref,
|
||||||
@@ -64,10 +63,9 @@
|
|||||||
function FileUploadselect(e) {
|
function FileUploadselect(e) {
|
||||||
for (let i in e.tempFiles) {
|
for (let i in e.tempFiles) {
|
||||||
const file = e.tempFiles[i]
|
const file = e.tempFiles[i]
|
||||||
$uploadFile(file).then(res => {
|
uploadFile(file).then(res => {
|
||||||
console.log(res);
|
|
||||||
imgList.value.push({
|
imgList.value.push({
|
||||||
url: res.data[0],
|
url: res,
|
||||||
path: file.path
|
path: file.path
|
||||||
})
|
})
|
||||||
}).catch(res=>{
|
}).catch(res=>{
|
||||||
@@ -104,7 +102,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function change() {
|
function change() {
|
||||||
console.log(getFileList());
|
|
||||||
emits('change', getFileList())
|
emits('change', getFileList())
|
||||||
}
|
}
|
||||||
defineExpose({
|
defineExpose({
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ const appConfig = {
|
|||||||
// 环境变量相关
|
// 环境变量相关
|
||||||
env: {},
|
env: {},
|
||||||
|
|
||||||
|
// wss: "wss://sockets.sxczgkj.com/wss", //测试环境
|
||||||
|
wss: "wss://czgeatws.sxczgkj.com/wss", //正式环境
|
||||||
// 环境变量常量
|
// 环境变量常量
|
||||||
ENV_ENUM: {
|
ENV_ENUM: {
|
||||||
DEVELOPMENT: 'development', // 本地调试地址
|
DEVELOPMENT: 'development', // 本地调试地址
|
||||||
|
|||||||
9
env/config.js
vendored
9
env/config.js
vendored
@@ -29,15 +29,8 @@ const processEnv = process.env.NODE_ENV
|
|||||||
|
|
||||||
// 改变env环境
|
// 改变env环境
|
||||||
function changeEnv(envMode){
|
function changeEnv(envMode){
|
||||||
|
|
||||||
appConfig.env = allEnvMap[envMode || processEnv]
|
appConfig.env = allEnvMap[envMode || processEnv]
|
||||||
|
appConfig.wss = allEnvMap[envMode || processEnv].JEEPAY_BASE_URL_WSS
|
||||||
// // 动态导包的方式:设置全局env配置项目 : 当参数不存在, 那么获取node环境
|
|
||||||
// import(`./env.${envMode || processEnv}.js`).then(module => {
|
|
||||||
// appConfig.env = module.default
|
|
||||||
// }).catch(() => {
|
|
||||||
// appConfig.env = production //当出现错误, 比如本地没有复制dev文件时, 默认使用生产环境
|
|
||||||
// })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default { changeEnv: changeEnv }
|
export default { changeEnv: changeEnv }
|
||||||
|
|||||||
10
env/env.development.js
vendored
10
env/env.development.js
vendored
@@ -1,6 +1,8 @@
|
|||||||
export default {
|
export default {
|
||||||
'JEEPAY_BASE_URL': 'https://b.rscygroup.com', // 请求URL(生产环境)
|
'JEEPAY_BASE_URL': 'http://192.168.1.31/', // 请求URL(生产环境)
|
||||||
'JEEPAY_BASE_URL_H5': 'https://b.rscygroup.com'
|
'JEEPAY_BASE_URL_H5': 'http://192.168.1.31/',
|
||||||
// 'JEEPAY_BASE_URL': 'http://192.168.1.8:9218' // 请求URL(测试环境)
|
'JEEPAY_BASE_URL_WSS': 'ws://192.168.1.31:2348' ,// sockets
|
||||||
// 'JEEPAY_BASE_URL': 'https://b.qilinshuzi.com' //支付网关URL
|
// 'JEEPAY_BASE_URL': 'https://cashier.sxczgkj.com/', // 请求URL(生产环境)
|
||||||
|
// 'JEEPAY_BASE_URL_H5': 'https://cashier.sxczgkj.com/',
|
||||||
|
// 'JEEPAY_BASE_URL_WSS': 'wss://czgeatws.sxczgkj.com/wss' // sockets
|
||||||
}
|
}
|
||||||
7
env/env.production.js
vendored
7
env/env.production.js
vendored
@@ -1,6 +1,5 @@
|
|||||||
export default {
|
export default {
|
||||||
'JEEPAY_BASE_URL': 'https://b.rscygroup.com', // 请求URL(生产环境)
|
'JEEPAY_BASE_URL': 'https://cashier.sxczgkj.com/', // 请求URL(生产环境)
|
||||||
'JEEPAY_BASE_URL_H5': 'https://b.rscygroup.com'
|
'JEEPAY_BASE_URL_H5': 'https://cashier.sxczgkj.com/',
|
||||||
// 'JEEPAY_BASE_URL': 'http://192.168.1.8:9218' // 请求URL(测试环境)
|
'JEEPAY_BASE_URL_WSS': 'wss://czgeatws.sxczgkj.com/wss' // sockets
|
||||||
// 'JEEPAY_BASE_URL': 'https://b.qilinshuzi.com' //支付网关URL
|
|
||||||
}
|
}
|
||||||
8
ext.json
8
ext.json
@@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"extEnable": true,
|
|
||||||
"extAppid":"wx9b4f8ff05754599f",
|
|
||||||
"directCommit": false,
|
|
||||||
"ext": {
|
|
||||||
"name": "wechat"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
16
http/api/area.js
Normal file
16
http/api/area.js
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import http from '@/http/http.js'
|
||||||
|
const request = http.request
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取区域列表
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function getShopArea(data, urlType = 'account') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/shopArea`,
|
||||||
|
method: "GET",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
136
http/api/buyer.js
Normal file
136
http/api/buyer.js
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
import http from '@/http/http.js'
|
||||||
|
const request = http.request
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取挂账人分页
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function getCreditBuyerPage(data, urlType = 'order') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/order/credit/buyer/page`,
|
||||||
|
method: "GET",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取挂账人详情
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function getCreditBuyerDetail(id, urlType = 'order') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/order/credit/buyer/${id}`,
|
||||||
|
method: "GET",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加挂账人
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function addCreditBuyer(data, urlType = 'order') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/order/credit/buyer`,
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑挂账人
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function editCreditBuyer(data, urlType = 'order') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/order/credit/buyer`,
|
||||||
|
method: "PUT",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除挂账人
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function delCreditBuyer(id, urlType = 'order') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/order/credit/buyer/${id}`,
|
||||||
|
method: "DELETE",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 还款
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function creditBuyerRepayment(data, urlType = 'order') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/order/credit/buyer/repayment`,
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 付款
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function creditBuyerOrderPay(data, urlType = 'order') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/order/credit/buyerOrder/pay`,
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 还款记录
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function creditRePaymentRecord(data, urlType = 'order') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/order/credit/paymentRecord/page`,
|
||||||
|
method: "GET",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 明细分页
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function creditBuyerOrderList(data, urlType = 'order') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/order/credit/buyerOrder/page`,
|
||||||
|
method: "GET",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 明细统计
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function creditBuyerOrderSummary(data, urlType = 'order') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/order/credit/buyerOrder/summary`,
|
||||||
|
method: "GET",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
86
http/api/callTable.js
Normal file
86
http/api/callTable.js
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
import http from '@/http/http.js'
|
||||||
|
const request = http.request
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取叫号队列
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function getCallTableQueue(data, urlType = 'account') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/callTable/queue`,
|
||||||
|
method: "GET",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取叫号记录列表
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function getCallRecord(data, urlType = 'account') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/callTable/callRecord`,
|
||||||
|
method: "GET",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取叫号桌型
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function getCallTable(data, urlType = 'account') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/callTable`,
|
||||||
|
method: "GET",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取叫号号码
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function callTableTakeNumber(data, urlType = 'account') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/callTable/takeNumber`,
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行叫号
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function callTableCall(data, urlType = 'account') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/callTable/call`,
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改叫号状态
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function updateCallTableState(data, urlType = 'account') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/callTable/updateState`,
|
||||||
|
method: "PUT",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
55
http/api/cateGory.js
Normal file
55
http/api/cateGory.js
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import http from '@/http/http.js'
|
||||||
|
const request = http.request
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取分类分页
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function categoryPage(data, urlType = 'product') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/prod/category/page`,
|
||||||
|
method: "GET",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分类添加
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function addCategory(data, urlType = 'product') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/prod/category`,
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分类修改
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function putCategory(data, urlType = 'product') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/prod/category`,
|
||||||
|
method: "PUT",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分类删除
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function delCategory(id, urlType = 'product') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/prod/category/${id}`,
|
||||||
|
method: "DELETE",
|
||||||
|
})
|
||||||
|
}
|
||||||
222
http/api/cons.js
Normal file
222
http/api/cons.js
Normal file
@@ -0,0 +1,222 @@
|
|||||||
|
import http from '@/http/http.js'
|
||||||
|
const request = http.request
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取耗材分页
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function getConsPage(data, urlType = 'product') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/product/cons/page`,
|
||||||
|
method: "GET",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取耗材列表
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function getConsList(data, urlType = 'product') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/product/cons/list`,
|
||||||
|
method: "GET",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 耗材添加
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function addCons(data, urlType = 'product') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/product/cons`,
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 耗材修改
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function editCons(data, urlType = 'product') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/product/cons`,
|
||||||
|
method: "PUT",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取耗材类别
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function getConsGrpupPage(data, urlType = 'product') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/product/consGroup/page`,
|
||||||
|
method: "GET",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取耗材类别
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function getConsGrpupList(data, urlType = 'product') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/product/consGroup/list`,
|
||||||
|
method: "GET",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增耗材类别
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function addConsGrpup(data, urlType = 'product') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/product/consGroup`,
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改耗材类别
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function editConsGrpup(data, urlType = 'product') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/product/consGroup`,
|
||||||
|
method: "PUT",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用耗材类别
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function consGrpupEnable(id, urlType = 'product') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/product/consGroup/enable/${id}`,
|
||||||
|
method: "POST",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 禁用耗材类别
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function consGrpupDisable(id, urlType = 'product') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/product/consGroup/disable/${id}`,
|
||||||
|
method: "POST",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 耗材入库
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function consStockIn(data, urlType = 'product') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/product/stock/in`,
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 耗材出库
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function stockOut(data, urlType = 'product') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/product/stock/out`,
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 库存盘点
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function stockCheck(data, urlType = 'product') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/product/stock/check`,
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 耗材报损
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function stockReportDamage(data, urlType = 'product') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/product/stock/reportDamage`,
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 耗材库存变动记录
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function stockFlow(data, urlType = 'product') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/product/stock/flow`,
|
||||||
|
method: "GET",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 耗材统计
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function consStatistics(data, urlType = 'product') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/product/cons/statistics`,
|
||||||
|
method: "GET",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
58
http/api/coupon.js
Normal file
58
http/api/coupon.js
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
import http from '@/http/http.js'
|
||||||
|
const request = http.request
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 店铺优惠券列表
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function getCouponList(data, urlType = 'account') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/coupon`,
|
||||||
|
method: "GET",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成订单后使用
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function getFindCoupon(data, urlType = 'account') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/coupon/findCoupon`,
|
||||||
|
method: "GET",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 店铺优惠券新增
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function addCoupon(data, urlType = 'account') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/coupon`,
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 店铺优惠券修改
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function updateCoupon(data, urlType = 'account') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/coupon`,
|
||||||
|
method: "PUT",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
30
http/api/freeDing.js
Normal file
30
http/api/freeDing.js
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import http from '@/http/http.js'
|
||||||
|
const request = http.request
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前店铺霸王餐配置信息列表
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function getFreeDing(data, urlType = 'account') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/freeDing`,
|
||||||
|
method: "GET",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改霸王餐配置信息
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function updateFreeDing(data, urlType = 'account') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/freeDing`,
|
||||||
|
method: "PUT",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
66
http/api/handover.js
Normal file
66
http/api/handover.js
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
import http from '@/http/http.js'
|
||||||
|
const request = http.request
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 交班记录-分页
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function getHandoverRecord(data, urlType = 'account') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/handoverRecord/page`,
|
||||||
|
method: "GET",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 交班记录-查看
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function getHandoverRecordView(id, urlType = 'account') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/handoverRecord/${id}`,
|
||||||
|
method: "GET",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 交班记录-导出
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function getHandoverRecordExport(id, urlType = 'account') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/handoverRecord/export/${id}`,
|
||||||
|
method: "GET",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 收银机-交班数据统计
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function getHandoverRecordTotal(data, urlType = 'account') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/handoverRecord/total`,
|
||||||
|
method: "GET",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 收银机-交班/关班
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function getHandoverRecordHandover(data, urlType = 'account') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/handoverRecord/handover`,
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
52
http/api/index.js
Normal file
52
http/api/index.js
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
import http from '@/http/http.js'
|
||||||
|
const request = http.request
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件上传
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function uploadFile(file, data, urlType = 'account') {
|
||||||
|
return http.upload(`${urlType}/admin/common/upload`,data,file)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订阅二维码
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function getShopMsgPushCode(data, urlType = 'account') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/shopMsgPush/code`,
|
||||||
|
method: "GET",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取店铺权限列表
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function getShopPermission(data, urlType = 'account') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/shopPermission`,
|
||||||
|
method: "GET",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据渠道获取版本信息
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function getVersion(data, urlType = 'account') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/version/${data.source}/${data.type}`,
|
||||||
|
method: "GET",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
30
http/api/login.js
Normal file
30
http/api/login.js
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import http from '@/http/http.js'
|
||||||
|
const request = http.request
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取验证码
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function authCaptcha(data, urlType = 'account') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/auth/captcha`,
|
||||||
|
method: "GET",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function login(data, urlType = 'account') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/auth/login`,
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
116
http/api/order.js
Normal file
116
http/api/order.js
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
import http from '@/http/http.js'
|
||||||
|
const request = http.request
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取订单列表
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function getOrderList(data, urlType = 'order') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/order`,
|
||||||
|
method: "GET",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单详情
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function getOrderById(data, urlType = 'order') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/order/getOrderById`,
|
||||||
|
method: "GET",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 历史订单(多次下单使用)
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function getHistoryOrder(data, urlType = 'order') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/order/historyOrder`,
|
||||||
|
method: "GET",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成订单
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function createOrder(data, urlType = 'order') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/order/createOrder`,
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单退款 只传订单id
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function refundOrder(data, urlType = 'order') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/order/refundOrder`,
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单打印
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function printOrder(data, urlType = 'order') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/order/print`,
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清空历史订单
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function cancelOrder(data, urlType = 'order') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/order/cancelOrder`,
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清空某一次历史订单
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function rmPlaceOrder(data, urlType = 'order') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/order/rmPlaceOrder`,
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
100
http/api/pay.js
Normal file
100
http/api/pay.js
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
import http from '@/http/http.js'
|
||||||
|
const request = http.request
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取店铺订单支付URL
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function getOrderPayUrl(data, urlType = 'order') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/pay/shopPayApi/orderPayUrl`,
|
||||||
|
method: "GET",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 扫码支付
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function scanPay(data, urlType = 'order') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/pay/scanPay`,
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 现金支付
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function cashPay(data, urlType = 'order') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/pay/cashPay`,
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 扫码/储值支付
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function microPay(data, urlType = 'order') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/pay/microPay`,
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 挂账支付
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function creditPay(data, urlType = 'order') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/pay/creditPay`,
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会员支付
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function vipPay(data, urlType = 'order') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/pay/vipPay`,
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询订单状态
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function queryOrderStatus(data, urlType = 'order') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/pay/queryOrderStatus`,
|
||||||
|
method: "GET",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
16
http/api/payType.js
Normal file
16
http/api/payType.js
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import http from '@/http/http.js'
|
||||||
|
const request = http.request
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取支付方式列表
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function getPayTypeList(data, urlType = 'account') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/payType`,
|
||||||
|
method: "GET",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
59
http/api/points.js
Normal file
59
http/api/points.js
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
import http from '@/http/http.js'
|
||||||
|
const request = http.request
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取订单可用积分及抵扣金额(支付页面使用)
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function calcUsablePoints(data, urlType = 'account') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/points/memberPoints/calcUsablePoints`,
|
||||||
|
method: "GET",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据积分计算可抵扣金额
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function calcDeductionAmount(data, urlType = 'account') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/points/memberPoints/calcDeductionAmount`,
|
||||||
|
method: "GET",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付完成扣减积分
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function payedDeductPoints(data, urlType = 'account') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/points/memberPoints/payedDeductPoints`,
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消费赠送积分
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function consumeAwardPoints(data, urlType = 'account') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/points/memberPoints/consumeAwardPoints`,
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
72
http/api/printer.js
Normal file
72
http/api/printer.js
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
import http from '@/http/http.js'
|
||||||
|
const request = http.request
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取打印机列表
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function getPrinter(data, urlType = 'account') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/printer`,
|
||||||
|
method: "GET",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取打印机详情
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function getPrinterDetail(data, urlType = 'account') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/printer/detail`,
|
||||||
|
method: "GET",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加打印机
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function addPrinter(data, urlType = 'account') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/printer`,
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改打印机
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function updatePrinter(data, urlType = 'account') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/printer`,
|
||||||
|
method: "PUT",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除打印机
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function delPrinter(data, urlType = 'account') {
|
||||||
|
return request({
|
||||||
|
url: `${urlType}/admin/printer`,
|
||||||
|
method: "DELETE",
|
||||||
|
data: {
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user