客户端小程序

This commit is contained in:
wtq
2026-05-12 15:45:41 +08:00
commit 555427f5da
133 changed files with 27166 additions and 0 deletions

21
.gitignore vendored Normal file
View File

@@ -0,0 +1,21 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
.DS_Store
dist
*.local
# Editor directories and files
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

10
.hbuilderx/launch.json Normal file
View File

@@ -0,0 +1,10 @@
{
"version" : "1.0",
"configurations" : [
{
"customPlaygroundType" : "local",
"playground" : "custom",
"type" : "uni-app:app-android"
}
]
}

20
index.html Normal file
View File

@@ -0,0 +1,20 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<script>
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
CSS.supports('top: constant(a)'))
document.write(
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
</script>
<title></title>
<!--preload-links-->
<!--app-context-->
</head>
<body>
<div id="app"><!--app-html--></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

13729
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

77
package.json Normal file
View File

@@ -0,0 +1,77 @@
{
"name": "uni-preset-vue",
"version": "0.0.0",
"scripts": {
"dev:custom": "uni -p",
"dev:h5": "uni",
"dev:h5:ssr": "uni --ssr",
"dev:mp-alipay": "uni -p mp-alipay",
"dev:mp-baidu": "uni -p mp-baidu",
"dev:mp-jd": "uni -p mp-jd",
"dev:mp-kuaishou": "uni -p mp-kuaishou",
"dev:mp-lark": "uni -p mp-lark",
"dev:mp-qq": "uni -p mp-qq",
"dev:mp-toutiao": "uni -p mp-toutiao",
"dev:mp-harmony": "uni -p mp-harmony",
"dev:mp-weixin": "uni -p mp-weixin",
"dev:mp-xhs": "uni -p mp-xhs",
"dev:quickapp-webview": "uni -p quickapp-webview",
"dev:quickapp-webview-huawei": "uni -p quickapp-webview-huawei",
"dev:quickapp-webview-union": "uni -p quickapp-webview-union",
"build:custom": "uni build -p",
"build:h5": "uni build",
"build:h5:ssr": "uni build --ssr",
"build:mp-alipay": "uni build -p mp-alipay",
"build:mp-baidu": "uni build -p mp-baidu",
"build:mp-jd": "uni build -p mp-jd",
"build:mp-kuaishou": "uni build -p mp-kuaishou",
"build:mp-lark": "uni build -p mp-lark",
"build:mp-qq": "uni build -p mp-qq",
"build:mp-toutiao": "uni build -p mp-toutiao",
"build:mp-harmony": "uni build -p mp-harmony",
"build:mp-weixin": "uni build -p mp-weixin",
"build:mp-xhs": "uni build -p mp-xhs",
"build:quickapp-webview": "uni build -p quickapp-webview",
"build:quickapp-webview-huawei": "uni build -p quickapp-webview-huawei",
"build:quickapp-webview-union": "uni build -p quickapp-webview-union",
"type-check": "vue-tsc --noEmit"
},
"dependencies": {
"@dcloudio/uni-app": "3.0.0-4080420251103001",
"@dcloudio/uni-app-harmony": "3.0.0-4080420251103001",
"@dcloudio/uni-app-plus": "3.0.0-4080420251103001",
"@dcloudio/uni-components": "3.0.0-4080420251103001",
"@dcloudio/uni-h5": "3.0.0-4080420251103001",
"@dcloudio/uni-mp-alipay": "3.0.0-4080420251103001",
"@dcloudio/uni-mp-baidu": "3.0.0-4080420251103001",
"@dcloudio/uni-mp-harmony": "3.0.0-4080420251103001",
"@dcloudio/uni-mp-jd": "3.0.0-4080420251103001",
"@dcloudio/uni-mp-kuaishou": "3.0.0-4080420251103001",
"@dcloudio/uni-mp-lark": "3.0.0-4080420251103001",
"@dcloudio/uni-mp-qq": "3.0.0-4080420251103001",
"@dcloudio/uni-mp-toutiao": "3.0.0-4080420251103001",
"@dcloudio/uni-mp-weixin": "3.0.0-4080420251103001",
"@dcloudio/uni-mp-xhs": "3.0.0-4080420251103001",
"@dcloudio/uni-quickapp-webview": "3.0.0-4080420251103001",
"@types/node": "^25.5.2",
"crypto-js": "^4.2.0",
"js-md5": "^0.8.3",
"jsencrypt": "^3.5.4",
"sass": "^1.99.0",
"vue": "^3.4.21",
"vue-i18n": "^9.1.9",
"vuex": "^4.1.0"
},
"devDependencies": {
"@dcloudio/types": "^3.4.8",
"@dcloudio/uni-automator": "3.0.0-4080420251103001",
"@dcloudio/uni-cli-shared": "3.0.0-4080420251103001",
"@dcloudio/uni-stacktracey": "3.0.0-4080420251103001",
"@dcloudio/vite-plugin-uni": "3.0.0-4080420251103001",
"@vue/runtime-core": "^3.4.21",
"@vue/tsconfig": "^0.1.3",
"typescript": "^4.9.4",
"vite": "5.2.8",
"vue-tsc": "^1.0.24"
}
}

10
shims-uni.d.ts vendored Normal file
View File

@@ -0,0 +1,10 @@
/// <reference types='@dcloudio/types' />
import 'vue'
declare module '@vue/runtime-core' {
type Hooks = App.AppInstance & Page.PageInstance;
interface ComponentCustomOptions extends Hooks {
}
}

27
src/App.vue Normal file
View File

@@ -0,0 +1,27 @@
<script setup lang="ts">
import { onLaunch, onShow, onHide } from "@dcloudio/uni-app";
import { store } from "./store";
onLaunch(async (query) => {
console.log("App Launch,扫码的参数信息",query);
wx.getLaunchOptionsSync((res:any) => {
console.log('获取本次应用启动的参数信息',res)
})
await store.dispatch('serveInfo/wxLogin',{authType:'wx',isJudg:true}) // 查看当前用户是否为新用户
// console.log('查看当前用户是否为新用户',res)
});
onShow(() => {
console.log("App Show");
});
onHide(() => {
console.log("App Hide");
});
</script>
<style>
@import './static/font/iconfont.css';
page {
background-color: #efefef;
}
</style>

25
src/api/config.ts Normal file
View File

@@ -0,0 +1,25 @@
/**
* model: 配置文件
* 作者zhang-shu-wei
* 日期2022年8月10日
* 邮箱2966211270@qq.com
*/
let url_config = '' // 用户登录
if (process.env.NODE_ENV === 'development') {
// 开发环境 配置域名
console.log('~开发环境~')
// url_config = "https://wx.jxc4.com"
// url_config = "http://192.168.0.75:8300"
url_config = "https://jxhorizon.jxc4.com"
} else {
// 生产环境
console.log('~生产环境~')
// url_config = "https://wx.jxc4.com"
// url_config = "http://192.168.0.75:8300"
url_config = "https://jxhorizon.jxc4.com"
}
export default url_config

95
src/api/https/login.ts Normal file
View File

@@ -0,0 +1,95 @@
/*************************************************
*@description: 登录模块
*@return {*}
*@param {}-
*/
import { setLoading } from '@/utils/tools'
import request from '../request'
const login = {
/*************************************************
* 获取微信登录code 已完成
*/
get_jx_code: (isLoading?:boolean): Promise<AnyObject> => new Promise((resolve, reject) => {
console.log('登录中----------',isLoading)
if(!isLoading) {
console.log('你走的if')
setLoading('登录中...')
}else{
console.log('走的时else')
}
uni.login({
provider: 'weixin',
success: (res) => {
resolve(res)
},
fail: (error) => {
reject(error)
}
})
}),
/*************************************************
* 登录 获取用户信息 已完成
* AuthType string `p:"auth_type" v:"required#登录类型不能为空"` // 登录类型,当前支持[pwd本地账号密码sms手机短信wx微信APPali支付宝小程序]
* AuthSecret string `p:"auth_secret"` // pwd:md5Pwd,wx:code,yzn:code
* AuthIDType string `p:"auth_id_type"` // pwd:userID / mobile
* AuthID string `p:"auth_id"` // pwd:AuthIDType值
* CId string `p:"c_id"`
* PromotionSource string `p:"promotion_source"` // 推广来源
*/
applets_login: (params: AnyObject,isLoading?:boolean): Promise<AnyObject> => {
if(!isLoading) setLoading('登录中...')
// return request.api('/v2/auth2/Login', 'POST', params)
return request.api('/jx_horizon/wechat/login', 'POST', params)
},
/*************************************************
* 获取手机登录验证码 已完成
* @Param authType query string true "验证类型[yzm]"
* @Param phone query string true "电话号码"
*/
send_verify_code: async (params: AnyObject): Promise<AnyObject> => {
return await request.api('/jx_horizon/wechat/sendVerifyCode', 'GET', params)
},
/**
* 解密用户信息 已完成
* @Param sessionKey query string true "key"
* @Param encryptedData query string true "加密信息"
* @Param iv query string true "iv"
*
* @Param type query string true "phone/name"
*
*/
decryUser: async (params: AnyObject): Promise<AnyObject> => {
return await request.api('/jx_horizon/wechat/decryUser', 'GET', params)
},
/*************************************************
* 获取推广用户的推广二维码 已完成
* @param vendorOrderID 订单id
* @Param scene query string true "推广人员信息"
* @Param page query string false "跳转页面"
*/
getTiktokOrWxCode: async (json: string | Record<string,string>): Promise<AnyObject> => {
return await request.api('/jx_horizon/wechat/qrCode', 'GET', json)
},
/*************************************************
* 查询用户账户余额 已完成
*/
queryAccountBalance: async (): Promise<AnyObject> => {
return await request.api('/jx_horizon/wechat/balance', 'GET')
}
}
export default login

96
src/api/https/order.ts Normal file
View File

@@ -0,0 +1,96 @@
/*************************************************
*@description: 登录模块
*@return {*}
*@param {}-
*/
import { setLoading } from '@/utils/tools'
import request from '../request'
import { store } from '@/store'
const order = {
/**用户支付 错误
* UserId string `p:"user_id" v:"required #用户ID不能为空"` // 用户ID
* Desc string `p:"desc"` // 商品描述
* OpenId string `p:"open_id" v:"required #openId不能为空"` // openId
* Amount int64 `p:"amount" v:"required #支付金额不能为空"` // 支付金额
*/
wechatPay:async (json:object): Promise<AnyObject> => {
return await request.api('/jx_horizon/wechat/pay', 'POST',json)
},
/**
* 配置用户充值金额 已查到,不知道干嘛的
* @Param typeId query string true "配置类型" income-充值/img-图片单价
*/
refillMoneyConfig: async (param:string): Promise<AnyObject> => {
return await request.api(`/jx_horizon/wechat/config?typeId=${param}`, 'GET')
},
/**
* 用户使用文生图
* VendorModel string `p:"vendor_model" v:"required #选用平台不不能为空"` // doubao(豆包)/lark(云雀)
* Prompt string `p:"prompt" v:"required #描述信息不能为空"`
* Image []string `p:"image"` // 图片信息
* IsTools bool `p:"is_tools"` // 是否联网搜索
*/
useText2Msg:async (json:object): Promise<AnyObject> => {
// 生成图片时间较长,超时时间放大
return await request.api('/jx_horizon/wechat/useText2Msg', 'POST',json,20000000)
},
/**
* 查询用户使用记录
* comModel.PageReq
* Rank string `p:"rank"` // desc/asc
* KeyWord string `p:"keyword"` // 模糊查询
*
* PageReq
* BeginTime string `p:"beginTime"` //开始时间
* EndTime string `p:"endTime"` //结束时间
* PageNum int `p:"pageNum"` //当前页码
* PageSize int `p:"pageSize"` //每页数
* Ctx context.Context `swaggerignore:"true"`
* OrderBy string //排序方式 根据字段排
*/
queryAccountInvoice : async (params: AnyObject): Promise<AnyObject> => {
return await request.api('/jx_horizon/wechat/invoice', 'POST',params)
},
/**
* 充值记录
* @Router /jx_horizon/wechat/payRecord [get]
* @Param startTime query string true "开始时间"
* @Param endTime query string true "结束时间"
* @Param status query int false "支付状态" // 1-待支付/2-已支付/3-支付成功/4-退款/5-失败)
* @Param number query int false "页码"
* @Param size query int false "页数
*/
queryPayRecord : async (params: AnyObject): Promise<AnyObject> => {
return await request.api('/jx_horizon/wechat/payRecord', 'GET',params)
},
/**
* 上传图片到七牛云
*/
get_qiniu_upload_token : async (params: AnyObject): Promise<AnyObject> => {
return await request.api('/jx_horizon/wechat/getQiNiuToken', 'GET',params)
},
/**
* 删除七牛云图片信息
*/
del_qiniu_img : async (imgs:string) => {
return await request.api('/jx_horizon/wechat/deleteQiNiuImg', 'POST',{imgs})
}
// https://jxhorizon.jxc4.com/jx_horizon/wechat/DeleteQiNiuImg deleteQiNiuImg
}
export default order

235
src/api/request.ts Normal file
View File

@@ -0,0 +1,235 @@
/**
*@description: 请求接口配置文件
*@return {*}
*@param
*/
import urlConfig from "./config";
import toast from "@/utils/toast";
import { getStorage } from "@/utils/storage";
import { store } from "@/store";
import { addTask, jx_trembling } from "@/utils/tools";
// import configCms from "@/utils/configCms";
// import log from '@/utils/log'
// 定义请求类型
type methodsType = "GET" | "OPTIONS" | "HEAD" | "POST" | "PUT" | "DELETE" | "TRACE" | "CONNECT" | undefined
// 定义方法中的类型
type FnApiType = {
(url: string, methods: methodsType, data?: AnyObject | string, timeout?: number, baseURL?: string, contentType?: string): Promise<AnyObject>
}
// 定义方法类型
interface Api {
api: FnApiType
}
// 请求类型请求头
let cType = 'application/x-www-form-urlencoded'
// 最大超时时间默认15秒
let timeouts: any = 0
// 清空定时器在800毫秒内数据请求回来了就清空定时器
let timer: any
// 最大请求加载图层时间
let timer1: any
// 保存请求中断
let requestTask: any = null
/*************************************************
* 封装请求方法
* @param {string} [url] 请求地址
* @param {methodsType} [method] 请求方法默认GET
* @param {object} [data] 请求参数默认""
* @param {number} [timeout] 请求超时时间
* @param {string} [baseURL] 请求根路径默认https://wx.jxc4.com
* @param {string} [contentType] 请求头类型默认'application/x-www-form-urlencoded'
* @return {promist} [resolve, reject] promist成功与失败
*/
const request: Api = {
// timeout = 1000 * 20000
api: (url, method = 'GET', data = "", timeout = 1000 * 20, baseURL = urlConfig, contentType = cType) => {
if (requestGuard(url)) {
return new Promise((resolve, reject) => { })
}
timeouts = timeout
// store.commit('storeInfo/jxLoadingFn', false) // 关闭自定义加载图vuex)
clearTimeout(timer)
timer = setTimeout(() => {
// 显示自定义加载图(vuex)
// store.commit('storeInfo/jxLoadingFn', true)
// uni.showNavigationBarLoading()
// 最大时间加载图
tremblingJxLoadingFn()
}, 600)
// if (url == '/v2/cms/GetNewOrderMsg') store.commit('storeInfo/jxLoadingFn', false)
return new Promise((resolve, reject) => {
requestTask = uni.request({
url: baseURL + url,
method: method,
data: data,
timeout: timeout,
header: {
'content-type': contentType,
'Authorization': getStorage('token') ? getStorage('token') : 'jxcs'
},
success: (res) => {
//#region
// let logData = {
// '日志记录时间': Date(),
// '调用接口': url,
// '请求方法': method,
// '请求参数': data,
// '请求超时时间': timeout,
// '请求域名': baseURL,
// '登录类型': getStorage('loginType') ? getStorage('loginType') : '未获取到用户登录类型',
// '用户TOKEN': getStorage('token') ? getStorage('token') : '未获取到用户TOKEN',
// '权限ID': getStorage('userType') ? getStorage('userType') : '未获取到用户权限ID',
// '用户ID': getStorage('userID') ? getStorage('userID') : '未获取到用户ID',
// '用户ID2': getStorage('userID2') ? getStorage('userID2') : '未获取到用户ID2',
// '用户手机号': getStorage('mobile') ? getStorage('mobile') : '未获取到用户手机号',
// '店铺ID': getStorage('storeID') ? getStorage('storeID') : '未获取到店铺ID',
// '店铺名字': getStorage('storeName') ? getStorage('storeName') : '未获取到店铺名字',
// '网络状态码': res.statusCode,
// '服务端数据': res.data
// }
//#endregion
// store.commit('storeInfo/jxLoadingFn', false) // 关闭自定义加载图vuex)
if (res.statusCode >= 200 && res.statusCode < 300) {
// log.info(JSON.stringify(logData))
// 通过token 验证 通过store 验证
if ((res.data as AnyObject).code == '-2') {
// uni.jxAlert({
// title: '提示',
// content: '登录信息已过期',
// confirmText: '重新登录',
// success: () => {
// cleatStorage()
// uni.reLaunch({ url: '/subPages/login/wxLogin/wxLogin' })
// }
// })
return false
} else {
// 验证通过
try {
const jsonData = JSON.parse((res.data as AnyObject).data)
resolve({
code: (res.data as AnyObject).code,
data: jsonData,
desc: (res.data as AnyObject).msg
})
} catch (error) {
resolve(res.data as AnyObject)
}
}
} else if (res.statusCode >= 400 && res.statusCode < 500) {
// log.warn(JSON.stringify(logData))
toast('客户端出错', 2)
reject('客户端出错')
} else if (res.statusCode >= 500) {
// log.warn(JSON.stringify(logData))
toast('服务端出错', 2)
reject('服务端出错')
} else {
// log.warn(JSON.stringify(logData))
toast('网络请求出错', 2)
}
},
fail: (error) => {
if (error.errMsg == 'request:fail abort') {
// 中断请求
return false
}
toast('网络请求超时', 2)
console.log('jx-网络请求超时', error);
reject(`网络请求超时 -- request.ts, ${error}`)
//#region
// let logData = {
// '日志记录时间': Date(),
// '调用接口': url,
// '请求方法': method,
// '请求参数': data,
// '请求超时时间': timeout,
// '请求域名': baseURL,
// '登录类型': getStorage('loginType') ? getStorage('loginType') : '未获取到用户登录类型',
// '用户TOKEN': getStorage('token') ? getStorage('token') : '未获取到用户TOKEN',
// '权限ID': getStorage('userType') ? getStorage('userType') : '未获取到用户权限ID',
// '用户ID': getStorage('userID') ? getStorage('userID') : '未获取到用户ID',
// '用户ID2': getStorage('userID2') ? getStorage('userID2') : '未获取到用户ID2',
// '用户手机号': getStorage('mobile') ? getStorage('mobile') : '未获取到用户手机号',
// '店铺ID': getStorage('storeID') ? getStorage('storeID') : '未获取到店铺ID',
// '店铺名字': getStorage('storeName') ? getStorage('storeName') : '未获取到店铺名字',
// '请求错误信息': error
// }
// log.error(JSON.stringify(logData)) // 普通请求日志
//#endregion
},
complete: () => {
uni.stopPullDownRefresh()
// uni.hideNavigationBarLoading()
// store.commit('storeInfo/jxLoadingFn', false) // 关闭自定义加载图vuex)
uni.hideLoading()
clearTimeout(timer) // 清空定时器
}
})
// 添加请求记录到缓存
if (url == '/v2/cms/GetNewOrderMsg') return
addTask(requestTask)
})
}
}
/*************************************************
* 防抖超时加载图层
*/
const tremblingJxLoadingFn = jx_trembling(() => {
clearTimeout(timer1)
timer1 = setTimeout(() => {
// store.commit('storeInfo/jxLoadingFn', false) // 关闭自定义加载图vuex)
clearTimeout(timer1)
}, timeouts)
}, 500)
/*************************************************
* 登录守卫
*/
function requestGuard(url: string) {
// 获取网络状态
uni.getNetworkType({
success: (res) => {
if (res.networkType == 'none') {
store.commit('serveInfo/setIsNetWorkS', false)
} else {
store.commit('serveInfo/setIsNetWorkS', true)
}
}
})
// // 验证token
// if (!getStorage('token') && !configCms.whiteListUrl.includes(url)) {
// // store.commit('serveInfo/setIsFirestLogin', true)
// return true
// }
// // 验证storeID
// if (!getStorage('storeID') && !configCms.whiteListUrl.includes(url)) {
// rulerStoreID()
// return true
// }
// // 验证网络状态
// if (!store.state.serveInfo.isNetWork) {
// return true
// }
// store.commit('serveInfo/setIsFirestLogin', getStorage('token') ? false : true)
return false
}
// // 门店防抖节流
// const rulerStoreID = jx_trembling(() => {
// uni.navigateTo({ url: "/subPages/switchStore/switchStore" })
// }, 1000)
export default request

View File

@@ -0,0 +1,40 @@
<template>
<view style="width: 100%;height:70rpx;" class="cell" @click="emitClick">
<view>
{{ text }}
</view>
<view style="transform: rotate(180deg);">
<image src="../../static/arrowLeft.png" style="width: 30rpx;height: 30rpx;"></image>
</view>
</view>
</template>
<script lang="ts" setup>
interface PropsType {
text: string
}
const props = defineProps<PropsType>()
const emit = defineEmits<{
(e: 'jumpTo'): void
}>()
function emitClick(){
emit('jumpTo')
}
</script>
<style lang="scss" scoped>
.cell{
display: flex;
justify-content: space-between;
border-bottom: 1rpx solid #c2c1c1; // dashed
height: 70rpx;
align-items: center;
font-size: 30rpx;
padding: 10rpx 20rpx;
box-sizing: border-box;
}
</style>

View File

@@ -0,0 +1,103 @@
<template>
<view class="drawer"
:class="{
'animation':props.isShowDrawer,
'anumationBack':!isInit && !props.isShowDrawer
}">
<view class="drawer_mask" @click="closeDrawer"></view>
<view class="drawer_content">
<slot></slot>
</view>
</view>
</template>
<script lang="ts" setup >
import { watch,ref } from 'vue';
interface PropsType {
isShowDrawer: boolean
}
const isInit = ref(true)
const props = defineProps<PropsType>()
watch(() => props.isShowDrawer,
() => {
isInit.value = false
})
const emit = defineEmits<{
(e: 'closeDrawer', data: boolean): void
}>()
function closeDrawer(){
// console.log('关闭dialog')
emit('closeDrawer',false)
}
</script>
<style lang="scss" scoped>
.status_bar {
height: var(--status-bar-height);
width: 100%;
}
.drawer{
position: fixed;
top: 0;
left: 0;
z-index: 999;
width: 100%;
height: 100%;
transform: translateX(-100%); /* 元素从左侧100%的位置开始 */
.drawer_mask{
width: 100%;
height: 100%;
background-color: rgba($color: #000000, $alpha: 0.1);
}
.drawer_content{
position: absolute;
top: 0;
left: 0;
width: 70%;
height: 100%;
background-color: #fff;
}
}
.animation{
animation: example 1s ease-out forwards; /* 应用动画持续时间为2秒缓动函数为ease-outforwards保持动画结束时的状态 */
}
.anumationBack{
animation: exampleBack 1s ease-out forwards; /* 应用动画持续时间为2秒缓动函数为ease-outforwards保持动画结束时的状态 */
}
@keyframes example {
from {
// background-color: red;
transform: translateX(-100%); /* 元素从左侧100%的位置开始 */
opacity: 0; /* 初始透明度为0 */
}
to {
transform: translateX(0); /* 元素移动到原始位置 */
opacity: 1; /* 最终透明度为1 */
}
}
@keyframes exampleBack {
from {
// background-color: red;
transform: translateX(0); /* 元素移动到原始位置 */
opacity: 1; /* 最终透明度为1 */
}
to {
transform: translateX(-100%); /* 元素从左侧100%的位置开始 */
opacity: 0; /* 初始透明度为0 */
}
}
</style>

View File

@@ -0,0 +1,57 @@
<template>
<view class="empty-root">
<image
class="img"
:src="src"
mode="scaleToFill"
/>
<text class="text">{{ title }}</text>
<slot></slot>
</view>
</template>
<script lang="ts" setup>
interface EmptyType {
icon?: string
size?: number
title?: string
color?: string
src?: string
}
withDefaults(defineProps<EmptyType>(), {
icon: 'kongzhuangtai',
size: 150,
title: '暂无数据...',
color: '#7fc86c',
// src: 'empty.png',
// src: '/static/image/global/empty.png',
src: 'https://image.jxc4.com/image/d0adecd3671e8a1c2294783b22a46426.png',
})
</script>
<style lang="scss" scoped>
.empty-root {
position: absolute;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 999999;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
.img {
width: 400rpx;
height: 400rpx;
}
.text {
color: v-bind(color);
text-decoration: none;
margin-top: -70rpx;
text-align: center;
}
}
</style>

View File

@@ -0,0 +1,29 @@
<template>
<text
class="iconfont"
:class="'icon-' + icon"
:style="{ 'font-size': size + 'rpx', color: color }"
></text>
</template>
<script lang="ts" setup>
/**
* @icon: iconfonti 图标
* @size: 图标大小
* @color图标颜色
*/
interface IconType {
icon: string;
size?: number;
color?: string;
}
withDefaults(defineProps<IconType>(), {
size: 32,
color: "#000",
});
</script>
<style lang="scss" scoped>
</style>

View File

@@ -0,0 +1,27 @@
<template>
<view class="jx-input">
<view class="left">
<slot name="left"></slot>
</view>
<slot name="middle"></slot>
<view class="left">
<slot name="right"></slot>
</view>
</view>
</template>
<script lang="ts" setup>
</script>
<style lang="scss" scoped>
.jx-input {
display: flex;
align-items: center;
width: 100%;
.left,
.right {
padding: 10rpx 20rpx 10rpx 20rpx;
}
}
</style>

View File

@@ -0,0 +1,72 @@
<template>
<view class="jx-load-more">
<view v-show="isLoad" class="isLoad">
<text class="load-icon"></text>
<text class="load-text">{{ loadText }}</text>
</view>
<text v-show="!isLoad">
<text class="text"></text>
&nbsp;{{ tip }}&nbsp;
<text class="text"></text>
</text>
</view>
</template>
<script lang="ts" setup >
interface jxLoadMoreType {
color?: string
loadText?: string
tip?: string
size?: string
isLoad: boolean
marginTop?: string
}
withDefaults(defineProps<jxLoadMoreType>(), {
color: '#aaa',
loadText: '正在加载中...',
tip: '没有更多了',
size: '22rpx',
marginTop: '0rpx',
})
</script>
<style lang="scss" scoped>
.jx-load-more {
display: flex;
justify-content: center;
align-items: center;
color: v-bind(color);
font-size: v-bind(size);
padding-bottom: 20rpx;
margin-top: v-bind(marginTop);
.load-icon {
display: inline-block;
width: 30rpx;
height: 30rpx;
border-width: 4rpx;
border-style: solid;
border-radius: 50%;
margin-right: 10rpx;
border-right-color: rgba($color: $jx-primary, $alpha: 0.2);
border-top-color: rgba($color: $jx-primary, $alpha: 0.2);
border-bottom-color: rgba($color: $jx-primary, $alpha: 0.2);
border-left-color: $jx-primary;
border-radius: 50%;
animation: identifier 0.7s linear infinite;
}
@keyframes identifier {
0% {
transform: rotate(0);
}
100% {
transform: rotate(360deg);
}
}
.text {
color: rgb(220, 220, 220);
}
}
</style>

View File

@@ -0,0 +1,612 @@
// import merchant from "@/api/https/merchant";
import login from "@/api/https/login";
import { store } from "@/store";
import { setStorage} from "@/utils/storage";
import toast from "@/utils/toast";
// import toast from "@/utils/toast";
// import { timeFormatD } from "@/utils/tools";
// import { utilsMd5 } from '@/utils/md5.js'
// import Bluetooth from '@/utils/bluetoothPrinter/bluetooth'
// import { store as newStore } from '@/store'
// import util from '@/utils/bluetoothPrinter/util'
// import login from "@/api/https/login";
// import order from "@/api/https/order";
// import { computed } from "vue";
// import { emojiAnanlyze } from '@/utils/emoji'
/**
* 今日营业数据
* @param data 事实订单数据
*/
function useGlobalFunc() {
// const bluetooth: any = getStorage('deviceName') ? new Bluetooth() : null
// /*************************************************
// * 获取实时订单数据
// * @time 2023年2月1日 11点17分
// * @param {data} 请求data数据
// * @return {res} code:响应状态 data:响应数据 desc:错误信息
// */
// async function globGetToDay(data: AnyObject) {
// let orderNumber = await merchant.get_store_order_sale_info(data);
// if (orderNumber.code == 0) {
// return orderNumber.data
// } else {
// toast("实时订单数据异常", 2);
// }
// }
// /*************************************************
// * 退出登录
// */
// function logOutFn() {
// cleatStorage('token')
// cleatStorage('userID')
// cleatStorage('userType')
// cleatStorage('storeID')
// cleatStorage('storeName')
// cleatStorage('userID2')
// cleatStorage('mobile')
// cleatStorage('isAgreement')
// cleatStorage('loginType')
// store.commit('serveInfo/setIsFirestLogin', true)
// }
/*************************************************
* 查看详情图片
* @time 2023-02-01 11:18:09
* @param {}-
* @return {*}
*/
async function previewImage(url: string | Array<string>,index?:number) {
new Promise((resolve, reject) => {
uni.previewImage({
current: index ? index : typeof url === 'string' ? url : url[0],
urls: Array.isArray(url) ? url : [url],
longPressActions:{
itemList:['保存图片'],
success(res){
uni.showModal({
title: '相册权限使用说明',
content: '便于您保存图片与运营进行交流等场景中写入相册文件内容',
complete: (result) => {
if (result.confirm) {
uni.saveImageToPhotosAlbum({
filePath: Array.isArray(url) ? url[res.index] : url,
complete(r) {
if (r.errMsg === 'saveImageToPhotosAlbum:ok') {
toast('保存成功')
} else {
toast('保存失败')
}
}
})
}
}
})
}
},
success: (res: any) => {
resolve(res)
},
fail: (err: any) => {
toast(err)
reject(err)
}
})
})
uni.vibrateShort({})
}
/*************************************************
* 存储用户信息
* @param {object} [data] 用户信息数据
*/
let serveInfoTimer: any = null
async function setUserInfo(data: AnyObject,userInfo:AnyObject) {
// setStorage("token", data.token);
// setStorage('userInfo',data.user)
// console.log('1111111111',JSON.parse(JSON.parse(data.user.extraInfo)).session_key)
// let userInfoDecry = await login.decryUser({
// sessionKey:JSON.parse(JSON.parse(data.user.extraInfo)).session_key,
// iv:userInfo.iv,
// encryptedData:userInfo.encryptedData,
// type:'name'
// })
// console.log('用户匿名信息,,,解密后的消息体',userInfoDecry)
// uni.navigateTo({ url: '/pages/index/index' })
// setStorage("userID", data.userID);
// setStorage("userID2", data.userID2);
// setStorage("mobile", data.mobile);
// setStorage("loginType", data.authBindInfo.type);
// jx_default_storage_plugin()
// // 防止ios app 出现认证信息还没有缓存就已经跳转请求了
// if (getStorage("storeID")) {
// // await store.dispatch('storeInfo/getOneStore', getStorage("storeID"))
// uni.switchTab({ url: '/pages/index/index' })
// } else {
// // let storeRes = await login.get_my_store_list({ version: '1.3.5' })
// // let dataList = storeRes.data || []
// // if (dataList.length == 0) {
// // // return uni.jxAlert({
// // // title: '提示',
// // // content: '该账号未绑定门店请联系运营绑定加盟联系电话18048531223'
// // // })
// // }
// // if (dataList.length == 1) {
// // let data = dataList[0]
// // setStorage("storeID", data.id);
// // setStorage("storeName", data.name)
// // uni.switchTab({ url: '/pages/merchant/index' })
// // return
// // }
// // clearTimeout(serveInfoTimer)
// // serveInfoTimer = setTimeout(() => {
// // uni.navigateTo({ url: "/subPages/switchStore/switchStore" })
// // }, 0)
// }
}
// /*************************************************
// * app 微信登录
// * @bangding {Function} 绑定
// * @seccess {Function} 登录成功
// */
// /*************************************************
// * 全局判断是否有新信息有信息就在tabar显示
// */
// async function newMessage() {
// let data = {
// storeIDs: JSON.stringify([+getStorage('storeID')]),
// fromReadCount: 0,
// toReadCount: 0,
// offset: 0,
// pageSize: -1,
// fromTime:
// timeFormatD(+new Date() - 7 * 24 * 60 * 60 * 1000) + ' 00:00:00',
// toTime: timeFormatD(+new Date()) + ' 23:59:59',
// }
// let msgRes = await merchant.Get_store_message_statuses(data)
// if (msgRes.code == 0) {
// let num = msgRes.data.totalCount
// // 没有信息,移除
// if (num == 0) {
// store.commit('storeInfo/setIsNewMessage', false)
// uni.removeTabBarBadge({ index: 3 })
// } else {
// store.commit('storeInfo/setIsNewMessage', true)
// // 有信息显示
// uni.setTabBarBadge({
// index: 3,
// text: num > 100 ? '99+' : '' + num,
// })
// }
// }
// }
// /**************************************************************
// * 复制订单信息内容
// * @param {String} data 需要复制的内容
// * @param {String} [text] 复制成功提示内容(非必填)
// * @param {string} [errorT] 复制失败提示内容(非必填)
// */
// function copyInfo(data: string, text = '复制成功', errorT = '复制失败') {
// uni.setClipboardData({
// data: data,
// success() {
// toast(text)
// },
// fail() {
// toast(errorT)
// }
// })
// uni.vibrateShort({})
// }
// /************************************************************
// * 拨打电话
// * @param {string} phoneNumber 将要拨号的手机号
// * @param {String} [text] 拨号成功提示内容(非必填)
// * @param {string} [errorT] 拨号失败提示内容(非必填)
// */
// function phoneCall(phoneNumber: string, text = '拨号完成', errorT = '取消拨号') {
// uni.makePhoneCall({
// phoneNumber: phoneNumber,
// success() {
// console.log(text)
// },
// fail() {
// toast(errorT)
// }
// })
// uni.vibrateShort({})
// }
// const businessKey = 'XKJPOIHJ233adf01KJIXlIeQDSDKFJAD' // 商户秘钥
// /*************************************************
// * 统一微信支付功能
// * 说明app暂未申请支付功能仅支持小程序支付
// * @param {number} [chargeMoney] 支付金额
// * @param {number | string} [storeID] 门店ID
// * @param {Function} [fn] 支付回调,成功或失败都会调用
// * @param {string} [vendorOrderID] 订单id
// *
// */
// async function globalPlayMoney(orderPayType: number, chargeMoney: number, StoreID: number | string, code: string, fn: Function, vendorOrderID = '') {
// let tempMoney = +chargeMoney * 100
// // 创建订单
// let data = {
// orderType: orderPayType,
// storeID: StoreID,
// price: tempMoney,
// vendorOrderID: vendorOrderID
// }
// let orderNum = await order.create_store_acct_order(data)
// // 支付订单
// let data1 = {
// subAppID: 'wx08a5c2a8581414ff',
// payType: orderPayType,
// vendorOrderID: orderNum.data,
// vendorPayType: 'W06',
// code: `weixinappcs_${code}`
// }
// let orderInfo = await order.pay4_user(data1)
// let newOrderInfo = orderInfo.data
// // 调用微信支付
// handleCreatePay(newOrderInfo.vendorOrderID, newOrderInfo.prepayID, JSON.parse(newOrderInfo.codeURL), fn)
// }
// // 微信支付
// function handleCreatePay(orderInfo: any, prepayID: number | string, codeURL: AnyObject, fn: Function) {
// let token = ''
// token = getStorage('token')
// let timeStamp: string
// let randomNum: number
// let strPay: string
// let nonceStr: string
// let packageA: string
// let paySign: string
// let signType = 'MD5'
// if (codeURL) {
// // 通联收银 payType 2
// timeStamp = codeURL.timeStamp
// nonceStr = codeURL.nonceStr
// packageA = codeURL.package
// signType = codeURL.signType
// paySign = codeURL.paySign
// } else {
// timeStamp = Math.round(new Date().getTime() / 1000).toString()
// randomNum = (Math.random() * 5) + 1
// strPay = timeStamp + token + randomNum
// nonceStr = utilsMd5.hex_md5(strPay)
// packageA = `prepay_id=${prepayID}`
// paySign = utilsMd5.hex_md5(`appId=wx4b5930c13f8b1170&nonceStr=${nonceStr}&package=${packageA}&signType=MD5&timeStamp=${timeStamp}&key=${businessKey}`)
// }
// uni.requestPayment({
// provider: 'wxpay',
// orderInfo: orderInfo,
// timeStamp: timeStamp,
// nonceStr: nonceStr,
// package: packageA,
// signType: signType,
// paySign: paySign,
// success: () => {
// toast('充值成功', 1)
// },
// fail: () => {
// toast('取消充值', 2)
// },
// complete: () => {
// fn && fn()
// }
// })
// }
// /*************************************************
// * 打开微信小程序
// * @param {string} [url] 跳转地址
// * @param {string} [id] 小程序原始ID
// */
// /*************************************************
// * 判断门店是否在营业中
// * @param {any} [newTime] 需要判断的时间
// */
// function isTrades(newTime: any): boolean {
// let storeInfo = newStore.state.storeInfo.allStoreInfo
// let businessTime: Array<any> = []
// businessTime[0] = storeInfo.openTime1
// businessTime[1] = storeInfo.closeTime1
// businessTime[2] = storeInfo.openTime2
// businessTime[3] = storeInfo.closeTime2
// // 获取当前时间进行比较
// let honer = newTime.getHours()
// let minutes = newTime.getMinutes() < 10 ? '0' + newTime.getMinutes() : newTime.getMinutes()
// let time: number = +(String(honer) + String(minutes))
// // true-未休息 false-休息中
// return (time >= businessTime[0] && time <= businessTime[1]) || (time >= businessTime[2] && time <= businessTime[3])
// }
// /*************************************************
// * 格式化今日订单数据
// */
// function wholeCalcPrice(calcData: AnyObject) {
// if (calcData.isPointStore) {
// if (calcData.isNotQuote || calcData.isZero) {
// return calcData.actualPayPrice
// ? (calcData.actualPayPrice / 100).toFixed(2)
// : 0;
// } else {
// if (calcData.isUpperfif) {
// return calcData.earningPrice
// ? (calcData.earningPrice / 100).toFixed(2)
// : 0;
// } else {
// return "请按平台查看";
// }
// }
// } else {
// if (calcData.isUpperfif || calcData.isZero) {
// return calcData.earningPrice
// ? (calcData.earningPrice / 100).toFixed(2)
// : 0;
// } else {
// return "请按平台查看";
// }
// }
// }
// /*************************************************
// * 格式化今日订单数据
// */
// function singleCalcPrice(calcData: AnyObject) {
// if (calcData.vendorPayPercentage != 0) {
// return calcData.vendorPayPercentage < 50 ? (calcData.actualPayPrice / 100).toFixed(2) : (calcData.earningPrice / 100).toFixed(2)
// } else {
// return calcData.isPointStore ? (calcData.actualPayPrice / 100).toFixed(2) : (calcData.earningPrice / 100).toFixed(2)
// }
// }
// /*************************************************
// * 查询打印机状态并连接
// */
// const playVoid = uni.createInnerAudioContext()
// function setPrinterStatus() {
// // 获取打印机信息
// let data: any = getStorage('commitBTDevCharact')
// setInterval(() => {
// let isPlay = store.state.storeInfo.isConnectPrinter
// // 判断打印机是否在线
// util.notifyBLEState(data.deviceId, data.serviceId, data.uuid)
// .then(async (res) => {
// if (res != 12) {
// console.log('连接失败')
// await bluetooth.reconnect()
// if (!isPlay) return
// playVoidFn()
// store.commit('storeInfo/setIsConnectPrinter', false)
// } else {
// console.log('连接正常')
// store.commit('storeInfo/setIsConnectPrinter', true)
// }
// }).catch(async () => {
// console.log('连接失败')
// await bluetooth.reconnect()
// if (!isPlay) return
// playVoidFn()
// store.commit('storeInfo/setIsConnectPrinter', false)
// })
// }, 1000 * 10)
// }
// // 播放音频
// function playVoidFn() {
// playVoid.src = 'https://image.jxc4.com/image/ee1174253ee2919a23d7ea5277b2141b.jpg'
// playVoid.stop()
// playVoid.play()
// }
/*************************************************
* 提示用户未勾选
*/
let time: any = null
function isUserAgreementFn() {
store.commit('serveInfo/setIsAgreementIf', false)
clearTimeout(time)
time = setTimeout(() => {
uni.vibrateShort({})
store.commit('serveInfo/setIsAgreementIf', true)
}, 200)
}
// // ******************** 判断是否有淘鲜达 *****************************
// //#region
// const storeMaps = computed(() => {
// return store.state.storeInfo.allStoreInfo
// })
// // function isTxd() {
// // let state = false
// // storeMaps.value.StoreMaps.forEach((item: AnyObject) => {
// // if (item.vendorID == 16) {
// // state = true
// // }
// // })
// // return state
// // }
// //#endregion
// /**
// * 查询美团/饿百的IM状态
// */
// const getMtStoreIMStatus = async () => {
// let mtStore = isExistPlatformID(1)
// let ebStore = isExistPlatformID(3)
// let data = []
// if (mtStore && mtStore.length > 0) {
// data.push({
// vendorID: 1,
// vendorOrgCode: mtStore[0].vendorOrgCode + '',
// vendorStoreID: mtStore[0].vendorStoreID + ''
// })
// }
// if (ebStore && ebStore.length > 0) data.push({
// vendorID: 3,
// vendorOrgCode: ebStore[0].vendorOrgCode + '',
// vendorStoreID: ebStore[0].vendorStoreID + ''
// })
// if (data.length === 0) return
// let res = await merchant.get_mt_store_im_status({ data: data })
// let arr: any = []
// if (res.code === '0') {
// res.data.forEach((item: AnyObject) => {
// if (item.errMsg && item.errMsg) arr.push({
// ...item,
// vendorID: +item.errMsg.substring(0, 1)
// })
// else arr.push({ ...item })
// })
// }
// store.commit('storeInfo/setImOnlineStatus', arr)
// }
// /**
// * 是否存在某个平台
// */
// function isExistPlatformID(platformID: number) {
// return storeMaps.value.StoreMaps && storeMaps.value.StoreMaps.length > 0 ? storeMaps.value.StoreMaps.filter((item: AnyObject) => item.vendorID == platformID) : []
// }
// /**
// * 是否含有聊天表情
// */
// function isCloudEmoji(emoji: string) {
// let emojiArr = emoji.match(/\[(.+?)\]/g)
// return emojiArr && emojiArr.length > 0 ? true : false
// }
// interface emojiType {
// type: string,
// text: string,
// emoji: string
// }
// /**
// * 解析emoji数据
// */
// function analyEmoji(emoji: string) {
// if (!isCloudEmoji(emoji)) {
// return [
// {
// type: 'text',
// text: emoji,
// emoji: ''
// }
// ]
// }
// // emoji = '[大哭][大哭][大哭][大哭][心碎][心碎][心碎]11111顶顶顶顶呃零零零零[流泪]iiiihdhggydgjfg kevbuygbhjbnb'
// let arr: emojiType[] = []
// let emojiArr: string[] = emoji.match(/\[(.+?)\]/g) || []
// if (emojiArr && emojiArr.length > 0) {
// emojiArr.map((item, index) => {
// let emojiImg = emojiAnanlyze(item) // 返回的emoji解析数据
// if (emojiImg === item) emojiImg = 'unknown:' + item // 未知表情
// let indexOf = emoji.indexOf(item) // item在聊天emoji中的位置
// if (indexOf === 0) {
// // emoji
// arr.push({
// type: 'emoji',
// text: '',
// emoji: emojiImg
// })
// // emoji之后的文字
// let afterSymbol = emoji.substring(indexOf + item.length, indexOf + item.length + 1)
// if (afterSymbol !== '[' && afterSymbol.length > 0 && index === emojiArr.length - 1) {
// arr.push({
// type: 'text',
// text: emoji.substring(indexOf + item.length),
// emoji: ''
// })
// }
// } else {
// // emoji之前的文字
// arr.push({
// type: 'text',
// text: emoji.substring(0, indexOf),
// emoji: ''
// })
// // emoji
// arr.push({
// type: 'emoji',
// text: '',
// emoji: emojiImg
// })
// // emoji之后的文字
// let afterSymbol = emoji.substring(indexOf + item.length, indexOf + item.length + 1)
// if (afterSymbol !== '[' && afterSymbol.length > 0 && index === emojiArr.length - 1) {
// arr.push({
// type: 'text',
// text: emoji.substring(indexOf + item.length),
// emoji: ''
// })
// }
// }
// emoji = emoji.replace(emoji.substring(0, indexOf + item.length), '') // 清除已处理完的数据
// })
// }
// return arr || []
// }
return {
// globGetToDay, //获取实时订单数据
previewImage, // 查看详情图
setUserInfo, // 储存用户信息
// newMessage, // 展示新信息
// copyInfo, // 复制信息
// phoneCall, // 拨打电话
// globalPlayMoney, // 统一支付
// isTrades, // 判断是否是在营业时间
// wholeCalcPrice, // 格式化今日订单数据
// singleCalcPrice, // 格式化今日订单数据
// setPrinterStatus, // 查询打印机状态并连接
// logOutFn, // 退出登录
isUserAgreementFn, // 提示用户未勾选
// // isTxd, // 判断是否有淘鲜达
// getMtStoreIMStatus, // 获取美团IM单聊状态
// analyEmoji, // 解析emoji表情
// isCloudEmoji // 是否含有emoji
}
}
export default useGlobalFunc

8
src/env.d.ts vendored Normal file
View File

@@ -0,0 +1,8 @@
/// <reference types="vite/client" />
declare module '*.vue' {
import { DefineComponent } from 'vue'
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
const component: DefineComponent<{}, {}, any>
export default component
}

8
src/main.ts Normal file
View File

@@ -0,0 +1,8 @@
import { createSSRApp } from "vue";
import App from "./App.vue";
export function createApp() {
const app = createSSRApp(App);
return {
app,
};
}

94
src/manifest.json Normal file
View File

@@ -0,0 +1,94 @@
{
"name" : "惊喜视界",
"appid" : "__UNI__9DBDF61",
"description" : "",
"versionName" : "1.0.0",
"versionCode" : "100",
"transformPx" : false,
/* 5+App */
"app-plus" : {
"usingComponents" : true,
"nvueStyleCompiler" : "uni-app",
"compilerVersion" : 3,
"splashscreen" : {
"alwaysShowBeforeRender" : true,
"waiting" : true,
"autoclose" : true,
"delay" : 0
},
/* */
"modules" : {},
/* */
"distribute" : {
/* android */
"android" : {
"permissions" : []
},
/* ios */
"ios" : {
"dSYMs" : false
},
/* SDK */
"sdkConfigs" : {},
"icons" : {
"android" : {
"hdpi" : "unpackage/res/icons/72x72.png",
"xhdpi" : "unpackage/res/icons/96x96.png",
"xxhdpi" : "unpackage/res/icons/144x144.png",
"xxxhdpi" : "unpackage/res/icons/192x192.png"
},
"ios" : {
"appstore" : "unpackage/res/icons/1024x1024.png",
"ipad" : {
"app" : "unpackage/res/icons/76x76.png",
"app@2x" : "unpackage/res/icons/152x152.png",
"notification" : "unpackage/res/icons/20x20.png",
"notification@2x" : "unpackage/res/icons/40x40.png",
"proapp@2x" : "unpackage/res/icons/167x167.png",
"settings" : "unpackage/res/icons/29x29.png",
"settings@2x" : "unpackage/res/icons/58x58.png",
"spotlight" : "unpackage/res/icons/40x40.png",
"spotlight@2x" : "unpackage/res/icons/80x80.png"
},
"iphone" : {
"app@2x" : "unpackage/res/icons/120x120.png",
"app@3x" : "unpackage/res/icons/180x180.png",
"notification@2x" : "unpackage/res/icons/40x40.png",
"notification@3x" : "unpackage/res/icons/60x60.png",
"settings@2x" : "unpackage/res/icons/58x58.png",
"settings@3x" : "unpackage/res/icons/87x87.png",
"spotlight@2x" : "unpackage/res/icons/80x80.png",
"spotlight@3x" : "unpackage/res/icons/120x120.png"
}
}
}
}
},
/* */
"quickapp" : {},
/* */
"mp-weixin" : {
"appid" : "wxcec60b03d814aba7",
"setting" : {
"urlCheck" : false,
"postcss" : true,
"minified" : true
},
"usingComponents" : true,
"lazyCodeLoading": "requiredComponents",
"permission" : {}
},
"mp-alipay" : {
"usingComponents" : true
},
"mp-baidu" : {
"usingComponents" : true
},
"mp-toutiao" : {
"usingComponents" : true
},
"uniStatistics" : {
"enable" : false
},
"vueVersion" : "3"
}

90
src/pages.json Normal file
View File

@@ -0,0 +1,90 @@
{
"lazyCodeLoading": "requiredComponents",
"easycom": {
"autoscan": true,
"custom": {
"^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue"
}
},
"pages": [ //pages数组中第一项表示应用启动页参考https://uniapp.dcloud.io/collocation/pages
{
"path": "pages/index/index",
"style": {
// "navigationBarTitleText": "惊喜视界"
"navigationStyle":"custom",
"disableScroll":true
}
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "惊喜视界",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8"
},
"subPackages":[
{
"root":"subPages/login",
"pages":[
{
"path":"index",
"style": {
"navigationBarTitleText": "登录"
}
}
]
},
{
"root": "subPages/agreement",
"pages": [
{
"path": "privacy",
"style": {
"navigationBarTitleText": "惊喜视界隐私协议"
}
},
{
"path": "user",
"style": {
"navigationBarTitleText": "惊喜视界用户协议"
}
},
{
"path": "about",
"style": {
"navigationBarTitleText": "关于京西"
}
}
]
},
{
"root":"subPages/mine",
"pages":[
{
"path":"order",
"style": {
"navigationBarTitleText": "我的订单"
}
},
{
"path":"historyTopic",
"style": {
"navigationBarTitleText": "历史话题"
}
},
{
"path":"refill",
"style": {
"navigationBarTitleText": "充值"
}
},
{
"path":"promote",
"style": {
"navigationBarTitleText": "我的推广码"
}
}
]
}
]
}

753
src/pages/index/index.vue Normal file
View File

@@ -0,0 +1,753 @@
<template>
<view class="status_bar"></view>
<view class="box" >
<view class="navi">
<view class="navi_but" @click.stop="showDrawer">
<image src="../../static/moreThan.png" class="img"></image>
</view>
<view class="text">惊喜视界</view>
</view>
<view class="contentCell">
<!-- <view class="content_cell_sys">
<image src="../../static/noLogin.png" style="width: 60rpx;height: 60rpx;" />
<view class="cell_text">好久不见甚是想念</view>
</view>
<view class="content_cell_user">
<image src="../../static/noLogin.png" style="width: 60rpx;height: 60rpx;" />
<view class="cell_text">白菜妖精</view>
</view>
</view> -->
<view v-for="(item,index) in historyList" :key="index" class="cell"
:class="{
'cell_sys' : item.usertType === 'sys',
'cell_user': item.usertType === 'user'
}">
<view>
<view class="avatar" :style="{
justifyContent:item.usertType === 'sys' ? 'flex-start' : 'flex-end'
}">
<view v-if="item.usertType === 'user'" class="nickname" >
<text>{{ item.nickName }}</text>
</view>
<!--
惊喜视界头像: https://image.jxc4.com/image/e1a731b7a1bff6e0afd0cd987f421daf.png
-->
<image :src="item.usertType === 'sys' ? 'https://image.jxc4.com/image/e1a731b7a1bff6e0afd0cd987f421daf.png' : '../../static/noLogin.png'" class="img" />
<view v-if="item.usertType === 'sys'" class="nickname">
<text >{{ item.nickName }}</text>
</view>
</view>
<view class="content">
<text>{{ item.usertType === 'sys' && index !== 0 ? `根据【${item.content}】生成的图片信息如下:`: item.content }}</text>
</view>
<view v-if=" item.usertType === 'sys' && index !==0 " class="backImg">
<!-- <view > -->
<image :src="item.vendorDescription" alt="图片加载中..." class="img" @tap="previewImg(item.vendorDescription)" @error="handleImgError(index)"/>
<!-- </view> -->
</view>
</view>
</view>
</view>
<view class="productImgTip" v-show="isLoadingImg">
<text class="txt" style="--i: 1"></text>
<text class="txt" style="--i: 2"></text>
<text class="txt" style="--i: 3"></text>
<text class="txt" style="--i: 4"></text>
<text class="txt" style="--i: 5"></text>
<text class="txt" style="--i: 6">,</text>
<text class="txt" style="--i: 7"></text>
<text class="txt" style="--i: 8"></text>
<text class="txt" style="--i: 9"></text>
<text class="txt" style="--i: 10">.</text>
<text class="txt" style="--i: 11">.</text>
<text class="txt" style="--i: 12">.</text>
</view>
<view class="foot_send" >
<view style="width: 60rpx;height: 60rpx;border-radius:50%;margin-right: 20rpx;font-size: 72rpx;margin-left: 20rpx;border:1rpx solid #3c3c3c;text-align: center;line-height: 60rpx;" @click="selectImg">+</view>
<input v-model="keyWord" placeholder="说点什么吧......" style="width: 100%;" >
<view style="border-radius: 20rpx;margin-right: 20rpx;width: 160rpx;height: 60rpx;display: flex;background-color: #007aff;color:#fff;align-items: center;justify-content: center;" @click="sendText">发送</view>
</view>
</view>
<!-- {{ isShowDrawer }} -->
<jx-drawer
:isShowDrawer="isShowDrawer"
@closeDrawer="closeDrawer">
<view class="drawer">
<view class="status_bar"></view>
<view class="content" v-if="isShowDrawer">
<view style="border: none;">
<view class="login" @click="jumpLogin">
<view>
<image :src="isLogin && userInfo.headUrl ? userInfo.headUrl : '../../static/noLogin.png'" class="avatar"></image>
</view>
<view class="login_but" v-if="!isLogin" style="font-weight: bold;">登录</view>
<view class="login_but" v-else >
<view style="width: 380rpx;white-space: nowrap;overflow:hidden;text-overflow: ellipsis;font-weight: bold;">{{ userInfo.nickName }}</view>
<view style="font-size: 36rpx;margin-top: 20rpx;">账户余额:¥{{ accountBalance.toFixed(2) }}</view>
</view>
</view>
<!-- 滑动内容 -->
<scroll-view class="drawer_center" scroll-y="true">
<jx-cell :text="'充值'" @jumpTo="jumpRefill"></jx-cell>
<jx-cell :text="'充值记录'" @jumpTo="jumpMyOrder"></jx-cell>
<jx-cell :text="'我的推广码'" @jumpTo="myPromte"></jx-cell>
<jx-cell :text="'查看历史话题'" @jumpTo="queryHistoryChat"></jx-cell>
<jx-cell :text="'联系客服'" @jumpTo="callPhone"></jx-cell>
</scroll-view>
</view>
<view>
<view @click="exitLogin" class="exitLogin" v-if="isLogin">退出登录</view>
<view class="foot_ball">您好欢迎来到惊喜视界</view>
</view>
</view>
</view>
</jx-drawer>
</template>
<script setup lang="ts">
import jxDrawer from '@/components/jx-drawer/index.vue'
import jxCell from '@/components/jx-cell/index.vue'
import toast from '@/utils/toast'
import { computed, ref } from 'vue'
import { store } from '@/store'
import order from '@/api/https/order'
import { onLoad, onShow } from '@dcloudio/uni-app'
import useGlobalFunc from '@/composables/useGlobalFunc'
import { qiniuyun } from '@/utils/qiniuUploader'
const {
previewImage, // 预览图片
} = useGlobalFunc()
let isLoadingImg = ref<boolean>(false)
const keyWord = ref('')
let isShowDrawer = ref(false)
onLoad((query) => {
console.log('初始化,query',query)
// getAccountInvoice()
})
/**
* 加载图片信息
*/
const defaultImg = 'https://image.jxc4.com/image/7f8c15f44bbcdbd9174df1797dfe74dd.jpg'
function handleImgError(index:number){
// 防止无限循环:如果已经是默认图,不再替换
if (historyList.value[index].vendorDescription !== defaultImg) {
historyList.value[index].vendorDescription = defaultImg
}
// console.log('加载图片信息',e,'number',index)
}
/*************************************************
* 预览图片
*/
function previewImg(url:string) {
// let arr = [skuName.img,skuName.img2,skuName.img3,skuName.img4,skuName.img5].filter(item => { return item && item.length > 0 })
previewImage(url)
}
/**
* 联系客服
*/
function callPhone(){
uni.makePhoneCall({
phoneNumber: '18048531223',
success() {
console.log('拨号完成')
},
fail() {
toast('取消拨号')
}
})
uni.vibrateShort({})
}
// function onChange(){
// console.log('聚焦11111111',isShowDrawer.value)
// }
/**
* 登录状态
*/
const isLogin = computed(() => {
return store.getters['serveInfo/isLogin']
})
/**
* 用户信息
*/
const userInfo =computed(() => {
return uni.getStorageSync('userInfo')
})
/**
* 账户余额
*/
const accountBalance = computed(() => {
return store.getters['serveInfo/accountBalance']
})
/**
* 上传图片 图生图
*/
// const uploadImgUrl = ref<string>('')
const qiniuyunUploadImg = qiniuyun() // 七牛云sdk
async function uploadImg(img: string){
let suffix = img.indexOf('.png') === -1 ? '.jpg' : '.png'
let params = {
suffix,
}
let res = await order.get_qiniu_upload_token(params)
if (res.code == 0) {
let filePath = img
qiniuyunUploadImg.upload(
filePath,
(res: any) => {
// 得到图片网址
let url = 'https://image.jxc4.com/'
let imgUrl = url + res.key
let str = uni.getStorageSync(imgUrl)
str = str && str.length ? ',' + imgUrl : imgUrl
uni.setStorageSync('uploadImgUrl',str)
toast('图片上传成功,请告诉我怎么修改文字',)
// sendClick({ msg: imgUrl, type: 2 })
// sendText(imgUrl)
},
(err: AnyObject) => {
toast('上传失败,请重试', 2)
},
{
uploadURL: 'https://up-z2.qiniup.com/',
key: res.data.fileName,
uptoken: res.data.token,
}
)
} else {
toast('上传失败', 2)
}
}
function selectImg(){
if(!isLogin.value) return toast('请登录')
uni.chooseImage({
success: (res: any) => {
// console.log('选择图片成功的路径',res)
res.tempFiles.forEach(async(item: AnyObject) => {
// console.log('选择多种图片时的数据',item)
await uploadImg(item.path)
})
},
})
}
/**
* 打开
*/
function showDrawer(){
isShowDrawer.value = true
}
/**
* 关闭
*/
function closeDrawer(){
isShowDrawer.value = false
}
/**
* 退出登录
*/
function exitLogin(){
uni.clearStorage()
store.commit('serveInfo/changeLoginStatus',false)
}
/**
* 跳转到登录
*/
async function jumpLogin(){
// let userInfo = uni.getStorageSync('userInfo') || ""
// if(!userInfo) await store.dispatch('serveInfo/wxLogin',{authType:'wx',isJudg:true}) // 查看当前用户是否为新用户
uni.navigateTo({url:'/subPages/login/index'})
}
/**
* 充值
*/
function jumpRefill() {
uni.navigateTo({url:'/subPages/mine/refill'})
}
/**
* 我的充值记录
*/
function jumpMyOrder(){
console.log('我的订单')
uni.navigateTo({url:'/subPages/mine/order'})
}
/**
* 我的推广码
*/
function myPromte(){
console.log('我的推广码------------')
uni.navigateTo({url:'/subPages/mine/promote'})
}
/**
* 查看历史话题
*/
function queryHistoryChat(){
console.log('查看历史话题')
uni.navigateTo({url:'/subPages/mine/historyTopic'})
}
onShow(() => {
// 刷新物料袋
getAccountInvoice()
})
const historyList = ref<AnyObject[]>([{
// id:'-1',
usertType:'sys',
nickName:'惊喜视界',
content:'嘿,好久不见,甚是想念。',
// vendorDescription:'https://image.jxc4.com/image/22bf05e025b99aa79ca44f6ffca425e6.jpg' // 图片url
},
// {
// // id:'-1',
// usertType:'user',
// nickName:'匿名11',
// content:'白菜妖精'
// }
])
async function getAccountInvoice(){
try {
if(!isLogin.value) return
let obj = {
rank:'desc', // desc/asc
orderBy:'created_at',
// keyword:keyword.value,
// beginTime:date1.value,
// endTime:date2.value,
// pageNum:page.value,
// pageSize:pageSize.value
}
let res = await order.queryAccountInvoice(obj)
if(res.code == 0 && res.data.total){
console.log('查询用户的使用记录',res)
let newArr = await combine(res.data.list || [])
historyList.value = historyList.value.concat(newArr || [])
// totalCount.value = res.data.total || 0
// [
// {
// createdAt: "2026-04-29 17:27:06"
// id: 10005
// jxPrice: 66
// orderId: "88515179626607"
// payMoney: 55
// status: "1"
// tokens: 100000
// updatedAt: "2026-04-29 17:27:06"
// urls: ""
// userDescription: "白菜妖精" // 土豆娃娃在云端游玩
// userId: "FCB66AB342B011F1AB95001D4320A900"
// vendorDescription: "https://ark-acg-cn-beijing.tos-cn-beijing.volces.com/doubao-seedream-5-0/0217774542470044acec6226078eafffb431763a23ccdf0fb00a2_0.png?X-Tos-Algorithm=TOS4-HMAC-SHA256&X-Tos-Credential=AKLTYWJkZTExNjA1ZDUyNDc3YzhjNTM5OGIyNjBhNDcyOTQ%2F20260429%2Fcn-beijing%2Ftos%2Frequest&X-Tos-Date=20260429T091755Z&X-Tos-Expires=86400&X-Tos-Signature=1cca8c0be33555d051b96aa8962e5437984b0d55360242b6fa16e0f9d0181b77&X-Tos-SignedHeaders=host"
// vendorId: "doubao"
// vendorPrice: 22
// vendorStatus: "1"
// }
// ]
console.log('打印物料电',historyList.value)
}
// popup.value.close()
} catch (error) {
}
}
function combine(arr:AnyObject[]){
let brr:AnyObject = []
let userInfo = uni.getStorageSync('userInfo')
arr.forEach(item => {
brr.push({
usertType:'user',
nickName:userInfo.nickName,
content:item.userDescription,
})
brr.push({
...item,
usertType:'sys',
nickName:'惊喜视界',
content:item.userDescription,
})
})
return brr
}
/**
* 发送文本
*/
async function sendText(){
try {
// let url = uni.getStorageSync('uploadImgUrl')
if(!isLogin.value) return toast('请登录')
if(keyWord.value.length === 0) return toast('请输入文字内容')
isLoadingImg.value = true
console.log('发送文本的内容111111111111111',keyWord.value)
let userInfo = uni.getStorageSync('userInfo')
console.log('userInfo',userInfo,'nickName',userInfo.nickName)
historyList.value.push({
usertType:'user',
nickName:userInfo.nickName,
content:keyWord.value,
})
let obj:AnyObject = {
vendorModel:'doubao',
prompt:keyWord.value,
isTools:false // 是否联网搜索
}
let url = uni.getStorageSync('uploadImgUrl')
console.log('11111111',url)
if(url) obj.image = url // 多张图,逗号隔开
// console.log('中间的菜篮,,参数',obj)
// return
let res = await order.useText2Msg(obj)
toast('发送成功,请等待......')
if(res.code == 0){
console.log('打印返回图片的信息',res)
historyList.value.push({
usertType:'sys',
nickName:'惊喜视界',
content:keyWord.value,
vendorDescription:res.data.imgs[0]
})
isLoadingImg.value = false
delImg(url)
// getAccountInvoice
}else{
// setTimeout(()=>{
// console.log('2000之后再回来',res)
// toast(res.desc)
// isLoadingImg.value = false
// },2000)
toast(res.desc)
isLoadingImg.value = false
}
} catch (error) {
console.log('error',error)
isLoadingImg.value = false
toast('生成错误')
}
}
/**
* 删除图片
*/
async function delImg(urls:string){
let res = await order.del_qiniu_img(urls)
uni.setStorageSync('uploadImgUrl','')
console.log('删除图片的结果',res)
}
</script>
<style lang="scss" scoped>
.status_bar {
height: var(--status-bar-height);
width: 100%;
}
// --status-bar-height
.box{
display: flex;
flex-direction: column;
justify-content: space-between;
border: none;
height: calc(100vh - 76rpx);
// border: 1rpx solid red;
.navi{
padding: 10rpx;
height: 100rpx;
width: 100%;
display: flex;
background-color: #efefef;
align-items: center;
justify-content: flex-start;
.navi_but{
width: 70rpx;
height: 70rpx;
border-radius: 50%;
background-color: #fff;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0rpx 0rpx 10rpx #888888;
margin-top: 10rpx;
.img{
width: 40rpx;
height: 40rpx;
}
}
.text{
margin-left: 20rpx;
font-size: 50rpx;
font-weight: bold;
height: 60rpx;
line-height: 60rpx;
// margin-bottom: 10rpx;
}
}
.contentCell{
flex: 1;
background-color: #efefef;
padding: 20rpx 10rpx;
overflow-x: auto;
// width: 50%;
// border: 1rpx solid rgb(81, 255, 0);
.cell{
margin-bottom: 30rpx;
display: flex;
}
.cell_sys{
justify-content: flex-start;
}
.cell_user {
justify-content: flex-end;
}
.avatar{
// border:1rpx solid red;
display: flex;
margin-bottom: 20rpx;
.img{
width: 60rpx;
height: 60rpx;
border-radius: 50%;
}
}
.nickname{
// margin-top: -20rpx;
// border:1rpx solid rgb(30, 255, 0);
height: 60rpx;
line-height: 60rpx;
padding: 0 20rpx;
}
.content,.backImg{
margin-left: 10rpx;
// border: 1rpx solid red;
background-color: #fff;
border-radius: 10rpx;
padding: 10rpx;
}
.backImg{
margin-top: 20rpx;
width: 400rpx;
display: flex;
justify-content: flex-start;
.img{
// transform: scale(0.5);
width: 400rpx;
height: 400rpx;
}
}
// .content_cell_sys,.content_cell_user{
// // display: flex;
// // .img{
// // width: 60rpx;
// // height: 60rpx;
// // }
// }
// .content_cell_sys{
// justify-content: flex-start;
// .cell_text{
// margin-left: 10rpx;
// }
// }
// .content_cell_user{
// // display: flex;
// justify-content: flex-end;
// .cell_text{
// margin-right: 10rpx;
// }
// }
// .cell_text{
// margin-left: 10rpx;
// // border: 1rpx solid red;
// background-color: #fff;
// border-radius: 10rpx;
// padding: 10rpx;
// }
}
}
.foot_send{
width: 90%;
height: 80rpx;
display: flex;
align-items: center;
margin: 0 auto;
border: 1rpx solid #5d5d5d;
border-radius: 50rpx;
margin-bottom: 20rpx;
}
.drawer{
border: none;
.content{
display: flex;
justify-content: space-between;
flex-direction: column;
height: 100vh;
}
.login{
width: 100%;
height: 140rpx;
// line-height: 100rpx;
// font-weight: bold;
font-size: 40rpx;
// text-align: center;
border-bottom: 5rpx solid #7c7c7c;
display: flex;
justify-content:flex-start;
align-items: center;
padding: 10rpx 20rpx;
box-sizing: border-box;
margin-top: 20rpx;
.avatar{
width: 70rpx;
height: 70rpx;
border-radius: 50%;
}
.login_but{
margin-left: 50rpx;
}
.drawer_center{
height: calc(100% - 292rpx);
}
}
.exitLogin{
width: 80%;
text-align: center;
background-color: #ff4646;
color: #fff;
padding: 20rpx ;
border-radius: 20rpx;
margin:0 auto;
margin-bottom: 20rpx;
}
.foot_ball{
height: 140rpx;
width: 100%;
text-align: center;
font-weight: bold;
font-size: 36rpx;
}
}
.productImgTip{
// font-size: 48px;
font-weight: bold;
color: #4c4c4c;
text-align: center;
// margin-top: 100px;
margin-bottom: 20rpx;
// border: 1rpx solid red;
padding: 20rpx;
background-color: rgb(37 37 37 / 13%);
.txt {
display: inline-block;
font-size: 40rpx;
animation: animate 2s ease-in-out infinite;
animation-delay: calc(0.1s * var(--i));
}
}
@keyframes animate {
0% {
transform: translateY(0rpx);
}
20% {
transform: translateY(-15rpx);
}
40%,
100% {
transform: translateY(0rpx);
}
}
// .productImgTip span {
// display: inline-block;
// animation: wordJump 1s ease-in-out infinite alternate;
// }
// border: 1rpx solid red;
// margin-bottom: 20rpx;
// display: inline-block;
// animation: wordJump 1s ease-in-out infinite alternate;
// /* 给每个字错开延迟,形成波浪效果 */
// .productImgTip span:nth-child(1) { animation-delay: 0s; }
// .productImgTip span:nth-child(2) { animation-delay: 0.1s; }
// .productImgTip span:nth-child(3) { animation-delay: 0.2s; }
// .productImgTip span:nth-child(4) { animation-delay: 0.3s; }
// .productImgTip span:nth-child(5) { animation-delay: 0.4s; }
// .productImgTip span:nth-child(6) { animation-delay: 0.5s; }
@keyframes wordJump {
0% { transform: translateY(0); }
100% { transform: translateY(-25px); }
}
</style>

6
src/shime-uni.d.ts vendored Normal file
View File

@@ -0,0 +1,6 @@
export {}
declare module "vue" {
type Hooks = App.AppInstance & Page.PageInstance;
interface ComponentCustomOptions extends Hooks {}
}

BIN
src/static/arrowLeft.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 B

BIN
src/static/backspace.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 488 B

BIN
src/static/emptyImg.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -0,0 +1,344 @@
@font-face {
font-family: "iconfont";
src: url('/static/font/iconfont.ttf') format('truetype');
}
/* 自定义图标 */
.icon-0 {
background-image: url(https://image.jxc4.com/image/884664b80ffd2eda64a4aab9f4dc402e.png);
}
.icon-1 {
background-image: url(http://image.jxc4.com/image/c4d4a4bf342e301733d16262e0cec2dc.png)
}
.icon-3 {
/* background-image: url(https://image.jxc4.com/image/9b6dc6f925111cf1d72175df9669c738.png) */
background-image: url(https://image.jxc4.com/image/06a27a6503a6695824bf361ded5f1d45.png)
}
.icon-4 {
background-image: url(https://image.jxc4.com/image/a8914f97edd3e8efa8aef4122fb86f78.png)
}
.icon-5 {
background-image: url(https://image.jxc4.com/image/e3d7c79e4fe65a687bafbccbad5c2c57.png)
}
.icon-9 {
background-image: url(http://image.jxc4.com/image/02a72aff88e6fb688472d3d34c275ea2.png)
}
.icon-16 {
background-image: url(https://image.jxc4.com/image/db9c805c2747a9f8cced29ef8ea7be75.jpg)
}
.icon-14 {
background-image: url(https://image.jxc4.com/image/32ff8463b62a4195e0a5d979eb0f46f3.png)
}
.icon-6 {
background-image: url(https://image.jxc4.com/image/57ed88f5b1c2122655dada08de40ed61.png);
}
.icon-103 {
background-image: url(http://image.jxc4.com/image/35cb1b9bbf9d78b6bb4b48fdae20d88f.png);
}
.icon-101 {
background-image: url(http://image.jxc4.com/image/223fccabb90ffeb8854e534c6ec1a43c.jpg)
}
.icon-105 {
background-image: url(http://image.jxc4.com/image/f4ef8fd49fc3d07f456c5fe19dc2ac44.jpg)
}
.icon-106 {
background-image: url(http://image.jxc4.com/image/938b1fc6aa3428f95182e30c87b887ab.png)
}
.promtion-sku-icon,
.promtion-sku-icon2,
.promotion-earning-icon {
position: absolute;
left: 0;
top: 20rpx;
width: 30rpx;
height: 30rpx;
background-color: white;
background-repeat: no-repeat;
background-position: center center;
background-size: 100%;
animation: bounce .5s infinite alternate;
}
.promotion-earning-icon {
height: 60rpx;
}
.promtion-sku-icon {
background-image: url(http://image.jxc4.com/image/21a32b90b1de684d70fa16a24b033be7.png);
}
.promtion-sku-icon2 {
background-image: url(http://image.jxc4.com/image/0be36cc81c28da0be8d1152dc3a2f9b5.png);
}
.promotion-earning-icon {
background-image: url(http://image.jxc4.com/image/194cd17fcce1c86e589251e9c9e4d87b.png);
}
/* 订单管理item样式 */
.position-relative {
font-size: 30rpx;
box-sizing: border-box;
position: relative;
border-radius: 10rpx !important;
overflow: hidden;
padding: 0rpx 15rpx;
margin: 35rpx 25rpx 0rpx 25rpx;
}
.promtion-sku-icon2 {
background-image: url(https://image.jxc4.com/image/b593ed3cb0b2bc4f012ad81eeacaf4f6.png);
}
.promtion-sku-icon {
background-image: url(https://image.jxc4.com/image/61daa3ff4294cd271fef44088c94d38c.png);
}
/* 兼容ios样式 */
.rest-time {
display: block;
box-sizing: border-box;
width: 186rpx;
height: 58rpx;
background-size: 100%;
text-align: right;
font-size: 36rpx;
font-weight: bold;
color: #fff;
line-height: 56rpx;
padding-right: 10rpx;
}
/* 已超时 */
.order-bg-cs {
display: block;
width: 186rpx;
height: 58rpx;
background: url(https://image.jxc4.com/image/28c4ddde0d2d427e7dd8ec852cd7984f.tem.png) center center no-repeat;
background-size: 100%;
font-size: 0;
}
/* 预订单 */
.order-bg-dsd {
display: block;
width: 186rpx;
height: 58rpx;
background: url(https://image.jxc4.com/image/96d3ae7a7b3748a9ad2fc4678c528a61.tem.png) center center no-repeat;
background-size: 100%;
font-size: 0;
}
/* time */
.picktime1 {
background: url(https://image.jxc4.com/image/9de64fdcd36aa43cf85c20f5361a486a.tem.png) center center no-repeat;
background-size: 100% 100%;
}
.canceltime {
background: url(https://image.jxc4.com/image/1ba2acde27582db3bcc801fab44729db.tem.png) center center no-repeat;
background-size: 100% 100%;
}
/* time < 10 */
.picktime2 {
background: url(https://image.jxc4.com/image/20b8cfeba3fa10114b7292ee53bde792.tem.png) center center no-repeat;
background-size: 100% 100%;
}
/* time < 5 */
.picktime3 {
background: url(https://image.jxc4.com/image/cd1e46e18fa2b7eeea72c4b5b4828b5b.tem.png) center center no-repeat;
background-size: 100% 100%;
}
/* time */
.arrived1 {
background: url(https://image.jxc4.com/image/68d5fbc3b1d925cb58a6dad714c45adb.tem.png) center center no-repeat;
background-size: 100% 100%;
}
/* time < 20 */
.arrived2 {
background: url(https://image.jxc4.com/image/628846b61f5a0a67aa15b1c6c0ab838f.tem.png) center center no-repeat;
background-size: 100% 100%;
}
/* time < 5 */
.arrived3 {
background: url(https://image.jxc4.com/image/47a56698feaf90e5b8376a4824f98475.tem.png) center center no-repeat;
background-size: 100% 100%;
}
/* 已送达 */
.order-delivered {
display: block;
box-sizing: border-box;
width: 186rpx;
height: 58rpx;
font-size: 36rpx;
font-weight: 500;
color: #4eb331;
text-align: right;
line-height: 58rpx;
}
/* 配送管理 */
.small {
font-size: 24rpx !important;
}
.red {
color: #D34B3B !important;
}
.green {
color: #4EB331 !important;
}
/* 系统图标 */
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-yijianshouquan:before {
content: "\e68f";
}
.icon-yuyin:before {
content: "\e69f";
}
.icon-jiantou_yemian_xiangxia:before {
content: "\eb0a";
}
.icon-erweima:before {
content: "\e60c";
}
.icon-xiangce:before {
content: "\e7f1";
}
.icon-qiehuan:before {
content: "\e607";
}
.icon-zhengque:before {
content: "\e628";
}
.icon-ziyuan:before {
content: "\e60f";
}
.icon-jiantou1:before {
content: "\e605";
}
.icon-jiahao:before {
content: "\eaf3";
}
.icon-24gf-telephone:before {
content: "\e96c";
}
.icon-zhuanfa:before {
content: "\e627";
}
.icon-cangpeitubiao_xiazaipandiandanxiazaidayinmoban:before {
content: "\e623";
}
.icon-shengyin:before {
content: "\e87c";
}
.icon-shijian:before {
content: "\e8a9";
}
.icon-xinxi:before {
content: "\e64e";
}
.icon-fuzhi:before {
content: "\e604";
}
.icon-shanchu:before {
content: "\e603";
}
.icon-xiangyoujiantou:before {
content: "\e65f";
}
.icon-xiangzuojiantou:before {
content: "\e660";
}
.icon-gengduo:before {
content: "\e602";
}
.icon-wenhaoxiao:before {
content: "\e8c8";
}
.icon-duihao:before {
content: "\e684";
}
.icon-shuxie:before {
content: "\e60e";
}
.icon-kongzhuangtai:before {
content: "\e6fe";
}
.icon-sousuo:before {
content: "\e62f";
}
.icon-weixin:before {
content: "\e601";
}
.icon-mima:before {
content: "\e600";
}
.icon-yanzhengma2:before {
content: "\e656";
}
.icon-shoujihao:before {
content: "\e62b";
}

Binary file not shown.

BIN
src/static/jxHorizon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 349 KiB

BIN
src/static/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
src/static/moreThan.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 B

BIN
src/static/noLogin.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 908 B

BIN
src/static/userCenter.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 674 B

45
src/store/index.ts Normal file
View File

@@ -0,0 +1,45 @@
/**
* 顶级模块
*/
// import { storeInfo, StoreInfoStoreType } from './useStoreInfoStore' // 门店信息模块
import { serveInfo, ServeinfoStoreType } from './useServeInfoStore'
import { InjectionKey } from 'vue'
import { createStore, Store, useStore as baseUserStore } from "vuex";
export interface State {
// storeInfo: StoreInfoStoreType // 门店信息
serveInfo: ServeinfoStoreType // 系统信息
}
export const key: InjectionKey<Store<State>> = Symbol()
export const store: Store<State> = createStore({
/**
* 同步修改 state 状态
*/
mutations: {},
/**
* 异步修改 state 调用 mutations 修改
*/
actions: {},
/**
* 逻辑复用计算属性
*/
getters: {},
/**
* 子模块
*/
modules: {
// storeInfo, // 门店信息
serveInfo, // 系统信息
}
})
export function useStore() {
return baseUserStore(key)
}

View File

@@ -0,0 +1,63 @@
// import Login from '@/api/https/login'
import login from "@/api/https/login";
import { setStorage } from "@/utils/storage";
import { log } from "node:console";
/**
* storeInfoStore 模块的 actions
*/
export default {
// get_services: async (store: any) => {
// let res = await Login.get_service_info()
// if (res.code == '0') store.commit('setServiceInfo', res.data.metaData)
// }
/**
* isJudg 是否对新用户进行拦截 authType = 'wx',isJudg = false}
*/
wxLogin:async (store:any,{authType = 'wx',isJudg = false,obj = {}}) => {
store.commit('changeLoginStatus',false) // 重置登录状态
let data = {}
if(authType == 'wx'){
// 微信登录
let getCode = await login.get_jx_code(isJudg);
data = {
authType,
authSecret: getCode.code,
}
}else if(authType == 'pwd' || authType == 'yzm'){
// 账号密码登录 或 验证码登录
data = obj
}
console.log('登录的参数信息',data)
let res = await login.applets_login(data,isJudg);
if(res.code == 0){
let user = res.data.user
setStorage("token", res.data.token);
setStorage('userInfo',user)
setStorage('mobile',user.phoneNumber)
if(user && user.phoneNumber.length === 0) store.commit('setIsBindMobile',{need:true}) // 是否需要需要绑定手机号
// console.log('判断是否为新用户999999999999999',res,'isJudg',isJudg,'store',store)
if(!isJudg){
store.commit('changeLoginStatus',true) // 老用户
// 查询用户信息
await store.dispatch('queryAccount') // 查询账余额
uni.navigateTo({ url: '/pages/index/index' }) // 调转到首页
}
}
},
/**
* 查询账户余额
*/
queryAccount:async(store:any) => {
console.log('初始化,获取账户余额')
let res = await login.queryAccountBalance()
if(res.code == 0){
store.commit('changeAccountBalance',res.data.balance / 100)
console.log('打印账户余额',res)
}
},
}

View File

@@ -0,0 +1,42 @@
/**
* storeInfoStore 模块的 getters
*/
import { ServeinfoStoreType } from './index'
export default {
// /**
// * 动态刷新订单状态 (updateOrder)
// * @param {number} updateOrder 动态刷新订单标识
// */
// getUpdateOrder(state: ServeinfoStoreType) {
// return state.updateOrder
// },
/**
* 是否同意了用户隐私协议
*/
isAgreement(state: ServeinfoStoreType) {
return state.isAgreement
},
/**
* 绑定手机号的信息
*/
isBindMobile(state: ServeinfoStoreType){
return state.isBindMobile
},
/**
* 登录状态
*/
isLogin(state: ServeinfoStoreType){
return state.isLogin
},
/**
* 账户余额
*/
accountBalance(state: ServeinfoStoreType){
return state.accountBalance
}
}

View File

@@ -0,0 +1,54 @@
/**
* 系统信息状态管理
*/
import { Module } from 'vuex'
import { State } from '../index'
import mutations from './mutations'
import actions from './actions'
import getters from './getters'
export interface ServeinfoStoreType {
/**
* 系统信息配置信息
*/
// orderUrl: string // 新账单地址
// sysInfo: string // 本机系统信息 // 蓝牙打印机状态
// updateOrder: number // 通过getters来动态刷新订单
// isFirstLogin: boolean // 是否显示立即登录
// appFilePath: any // app下载的文件
isNetWork: boolean // 手机是否连接上网络
isAgreement: boolean // 是否同意用户协议
isAgreementIf: boolean // 勾选协议问题
// serviceInfo: object // 服务信息
isBindMobile:object // 绑定手机号信息
isLogin:boolean // 登录状态
accountBalance:number // 账户余额
}
/**
* 服务器配置
*/
export const serveInfo: Module<ServeinfoStoreType, State> = {
// 开启命名空间
namespaced: true,
state: (): ServeinfoStoreType => ({
// orderUrl: '', // 新账单地址
// sysInfo: '{"osVersion":"10.0.0","osName":"ios"}',// 本机系统信息 // 蓝牙打印机状态
// updateOrder: 0, // 通过getters来动态刷新订单
// isFirstLogin: false, // 是否显示立即登录
// appFilePath: '', // app下载的文件
isNetWork: true, // 手机是否连接上网络默认有网
isAgreement: false, // 是否同意用户协议
isAgreementIf: false, // 勾选协议问题
// serviceInfo: {}, // 服务信息
isBindMobile:{
need:false
}, // 是否需要绑定手机号
isLogin:false, // 更改登录状态
accountBalance:0
}),
mutations,
actions,
getters
}

View File

@@ -0,0 +1,113 @@
/**
* serveInfoStore 模块的 mutations
*/
import { ServeinfoStoreType } from './index'
export default {
// /**
// * 保存新账单地址 (orderUrl)
// * @param {string} orderUrl 新账单地址
// * @param {string} payload 新账单地址
// */
// setOrderUrl(state: ServeinfoStoreType, payload: string) {
// state.orderUrl = payload
// },
// /**
// * 保存本机系统信息 (sysInfo)
// * @param {string} sysInfo 本机系统信息
// * @param {string} payload 本机系统信息
// */
// setSystemInfo(state: ServeinfoStoreType, payload: string) {
// state.sysInfo = payload
// },
// /**
// * 新订单来了,刷新状态 updateOrder
// * @param {number} updateOrder 打印机的个个服务状态
// * @param {number} payload 打印机的个个服务状态
// */
// setUpdateOrder(state: ServeinfoStoreType, payload: number) {
// state.updateOrder = payload
// },
// /**
// * 新订单来了,刷新状态 updateOrder
// * @param {number} updateOrder 更新订单
// * @param {number} payload 新订单时间
// */
// setIsFirestLogin(state: ServeinfoStoreType, payload: boolean) {
// state.isFirstLogin = payload
// },
// /*************************************************
// * 保存app下载的文件(appFilePath)
// * @param {boolean} updateOrder 打印机的个个服务状态
// * @param {boolean} payload 打印机的个个服务状态
// */
// setAppFilePath(state: ServeinfoStoreType, payload: boolean) {
// state.appFilePath = payload
// },
/*************************************************
* 保存网络状态(isNetWork)
* @param {boolean} isNetWork 打印机的个个服务状态
* @param {boolean} payload 打印机的个个服务状态
*/
setIsNetWorkS(state: ServeinfoStoreType, payload: boolean) {
state.isNetWork = payload
},
/*************************************************
* 是否勾选协议(isAgreement)
* @param {boolean} isAgreement 是否同意用户协议
* @param {boolean} payload 用户协议勾选状态
*/
setIsAgreement(state: ServeinfoStoreType, payload: boolean) {
state.isAgreement = payload
},
/*************************************************
* 是否勾选协议(isAgreementIf)
* @param {boolean} isAgreementIf 是否同意用户协议
* @param {boolean} payload 用户协议勾选状态
*/
setIsAgreementIf(state: ServeinfoStoreType, payload: boolean) {
state.isAgreementIf = payload
},
// /*************************************************
// * 保存系统服务信息
// */
// setServiceInfo(state: ServeinfoStoreType, payload: Object) {
// state.serviceInfo = payload
// },
/**
* 保存绑定手机号的应用信息
*/
setIsBindMobile(state: ServeinfoStoreType, payload: Object) {
console.log('你修改了没有',payload)
state.isBindMobile = payload
},
/**
* 修改登录状态
*/
changeLoginStatus(state: ServeinfoStoreType, flag: boolean){
state.isLogin = flag
},
/**
* accountBalance
*/
changeAccountBalance(state: ServeinfoStoreType, money: number){
state.accountBalance = money
}
}

View File

@@ -0,0 +1,31 @@
<template>
<view class="center">
京西京西菜市成立于2015年6月主要从事生鲜超市外卖运营管理是主流外卖平台全国KA品牌是全国第一家主营生鲜外卖运营服务的企业开创了生鲜品类在外卖平台的品牌定义平均每年服务上百万家庭并帮助菜市场创业者菜店店主水果店主超市便利店等伙伴拥抱互联网实现了从0到1的蜕变
</view>
<view class="img">
<image
style="width: 130px; height: 130px"
src="https://image.jxc4.com/image/6a24f3427885866086407a9af8550b09.tem.jpg"
mode="scaleToFill"
/>
</view>
<view class="title">更多服务内容请关注微信公众号"京西菜市"</view>
</template>
<script lang="ts" setup>
</script>
<style lang="scss" scoped>
.center {
box-sizing: border-box;
padding: 20rpx;
}
.img {
text-align: center;
}
.title {
text-align: center;
}
</style>

View File

@@ -0,0 +1,102 @@
<template>
<view class="service-wrap">
<div class="paper-title">惊喜视界用户隐私协议</div>
<pre>
惊喜视界尊重和保护用户的隐私本隐私政策将告诉您我们如何收集和使用有关您的信息以及我们如何保护这些信息的安全您成为惊喜视界用户前务必仔细阅读本隐私条款并同意所有隐私条款本隐私政策条款在您注册成为惊喜视界用户后立即生效并对您及惊喜视界产生约束力
我们可能收集的用户信息
我们提供服务时可能会收集储存和使用下列与您有关的信息如果您不提供相关信息可能无法注册成为我们的用户或无法享受我们提供的某些服务或者无法达到相关服务拟达到的效果
1您提供的信息
您在注册账户或使用我们的服务时向我们提供的相关个人信息例如电话号码身份证号码银行卡号等
您通过我们的服务向其他方提供的共享信息以及您使用我们的服务时所储存的信息
2其他方分享的您的信息
其他方使用我们的服务时所提供有关您的共享信息
3我们获取的您的信息 您使用服务时我们可能收集如下信息
日志信息指您使用我们的服务时系统可能通过cookieswebbeacon或其他方式自动采集的技术信息包括设备或软件信息例如您的移动设备网页浏览器或用于接入我们服务的其他程序所提供的配置信息您的IP地址和移动设备所用的版本和设备识别码以及您在使用我们服务时要求提供的其他信息和内容详情
<!--
位置信息指您开启设备定位功能并使用我们基于位置提供的相关服务时收集的有关您位置的信息您可以通过关闭定位功能停止对您的地理位置信息的收集
交易信息指我们对您在惊喜视界平台上形成的交易数据信息进行分析并形成用户信用数据库 -->
我们可能如何使用用户信息
1在我们提供服务时用于身份验证客户服务安全防范诈骗监测存档和备份用途确保我们向您提供的产品和服务的安全性
2帮助我们设计新服务改善我们现有服务
3使我们更加了解您如何接入和使用我们的服务从而针对性地回应您的个性化需求
4软件认证或管理软件升级
5让您参与有关我们产品和服务的调查
为了让您有更好的体验改善我们的服务或您同意的其他用途在符合相关法律法规的前提下我们可能将通过某一项服务所收集的信息以汇集信息或者个性化的方式用于我们的其他服务例如在您使用我们的一项服务时所收集的信息可能在另一服务中用于向您提供特定内容或向您展示与您相关的非普遍推送的信息如果我们在相关服务中提供了相应选项您也可以授权我们将该服务所提供和储存的信息用于我们的其他服务
我们可能与第三方共享的用户信息
在下列情况下我们可能会共享您的个人信息
<!-- 1您逾期未偿还借款本息我们将向公众包括但不限于出借人您手机通讯录中不时更新的联系人该等联系人手机中不时更新的联系人您提供的社交账号的联系人或群体披露您的用户信息 -->
2其他注册用户就您在惊喜视界活动中的违约行为发起诉讼程序时我们将应该等注册用户的请求向该等注册用户披露您的用户信息
3应行政司法部门的要求向该等机构提供您的用户信息
<!-- 4债权人委托催收时向受托催收主体提供您的用户信息 -->
5您通过惊喜视界平台向第三方合作机构申请相关产品服务时我们将根据您的授权向第三方提供您的用户信息
6我们以及我们的关联公司可能将您的个人信息与我们的关联公司合作伙伴及第三方服务供应商承包商及代理例如代表我们发出短信或推送通知的通讯服务提供商为我们提供位置数据的地图服务供应商分享他们可能并非位于您所在的法域为了我们向您提供或改善我们的服务
随着我们业务的持续发展我们以及我们的关联公司有可能进行合并收购资产转让或类似的交易您的个人信息有可能作为此类交易的一部分而被转移
依据法律要求必须向第三方提供您的用户信息的情形
我们如何保护用户信息
我们使用各种安全技术和程序以防信息的丢失不当使用未经授权阅览或披露但请您理解由于技术的限制以及可能存在的各种恶意手段在互联网行业即便竭尽所能加强安全措施也不可能始终保证信息百分之百的安全您需要了解您接入我们的服务所用的系统和通讯网络有可能因我们可控范围外的因素而出现问题
账户注销
当用户需要注销本账号时可联系 惊喜视界 客服人员进行验证注销
隐私政策的修改
由于法律法规的变更以及为了与互联网的新发展和可能的发展趋势保持同步我们可能会不定时修改本政策因此我们保留自行决定实施此类修改的权利如该等修订造成您在本隐私政策下权利的实质减少我们将在修订生效前通过在主页上显著位置提示或向您推送通知或以其他方式通知您在该种情况下若您继续使用我们的服务即表示同意受经修订的本隐私政策的约束
</pre
>
</view>
</template>
<script lang="ts" setup>
</script>
<style lang="scss">
.service-wrap {
padding: 30rpx;
box-sizing: border-box;
.paper-title {
padding: 20rpx;
text-align: center;
font-size: 40rpx;
line-height: 40rpx;
}
pre {
letter-spacing: 1px;
font-size: 28rpx;
white-space: pre-wrap;
white-space: -moz-pre-wrap;
white-space: -pre-wrap;
white-space: -o-pre-wrap;
word-wrap: break-word;
}
}
</style>

View File

@@ -0,0 +1,207 @@
<template>
<view class="service-wrap">
<div class="paper-title">惊喜视界用户协议</div>
<pre>
惊喜视界账号使用协议
欢迎您注册使用惊喜视界账号
本协议系您与成都若溪科技有限公司就惊喜视界账号的注册和使用而订立的成都若溪科技有限公司如下简称惊喜视界在此特别提醒您认真阅读充分理解本协议各条款特别是涉及服务费用条款免除或者限制惊喜视界责任的条款对您的权利限制条款争议解决和法律适用条款等此类条款将以加粗的形式提示您注意请您审慎阅读并选择接受或不接受本协议限制民事行为能力人应在监护人或法定代理人陪同下阅读除非您接受本协议所有条款否则您无权注册使用惊喜视界账号您的注册和使用惊喜视界账号行为将视为您已充分理解本协议即本协议及后续更新版本或开通或使用某项服务的单项协议并同意接受本协议各项条款的约束
关于惊喜视界账号
1惊喜视界账号系由惊喜视界所有的用于识别您身份的标识账号的所有权属于惊喜视界您作为初始申请注册人仅拥有您所注册账号的使用权
2您可通过惊喜视界账号享受惊喜视界及关联公司提供的单项服务包括但不限于惊喜视界小程序服务您亦可通过惊喜视界账号向惊喜视界购买品鉴券以便您享受惊喜视界及关联公司的各种产品和增值服务
3. 本服务条款的效力范围及于惊喜视界及关联公司的一切产品和服务您在享受任何单项服务时应当受本服务条款的约束当您使用惊喜视界各单项服务时您同意以单项服务要求的方式同意该单项服务的服务条款以及惊喜视界在该单项服务中发出的各类公告下列简称为单项条款在此情况下单项条款与本服务条款同时对您产生效力若单项条款与本服务条款存在同类条款的冲突则在单项条款约束范围内应以单项条款为准
账号使用规则
1注册账号
1.1 您确认在您开始注册程序使用惊喜视界服务前您应当具备中华人民共和国法律规定的与您行为相适应的民事行为能力若您不具备前述与您行为相适应的民事行为能力则您及您的监护人应依照法律规定承担因此而导致的一切后果
1.2 您应提供及时详尽及准确的个人资料并不断更新注册资料符合及时详尽准确的要求您保证在注册时所提交的所有资料包括但不限于手机号码生日等真实准确合法有效且系您本人的资料如果因注册信息不真实或更新不及时而引发的相关问题 惊喜视界不负任何责任您可以通过惊喜视界账号设置页面查询更正您的信息您应当通过真实身份信息认证注册账号且您提交的账号名称头像和简介等注册信息中不得出现违法和不良信息经惊喜视界审核如存在上述情况惊喜视界将不予注册同时在注册后如发现您以虚假信息骗取账号名称注册或您的账号头像简介等注册信息存在违法和不良信息的惊喜视界有权不经通知单方采取限期改正暂停使用终止账号等措施当您按照注册页面提示填写信息阅读并同意本协议条款且完成全部注册程序后您可获得惊喜视界账号并成为惊喜视界用户
2.账号使用
2.1 您应对您账号项下的所有行为结果负责
2.2 由于您的惊喜视界账号关联您的个人信息及惊喜视界商业信息您的惊喜视界账号仅限您本人使用未经惊喜视界同意您直接或间接授权第三方使用您惊喜视界账号或获取您账号项下信息的行为无效如惊喜视界根据惊喜视界各平台规则中约定的违约认定程序及标准判断您惊喜视界账号的使用可能危及您的账号安全及或惊喜视界信息安全的惊喜视界可拒绝提供相应服务或终止本协议
2.3 若您选择第三方账号登陆惊喜视界的服务第三方账号将与您的惊喜视界账号相关联惊喜视界将根据您授权第三方提供的信息而使用您的信息如头像您后续使用该惊喜视界账号的行为受本协议约束
3.账号保管和找回
3.1 惊喜视界账号包括账号名称和手机号您可使用设置的账号名称手机号登录您应妥善保管好您的账号因您个人原因导致的账号信息遗失如需找回惊喜视界账号信息请按照惊喜视界账号找回流程提供相应的信息并确保提供的信息合法真实有效若提供的信息不符合要求无法通过惊喜视界安全验证惊喜视界有权拒绝提供账号找回服务
3.2 如果您当前使用的惊喜视界账号并非您初始申请注册的或通过惊喜视界提供的其他途径获得的但您却知悉该惊喜视界账号当前的手机号您不得用该惊喜视界账号登录或进行任何操作并请您在第一时间通知惊喜视界或者该惊喜视界账号的初始申请注册人
4账号转让
4.1 您可在本协议约定的范围内使用惊喜视界账号您不得恶意注册惊喜视界账号不得赠与借用租用有偿或无偿转让或售卖惊喜视界账号或者以其他方式许可非初始申请注册人使用惊喜视界账号惊喜视界有权对上述行为进行独立判断并处理您应当自行承担由此产生的任何责任同时惊喜视界保留追究上述行为人法律责任的权利且由此产生的一切责任均由您承担
4.2 惊喜视界有权根据法律法规对您采取以下措施
4.2.1 如您违反法律法规惊喜视界各单项条款或业务规则的规定惊喜视界有权进行独立判断并随时采取限期改正暂停使用终止您对惊喜视界账号的使用且根据实际情况决定是否恢复使用
4.2.2 如果惊喜视界发现您并非该账号初始申请注册人惊喜视界有权在未经通知的情况下终止您使用该账号
4.2.3 惊喜视界按照本规则或相关法律法规限期改正暂停使用或终止您对惊喜视界账号的使用而由此给您带来的损失包括但不限于通信中断用户资料和相关数据等的清空等由您自行承担
5.账号回收
5.1为了防止资源占用如您连续24个月未使用您的惊喜视界账号或未通过惊喜视界认可的其他方式登录过您的账号惊喜视界有权对该账号进行注销您将不能再通过该账号登录或使用相关服务如该账号有关联的待处理交易或余额等惊喜视界会在合理范围内协助您处理请您按照惊喜视界提示的方式进行操作
6. 账号安全
6.1 您的账号为您自行设置并由您保管惊喜视界任何时候均不会主动要求您提供您的账号手机号建议您采取特定措施保护您的账号安全包括但不限于安装防病毒木马软件等措施
6.2 惊喜视界账号因您主动泄露或因您遭受他人攻击诈骗等行为导致的损失及后果惊喜视界并不承担责任您应通过司法行政等救济途径向侵权行为人追偿
7.账号注销
7.1 在需要终止使用惊喜视界账号服务时符合以下条件的您可以申请注销您的惊喜视界账号
7.1.1 您仅能申请注销您本人的账号并依照惊喜视界的流程进行注销
7.1.2 您仍应对您在注销账号前且使用惊喜视界服务期间的行为承担相应责任
7.1.3 您应当知晓您的账号终止意味着您的用户内容将从我们的活动数据库中删除
用户权利和义务
1.您在使用惊喜视界服务时必须遵守网络安全法互联网新闻信息服务管理规定等中华人民共和国相关法律法规的规定您应同意将不会利用本服务进行任何违法或不正当的活动包括但不限于下列行为:
1.1上载展示张贴传播或以其他方式传送含有下列内容之一的信息
1.1.1 反对宪法所确定的基本原则的
1.1.2 危害 国家安全泄露国家秘密颠覆国家政权破坏国家统一的
1.1.3 损害国家荣誉和利益的
1.1.4 煽动民族仇恨民族歧视破坏民族团结的
1.1.5 破坏国家宗教政策宣扬邪教和封建迷信的
1.1.6 散布谣言扰乱社会秩序破坏社会稳定的
1.1.7 散布淫秽色情赌博暴力凶杀恐怖或者教唆犯罪的
1.1.8 侮辱或者诽谤他人侵害他人合法权利的
1.1.9 含有虚假有害胁迫侵害他人隐私骚扰侵害中伤粗俗猥亵或其他道德上令人反感的内容
1.1.10 含有中国法律法规规章条例以及任何具有法律效力之规范所限制或禁止的其他内容的
1.2 不利用惊喜视界服务从事以下活动
1.2.1 未经允许进入计算机信息网络或者使用计算机信息网络资源的
1.2.2 未经允许对计算机信息网络功能进行删除修改或者增加的
1.2.3 未经允许对进入计算机信息网络中存储处理或者传输的数据和应用程序进行删除修改或者增加的
1.2.4 故意制作传播计算机病毒等破坏性程序的
1.2.5 进行任何诸如发布广告销售商品的商业行为或者进行任何非法的侵害惊喜视界利益的行为如贩卖可币游戏币外挂道具等
1.2.6 其他危害计算机信息网络安全的行为
2.您违反本协议或相关的服务条款的规定导致或产生的任何第三方向惊喜视界与合作公司关联公司主张的任何索赔要求或损失包括合理的律师费您同意赔偿惊喜视界与合作公司关联公司并使之免受损害同时惊喜视界有权视您的行为性质采取包括但不限于删除发布信息内容暂停使用许可终止服务限制使用惊喜视界账号追究法律责任等措施同时惊喜视界会视司法部门的要求协助调查
3.您不得对惊喜视界服务任何部分或惊喜视界服务之使用或获得进行复制拷贝出售转售或用于任何其他商业目的
4.您须对自己在使用惊喜视界服务过程中的行为承担法律责任您承担法律责任的形式包括但不限于对受到侵害者进行赔偿以及在惊喜视界首先承担了因您的行为导致的行政处罚或侵权损害赔偿责任后您应给予惊喜视界等额的赔偿
5.在任何情况下惊喜视界都不对您或任何第三方因本协议产生的任何间接性后果性惩戒性的偶然的特殊或惩罚性的损害赔偿承担责任
免责声明
1.如发生下述情形惊喜视界不承担任何法律责任
1.1 依据法律规定或相关政府部门的要求提供您的个人信息
1.2 由于您的使用不当或其他自身原因而导致任何个人信息的泄露
1.3 任何由于黑客攻击电脑病毒的侵入非法内容信息骚扰信息的屏蔽政府管制以及其他任何网络技术通信线路信息安全管理措施等原因造成的服务中断受阻等不能满足您要求的情形
1.4 因第三方如运营商的通讯线路故障技术问题网络电脑故障系统不稳定及其他因不可抗力造成的损失的情形
1.5 使用惊喜视界产品程序及服务可能存在的来自他人匿名或冒名的含有威胁诽谤令人反感或非法内容的信息而招致的风险
1.6 用户之间通过本网站或惊喜视界产品程序及服务与其他用户交往因受误导或欺骗而导致或可能导致的任何心理生理上的伤害以及经济上的损失
1.7 惊喜视界服务明文声明不以明示默示或以任何形式对惊喜视界及其合作公司服务之及时性安全性准确性做出担保
1.8 您在利用惊喜视界账号所发布的任何内容并不代表和反映惊喜视界的任何观点或政策惊喜视界对此不承担任何责任
1.9 在任何情况下惊喜视界均不对任何间接性后果性惩罚性偶然性特殊性或刑罚性的损害包括因您使用惊喜视界服务而遭受的利润损失承担责任尽管本协议中可能含有相悖的规定我们对您承担的全部责任无论因何原因或何种行为方式始终不超过您在注册期内因使用惊喜视界服务而支付给惊喜视界的费用(如有)
2. 您可以选择使用您已有的第三方账号关联惊喜视界账号惊喜视界对于因第三方原因对您造成的损失不承担任何责任
知识产权
1. 您在惊喜视界发布的信息不得侵犯任何第三人的知识产权未经具有相关所有权人之事先书面同意您不得以任何方式上传发布修改传播或复制任何受著作权保护的材料商标或属于其他人的专有信息如果收到任何著作权人或其合法代表发给惊喜视界的适当通知后我们将在审查的基础上移除该等侵犯他人著作权的内容
2. 您在使用惊喜视界服务时利用惊喜视界账号发表上传的文字图片视频软件以及表演等原创信息的知识产权归您所有但是您确认您对该等信息的发表上传行为视同为对惊喜视界非独占地永久地不可撤销地授予该等信息相关全部知识产权的使用复制等权利并且您同意惊喜视界可转授权上述权利
3. 除非经过惊喜视界的在先书面同意您未获得权利使用惊喜视界的任何知识产权您保证陈述并承诺您尊重惊喜视界的知识产权您不会以自己名义或促使第三方也不会同意或放任任何第三方为了其任何营销广告促销或其他目的在任何法域以任何方式申请与惊喜视界或惊喜视界关联公司商标相似的商标域名无线网站互联网搜索词或任何商号服务标志如出现上述情况您须将所有相关权利转让给惊喜视界费用由您承担如因您违反本条款约定而给惊喜视界造成损失的该损失全部由您承担
修订
1. 鉴于互联网相关技术市场业务模式等等的发展迅速您同意惊喜视界有权随时根据中华人民共和国有关法律法规的变化互联网的发展以及公司经营状况和经营策略的调整等不定时地制定修改本协议及各类规则如有修订惊喜视界将通过法定程序通知经修订的协议规则一经公布则立即自动生效且成为本服务协议不可分割的一部分如您不同意上述修订则您必须立即停止使用本协议下各项服务您继续登录或继续使用惊喜视界服务则表明您认可并接受经修订的协议规则
终止
7.1 本协议自您接受之日起生效在您使用惊喜视界服务的过程中持续有效直至依据本协议终止
7.2 尽管有上述规定如果您使用惊喜视界服务的时间早于您接受本协议的时间您在此知晓或应当知晓并同意本协议于您第一次使用惊喜视界服务时生效除非依据本协议提前终止
7.3 我们可能会依据法律的规定保留您使用惊喜视界服务或者惊喜视界账号的权利无论是否通知我们将在任何时间以任何原因终止本协议包括出于善意地相信您违反了我们可接受使用政策或本协议的其他规定
7.4 不受前款规定所限如果您侵犯第三人的著作权且惊喜视界接到著作权人或著作权人的合法代理人的通知后惊喜视界保留终止本协议的权利
其他
8.1 反馈
8.1.1 您对惊喜视界提出建议或称反馈即视为您向惊喜视界转让反馈的全部权利并同意惊喜视界有权利以任何合理方式使用此反馈及其相关信息我们将视此类反馈信息为非保密且非专有
8.1.2 您已同意您不会向惊喜视界提供任何您视为保密和专有的信息
8.2 隐私政策
8.2.1 请查阅我们的隐私政策隐私政策为与本协议效力等同且不可分割的一部分
8.3 通知
8.3.1 在注册惊喜视界账号时您应该向惊喜视界提供真实有效的联系方式包括您的手机号码等对于联系方式发生变更的您有义务及时更新有关信息并保持可被联系的状态惊喜视界将向您的上述联系方式的其中之一或其中若干向您送达各类通知而此类通知的内容可能对您的权利义务产生重大的有利或不利影响请您务必及时关注您所提供的手机号码无法使用或者因任何原因我们无法将通知送达给您而产生的风险由您自行承担
8.4 适用法律
8.4.1 本协议适用中华人民共和国法律
8.4.2 如果双方发生纠纷应本着友好的原则协商解决如协商不成应向北京市海淀区人民法院提起诉讼若单项条款与本服务条款在管辖约定内容上存在冲突则在单项条款约束范围内应以单项条款为准
8.5 独立性
8.5.1 若本协议中的某些条款因故无法适用则本协议的其他条款继续适用且无法适用的条款将会被修改以便能够依法适用
</pre
>
</view>
</template>
<script lang="ts" setup>
</script>
<style lang="scss">
.service-wrap {
padding: 30rpx;
box-sizing: border-box;
.paper-title {
padding: 20rpx;
text-align: center;
font-size: 40rpx;
line-height: 40rpx;
}
pre {
letter-spacing: 1px;
font-size: 28rpx;
white-space: pre-wrap;
white-space: -moz-pre-wrap;
white-space: -pre-wrap;
white-space: -o-pre-wrap;
word-wrap: break-word;
}
}
</style>

View File

@@ -0,0 +1,159 @@
<template>
<view class="code-from-root">
<jx-input>
<template #left>
<jx-icon icon="shoujihao" color="#aaa8" :size="36"></jx-icon>
</template>
<template #middle>
<uni-easyinput
primaryColor="#aaa"
class="input"
:inputBorder="false"
type="text"
v-model="phone"
placeholder="请输入手机号"
/>
</template>
</jx-input>
</view>
<view class="code-from-root">
<jx-input>
<template #left>
<jx-icon icon="yanzhengma2" color="#aaa"></jx-icon>
</template>
<template #middle>
<uni-easyinput
primaryColor="#aaa"
class="input"
:inputBorder="false"
maxlength="6"
type="text"
v-model="code"
placeholder="请输入验证码"
/>
</template>
<template #right>
<text class="send-code" @tap="sendCode">{{ codeText }}</text>
</template>
</jx-input>
</view>
<button class="code-login-btn" @tap="codeLogin">登录</button>
</template>
<script lang="ts" setup>
import jxIcon from '@/components/jx-icon/jx-icon.vue'
import jxInput from '@/components/jx-input/jx-input.vue'
import toast from '@/utils/toast'
import { onBeforeUnmount, ref, Ref } from 'vue'
import { jx_throttles } from '@/utils/tools'
import { store } from '@/store'
import login from '@/api/https/login'
import useGlobalFunc from '@/composables/useGlobalFunc'
const { isUserAgreementFn } = useGlobalFunc()
const phone: Ref<string> = ref('')
const code: Ref<string> = ref('')
const emit = defineEmits<{
(e: 'codeLogin', data: AnyObject): void
}>()
async function codeLogin() {
if (!store.state.serveInfo.isAgreement) {
isUserAgreementFn()
return false
}
let phoneRuler = /^(?:(?:\+|00)86)?1\d{10}$/
if (!phoneRuler.test(phone.value) && phone.value != '91112345678')
return toast('手机号不规范')
if (code.value.length < 6) return toast('验证码不规范')
let data = {
authSecret: code.value,
authType: 'yzm',
authID: phone.value,
auth_id_type:'phone_number'
}
await store.dispatch('serveInfo/wxLogin',{authType:'yzm',isJudg:false,obj:data})
// let res = await login.applets_login(data)
// if (res.code == 0) {
// emit('codeLogin', res.data)
// } else {
// toast(res.desc)
// }
}
/**
* 发送验证码
*/
const codeText = ref<string>('发送验证码')
function sendCode() {
if (!store.state.serveInfo.isAgreement) {
store.commit('serveInfo/setIsAgreementIf', true)
return false
}
let phoneRuler = /^(?:(?:\+|00)86)?1\d{10}$/
if (!phoneRuler.test(phone.value) && phone.value != '91112345678')
return toast('手机号不规范')
sendCodeThroottle()
}
/**
* 节流
*/
let sendCodeTimer: any = null
const sendCodeThroottle = jx_throttles({
time: 60000,
success: async () => {
const data = {
authType: 'yzm',
phone: phone.value,
}
let phoneCode = await login.send_verify_code(data)
if (phoneCode.code == 0) {
toast('验证码发送成功')
let num = 60
sendCodeTimer = setInterval(() => {
codeText.value = `${num--}秒后重发`
if (num <= 0) {
codeText.value = '重新发送'
num = 60
clearInterval(sendCodeTimer)
}
}, 1000)
} else {
toast('发送失败', 2)
}
},
})
onBeforeUnmount(() => {
clearInterval(sendCodeTimer)
})
</script>
<style lang="scss" scoped>
.code-from-root {
border-bottom: 2rpx solid rgb(234, 234, 234);
line-height: 70rpx;
margin-bottom: 30rpx;
input {
width: 100%;
}
.send-code {
white-space: nowrap;
color: #aaa;
font-size: 28rpx;
}
}
.code-login-btn {
border-radius: 100rpx;
margin-top: 60rpx;
color: rgb(255, 255, 255);
background-color: $jx-login;
}
</style>

View File

@@ -0,0 +1,695 @@
<template>
<view style="width: 100vw;text-align: center;">
<!-- https://image.jxc4.com/image/42c1adf2f3fb7b913cfde602f3b9e98f.jpg -->
<image
class="logo"
src="../../static/jxHorizon.png"
mode="scaleToFill"
/>
</view>
<view class="center-root">
<view class="tab-root">
<text class="icon">|</text>
<text
class="tab-item"
v-for="(item, i) in loginTypeList"
:key="i"
:class="{ active: i == activeItem }"
@tap="activeItem = i"
>{{ item.title }}</text
>
</view>
<swiper
:duration="200"
class="swiper"
@change="change"
:current="activeItem">
<swiper-item>
<view class="form-root">
<CodeLogin @codeLogin="codeLogin" />
</view>
</swiper-item>
<swiper-item>
<view class="form-root">
<PasWordLogin @pwdLogin="pwdLogin" />
</view>
</swiper-item>
</swiper>
<!-- <view class="form-root">
<view class="pwd-from-root">
<jx-input>
<template #left>
<jx-icon icon="shoujihao" color="#aaa" :size="60"></jx-icon>
</template>
<template #middle>
<uni-easyinput
primaryColor="#aaa"
:inputBorder="false"
class="input"
type="text"
v-model="phone"
placeholder="请输入用户名"
/>
</template>
</jx-input>
</view>
<view class="pwd-from-root" style="margin-top: 20rpx;">
<jx-input>
<template #left>
<jx-icon icon="mima" color="#aaa" :size="60"></jx-icon>
</template>
<template #middle>
<uni-easyinput
primaryColor="#aaa"
:inputBorder="false"
class="input"
type="password"
v-model="pwd"
placeholder="请输入密码"
/>
</template>
</jx-input>
</view>
</view> -->
<!-- @getphonenumber="weixiniLogin" -->
<button
class="btn"
@tap="clickLogin"
v-if="!store.getters['serveInfo/isAgreement']"
>
<jx-icon icon="yijianshouquan" color="#fff" :size="44"></jx-icon>
<text>一键登录</text>
</button>
<button
class="btn"
@tap="noNeedBind"
v-if="store.getters['serveInfo/isAgreement'] && !store.getters['serveInfo/isBindMobile'].need"
>
<jx-icon icon="yijianshouquan" color="#fff" :size="44"></jx-icon>
<text>一键登录</text>
</button>
<button
v-if="store.getters['serveInfo/isAgreement'] && store.getters['serveInfo/isBindMobile'].need"
class="btn"
open-type="getPhoneNumber"
@getphonenumber="getPhoneNum"
>
<jx-icon icon="yijianshouquan" color="#fff" :size="44"></jx-icon>
<text>一键登录</text>
</button>
<!-- <view class="other_login">
<text>其它方式登录</text>
</view> -->
<view class="copyright-root" style="position: absolute;bottom: 140rpx;">
<view class="center" >
<label>
<checkbox-group @change="agreement">
<checkbox
:checked="store.getters['serveInfo/isAgreement']"
value="cb"
color="#2dd091"
style="transform: scale(0.7); border-radius: 50%"
/>我已阅读并同意
</checkbox-group>
</label>
<text class="text" @tap="user">用户协议</text>
<text class="text" @tap="privacy">隐私协议</text>
<view
class="lab"
>请勾选同意后在进行登录</view
>
</view>
</view>
<view class="info">欢迎进入惊喜视界</view>
</view>
<!-- <uni-popup ref="wxPopup" type="bottom">
<view class="wxPopup-root">
<view class="text">
<view class="agreement-title">用户协议及隐私协议</view>
<view class="content">
本协议系您与成都若溪科技有限公司就京西菜市帐号的注册和使用而订立的成都若溪科技有限公司如下简称京西菜市在此特别提醒您认真阅读充分理解本协议各条款特别是涉及服务费用条款免除或者限制京西菜市责任的条款对您的权利限制条款争议解决和法律适用条款等此类条款将以加粗的形式提示您注意请您审慎阅读并选择接受或不接受本协议限制民事行为能力人应在监护人或法定代理人陪同下阅读除非您接受本协议所有条款否则您无权注册使用京西菜市帐号您的注册和使用京西菜市帐号行为将视为您已充分理解本协议即本协议及后续更新版本或开通或使用某项服务的单项协议并同意接受本协议各项条款的约束
</view>
<view class="agreement">
点击同意即代表您已阅读并同意
<text class="text" @tap="user">用户协议</text>
<text class="text" @tap="privacy">隐私协议</text>
</view>
</view>
<view class="btn">
<view class="reject" @tap="wxPopup.close()">拒绝</view>
<button
class="resolve"
open-type="getPhoneNumber"
@getphonenumber="weixiniLogin"
>
同意
</button>
</view>
</view>
</uni-popup> -->
</template>
<script lang="ts" setup>
import CodeLogin from './codeLogin/codeLogin.vue'
import PasWordLogin from './paswordLogin/paswordLogin.vue'
import { computed, ref, Ref } from 'vue'
import { md5 } from 'js-md5'
import toast from '@/utils/toast'
import login from '@/api/https/login'
import useGlobalFunc from "@/composables/useGlobalFunc";
import { store } from '@/store'
import { getStorage, setStorage } from '@/utils/storage'
import { onLoad } from '@dcloudio/uni-app';
const {
// setUserInfo,
isUserAgreementFn
} = useGlobalFunc()
onLoad(() => {
// console.log('页面初始化',store.state)
})
const phone: Ref<string> = ref('')
const pwd: Ref<string> = ref('')
interface LoginType {
title: string;
}
const loginTypeList: Ref<LoginType[]> = ref([
{ title: "验证码登录" },
{ title: "密码登录" },
]);
const activeItem: Ref<number> = ref(0);
async function pwdLogin() {
if (phone.value == '') return toast('请输入用户名')
if (pwd.value.length == 0) return toast('密码不规范')
let data = {
authType: 'pwd',
authIDType: 'mobile',
authID: phone.value,
authSecret: md5(pwd.value),
}
let res = await login.applets_login(data)
if (res.code == 0) {
console.log('登录成功')
} else {
toast(res.desc)
}
}
/**
* 新用户,解密手机号并绑定
*/
async function getPhoneNum(e:AnyObject){
console.log('获取手机号',e.detail)
let userInfo = uni.getStorageSync('userInfo')
if(e.detail.errMsg === 'getPhoneNumber:ok'){
let res = await login.decryUser({
sessionKey:userInfo.session_key,
iv:e.detail.iv,
encryptedData:e.detail.encryptedData,
type:'phone'
})
if(res.data == 0){
// 绑定成功
// setUserInfo(res.data)
uni.navigateTo({ url: '/pages/index/index' })
}
}
}
/*************************************************
* 切换登录信息
*/
function change(res: AnyObject) {
activeItem.value = res.detail.current
}
/**
* 微信登录
*/
function clickLogin(){
if (!store.state.serveInfo.isAgreement) {
isUserAgreementFn()
return false
}
}
/**
* 验证码登录
*/
function codeLogin(data: AnyObject) {
// setUserInfo(data)
// saveUserType()
}
// 非首次登录 不需要绑定手机号
function noNeedBind (){
if(store.getters['serveInfo/isBindMobile'].need) return // 不需要绑定
silenceLogin()
}
/**
* 登录 e?: AnyObject
*/
async function silenceLogin() {
await store.dispatch('serveInfo/wxLogin',{authType:'wx'})
// let data = uni.getStorageSync('userInfo') // getStorage('userInfo')
// console.log('11111111',data)
// let userInfoDecry = await login.decryUser({
// sessionKey:data.session_key,
// iv:'微信用户', // 昵称
// encryptedData:'https://thirdwx.qlogo.cn/mmopen/vi_32/POgEwh4mIHO4nibH0KlMECNjjGxQUq24ZEaGT4poC6icRiccVGKSyXwibcPq4BWmiaIGuG1icwxaQX6grC9VemZoJ8rg/132', // 头像
// type:'name'
// })
// uni.getUserProfile({
// desc:'用于个性化头像展示',
// success:async (userInfo) => {
// let data = uni.getStorageSync('userInfo') // getStorage('userInfo')
// // https://thirdwx.qlogo.cn/mmopen/vi_32/POgEwh4mIHO4nibH0KlMECNjjGxQUq24ZEaGT4poC6icRiccVGKSyXwibcPq4BWmiaIGuG1icwxaQX6grC9VemZoJ8rg/132
// // 微信用户
// console.log(data,'111111111111存储的信息',userInfo)
// let userInfoDecry = await login.decryUser({
// sessionKey:JSON.parse(JSON.parse(data.extraInfo)).session_key,
// iv:userInfo.userInfo.nickName, // 昵称
// encryptedData:userInfo.userInfo.avatarUrl, // 头像
// type:'name'
// })
// // console.log('解密后的信息',userInfoDecry)
// // let getCode = await login.get_jx_code();
// // if (getCode) {
// // let data = {
// // authType: "wx",
// // authSecret: getCode.code,
// // };
// // let res = await login.applets_login(data);
// // if (res.code == 0) {
// // // 登录成功
// // console.log('登录成功',res.data)
// // // en2tNW9y6rn8tM9KXI720Q==
// // setUserInfo(res.data,userInfo);
// // // if (userInfo.data.tokenType == 1) {
// // // setUserInfo(userInfo.data);
// // // saveUserType()
// // // }
// // // // 首次登录绑定用户手机号
// // // if (userInfo.data.tokenType != 1) {
// // // setStorage('token', userInfo.data.token)
// // // bangdingMobile(e!, userInfo.data.token)
// // // }
// // } else {
// // toast("登录失败", 2);
// // }
// // }
// }
// })
}
// // 存储用户信息
// async function saveUserType() {
// // let res = await login.get_self_info()
// // if (res.code == 0) {
// // setStorage('userType', res.data.type)
// // } else {
// // setStorage('userType', 0)
// // }
// }
// // 绑定手机号码
// async function bangdingMobile(e: AnyObject, token: AnyObject) {
// let data = {
// "data": e.detail.encryptedData,
// "iv": e.detail.iv,
// "appID": 'wx08a5c2a8581414ff'
// }
// // let resData = await login.getUser_by_mini_info(data)
// // if (resData.code == 0) {
// // // 有手机号码,绑定
// // if (resData.data.isExist) {
// // let data = {
// // authToken: token,
// // mobile: resData.data.mobile,
// // }
// // let ress = await login.add_auth_bind(data)
// // if (ress.code == 0) {
// // setStorage('token', '85e60d6a-f1f8-4837-9c7d-d7072b0ba1c6')
// // let infoData = await login.get_token_info()
// // setStorage('token', infoData.data.token)
// // setStorage('userID', infoData.data.userID)
// // bindsns(resData.data.mobile)
// // } else {
// // toast('登录失败', 2)
// // }
// // }
// // // 没手机号码
// // if (!resData.data.isExist) {
// // let oldData = {
// // "userID2": resData.data.mobile,
// // "name": resData.data.mobile,
// // "avatar": 'https://image.jxc4.com/jxwhite.png',
// // "mobile": resData.data.mobile
// // }
// // let data = {
// // authToken: getStorage('token'),
// // payload: JSON.stringify(oldData)
// // }
// // let res = await login.register_user(data)
// // if (res.code == 0) {
// // setStorage('token', res.data.token)
// // setStorage('token', '85e60d6a-f1f8-4837-9c7d-d7072b0ba1c6')
// // let infoData = await login.get_token_info()
// // setStorage('token', infoData.data.token)
// // setStorage('userID', infoData.data.userID)
// // bindsns(false)
// // } else {
// // toast('登录失败', 2)
// // }
// // }
// // } else {
// // toast('登录失败', 2)
// // }
// }
// // 获取新信息
// function bindsns(mobile: string | boolean) {
// if (mobile) {
// uni.navigateTo({
// url: `/subPages/login/bindSNS/bindSNS?mobile=${mobile}`
// })
// } else {
// uni.navigateTo({
// url: '/subPages/login/bindSNS/bindSNS'
// })
// }
// }
// 微信登录弹窗实例
// const wxPopup = ref<any>(null)
// 微信登录
// async function weixiniLogin(e: AnyObject) {
// wxPopup.value.close()
// if (e.detail.errMsg == "getPhoneNumber:ok") {
// silenceLogin(e)
// }
// }
/*************************************************
* 是否同意协议
*/
const isAgreement = ref<boolean>(false)
/**
* 勾选
*/
function agreement(e: AnyObject) {
if (e.detail.value.length) {
// 同意
isAgreement.value = true
store.commit('serveInfo/setIsAgreement', true)
store.commit('serveInfo/setIsAgreementIf', false)
} else {
// 不同意
store.commit('serveInfo/setIsAgreement', false)
isAgreement.value = false
}
}
/**
* 用户协议
*/
function user(){
uni.navigateTo({ url: '/subPages/agreement/user' })
}
/**
* 隐私协议
*/
function privacy(){
uni.navigateTo({ url: '/subPages/agreement/privacy' })
}
</script>
<style lang="scss" scoped>
// @import './index.scss';
// .loginCss{
// width: 100vw;
// height: 100rpx;
// line-height: 100rpx;
// border-bottom: 1rpx solid #eee;
// text-align: center;
// }
::v-deep .uni-easyinput__content-input {
background-color: #efefef !important;
// font-size: 44rpx;
}
::v-deep .uni-easyinput__content,.uni-easyinput__content > .content-clear-icon{
background-color: #efefef !important;
// .content-clear-icon{
// background-color: #efefef;
// }
}
// ::v-deep .uni-easyinput__placeholder-class{
// font-size: 44rpx;
// }
.pwd-from-root{
border-bottom:1rpx solid #d8d8d8;
}
.btn{
background-color: #5ef3e5;
border-radius: 100rpx;
margin-top: -20rpx;
font-size: 36rpx;
height: 92rpx;
color: #fff;
line-height: 92rpx;
width: 90%;
}
.pwd-login-btn {
width: 90%;
border-radius: 100rpx;
margin-top: 60rpx;
color: rgb(255, 255, 255);
background-color: $jx-login;
}
.logo {
width: 350rpx;
height: 350rpx;
margin: 50rpx 0;
}
.center-root {
box-sizing: border-box;
padding: 30rpx 0rpx;
width: 750rpx;
.tab-root {
width: 100%;
display: flex;
align-items: center;
justify-content: space-evenly;
color: #aaa;
margin-bottom: 50rpx;
.icon {
order: 2;
}
.tab-item:first-child {
order: 1;
}
.tab-item:last-child {
order: 3;
}
.tab-item {
padding: 10rpx 40rpx;
border-radius: 50rpx;
font-weight: bold;
font-size: 40rpx;
}
.active {
color: #fff;
font-weight: bold;
color: $jx-login;
}
}
.form-root {
box-sizing: border-box;
width: 100%;
padding: 0 50rpx;
}
.weixin-login-root {
display: flex;
flex-direction: column;
align-items: center;
margin-top: 100rpx;
margin-bottom: 100rpx;
.text-root {
display: flex;
align-items: center;
justify-content: center;
.hr {
width: 400rpx;
border-bottom: 1rpx solid #e6e6e6;
z-index: 0;
width: 150rpx;
border-bottom: 1rpx solid #e6e6e6;
background-color: #e6e6e6;
}
.weixin-text {
position: relative;
padding: 0 10rpx;
color: #bbbbbb;
}
}
button {
display: flex;
justify-content: center;
align-items: center;
height: 110rpx;
width: 110rpx;
background-color: $jx-login !important;
border-radius: 50%;
margin-top: 20rpx;
}
}
}
.other_login{
width: 100%;
margin-top: 30rpx;
text-align: center;
}
.info {
position: absolute;
width: 100%;
text-align: center;
bottom: 60rpx;
color: rgb(126, 126, 126);
font-size: 36rpx;
// font-weight: bold;
}
.copyright-root {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
text-align: center;
// font-size: 26rpx;
font-size: 32rpx;
.text {
color: $jx-login;
}
.center {
display: flex;
justify-content: center;
align-items: center;
position: relative;
.lab {
position: absolute;
padding: 7rpx 10rpx;
background-color: #656a70;
color: #fff;
left: 0rpx;
top: 60rpx;
border-radius: 10rpx;
opacity: 0;
transition: all 0.2s;
}
.lab::after {
content: '';
position: absolute;
width: 0;
height: 0;
border-left: 11rpx solid transparent;
border-right: 11rpx solid transparent;
border-bottom: 12rpx solid #656a70;
left: 12rpx;
top: -11rpx;
}
.lab-active {
opacity: 1 !important;
}
}
.center-active {
animation: identifier 0.2s;
}
}
.swiper {
height: 450rpx;
}
@keyframes identifier {
0% {
transform: translateX(20rpx);
}
20% {
transform: translateX(0rpx);
}
40% {
transform: translateX(20rpx);
}
60% {
transform: translateX(0rpx);
}
40% {
transform: translateX(20rpx);
}
100% {
transform: translateX(0rpx);
}
}
</style>

View File

@@ -0,0 +1,98 @@
<template>
<view class="pwd-from-root">
<jx-input>
<template #left>
<jx-icon icon="shoujihao" color="#aaa" :size="36"></jx-icon>
</template>
<template #middle>
<uni-easyinput
primaryColor="#aaa"
:inputBorder="false"
class="input"
type="text"
v-model="phone"
placeholder="请输入用户名"
/>
</template>
</jx-input>
</view>
<view class="pwd-from-root">
<jx-input>
<template #left>
<jx-icon icon="mima" color="#aaa"></jx-icon>
</template>
<template #middle>
<uni-easyinput
primaryColor="#aaa"
:inputBorder="false"
class="input"
type="password"
v-model="pwd"
placeholder="请输入密码"
/>
</template>
</jx-input>
</view>
<button class="pwd-login-btn" @tap="pwdLogin">登录</button>
</template>
<script lang="ts" setup>
import jxIcon from '@/components/jx-icon/jx-icon.vue'
import jxInput from '@/components/jx-input/jx-input.vue'
import toast from '@/utils/toast'
import { md5 } from 'js-md5'
import { Ref, ref } from 'vue'
import { store } from '@/store'
import useGlobalFunc from '@/composables/useGlobalFunc'
import login from '@/api/https/login'
const { isUserAgreementFn } = useGlobalFunc()
const phone: Ref<string> = ref('')
const pwd: Ref<string> = ref('')
const emit = defineEmits<{
(e: 'pwdLogin', data: AnyObject): void
}>()
async function pwdLogin() {
if (!store.state.serveInfo.isAgreement) {
isUserAgreementFn()
return false
}
if (phone.value == '') return toast('请输入用户名')
if (pwd.value.length == 0) return toast('密码不规范')
let data = {
authType: 'pwd',
authIDType: 'user_id2',
authID: phone.value,
authSecret: md5(pwd.value),
}
let res = await login.applets_login(data)
if (res.code == 0) {
emit('pwdLogin', res.data)
} else {
toast(res.desc)
}
}
</script>
<style lang="scss" scoped>
.pwd-from-root {
border-bottom: 2rpx solid rgb(234, 234, 234);
line-height: 70rpx;
margin-bottom: 30rpx;
input {
width: 100%;
}
}
.pwd-login-btn {
border-radius: 100rpx;
margin-top: 60rpx;
color: rgb(255, 255, 255);
background-color: $jx-login;
}
</style>

View File

@@ -0,0 +1,136 @@
import { store } from "@/store";
import { onBeforeUnmount, ref, Ref } from "vue";
import useGlobalFunc from "@/composables/useGlobalFunc";
// import { store } from "@/store";
import { setStorage } from "@/utils/storage";
import login from '@/api/https/login'
import { onShow } from "@dcloudio/uni-app";
import toast from "@/utils/toast";
/**
*@description: 微信登录功能模块
*@return {*}
*@param {}-
*/
function weixinFn() {
const {
setUserInfo,
} = useGlobalFunc()
/**
* 定义切换标题数据
*/
interface LoginType {
title: string;
}
const loginTypeList: Ref<LoginType[]> = ref([
{ title: "验证码登录" },
{ title: "密码登录" },
]);
const activeItem: Ref<number> = ref(1);
onShow(() => {
store.commit('serveInfo/setIsAgreement', false)
store.commit('serveInfo/setIsAgreementIf', false)
})
/*************************************************
* 存储用户信息
*/
async function saveUserType() {
// let res = await login.get_self_info()
// if (res.code == 0) {
// setStorage('userType', res.data.type)
// } else {
// setStorage('userType', 0)
// }
}
/**
* 验证码登录
*/
function codeLogin(data: AnyObject) {
setUserInfo(data)
saveUserType()
}
/**
* 密码登录
*/
// /**
// * 微信登录
// */
// let appWxLoginFnTimer: any = null
// let appWxLoginFnTimer2: any = null
/**
* 用户协议
*/
function user() {
uni.navigateTo({ url: '/subPages/agreement/user' })
}
/**
* 隐私协议
*/
function privacy() {
uni.navigateTo({ url: '/subPages/agreement/privacy' })
}
/*************************************************
* 是否同意协议
*/
const isAgreement = ref<boolean>(false)
function agreement(e: AnyObject) {
if (e.detail.value.length) {
// 同意
isAgreement.value = true
store.commit('serveInfo/setIsAgreement', true)
store.commit('serveInfo/setIsAgreementIf', false)
} else {
// 不同意
store.commit('serveInfo/setIsAgreement', false)
isAgreement.value = false
}
}
/*************************************************
* 切换登录信息
*/
function change(res: AnyObject) {
activeItem.value = res.detail.current
}
// /*************************************************
// * 收尾工作
// */
// onBeforeUnmount(() => {
// store.commit('serveInfo/setIsAgreement', false)
// clearTimeout(appWxLoginFnTimer)
// clearTimeout(appWxLoginFnTimer2)
// })
return {
loginTypeList, // 切换tab
activeItem, // 切换高亮
codeLogin, // 验证码登录
// pwdLogin, // 密码登录
user, // 用户协议
privacy, // 隐私协议
change, // 切换
agreement, // 是否同意协议
isAgreement, // 是否同意协议
}
}
export default weixinFn

View File

@@ -0,0 +1,458 @@
<template>
<!-- @tap="getPhone" -->
<view class="filter-root">
<text class="btn" @tap="openPopup">更多条件</text>
<uni-search-bar
v-model="keyword"
@confirm="searchStore(keyword)"
@clear="clearIpt"
cancelButton="none"
clearButton="auto"
@input="changeIpt(keyword)"
:placeholder="'请输入搜索关键字'"
/>
</view>
<view v-if="historyList.length">
<scroll-view
scroll-y
style="height: calc(100vh - 182rpx)"
refresher-enabled
:refresher-triggered="triggered"
@scrolltolower="scrolltolower"
class="list"
@refresherrefresh="refresherrefresh">
<view v-for="(item,index) in historyList" :key="index" class="list_item">
<view class="desc">
<view>话题:{{ item.userDescription }}</view>
<view>创建时间:{{ item.createdAt }}</view>
<view>价格:
<text style="font-size: 36rpx;color: red;">¥{{ (item.payMoney / 100 ).toFixed(2) }}</text>
<text style="text-decoration: line-through;">¥{{ (item.jxPrice / 100).toFixed(2) }}</text>
</view>
</view>
<!-- / -->
<image :src="item.vendorDescription" alt="加载中..." class="img" @tap="previewImg(item.vendorDescription)" @error="handleImgError(index)"></image>
</view>
<jx-load-more
v-show="totalCount >= 4"
:isLoad="isLoad"
:size="'30rpx'"
tip="没有更多记录"
/>
</scroll-view>
</view>
<jx-empty v-else title="没有历史话题"></jx-empty>
<!-- <view v-if="historyList && historyList.length >0" class="list">
历史话题
</view> -->
<uni-popup ref="popup" type="top">
<view class="switch-filter">
<view class="condition">查询条件</view>
<view class="item">
<text class="title">查询时间</text>
<view class="root">
<picker
class="value"
mode="date"
:value="date1"
start="2010-01-01"
:end="endDate"
@change="dateChange1"
>{{ date1 }}</picker
>
<text></text>
<picker
class="value"
mode="date"
:value="date2"
start="2010-01-01"
:end="endDate"
@change="dateChange2"
>{{ date2 }}</picker
>
</view>
</view>
<view class="item">
<text class="title">关键字段</text>
<picker
class="value"
mode="selector"
:value="vendor"
:range="vendorArr"
range-key="name"
@change="dateChange3"
>{{ vendorArr[vendor].name }}</picker
>
</view>
<view class="item">
<text class="title">排序方式</text>
<picker
class="value"
mode="selector"
:value="sortIndex"
:range="sortArr"
range-key="name"
@change="dateChange4"
>{{ sortArr[sortIndex].name }}</picker
>
</view>
<!--<view class="item" v-if="orderState == 6">
<text class="title">售后方式</text>
<picker
class="value"
mode="selector"
:value="appealTypes1"
:range="appealTypesArr"
range-key="name"
@change="dateChange5"
>{{ appealTypesArr[appealTypes1].name }}</picker
>
</view>
<view class="item" v-if="orderState == 6">
<text class="title">售后状态</text>
<picker
class="value"
mode="selector"
:value="afsStatus1"
:range="afsStatusArr"
range-key="name"
@change="dateChange6"
>{{ afsStatusArr[afsStatus1].name }}</picker
>
</view> -->
<view class="btnRoot">
<text class="cancel" @tap="popup.close()">取消</text>
<text class="confirm" @tap="confirm">确定</text>
</view>
</view>
</uni-popup>
</template>
<script lang="ts" setup>
import order from '@/api/https/order';
import JxEmpty from '@/components/jx-empty/jx-empty.vue';
import useGlobalFunc from '@/composables/useGlobalFunc';
import { store } from '@/store';
import toast from '@/utils/toast';
import { jx_throttles, timeFormatD } from '@/utils/tools';
import { onLoad } from '@dcloudio/uni-app';
import { computed, onMounted, ref } from 'vue';
const historyList = ref<AnyObject[]>([])
const {
previewImage, // 预览图片
} = useGlobalFunc()
/*************************************************
* 预览图片
*/
function previewImg(url:string) {
// let arr = [skuName.img,skuName.img2,skuName.img3,skuName.img4,skuName.img5].filter(item => { return item && item.length > 0 })
if(url.length === 0) return toast('请选择正确的图片')
previewImage(url)
}
/**
* 加载图片信息
*/
const defaultImg = 'https://image.jxc4.com/image/0d2cc478f955889455861fe519e02d15.png'
function handleImgError(index:number){
// 防止无限循环:如果已经是默认图,不再替换
if (historyList.value[index].vendorDescription !== defaultImg) {
historyList.value[index].vendorDescription = defaultImg
}
// console.log('加载图片信息',e,'number',index)
}
/**
* 筛选条件实例对象
*/
const popup = ref<any>(null)
const keyword = ref<string>('')
/**
* 起始时间,结束时间
*/
const date1 = ref<string>(
timeFormatD(+new Date(new Date().getTime() - 1000 * 60 * 60 * 24 * 7))
// timeFormatD(+new Date(new Date().getTime() - 1000 * 60 * 60 * 24 * 2))
)
const date2 = ref<string>(timeFormatD(+new Date()))
const endDate = ref<string>('')
type vendorArrType = {
id: string
name: string
}
const vendor = ref<number>(0)
const vendorArr = ref<Array<vendorArrType>>([
{ id: 'created_at', name: '创建时间' },
{ id: 'updated_at', name: '更新时间' },
{ id: 'vendor_id', name: '来源' }
])
const sortIndex = ref<number>(0)
const sortArr = ref<vendorArrType[]>([
{ id: 'desc', name: '降序' },
{ id: 'asc', name: '升序' },
])
const totalCount = ref<number>(0)
onMounted(() => {
console.log('popup',popup.value)
})
/**
* 登录状态
*/
const isLogin = computed(() => {
return store.getters['serveInfo/isLogin']
})
onLoad(async () => {
if(!isLogin.value) return
await getAccountInvoice()
})
async function getAccountInvoice(){
try {
let obj = {
rank:sortArr.value[sortIndex.value].id, // desc/asc
orderBy:vendorArr.value[vendor.value].id,
keyword:keyword.value,
beginTime:date1.value,
endTime:date2.value,
pageNum:page.value,
pageSize:pageSize.value
}
let res = await order.queryAccountInvoice(obj)
if(res.code == 0){
console.log('查询用户的使用记录',res)
historyList.value = historyList.value.concat(res.data.list || [])
totalCount.value = res.data.total || 0
}
popup.value.close()
} catch (error) {
}
}
// const totalCount = ref<>(0)
function dataHoming(){
historyList.value = []
page.value = 1
totalCount.value = 0
}
/**
* 下拉刷新
*/
const triggered = ref<boolean>(false)
let onPullDownRefreshTimer: any = ''
function refresherrefresh() {
triggered.value = true
clearTimeout(onPullDownRefreshTimer)
onPullDownRefreshTimer = setTimeout(() => {
triggered.value = false
dataHoming()
// oneMenuClick(isFilter.value)
// if (isFilter.value == 'hot') return
// leftBarRef.value.GetStoreCategoryMap()
getAccountInvoice()
}, 500)
}
/*************************************************
* 页面触底,加载更多数据
*/
const page = ref<number>(1) // 第几页
const pageSize = ref<number>(20) // 每页条数20
const isLoad = ref<boolean>(false) // 加载图
function scrolltolower() {
console.log('页面触底,加载更多数据,1111111',totalCount.value)
page.value++
if (pageSize.value * (page.value - 1) > totalCount.value || totalCount.value < pageSize.value) {
isLoad.value = false
} else {
if (isLoad.value) return
getAccountInvoice()
}
}
function dateChange4(e: AnyObject) {
vendor.value = e.detail.value
}
function dateChange3(e: AnyObject) {
vendor.value = e.detail.value
}
function dateChange1(e: AnyObject) {
date1.value = e.detail.value
}
function dateChange2(e: AnyObject) {
date2.value = e.detail.value
}
async function searchStore(keywords: string) {
keyword.value = keywords
historyList.value = []
console.log('赛选的内容,,完成搜索',keyword.value)
await getAccountInvoice()
}
function openPopup(){
console.log('打开弹框',popup.value)
popup.value.open()
}
/**
* 弹框确认
*/
async function confirm(){
historyList.value = []
await getAccountInvoice()
}
/**
* 清空输入框
*/
async function clearIpt() {
keyword.value = ''
// reset()
}
/**
* 输入框输入值变化
*/
// let trembling = jx_trembling(getOrderAllInfo, 800)
// let trembling2 = jx_trembling(getAfsOrders, 800)
async function changeIpt(keywords: string) {
keyword.value = keywords
// reset()
}
</script>
<style lang="scss" scoped>
.list{
// border: 1rpx solid red;
// width: 750rpx;
// box-sizing: border-box;
padding: 10rpx 20rpx;
.list_item{
// .desc{
// display: flex;
// }
margin-bottom: 40rpx;
background-color: #fff;
border: 1rpx solid #eee;
padding:10rpx 30rpx;
border-radius: 15rpx;
display: flex;
.desc{
width: calc(100% - 200rpx);
height: 200rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.img{
width: 200rpx;
height: 200rpx;
border-radius: 50%;
}
}
}
.filter-root {
box-sizing: border-box;
height: 90rpx;
padding: 15rpx;
background-color: #fff;
display: flex;
align-items: center;
.btn {
padding: 8rpx 0;
width: 160rpx;
text-align: center;
background-color: $jx-primary;
color: #fff;
font-size: 28rpx;
border-radius: 100rpx;
margin-right: 15rpx;
}
:deep(.uni-searchbar) {
padding: 0 !important;
width: 545rpx !important;
.uni-searchbar__box {
border-radius: 100rpx !important;
height: auto !important;
}
}
}
.switch-filter {
background-color: #fff;
.condition {
text-align: center;
color: #999999;
}
box-sizing: border-box;
border-radius: 10rpx;
padding: 20rpx 40rpx 10rpx 40rpx;
.item {
display: flex;
margin-top: 35rpx;
.root {
display: flex;
align-items: center;
text {
padding: 0 10rpx;
}
}
.title {
color: #999999;
}
.value {
padding: 5rpx 15rpx;
border: 1rpx solid #bebebe;
border-radius: 10rpx;
}
}
.btnRoot {
display: flex;
justify-content: space-between;
margin-top: 30rpx;
border-top: 1rpx solid #999999;
.cancel,
.confirm {
color: #696969;
text-align: center;
width: 100%;
padding: 20rpx;
}
.confirm {
color: #000;
border-left: 1rpx solid #999999;
}
}
}
</style>

157
src/subPages/mine/order.vue Normal file
View File

@@ -0,0 +1,157 @@
<template>
<view class="top">
<view v-for="(item,index) in orderStautsList" :key="index" class="top_item" :class="{
'active_text':status === item.id
}" @tap="clickTab(item)">
{{ item.name }}
</view>
</view>
<view v-if="totalCount" class="payCard">
<view v-for="(item,index) in payList" :key="index" class="cardItem">
<view class="title">
<view>{{ item.orderId }}</view>
<view>{{ item.createdAt }}</view>
</view>
<view class="payInfo">
<view>{{ `${(item.payFee / 100).toFixed(2)}` }}</view>
<view>{{ item.status === '1' ? '待支付' : item.status === '2' ? '已支付' : item.status === '3' ? '支付成功' : item.status === '4' ? '退款' : item.status === '5' ? '失败': '未知' }}</view>
</view>
</view>
</view>
<JxEmpty v-else title="没有查到充值记录"></JxEmpty>
</template>
<script lang="ts" setup>
import order from '@/api/https/order';
import JxEmpty from '@/components/jx-empty/jx-empty.vue';
import { store } from '@/store';
import { timeFormatD } from '@/utils/tools';
import { onLoad } from '@dcloudio/uni-app';
import { computed, ref } from 'vue';
// const active = ref(0)
const orderStautsList = ref([
{
id:0,
name:'全部'
},
{
id:1,
name:'待支付'
},
{
id:2,
name:'已支付'
},
{
id:3,
name:'支付成功'
},
// {
// id:4,
// name:'退款'
// },
// {
// id:5,
// name:'失败'
// }
])
let payList = ref<AnyObject[]>([])
let totalCount = ref<number>(0)
let status = ref<number>(0) // 订单状态
onLoad(async () => {
// await initPayList()
})
const isLogin = computed(() => {
return store.getters['serveInfo/isLogin']
})
function clickTab(item:AnyObject){
status.value = item.id
initPayList()
}
async function initPayList(){
// let endTime = timeFormatD(+(new Date()))
if(!isLogin.value) return
let obj:AnyObject = {
startTime:timeFormatD(+new Date() - 7 * 24 * 60 * 60 * 1000) + ' 00:00:00',
endTime: timeFormatD(+new Date()) + ' 23:59:59',
// status:3,
number:1,
size:30
}
if(status.value) obj.status = status.value
let res = await order.queryPayRecord(obj)
if(res.code == 0){
payList.value = res.data.list || []
totalCount.value = res.data.count
console.log('获取我的充值记录信息',res)
}
}
</script>
<style lang="scss" scoped>
.top{
display: flex;
width: 750rpx;
box-sizing: border-box;
border-bottom: 1rpx solid rgb(189, 187, 187);
background-color: #fff;
justify-content:space-between ;
.top_item{
// width: ;
padding: 10rpx 20rpx;
font-size: 36rpx;
// border-bottom:4rpx solid rgb(189, 187, 187);
}
.active_text{
background-color: #efefef;
// text-decoration: underline;
border-bottom:4rpx solid #949494;
}
}
.payCard{
margin-top: 20rpx;
.cardItem{
// border:1rpx solid red;
background-color: #fff;
padding: 10rpx;
padding-left: 20rpx;
padding-right: 20rpx;
box-sizing: border-box;
margin:0 auto;
width: 90%;
border-radius: 20rpx;
margin-bottom: 20rpx;
}
.title,.payInfo{
width: 100%;
display: flex;
justify-content: space-between;
padding-bottom: 20rpx;
padding-top: 20rpx;
}
.title{
border-bottom: 1rpx solid #eee;
// padding-bottom: 20rpx;
// padding-top: 20rpx;
}
}
</style>

View File

@@ -0,0 +1,88 @@
<template>
<view style="width: 100%;margin-top: 100rpx;text-align: center;" v-if="isLogin">
<image :src="imgUrl" alt="" style="width: 400rpx;height: 400rpx;"/>
<view @click="downloadCode" style="margin: 20rpx auto;background-color:#409EFF;width: 300rpx;color: #fff;padding: 20rpx;border-radius: 100rpx;">保存小程序推广码</view>
</view>
<JxEmpty v-else title="您还未登录" ></JxEmpty>
</template>
<script lang="ts" setup>
import login from '@/api/https/login'
import JxEmpty from '@/components/jx-empty/jx-empty.vue'
import { store } from '@/store'
import toast from '@/utils/toast'
import { errToast, modal } from '@/utils/uniApi'
import { onShow } from '@dcloudio/uni-app'
import { computed, ref } from 'vue'
const imgUrl = ref('')
onShow(async () => {
try {
// this.showLoad()
await reqGetWxcode()
} catch (e) {
// errToast(e)
} finally {
// this.hideLoad()
}
})
const isLogin = computed(() => {
return store.getters['serveInfo/isLogin']
})
async function reqGetWxcode(){
try {
let mobile = uni.getStorageSync('mobile')
if(!mobile) return
let str = {scene:'promote=' + mobile,
// page:'pages/index/index'
}
console.log('打印参数信息',mobile)
let res = await login.getTiktokOrWxCode(str)
console.log('获取推荐码信息',res)
if(res.code == 0){
// #ifdef MP-WEIXIN
imgUrl.value = res.data.qrCode
// #endif
}
console.log(res,'111111111111111111',imgUrl.value)
// #ifdef MP-TOUTIAO
// imgUrl.value = res.tiktok
// #endif
} catch (e) {
throw e
}
}
/**
* 保存小程序推广码
*/
async function downloadCode(){
console.log('保存推广码-------',imgUrl.value)
// const [err, res] = await uni.downloadFile({ url: imgUrl.value })
uni.downloadFile({
url: imgUrl.value,
complete(res){
console.log('下载图片成功的方法',res)
if(res.statusCode == 200){
uni.saveImageToPhotosAlbum({
filePath: res.tempFilePath,
complete(r) {
console.log('1111111111,保存商品图片',r)
if (r.errMsg === 'saveImageToPhotosAlbum:ok') {
toast('保存成功')
} else {
toast('保存失败')
}
}
})
}
}
})
}
</script>

View File

@@ -0,0 +1,390 @@
<template>
<view v-if="isLogin">
<view class="pay">
<view class="img">
<div>
<image class="img-item" src="https://image.jxc4.com/image/e1a731b7a1bff6e0afd0cd987f421daf.png" alt="" />
</div>
<div class="title">
<div>惊喜视界</div>
<!-- <div v-if="payInfor.name" class="title-storeName">({{ payInfor.name }})</div> -->
</div>
</view>
<view class="input-box">充值金额:<input class="input" type="text" :disabled="true" v-model="consumeFeeValue" /></view>
<view v-if="moneyArr && moneyArr.length > 0" class="refillCard" style="margin-top: 100rpx;">
<view v-for="(item,index) in moneyArr" :key="index" class="card" @click="surePay(item)">
<view class="discountPrice">折扣:<text class="text">¥{{ (item.discountPrice / 100).toFixed(2) }}</text></view>
<view class="originalPrice">原价:<text class="text">¥{{ (item.price /100).toFixed(2) }}</text></view>
</view>
</view>
</view>
</view>
<JxEmpty v-else title="您还未登录"></JxEmpty>
<!-- <view @click="sureRefill">确认充值</view> -->
<!-- 键盘 -->
<!-- <view class="key-board" >
<view class="key">
<view class="key-num">
<view class="key-num-text" hover-class="bg_red" @click="clickNum(1)">1</view>
<view class="key-num-text" hover-class="bg_red" @click="clickNum(2)">2</view>
<view class="key-num-text" hover-class="bg_red" @click="clickNum(3)">3</view>
</view>
<view class="key-num">
<view class="key-num-text" hover-class="bg_red" @click="clickNum(4)">4</view>
<view class="key-num-text" hover-class="bg_red" @click="clickNum(5)">5</view>
<view class="key-num-text" hover-class="bg_red" @click="clickNum(6)">6</view>
</view>
<view class="key-num">
<view class="key-num-text" hover-class="bg_red" @click="clickNum(7)">7</view>
<view class="key-num-text" hover-class="bg_red" @click="clickNum(8)">8</view>
<view class="key-num-text" hover-class="bg_red" @click="clickNum(9)">9</view>
</view>
<view class="key-num">
<view class="zero" hover-class="bg_red" @click="clickNum(0)">0</view>
<view class="point" hover-class="bg_red" @click="clickNum('.')">.</view>
</view>
</view>
<view class="key-text">
<view class="del" @click="clickNum('del')" hover-class="bg_red">
</view>
<view class="sure-pay" @click="surePay">
<view class="sure-pay-text" >充值</view>
</view>
</view>
</view> -->
</template>
<script lang="ts" setup>
import toast from '@/utils/toast';
import { computed, ref } from 'vue';
import orderPage from "@/api/https/order";
import { utilsMd5 } from '@/utils/md5.js'
import { onLoad } from '@dcloudio/uni-app';
import JSEncrypt from 'jsencrypt'
// import CryptoJS from 'crypto-js';
import CryptoJS from 'crypto-js';
import { store } from '@/store';
import JxEmpty from '@/components/jx-empty/jx-empty.vue';
const consumeFeeValue =ref('')
function clickNum(str:string | number){
// if (!isLogin) {
// toast('请登录')
// // jumpPage('navigateTo','/pagesAuth/auth-index/index?type=jxPay')
// // return
// }else{
if(str!=='del'){
if((consumeFeeValue.value.indexOf('.') !== -1 && str === '.') || (consumeFeeValue.value.length === 0 && str === '.')) return
if(consumeFeeValue.value.length === 1 && consumeFeeValue.value === '0') {
if(str!=='.') {
toast('输入错误')
return
}
}
if(consumeFeeValue.value.includes('.')){
if(consumeFeeValue.value.split('.')[1].length>=2) return
consumeFeeValue.value = consumeFeeValue.value + str
}else{
consumeFeeValue.value = consumeFeeValue.value + str
}
}else{
// 退格
if(consumeFeeValue.value.length === 0) return
consumeFeeValue.value = consumeFeeValue.value.substring(0,consumeFeeValue.value.length-1)
}
// }
}
const moneyArr = ref<AnyObject[]>([])
/**
* 登录状态
*/
const isLogin = computed(() => {
return store.getters['serveInfo/isLogin']
})
onLoad(async () => {
if(!isLogin.value) return
let res = await orderPage.refillMoneyConfig('income')
// console.log('配置充值金额',res)
if(res.code == 0){
moneyArr.value = res.data.config
console.log('配置充值金额',moneyArr.value)
}
})
// sureRefill(){
// }
/**
* 确认支付
*/
async function surePay(row:AnyObject){
console.log('确认支付,999999999',row)
// let user = uni.getStorageSync('userInfo')
// let payInfo = await orderPage.wechatPay(
// {
// "userId": '',
// // "desc": '',
// "openId": user.authId,
// "amount": Number(row.discountPrice)*100,
// }
// )
// // console.log('打印支付信息',payInfo)
// await handleCreatePay(payInfo.vendorOrderID, payInfo.prepayID, JSON.parse(payInfo.codeURL))
// toast('支付成功')
if(row && row.discountPrice ) consumeFeeValue.value ='' + row.discountPrice / 100
if(consumeFeeValue.value.length === 0){
toast('请输入充值金额')
}else{
if(consumeFeeValue.value.indexOf('.') !== -1) {
if (consumeFeeValue.value.split('.')[1].replace(/(0+)$/g, "")) {
consumeFeeValue.value = consumeFeeValue.value.split('.')[0] + '.' + consumeFeeValue.value.split('.')[1].replace(/(0+)$/g,"")
} else {
consumeFeeValue.value = consumeFeeValue.value.split('.')[0]
}
}
let user = uni.getStorageSync('userInfo')
let payInfo = await orderPage.wechatPay(
{
"userId": '',
"desc": '充值',
"openId": user.authId,
"amount": Number(consumeFeeValue.value)*100,
}
)
if(payInfo.code == 0){
// ayInfo.data.weChatPay prepayID
await handleCreatePay(payInfo.data)
}
// console.log('打印支付信息',payInfo)
toast('支付成功')
}
}
// 支付相关
// const businessName = '1390686702' // 商户号
async function handleCreatePay( payInfo:AnyObject){
let timeStamp = payInfo.timeStamp // 时间戳
let nonceStr = payInfo.nonce // 随机字符串
let packageA = `prepay_id=${payInfo.prepay_id}`
const paySign = payInfo.sign
wx.requestPayment({
timeStamp:timeStamp,
nonceStr,
package:packageA,
signType:'RSA', // MD5 RSA
paySign:paySign,
complete(res:any){
console.log('掉起支付的数据',res)
}
})
}
// async function getProvider(service = 'payment') {
// try {
// let res = await uni.getProvider({ service:'payment' })
// if (res.errMsg === 'getProvider:ok') return res
// else throw res
// } catch (e) {
// console.error(e)
// throw e
// }
// }
</script>
<style lang="scss" scoped >
.pay{
background-color: #f3f3f3;
height: 100vh;
overflow: hidden;
.img{
margin-top:16rpx;
margin-left:20rpx;
display:flex;
margin-top: 80rpx;
}
.img-item{
width: 150rpx;
height:150rpx;
}
.title{
// width: 150px;
// border: 1px solid red;
width: 100%;
font-size: 50rpx;
height: 150rpx;
line-height: 75rpx;
font-weight: bold;
margin-left:20rpx;
// margin-top: ;
// text-align: center;
}
.title-storeName{
font-size: 30rpx;
color:#696969;
}
.jxPaybut{
text-align: center;
height: 80rpx;
line-height: 80rpx;
width: 650rpx;
border-radius: 20rpx;
margin: 200rpx auto;
background-color: #4EB331;
color:#fff;
}
.backApp{
// border:1rpx solid red;
width: 100px;
// height: 50px;
// display: flex;
background-color: #bdbebe;
margin-right:50rpx;
color:#fff;
box-shadow: 1px 2px 1px 1px #838282;
}
// 金额输入框
.input-box{
display:flex;
justify-content: space-between;
padding:30rpx;
background-color: #fff;
margin:80rpx 40rpx;
border-radius: 20rpx;
}
.input{
// border: 1px solid rgb(70, 64, 64);
width: 200px;
text-align: right;
}
// 键盘
.key-board{
position: fixed;
bottom:0;
width:750rpx;
box-sizing: border-box;
height: calc(100%/3);
background-color: #fff;
}
.key-board,.key-num{
display: flex;
justify-content: space-between;
}
.key-num{
// border:1px solid rgb(113, 225, 61);
width: 100%;
height: calc(100%/4);
box-sizing: border-box;
&-text{
border: 1rpx solid rgb(178, 178, 178);
width: 100%;
text-align: center;
padding-top: 12px;
}
}
.bg_red{
background-color: #f0f1f0 !important;
}
.key{
width:calc(100%/4*3);
}
.key-text{
border:1rpx solid rgb(178, 178, 178);
width: calc(100%/4*1);
height: 100%;
box-sizing: border-box;
}
.zero{
width: calc(100%/3*2);
box-sizing: border-box;
border: 1rpx solid rgb(178, 178, 178);
padding-top: 12px;
padding-left:calc(100%/3*0.45);
}
.point{
border: 1rpx solid rgb(178, 178, 178);
width: calc(100%/3*1);
box-sizing: border-box;
text-align: center;
padding-top: 12px;
}
.del{
height: 25%;
border-bottom: 1rpx solid rgb(178, 178, 178);
text-align: center;
padding-top: 12px;
box-sizing: border-box;
// background: url('@/assets/images/backspace.png') center no-repeat;
background: url('../../static/backspace.png') center no-repeat;
}
.sure-pay{
border-top: 1rpx solid rgb(178, 178, 178);
width: 100px;
height: 75%;
text-align: center;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
&-text{
width:40px;
margin: 50% auto;
color:#fff;
font-size: 40rpx;
}
background-color: #4EB331;
}
}
.refillCard{
display: flex;
justify-content: space-around;
.card{
border: 1rpx solid rgb(168, 172, 168);
width: 200rpx;
// box-shadow: 0 0 2rpx #7c7c7c;
// box-sizing: 10px 10px 5px #ff0000;
text-align: center;
height: 100rpx;
line-height: 50rpx;
border-radius: 20rpx;
background-color: #eee;
.discountPrice{
.text{
color: #ff1d15;
}
}
.originalPrice{
.text{
text-decoration: line-through;
}
}
}
}
</style>

64
src/uni.scss Normal file
View File

@@ -0,0 +1,64 @@
$jx-primary: #4eb331;
$jx-warring: #e70808;
$jx-login: #2dd091;
/* 行为相关颜色 */
$uni-color-primary: #007aff;
$uni-color-success: #4cd964;
$uni-color-warning: #f0ad4e;
$uni-color-error: #dd524d;
/* 文字基本颜色 */
$uni-text-color: #333; // 基本色
$uni-text-color-inverse: #fff; // 反色
$uni-text-color-grey: #999; // 辅助灰色,如加载更多的提示信息
$uni-text-color-placeholder: #808080;
$uni-text-color-disable: #c0c0c0;
/* 背景颜色 */
$uni-bg-color: #fff;
$uni-bg-color-grey: #f8f8f8;
$uni-bg-color-hover: #f1f1f1; // 点击状态颜色
$uni-bg-color-mask: rgba(0, 0, 0, 0.4); // 遮罩颜色
/* 边框颜色 */
$uni-border-color: #c8c7cc;
/* 尺寸变量 */
/* 文字尺寸 */
$uni-font-size-sm: 12px;
$uni-font-size-base: 14px;
$uni-font-size-lg: 16;
/* 图片尺寸 */
$uni-img-size-sm: 20px;
$uni-img-size-base: 26px;
$uni-img-size-lg: 40px;
/* Border Radius */
$uni-border-radius-sm: 2px;
$uni-border-radius-base: 3px;
$uni-border-radius-lg: 6px;
$uni-border-radius-circle: 50%;
/* 水平间距 */
$uni-spacing-row-sm: 5px;
$uni-spacing-row-base: 10px;
$uni-spacing-row-lg: 15px;
/* 垂直间距 */
$uni-spacing-col-sm: 4px;
$uni-spacing-col-base: 8px;
$uni-spacing-col-lg: 12px;
/* 透明度 */
$uni-opacity-disabled: 0.3; // 组件禁用态的透明度
/* 文章场景相关 */
$uni-color-title: #2c405a; // 文章标题颜色
$uni-font-size-title: 20px;
$uni-color-subtitle: #555; // 二级标题颜色
$uni-font-size-subtitle: 18px;
$uni-color-paragraph: #3f536e; // 文章段落颜色
$uni-font-size-paragraph: 15px;

View File

@@ -0,0 +1,121 @@
## 1.1.222025-09-19
- 修复 禁用状态下背景不生效的问题
## 1.1.212025-08-26
- 修复 在 @input 中修改 v-model 不生效的问题
## 1.1.202025-08-19
- 修复 微信小程序平台样式警告问题
## 1.1.192024-07-18
- 修复 初始值传入 null 导致input报错的bug
## 1.1.182024-04-11
- 修复 easyinput组件双向绑定问题
## 1.1.172024-03-28
- 修复 在头条小程序下丢失事件绑定的问题
## 1.1.162024-03-20
- 修复 在密码输入情况下 清除和小眼睛覆盖bug 在edge浏览器下显示双眼睛bug
## 1.1.152024-02-21
- 新增 左侧插槽left
## 1.1.142024-02-19
- 修复 onBlur的emit传值错误
## 1.1.122024-01-29
- 补充 adjust-position文档属性补充
## 1.1.112024-01-29
- 补充 adjust-position属性传递值Boolean当键盘弹起时是否自动上推页面
## 1.1.102024-01-22
- 去除 移除无用的log输出
## 1.1.92023-04-11
- 修复 vue3 下 keyboardheightchange 事件报错的bug
## 1.1.82023-03-29
- 优化 trim 属性默认值
## 1.1.72023-03-29
- 新增 cursor-spacing 属性
## 1.1.62023-01-28
- 新增 keyboardheightchange 事件,可监听键盘高度变化
## 1.1.52022-11-29
- 优化 主题样式
## 1.1.42022-10-27
- 修复 props 中背景颜色无默认值的bug
## 1.1.02022-06-30
- 新增 在 uni-forms 1.4.0 中使用可以在 blur 时校验内容
- 新增 clear 事件,点击右侧叉号图标触发
- 新增 change 事件 ,仅在输入框失去焦点或用户按下回车时触发
- 优化 组件样式,组件获取焦点时高亮显示,图标颜色调整等
## 1.0.52022-06-07
- 优化 clearable 显示策略
## 1.0.42022-06-07
- 优化 clearable 显示策略
## 1.0.32022-05-20
- 修复 关闭图标某些情况下无法取消的 bug
## 1.0.22022-04-12
- 修复 默认值不生效的 bug
## 1.0.12022-04-02
- 修复 value 不能为 0 的 bug
## 1.0.02021-11-19
- 优化 组件 UI并提供设计资源详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-easyinput](https://uniapp.dcloud.io/component/uniui/uni-easyinput)
## 0.1.42021-08-20
- 修复 在 uni-forms 的动态表单中默认值校验不通过的 bug
## 0.1.32021-08-11
- 修复 在 uni-forms 中重置表单,错误信息无法清除的问题
## 0.1.22021-07-30
- 优化 vue3 下事件警告的问题
## 0.1.1
- 优化 errorMessage 属性支持 Boolean 类型
## 0.1.02021-07-13
- 组件兼容 vue3如何创建 vue3 项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
## 0.0.162021-06-29
- 修复 confirmType 属性(仅 type="text" 生效)导致多行文本框无法换行的 bug
## 0.0.152021-06-21
- 修复 passwordIcon 属性拼写错误的 bug
## 0.0.142021-06-18
- 新增 passwordIcon 属性,当 type=password 时是否显示小眼睛图标
- 修复 confirmType 属性不生效的问题
## 0.0.132021-06-04
- 修复 disabled 状态可清出内容的 bug
## 0.0.122021-05-12
- 新增 组件示例地址
## 0.0.112021-05-07
- 修复 input-border 属性不生效的问题
## 0.0.102021-04-30
- 修复 ios 遮挡文字、显示一半的问题
## 0.0.92021-02-05
- 调整为 uni_modules 目录规范
- 优化 兼容 nvue 页面

View File

@@ -0,0 +1,54 @@
/**
* @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)
}
}
}
/**
* @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)
}
}
}
}

View File

@@ -0,0 +1,662 @@
<template>
<view class="uni-easyinput" :class="{ 'uni-easyinput-error': msg }" :style="boxStyle">
<view class="uni-easyinput__content" :class="inputContentClass" :style="inputContentStyle">
<uni-icons v-if="prefixIcon" class="content-clear-icon" :type="prefixIcon" color="#c0c4cc" @click="onClickIcon('prefix')" size="22"></uni-icons>
<slot name="left">
</slot>
<!-- #ifdef MP-ALIPAY -->
<textarea :enableNative="enableNative" v-if="type === 'textarea'" class="uni-easyinput__content-textarea" :class="{ 'input-padding': inputBorder }" :name="name" :value="val" :placeholder="placeholder" :placeholderStyle="placeholderStyle" :disabled="disabled" placeholder-class="uni-easyinput__placeholder-class" :maxlength="inputMaxlength" :focus="focused" :autoHeight="autoHeight" :cursor-spacing="cursorSpacing" :adjust-position="adjustPosition" @input="onInput" @blur="_Blur" @focus="_Focus" @confirm="onConfirm" @keyboardheightchange="onkeyboardheightchange"></textarea>
<input :enableNative="enableNative" v-else :type="type === 'password' ? 'text' : type" class="uni-easyinput__content-input" :style="inputStyle" :name="name" :value="val" :password="!showPassword && type === 'password'" :placeholder="placeholder" :placeholderStyle="placeholderStyle" placeholder-class="uni-easyinput__placeholder-class" :disabled="disabled" :maxlength="inputMaxlength" :focus="focused" :confirmType="confirmType" :cursor-spacing="cursorSpacing" :adjust-position="adjustPosition" @focus="_Focus" @blur="_Blur" @input="onInput" @confirm="onConfirm" @keyboardheightchange="onkeyboardheightchange" />
<!-- #endif -->
<!-- #ifndef MP-ALIPAY -->
<textarea v-if="type === 'textarea'" class="uni-easyinput__content-textarea" :class="{ 'input-padding': inputBorder }" :name="name" :value="val" :placeholder="placeholder" :placeholderStyle="placeholderStyle" :disabled="disabled" placeholder-class="uni-easyinput__placeholder-class" :maxlength="inputMaxlength" :focus="focused" :autoHeight="autoHeight" :cursor-spacing="cursorSpacing" :adjust-position="adjustPosition" @input="onInput" @blur="_Blur" @focus="_Focus" @confirm="onConfirm" @keyboardheightchange="onkeyboardheightchange"></textarea>
<input v-else :type="type === 'password' ? 'text' : type" class="uni-easyinput__content-input" :style="inputStyle" :name="name" :value="val" :password="!showPassword && type === 'password'" :placeholder="placeholder" :placeholderStyle="placeholderStyle" placeholder-class="uni-easyinput__placeholder-class" :disabled="disabled" :maxlength="inputMaxlength" :focus="focused" :confirmType="confirmType" :cursor-spacing="cursorSpacing" :adjust-position="adjustPosition" @focus="_Focus" @blur="_Blur" @input="onInput" @confirm="onConfirm" @keyboardheightchange="onkeyboardheightchange" />
<!-- #endif -->
<template v-if="type === 'password' && passwordIcon">
<!-- 开启密码时显示小眼睛 -->
<uni-icons v-if="isVal" class="content-clear-icon" :class="{ 'is-textarea-icon': type === 'textarea' }" :type="showPassword ? 'eye-slash-filled' : 'eye-filled'" :size="22" :color="focusShow ? primaryColor : '#c0c4cc'" @click="onEyes"></uni-icons>
</template>
<template v-if="suffixIcon">
<uni-icons v-if="suffixIcon" class="content-clear-icon" :type="suffixIcon" color="#c0c4cc" @click="onClickIcon('suffix')" size="22"></uni-icons>
</template>
<template v-else>
<uni-icons v-if="clearable && isVal && !disabled && type !== 'textarea'" class="content-clear-icon" :class="{ 'is-textarea-icon': type === 'textarea' }" type="clear" :size="clearSize" :color="msg ? '#dd524d' : focusShow ? primaryColor : '#c0c4cc'" @click="onClear"></uni-icons>
</template>
<slot name="right"></slot>
</view>
</view>
</template>
<script>
/**
* Easyinput 输入框
* @description 此组件可以实现表单的输入与校验,包括 "text" 和 "textarea" 类型。
* @tutorial https://ext.dcloud.net.cn/plugin?id=3455
* @property {String} value 输入内容
* @property {String } type 输入框的类型默认text password/text/textarea/..
* @value text 文本输入键盘
* @value textarea 多行文本输入键盘
* @value password 密码输入键盘
* @value number 数字输入键盘注意iOS上app-vue弹出的数字键盘并非9宫格方式
* @value idcard 身份证输入键盘信、支付宝、百度、QQ小程序
* @value digit 带小数点的数字键盘 App的nvue页面、微信、支付宝、百度、头条、QQ小程序支持
* @property {Boolean} clearable 是否显示右侧清空内容的图标控件点击可清空输入框内容默认true
* @property {Boolean} autoHeight 是否自动增高输入区域type为textarea时有效默认true
* @property {String } placeholder 输入框的提示文字
* @property {String } placeholderStyle placeholder的样式(内联样式,字符串),如"color: #ddd"
* @property {Boolean} focus 是否自动获得焦点默认false
* @property {Boolean} disabled 是否禁用默认false
* @property {Number } maxlength 最大输入长度,设置为 -1 的时候不限制最大长度默认140
* @property {String } confirmType 设置键盘右下角按钮的文字仅在type="text"时生效默认done
* @property {Number } clearSize 清除图标的大小单位px默认15
* @property {String} prefixIcon 输入框头部图标
* @property {String} suffixIcon 输入框尾部图标
* @property {String} primaryColor 设置主题色(默认#2979ff
* @property {Boolean} trim 是否自动去除两端的空格
* @property {Boolean} cursorSpacing 指定光标与键盘的距离,单位 px
* @property {Boolean} ajust-position 当键盘弹起时是否上推内容默认值true
* @value both 去除两端空格
* @value left 去除左侧空格
* @value right 去除右侧空格
* @value start 去除左侧空格
* @value end 去除右侧空格
* @value all 去除全部空格
* @value none 不去除空格
* @property {Boolean} inputBorder 是否显示input输入框的边框默认true
* @property {Boolean} passwordIcon type=password时是否显示小眼睛图标
* @property {Object} styles 自定义颜色
* @event {Function} input 输入框内容发生变化时触发
* @event {Function} focus 输入框获得焦点时触发
* @event {Function} blur 输入框失去焦点时触发
* @event {Function} confirm 点击完成按钮时触发
* @event {Function} iconClick 点击图标时触发
* @example <uni-easyinput v-model="mobile"></uni-easyinput>
*/
function obj2strClass(obj) {
let classess = '';
for (let key in obj) {
const val = obj[key];
if (val) {
classess += `${key} `;
}
}
return classess;
}
function obj2strStyle(obj) {
let style = '';
for (let key in obj) {
const val = obj[key];
style += `${key}:${val};`;
}
return style;
}
export default {
name: 'uni-easyinput',
emits: [
'click',
'iconClick',
'update:modelValue',
'input',
'focus',
'blur',
'confirm',
'clear',
'eyes',
'change',
'keyboardheightchange'
],
model: {
prop: 'modelValue',
event: 'update:modelValue'
},
options: {
// #ifdef MP-TOUTIAO
virtualHost: false,
// #endif
// #ifndef MP-TOUTIAO
virtualHost: true
// #endif
},
inject: {
form: {
from: 'uniForm',
default: null
},
formItem: {
from: 'uniFormItem',
default: null
}
},
props: {
name: String,
value: [Number, String],
modelValue: [Number, String],
type: {
type: String,
default: 'text'
},
clearable: {
type: Boolean,
default: true
},
autoHeight: {
type: Boolean,
default: false
},
placeholder: {
type: String,
default: ' '
},
placeholderStyle: String,
focus: {
type: Boolean,
default: false
},
disabled: {
type: Boolean,
default: false
},
maxlength: {
type: [Number, String],
default: 140
},
confirmType: {
type: String,
default: 'done'
},
clearSize: {
type: [Number, String],
default: 24
},
inputBorder: {
type: Boolean,
default: true
},
prefixIcon: {
type: String,
default: ''
},
suffixIcon: {
type: String,
default: ''
},
trim: {
type: [Boolean, String],
default: false
},
cursorSpacing: {
type: Number,
default: 0
},
passwordIcon: {
type: Boolean,
default: true
},
adjustPosition: {
type: Boolean,
default: true
},
primaryColor: {
type: String,
default: '#2979ff'
},
styles: {
type: Object,
default () {
return {
color: '#333',
backgroundColor: '#fff',
disableColor: '#F7F6F6',
borderColor: '#e5e5e5'
};
}
},
errorMessage: {
type: [String, Boolean],
default: ''
},
// #ifdef MP-ALIPAY
enableNative: {
type: Boolean,
default: false
}
// #endif
},
data() {
return {
focused: false,
val: '',
showMsg: '',
border: false,
isFirstBorder: false,
showClearIcon: false,
showPassword: false,
focusShow: false,
localMsg: '',
isEnter: false // 用于判断当前是否是使用回车操作
};
},
computed: {
// 输入框内是否有值
isVal() {
const val = this.val;
// fixed by mehaotian 处理值为0的情况字符串0不在处理范围
if (val || val === 0) {
return true;
}
return false;
},
msg() {
// console.log('computed', this.form, this.formItem);
// if (this.form) {
// return this.errorMessage || this.formItem.errMsg;
// }
// TODO 处理头条 formItem 中 errMsg 不更新的问题
return this.localMsg || this.errorMessage;
},
// 因为uniapp的input组件的maxlength组件必须要数值这里转为数值用户可以传入字符串数值
inputMaxlength() {
return Number(this.maxlength);
},
// 处理外层样式的style
boxStyle() {
return `color:${
this.inputBorder && this.msg ? '#e43d33' : this.styles.color
};`;
},
// input 内容的类和样式处理
inputContentClass() {
return obj2strClass({
'is-input-border': this.inputBorder,
'is-input-error-border': this.inputBorder && this.msg,
'is-textarea': this.type === 'textarea',
'is-disabled': this.disabled,
'is-focused': this.focusShow
});
},
inputContentStyle() {
const focusColor = this.focusShow ?
this.primaryColor :
this.styles.borderColor;
const borderColor =
this.inputBorder && this.msg ? '#dd524d' : focusColor;
return obj2strStyle({
'border-color': borderColor || '#e5e5e5',
'background-color': this.disabled ?
this.styles.disableColor : this.styles.backgroundColor
});
},
// input右侧样式
inputStyle() {
const paddingRight =
this.type === 'password' || this.clearable || this.prefixIcon ?
'' :
'10px';
return obj2strStyle({
'padding-right': paddingRight,
'padding-left': this.prefixIcon ? '' : '10px'
});
}
},
watch: {
value(newVal) {
// fix by mehaotian 解决 值为null的情况下input报错的bug
if (newVal === null) {
this.val = '';
return
}
this.val = newVal;
},
modelValue(newVal) {
if (newVal === null) {
this.val = '';
return
}
this.val = newVal;
},
focus(newVal) {
this.$nextTick(() => {
this.focused = this.focus;
this.focusShow = this.focus;
});
}
},
created() {
this.init();
// TODO 处理头条vue3 computed 不监听 inject 更改的问题formItem.errMsg
if (this.form && this.formItem) {
this.$watch('formItem.errMsg', newVal => {
this.localMsg = newVal;
});
}
},
mounted() {
this.$nextTick(() => {
this.focused = this.focus;
this.focusShow = this.focus;
});
},
methods: {
/**
* 初始化变量值
*/
init() {
if (this.value || this.value === 0) {
this.val = this.value;
} else if (
this.modelValue ||
this.modelValue === 0 ||
this.modelValue === ''
) {
this.val = this.modelValue;
} else {
// fix by ht 如果初始值为null则input报错待框架修复
this.val = '';
}
},
/**
* 点击图标时触发
* @param {Object} type
*/
onClickIcon(type) {
this.$emit('iconClick', type);
},
/**
* 显示隐藏内容,密码框时生效
*/
onEyes() {
this.showPassword = !this.showPassword;
this.$emit('eyes', this.showPassword);
},
/**
* 输入时触发
* @param {Object} event
*/
onInput(event) {
let value = event.detail.value;
// 判断是否去除空格
if (this.trim) {
if (typeof this.trim === 'boolean' && this.trim) {
value = this.trimStr(value);
}
if (typeof this.trim === 'string') {
value = this.trimStr(value, this.trim);
}
}
if (this.errMsg) this.errMsg = '';
this.val = value;
// TODO 兼容 vue3
this.$emit('update:modelValue', value);
// fix by ht input 修改一定要放在 update:modelvalue 后面避免在input中修改值导致 v-model 不生效
// TODO 兼容 vue2
this.$emit('input', value);
},
/**
* 外部调用方法
* 获取焦点时触发
* @param {Object} event
*/
onFocus() {
this.$nextTick(() => {
this.focused = true;
});
this.$emit('focus', null);
},
_Focus(event) {
this.focusShow = true;
this.$emit('focus', event);
},
/**
* 外部调用方法
* 失去焦点时触发
* @param {Object} event
*/
onBlur() {
this.focused = false;
this.$emit('blur', null);
},
_Blur(event) {
let value = event.detail.value;
this.focusShow = false;
this.$emit('blur', event);
// 根据类型返回值在event中获取的值理论上讲都是string
if (this.isEnter === false) {
this.$emit('change', this.val);
}
// 失去焦点时参与表单校验
if (this.form && this.formItem) {
const { validateTrigger } = this.form;
if (validateTrigger === 'blur') {
this.formItem.onFieldChange();
}
}
},
/**
* 按下键盘的发送键
* @param {Object} e
*/
onConfirm(e) {
this.$emit('confirm', this.val);
this.isEnter = true;
this.$emit('change', this.val);
this.$nextTick(() => {
this.isEnter = false;
});
},
/**
* 清理内容
* @param {Object} event
*/
onClear(event) {
this.val = '';
// TODO 兼容 vue2
this.$emit('input', '');
// TODO 兼容 vue2
// TODO 兼容 vue3
this.$emit('update:modelValue', '');
// 点击叉号触发
this.$emit('clear');
},
/**
* 键盘高度发生变化的时候触发此事件
* 兼容性微信小程序2.7.0+、App 3.1.0+
* @param {Object} event
*/
onkeyboardheightchange(event) {
this.$emit('keyboardheightchange', event);
},
/**
* 去除空格
*/
trimStr(str, pos = 'both') {
if (pos === 'both') {
return str.trim();
} else if (pos === 'left') {
return str.trimLeft();
} else if (pos === 'right') {
return str.trimRight();
} else if (pos === 'start') {
return str.trimStart();
} else if (pos === 'end') {
return str.trimEnd();
} else if (pos === 'all') {
return str.replace(/\s+/g, '');
} else if (pos === 'none') {
return str;
}
return str;
}
}
};
</script>
<style lang="scss">
$uni-error: #e43d33;
$uni-border-1: #dcdfe6 !default;
.uni-easyinput {
/* #ifndef APP-NVUE */
width: 100%;
/* #endif */
flex: 1;
position: relative;
text-align: left;
color: #333;
font-size: 14px;
}
.uni-easyinput__content {
flex: 1;
/* #ifndef APP-NVUE */
width: 100%;
display: flex;
box-sizing: border-box;
// min-height: 36px;
/* #endif */
flex-direction: row;
align-items: center;
// 处理border动画刚开始显示黑色的问题
border-color: #fff;
transition-property: border-color;
transition-duration: 0.3s;
}
.uni-easyinput__content-input {
/* #ifndef APP-NVUE */
width: auto;
/* #endif */
position: relative;
overflow: hidden;
flex: 1;
line-height: 1;
font-size: 14px;
height: 35px;
}
.uni-easyinput__placeholder-class {
color: #999;
font-size: 12px;
// font-weight: 200;
}
.is-textarea {
align-items: flex-start;
}
.is-textarea-icon {
margin-top: 5px;
}
.uni-easyinput__content-textarea {
position: relative;
overflow: hidden;
flex: 1;
line-height: 1.5;
font-size: 14px;
margin: 6px;
margin-left: 0;
height: 80px;
min-height: 80px;
/* #ifndef APP-NVUE */
min-height: 80px;
width: auto;
/* #endif */
}
.input-padding {
padding-left: 10px;
}
.content-clear-icon {
padding: 0 5px;
}
.label-icon {
margin-right: 5px;
margin-top: -1px;
}
// 显示边框
.is-input-border {
/* #ifndef APP-NVUE */
display: flex;
box-sizing: border-box;
/* #endif */
flex-direction: row;
align-items: center;
border: 1px solid $uni-border-1;
border-radius: 4px;
/* #ifdef MP-ALIPAY */
overflow: hidden;
/* #endif */
}
.uni-error-message {
position: absolute;
bottom: -17px;
left: 0;
line-height: 12px;
color: $uni-error;
font-size: 12px;
text-align: left;
}
.uni-error-msg--boeder {
position: relative;
bottom: 0;
line-height: 22px;
}
.is-input-error-border {
border-color: $uni-error;
.uni-easyinput__placeholder-class {
// color: mix(#fff, $uni-error, 50%);
}
}
.uni-easyinput--border {
margin-bottom: 0;
padding: 10px 15px;
// padding-bottom: 0;
border-top: 1px #eee solid;
}
.uni-easyinput-error {
padding-bottom: 0;
}
.is-first-border {
/* #ifndef APP-NVUE */
border: none;
/* #endif */
/* #ifdef APP-NVUE */
border-width: 0;
/* #endif */
}
.is-disabled {
background-color: #f7f6f6;
color: #d5d5d5;
.uni-easyinput__placeholder-class {
color: #d5d5d5;
font-size: 12px;
}
}
</style>

View File

@@ -0,0 +1,107 @@
{
"id": "uni-easyinput",
"displayName": "uni-easyinput 增强输入框",
"version": "1.1.22",
"description": "Easyinput 组件是对原生input组件的增强",
"keywords": [
"uni-ui",
"uniui",
"input",
"uni-easyinput",
"输入框"
],
"repository": "https://github.com/dcloudio/uni-ui",
"engines": {
"HBuilderX": "",
"uni-app": "^4.07",
"uni-app-x": ""
},
"directories": {
"example": "../../temps/example_temps"
},
"dcloudext": {
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
"type": "component-vue",
"darkmode": "x",
"i18n": "x",
"widescreen": "x"
},
"uni_modules": {
"dependencies": [
"uni-scss",
"uni-icons"
],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "x",
"aliyun": "x",
"alipay": "x"
},
"client": {
"uni-app": {
"vue": {
"vue2": "√",
"vue3": "√"
},
"web": {
"safari": "√",
"chrome": "√"
},
"app": {
"vue": "√",
"nvue": "-",
"android": "√",
"ios": "√",
"harmony": "√"
},
"mp": {
"weixin": "√",
"alipay": "√",
"toutiao": "√",
"baidu": "√",
"kuaishou": "√",
"jd": "√",
"harmony": "√",
"qq": "√",
"lark": "-"
},
"quickapp": {
"huawei": "-",
"union": "-"
}
},
"uni-app-x": {
"web": {
"safari": "-",
"chrome": "-"
},
"app": {
"android": "-",
"ios": "-",
"harmony": "-"
},
"mp": {
"weixin": "-"
}
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
### Easyinput 增强输入框
> **组件名uni-easyinput**
> 代码块: `uEasyinput`
easyinput 组件是对原生input组件的增强 ,是专门为配合表单组件[uni-forms](https://ext.dcloud.net.cn/plugin?id=2773)而设计的easyinput 内置了边框,图标等,同时包含 input 所有功能
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-easyinput)
#### 如使用过程中有任何问题或者您对uni-ui有一些好的建议欢迎加入 uni-ui 交流群871950839

View File

@@ -0,0 +1,44 @@
## 2.0.122025-08-26
- 优化 uni-app x 下 size 类型问题
## 2.0.112025-08-18
- 修复 图标点击事件返回
## 2.0.92024-01-12
fix: 修复图标大小默认值错误的问题
## 2.0.82023-12-14
- 修复 项目未使用 ts 情况下打包报错的bug
## 2.0.72023-12-14
- 修复 size 属性为 string 时不加单位导致尺寸异常的bug
## 2.0.62023-12-11
- 优化 兼容老版本icon类型如 top bottom 等
## 2.0.52023-12-11
- 优化 兼容老版本icon类型如 top bottom 等
## 2.0.42023-12-06
- 优化 uni-app x 下示例项目图标排序
## 2.0.32023-12-06
- 修复 nvue下引入组件报错的bug
## 2.0.22023-12-05
-优化 size 属性支持单位
## 2.0.12023-12-05
- 新增 uni-app x 支持定义图标
## 1.3.52022-01-24
- 优化 size 属性可以传入不带单位的字符串数值
## 1.3.42022-01-24
- 优化 size 支持其他单位
## 1.3.32022-01-17
- 修复 nvue 有些图标不显示的bug兼容老版本图标
## 1.3.22021-12-01
- 优化 示例可复制图标名称
## 1.3.12021-11-23
- 优化 兼容旧组件 type 值
## 1.3.02021-11-19
- 新增 更多图标
- 优化 自定义图标使用方式
- 优化 组件UI并提供设计资源详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-icons](https://uniapp.dcloud.io/component/uniui/uni-icons)
## 1.1.72021-11-08
## 1.2.02021-07-30
- 组件兼容 vue3如何创建vue3项目详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
## 1.1.52021-05-12
- 新增 组件示例地址
## 1.1.42021-02-05
- 调整为uni_modules目录规范

View File

@@ -0,0 +1,91 @@
<template>
<text class="uni-icons" :style="styleObj">
<slot>{{unicode}}</slot>
</text>
</template>
<script>
import { fontData, IconsDataItem } from './uniicons_file'
/**
* Icons 图标
* @description 用于展示 icon 图标
* @tutorial https://ext.dcloud.net.cn/plugin?id=28
* @property {Number} size 图标大小
* @property {String} type 图标图案,参考示例
* @property {String} color 图标颜色
* @property {String} customPrefix 自定义图标
* @event {Function} click 点击 Icon 触发事件
*/
export default {
name: "uni-icons",
props: {
type: {
type: String,
default: ''
},
color: {
type: String,
default: '#333333'
},
size: {
type: [Number, String],
default: 16
},
fontFamily: {
type: String,
default: ''
}
},
data() {
return {};
},
computed: {
unicode() : string {
let codes = fontData.find((item : IconsDataItem) : boolean => { return item.font_class == this.type })
if (codes !== null) {
return codes.unicode
}
return ''
},
iconSize() : string {
const size = this.size
if (typeof size == 'string') {
const reg = /^[0-9]*$/g
return reg.test(size as string) ? '' + size + 'px' : '' + size;
// return '' + this.size
}
return this.getFontSize(size as number)
},
styleObj() : UTSJSONObject {
if (this.fontFamily !== '') {
return { color: this.color, fontSize: this.iconSize, fontFamily: this.fontFamily }
}
return { color: this.color, fontSize: this.iconSize }
}
},
created() { },
methods: {
/**
* 字体大小
*/
getFontSize(size : number) : string {
return size + 'px';
},
},
}
</script>
<style scoped>
@font-face {
font-family: UniIconsFontFamily;
src: url('./uniicons.ttf');
}
.uni-icons {
font-family: UniIconsFontFamily;
font-size: 18px;
font-style: normal;
color: #333;
}
</style>

View File

@@ -0,0 +1,110 @@
<template>
<!-- #ifdef APP-NVUE -->
<text :style="styleObj" class="uni-icons" @click="_onClick">{{unicode}}</text>
<!-- #endif -->
<!-- #ifndef APP-NVUE -->
<text :style="styleObj" class="uni-icons" :class="['uniui-'+type,customPrefix,customPrefix?type:'']" @click="_onClick">
<slot></slot>
</text>
<!-- #endif -->
</template>
<script>
import { fontData } from './uniicons_file_vue.js';
const getVal = (val) => {
const reg = /^[0-9]*$/g
return (typeof val === 'number' || reg.test(val)) ? val + 'px' : val;
}
// #ifdef APP-NVUE
var domModule = weex.requireModule('dom');
import iconUrl from './uniicons.ttf'
domModule.addRule('fontFace', {
'fontFamily': "uniicons",
'src': "url('" + iconUrl + "')"
});
// #endif
/**
* Icons 图标
* @description 用于展示 icons 图标
* @tutorial https://ext.dcloud.net.cn/plugin?id=28
* @property {Number} size 图标大小
* @property {String} type 图标图案,参考示例
* @property {String} color 图标颜色
* @property {String} customPrefix 自定义图标
* @event {Function} click 点击 Icon 触发事件
*/
export default {
name: 'UniIcons',
emits: ['click'],
props: {
type: {
type: String,
default: ''
},
color: {
type: String,
default: '#333333'
},
size: {
type: [Number, String],
default: 16
},
customPrefix: {
type: String,
default: ''
},
fontFamily: {
type: String,
default: ''
}
},
data() {
return {
icons: fontData
}
},
computed: {
unicode() {
let code = this.icons.find(v => v.font_class === this.type)
if (code) {
return code.unicode
}
return ''
},
iconSize() {
return getVal(this.size)
},
styleObj() {
if (this.fontFamily !== '') {
return `color: ${this.color}; font-size: ${this.iconSize}; font-family: ${this.fontFamily};`
}
return `color: ${this.color}; font-size: ${this.iconSize};`
}
},
methods: {
_onClick(e) {
this.$emit('click', e)
}
}
}
</script>
<style lang="scss">
/* #ifndef APP-NVUE */
@import './uniicons.css';
@font-face {
font-family: uniicons;
src: url('./uniicons.ttf');
}
/* #endif */
.uni-icons {
font-family: uniicons;
text-decoration: none;
text-align: center;
}
</style>

View File

@@ -0,0 +1,664 @@
.uniui-cart-filled:before {
content: "\e6d0";
}
.uniui-gift-filled:before {
content: "\e6c4";
}
.uniui-color:before {
content: "\e6cf";
}
.uniui-wallet:before {
content: "\e6b1";
}
.uniui-settings-filled:before {
content: "\e6ce";
}
.uniui-auth-filled:before {
content: "\e6cc";
}
.uniui-shop-filled:before {
content: "\e6cd";
}
.uniui-staff-filled:before {
content: "\e6cb";
}
.uniui-vip-filled:before {
content: "\e6c6";
}
.uniui-plus-filled:before {
content: "\e6c7";
}
.uniui-folder-add-filled:before {
content: "\e6c8";
}
.uniui-color-filled:before {
content: "\e6c9";
}
.uniui-tune-filled:before {
content: "\e6ca";
}
.uniui-calendar-filled:before {
content: "\e6c0";
}
.uniui-notification-filled:before {
content: "\e6c1";
}
.uniui-wallet-filled:before {
content: "\e6c2";
}
.uniui-medal-filled:before {
content: "\e6c3";
}
.uniui-fire-filled:before {
content: "\e6c5";
}
.uniui-refreshempty:before {
content: "\e6bf";
}
.uniui-location-filled:before {
content: "\e6af";
}
.uniui-person-filled:before {
content: "\e69d";
}
.uniui-personadd-filled:before {
content: "\e698";
}
.uniui-arrowthinleft:before {
content: "\e6d2";
}
.uniui-arrowthinup:before {
content: "\e6d3";
}
.uniui-arrowthindown:before {
content: "\e6d4";
}
.uniui-back:before {
content: "\e6b9";
}
.uniui-forward:before {
content: "\e6ba";
}
.uniui-arrow-right:before {
content: "\e6bb";
}
.uniui-arrow-left:before {
content: "\e6bc";
}
.uniui-arrow-up:before {
content: "\e6bd";
}
.uniui-arrow-down:before {
content: "\e6be";
}
.uniui-arrowthinright:before {
content: "\e6d1";
}
.uniui-down:before {
content: "\e6b8";
}
.uniui-bottom:before {
content: "\e6b8";
}
.uniui-arrowright:before {
content: "\e6d5";
}
.uniui-right:before {
content: "\e6b5";
}
.uniui-up:before {
content: "\e6b6";
}
.uniui-top:before {
content: "\e6b6";
}
.uniui-left:before {
content: "\e6b7";
}
.uniui-arrowup:before {
content: "\e6d6";
}
.uniui-eye:before {
content: "\e651";
}
.uniui-eye-filled:before {
content: "\e66a";
}
.uniui-eye-slash:before {
content: "\e6b3";
}
.uniui-eye-slash-filled:before {
content: "\e6b4";
}
.uniui-info-filled:before {
content: "\e649";
}
.uniui-reload:before {
content: "\e6b2";
}
.uniui-micoff-filled:before {
content: "\e6b0";
}
.uniui-map-pin-ellipse:before {
content: "\e6ac";
}
.uniui-map-pin:before {
content: "\e6ad";
}
.uniui-location:before {
content: "\e6ae";
}
.uniui-starhalf:before {
content: "\e683";
}
.uniui-star:before {
content: "\e688";
}
.uniui-star-filled:before {
content: "\e68f";
}
.uniui-calendar:before {
content: "\e6a0";
}
.uniui-fire:before {
content: "\e6a1";
}
.uniui-medal:before {
content: "\e6a2";
}
.uniui-font:before {
content: "\e6a3";
}
.uniui-gift:before {
content: "\e6a4";
}
.uniui-link:before {
content: "\e6a5";
}
.uniui-notification:before {
content: "\e6a6";
}
.uniui-staff:before {
content: "\e6a7";
}
.uniui-vip:before {
content: "\e6a8";
}
.uniui-folder-add:before {
content: "\e6a9";
}
.uniui-tune:before {
content: "\e6aa";
}
.uniui-auth:before {
content: "\e6ab";
}
.uniui-person:before {
content: "\e699";
}
.uniui-email-filled:before {
content: "\e69a";
}
.uniui-phone-filled:before {
content: "\e69b";
}
.uniui-phone:before {
content: "\e69c";
}
.uniui-email:before {
content: "\e69e";
}
.uniui-personadd:before {
content: "\e69f";
}
.uniui-chatboxes-filled:before {
content: "\e692";
}
.uniui-contact:before {
content: "\e693";
}
.uniui-chatbubble-filled:before {
content: "\e694";
}
.uniui-contact-filled:before {
content: "\e695";
}
.uniui-chatboxes:before {
content: "\e696";
}
.uniui-chatbubble:before {
content: "\e697";
}
.uniui-upload-filled:before {
content: "\e68e";
}
.uniui-upload:before {
content: "\e690";
}
.uniui-weixin:before {
content: "\e691";
}
.uniui-compose:before {
content: "\e67f";
}
.uniui-qq:before {
content: "\e680";
}
.uniui-download-filled:before {
content: "\e681";
}
.uniui-pyq:before {
content: "\e682";
}
.uniui-sound:before {
content: "\e684";
}
.uniui-trash-filled:before {
content: "\e685";
}
.uniui-sound-filled:before {
content: "\e686";
}
.uniui-trash:before {
content: "\e687";
}
.uniui-videocam-filled:before {
content: "\e689";
}
.uniui-spinner-cycle:before {
content: "\e68a";
}
.uniui-weibo:before {
content: "\e68b";
}
.uniui-videocam:before {
content: "\e68c";
}
.uniui-download:before {
content: "\e68d";
}
.uniui-help:before {
content: "\e679";
}
.uniui-navigate-filled:before {
content: "\e67a";
}
.uniui-plusempty:before {
content: "\e67b";
}
.uniui-smallcircle:before {
content: "\e67c";
}
.uniui-minus-filled:before {
content: "\e67d";
}
.uniui-micoff:before {
content: "\e67e";
}
.uniui-closeempty:before {
content: "\e66c";
}
.uniui-clear:before {
content: "\e66d";
}
.uniui-navigate:before {
content: "\e66e";
}
.uniui-minus:before {
content: "\e66f";
}
.uniui-image:before {
content: "\e670";
}
.uniui-mic:before {
content: "\e671";
}
.uniui-paperplane:before {
content: "\e672";
}
.uniui-close:before {
content: "\e673";
}
.uniui-help-filled:before {
content: "\e674";
}
.uniui-paperplane-filled:before {
content: "\e675";
}
.uniui-plus:before {
content: "\e676";
}
.uniui-mic-filled:before {
content: "\e677";
}
.uniui-image-filled:before {
content: "\e678";
}
.uniui-locked-filled:before {
content: "\e668";
}
.uniui-info:before {
content: "\e669";
}
.uniui-locked:before {
content: "\e66b";
}
.uniui-camera-filled:before {
content: "\e658";
}
.uniui-chat-filled:before {
content: "\e659";
}
.uniui-camera:before {
content: "\e65a";
}
.uniui-circle:before {
content: "\e65b";
}
.uniui-checkmarkempty:before {
content: "\e65c";
}
.uniui-chat:before {
content: "\e65d";
}
.uniui-circle-filled:before {
content: "\e65e";
}
.uniui-flag:before {
content: "\e65f";
}
.uniui-flag-filled:before {
content: "\e660";
}
.uniui-gear-filled:before {
content: "\e661";
}
.uniui-home:before {
content: "\e662";
}
.uniui-home-filled:before {
content: "\e663";
}
.uniui-gear:before {
content: "\e664";
}
.uniui-smallcircle-filled:before {
content: "\e665";
}
.uniui-map-filled:before {
content: "\e666";
}
.uniui-map:before {
content: "\e667";
}
.uniui-refresh-filled:before {
content: "\e656";
}
.uniui-refresh:before {
content: "\e657";
}
.uniui-cloud-upload:before {
content: "\e645";
}
.uniui-cloud-download-filled:before {
content: "\e646";
}
.uniui-cloud-download:before {
content: "\e647";
}
.uniui-cloud-upload-filled:before {
content: "\e648";
}
.uniui-redo:before {
content: "\e64a";
}
.uniui-images-filled:before {
content: "\e64b";
}
.uniui-undo-filled:before {
content: "\e64c";
}
.uniui-more:before {
content: "\e64d";
}
.uniui-more-filled:before {
content: "\e64e";
}
.uniui-undo:before {
content: "\e64f";
}
.uniui-images:before {
content: "\e650";
}
.uniui-paperclip:before {
content: "\e652";
}
.uniui-settings:before {
content: "\e653";
}
.uniui-search:before {
content: "\e654";
}
.uniui-redo-filled:before {
content: "\e655";
}
.uniui-list:before {
content: "\e644";
}
.uniui-mail-open-filled:before {
content: "\e63a";
}
.uniui-hand-down-filled:before {
content: "\e63c";
}
.uniui-hand-down:before {
content: "\e63d";
}
.uniui-hand-up-filled:before {
content: "\e63e";
}
.uniui-hand-up:before {
content: "\e63f";
}
.uniui-heart-filled:before {
content: "\e641";
}
.uniui-mail-open:before {
content: "\e643";
}
.uniui-heart:before {
content: "\e639";
}
.uniui-loop:before {
content: "\e633";
}
.uniui-pulldown:before {
content: "\e632";
}
.uniui-scan:before {
content: "\e62a";
}
.uniui-bars:before {
content: "\e627";
}
.uniui-checkbox:before {
content: "\e62b";
}
.uniui-checkbox-filled:before {
content: "\e62c";
}
.uniui-shop:before {
content: "\e62f";
}
.uniui-headphones:before {
content: "\e630";
}
.uniui-cart:before {
content: "\e631";
}

View File

@@ -0,0 +1,664 @@
export type IconsData = {
id : string
name : string
font_family : string
css_prefix_text : string
description : string
glyphs : Array<IconsDataItem>
}
export type IconsDataItem = {
font_class : string
unicode : string
}
export const fontData = [
{
"font_class": "arrow-down",
"unicode": "\ue6be"
},
{
"font_class": "arrow-left",
"unicode": "\ue6bc"
},
{
"font_class": "arrow-right",
"unicode": "\ue6bb"
},
{
"font_class": "arrow-up",
"unicode": "\ue6bd"
},
{
"font_class": "auth",
"unicode": "\ue6ab"
},
{
"font_class": "auth-filled",
"unicode": "\ue6cc"
},
{
"font_class": "back",
"unicode": "\ue6b9"
},
{
"font_class": "bars",
"unicode": "\ue627"
},
{
"font_class": "calendar",
"unicode": "\ue6a0"
},
{
"font_class": "calendar-filled",
"unicode": "\ue6c0"
},
{
"font_class": "camera",
"unicode": "\ue65a"
},
{
"font_class": "camera-filled",
"unicode": "\ue658"
},
{
"font_class": "cart",
"unicode": "\ue631"
},
{
"font_class": "cart-filled",
"unicode": "\ue6d0"
},
{
"font_class": "chat",
"unicode": "\ue65d"
},
{
"font_class": "chat-filled",
"unicode": "\ue659"
},
{
"font_class": "chatboxes",
"unicode": "\ue696"
},
{
"font_class": "chatboxes-filled",
"unicode": "\ue692"
},
{
"font_class": "chatbubble",
"unicode": "\ue697"
},
{
"font_class": "chatbubble-filled",
"unicode": "\ue694"
},
{
"font_class": "checkbox",
"unicode": "\ue62b"
},
{
"font_class": "checkbox-filled",
"unicode": "\ue62c"
},
{
"font_class": "checkmarkempty",
"unicode": "\ue65c"
},
{
"font_class": "circle",
"unicode": "\ue65b"
},
{
"font_class": "circle-filled",
"unicode": "\ue65e"
},
{
"font_class": "clear",
"unicode": "\ue66d"
},
{
"font_class": "close",
"unicode": "\ue673"
},
{
"font_class": "closeempty",
"unicode": "\ue66c"
},
{
"font_class": "cloud-download",
"unicode": "\ue647"
},
{
"font_class": "cloud-download-filled",
"unicode": "\ue646"
},
{
"font_class": "cloud-upload",
"unicode": "\ue645"
},
{
"font_class": "cloud-upload-filled",
"unicode": "\ue648"
},
{
"font_class": "color",
"unicode": "\ue6cf"
},
{
"font_class": "color-filled",
"unicode": "\ue6c9"
},
{
"font_class": "compose",
"unicode": "\ue67f"
},
{
"font_class": "contact",
"unicode": "\ue693"
},
{
"font_class": "contact-filled",
"unicode": "\ue695"
},
{
"font_class": "down",
"unicode": "\ue6b8"
},
{
"font_class": "bottom",
"unicode": "\ue6b8"
},
{
"font_class": "download",
"unicode": "\ue68d"
},
{
"font_class": "download-filled",
"unicode": "\ue681"
},
{
"font_class": "email",
"unicode": "\ue69e"
},
{
"font_class": "email-filled",
"unicode": "\ue69a"
},
{
"font_class": "eye",
"unicode": "\ue651"
},
{
"font_class": "eye-filled",
"unicode": "\ue66a"
},
{
"font_class": "eye-slash",
"unicode": "\ue6b3"
},
{
"font_class": "eye-slash-filled",
"unicode": "\ue6b4"
},
{
"font_class": "fire",
"unicode": "\ue6a1"
},
{
"font_class": "fire-filled",
"unicode": "\ue6c5"
},
{
"font_class": "flag",
"unicode": "\ue65f"
},
{
"font_class": "flag-filled",
"unicode": "\ue660"
},
{
"font_class": "folder-add",
"unicode": "\ue6a9"
},
{
"font_class": "folder-add-filled",
"unicode": "\ue6c8"
},
{
"font_class": "font",
"unicode": "\ue6a3"
},
{
"font_class": "forward",
"unicode": "\ue6ba"
},
{
"font_class": "gear",
"unicode": "\ue664"
},
{
"font_class": "gear-filled",
"unicode": "\ue661"
},
{
"font_class": "gift",
"unicode": "\ue6a4"
},
{
"font_class": "gift-filled",
"unicode": "\ue6c4"
},
{
"font_class": "hand-down",
"unicode": "\ue63d"
},
{
"font_class": "hand-down-filled",
"unicode": "\ue63c"
},
{
"font_class": "hand-up",
"unicode": "\ue63f"
},
{
"font_class": "hand-up-filled",
"unicode": "\ue63e"
},
{
"font_class": "headphones",
"unicode": "\ue630"
},
{
"font_class": "heart",
"unicode": "\ue639"
},
{
"font_class": "heart-filled",
"unicode": "\ue641"
},
{
"font_class": "help",
"unicode": "\ue679"
},
{
"font_class": "help-filled",
"unicode": "\ue674"
},
{
"font_class": "home",
"unicode": "\ue662"
},
{
"font_class": "home-filled",
"unicode": "\ue663"
},
{
"font_class": "image",
"unicode": "\ue670"
},
{
"font_class": "image-filled",
"unicode": "\ue678"
},
{
"font_class": "images",
"unicode": "\ue650"
},
{
"font_class": "images-filled",
"unicode": "\ue64b"
},
{
"font_class": "info",
"unicode": "\ue669"
},
{
"font_class": "info-filled",
"unicode": "\ue649"
},
{
"font_class": "left",
"unicode": "\ue6b7"
},
{
"font_class": "link",
"unicode": "\ue6a5"
},
{
"font_class": "list",
"unicode": "\ue644"
},
{
"font_class": "location",
"unicode": "\ue6ae"
},
{
"font_class": "location-filled",
"unicode": "\ue6af"
},
{
"font_class": "locked",
"unicode": "\ue66b"
},
{
"font_class": "locked-filled",
"unicode": "\ue668"
},
{
"font_class": "loop",
"unicode": "\ue633"
},
{
"font_class": "mail-open",
"unicode": "\ue643"
},
{
"font_class": "mail-open-filled",
"unicode": "\ue63a"
},
{
"font_class": "map",
"unicode": "\ue667"
},
{
"font_class": "map-filled",
"unicode": "\ue666"
},
{
"font_class": "map-pin",
"unicode": "\ue6ad"
},
{
"font_class": "map-pin-ellipse",
"unicode": "\ue6ac"
},
{
"font_class": "medal",
"unicode": "\ue6a2"
},
{
"font_class": "medal-filled",
"unicode": "\ue6c3"
},
{
"font_class": "mic",
"unicode": "\ue671"
},
{
"font_class": "mic-filled",
"unicode": "\ue677"
},
{
"font_class": "micoff",
"unicode": "\ue67e"
},
{
"font_class": "micoff-filled",
"unicode": "\ue6b0"
},
{
"font_class": "minus",
"unicode": "\ue66f"
},
{
"font_class": "minus-filled",
"unicode": "\ue67d"
},
{
"font_class": "more",
"unicode": "\ue64d"
},
{
"font_class": "more-filled",
"unicode": "\ue64e"
},
{
"font_class": "navigate",
"unicode": "\ue66e"
},
{
"font_class": "navigate-filled",
"unicode": "\ue67a"
},
{
"font_class": "notification",
"unicode": "\ue6a6"
},
{
"font_class": "notification-filled",
"unicode": "\ue6c1"
},
{
"font_class": "paperclip",
"unicode": "\ue652"
},
{
"font_class": "paperplane",
"unicode": "\ue672"
},
{
"font_class": "paperplane-filled",
"unicode": "\ue675"
},
{
"font_class": "person",
"unicode": "\ue699"
},
{
"font_class": "person-filled",
"unicode": "\ue69d"
},
{
"font_class": "personadd",
"unicode": "\ue69f"
},
{
"font_class": "personadd-filled",
"unicode": "\ue698"
},
{
"font_class": "personadd-filled-copy",
"unicode": "\ue6d1"
},
{
"font_class": "phone",
"unicode": "\ue69c"
},
{
"font_class": "phone-filled",
"unicode": "\ue69b"
},
{
"font_class": "plus",
"unicode": "\ue676"
},
{
"font_class": "plus-filled",
"unicode": "\ue6c7"
},
{
"font_class": "plusempty",
"unicode": "\ue67b"
},
{
"font_class": "pulldown",
"unicode": "\ue632"
},
{
"font_class": "pyq",
"unicode": "\ue682"
},
{
"font_class": "qq",
"unicode": "\ue680"
},
{
"font_class": "redo",
"unicode": "\ue64a"
},
{
"font_class": "redo-filled",
"unicode": "\ue655"
},
{
"font_class": "refresh",
"unicode": "\ue657"
},
{
"font_class": "refresh-filled",
"unicode": "\ue656"
},
{
"font_class": "refreshempty",
"unicode": "\ue6bf"
},
{
"font_class": "reload",
"unicode": "\ue6b2"
},
{
"font_class": "right",
"unicode": "\ue6b5"
},
{
"font_class": "scan",
"unicode": "\ue62a"
},
{
"font_class": "search",
"unicode": "\ue654"
},
{
"font_class": "settings",
"unicode": "\ue653"
},
{
"font_class": "settings-filled",
"unicode": "\ue6ce"
},
{
"font_class": "shop",
"unicode": "\ue62f"
},
{
"font_class": "shop-filled",
"unicode": "\ue6cd"
},
{
"font_class": "smallcircle",
"unicode": "\ue67c"
},
{
"font_class": "smallcircle-filled",
"unicode": "\ue665"
},
{
"font_class": "sound",
"unicode": "\ue684"
},
{
"font_class": "sound-filled",
"unicode": "\ue686"
},
{
"font_class": "spinner-cycle",
"unicode": "\ue68a"
},
{
"font_class": "staff",
"unicode": "\ue6a7"
},
{
"font_class": "staff-filled",
"unicode": "\ue6cb"
},
{
"font_class": "star",
"unicode": "\ue688"
},
{
"font_class": "star-filled",
"unicode": "\ue68f"
},
{
"font_class": "starhalf",
"unicode": "\ue683"
},
{
"font_class": "trash",
"unicode": "\ue687"
},
{
"font_class": "trash-filled",
"unicode": "\ue685"
},
{
"font_class": "tune",
"unicode": "\ue6aa"
},
{
"font_class": "tune-filled",
"unicode": "\ue6ca"
},
{
"font_class": "undo",
"unicode": "\ue64f"
},
{
"font_class": "undo-filled",
"unicode": "\ue64c"
},
{
"font_class": "up",
"unicode": "\ue6b6"
},
{
"font_class": "top",
"unicode": "\ue6b6"
},
{
"font_class": "upload",
"unicode": "\ue690"
},
{
"font_class": "upload-filled",
"unicode": "\ue68e"
},
{
"font_class": "videocam",
"unicode": "\ue68c"
},
{
"font_class": "videocam-filled",
"unicode": "\ue689"
},
{
"font_class": "vip",
"unicode": "\ue6a8"
},
{
"font_class": "vip-filled",
"unicode": "\ue6c6"
},
{
"font_class": "wallet",
"unicode": "\ue6b1"
},
{
"font_class": "wallet-filled",
"unicode": "\ue6c2"
},
{
"font_class": "weibo",
"unicode": "\ue68b"
},
{
"font_class": "weixin",
"unicode": "\ue691"
}
] as IconsDataItem[]
// export const fontData = JSON.parse<IconsDataItem>(fontDataJson)

View File

@@ -0,0 +1,649 @@
export const fontData = [
{
"font_class": "arrow-down",
"unicode": "\ue6be"
},
{
"font_class": "arrow-left",
"unicode": "\ue6bc"
},
{
"font_class": "arrow-right",
"unicode": "\ue6bb"
},
{
"font_class": "arrow-up",
"unicode": "\ue6bd"
},
{
"font_class": "auth",
"unicode": "\ue6ab"
},
{
"font_class": "auth-filled",
"unicode": "\ue6cc"
},
{
"font_class": "back",
"unicode": "\ue6b9"
},
{
"font_class": "bars",
"unicode": "\ue627"
},
{
"font_class": "calendar",
"unicode": "\ue6a0"
},
{
"font_class": "calendar-filled",
"unicode": "\ue6c0"
},
{
"font_class": "camera",
"unicode": "\ue65a"
},
{
"font_class": "camera-filled",
"unicode": "\ue658"
},
{
"font_class": "cart",
"unicode": "\ue631"
},
{
"font_class": "cart-filled",
"unicode": "\ue6d0"
},
{
"font_class": "chat",
"unicode": "\ue65d"
},
{
"font_class": "chat-filled",
"unicode": "\ue659"
},
{
"font_class": "chatboxes",
"unicode": "\ue696"
},
{
"font_class": "chatboxes-filled",
"unicode": "\ue692"
},
{
"font_class": "chatbubble",
"unicode": "\ue697"
},
{
"font_class": "chatbubble-filled",
"unicode": "\ue694"
},
{
"font_class": "checkbox",
"unicode": "\ue62b"
},
{
"font_class": "checkbox-filled",
"unicode": "\ue62c"
},
{
"font_class": "checkmarkempty",
"unicode": "\ue65c"
},
{
"font_class": "circle",
"unicode": "\ue65b"
},
{
"font_class": "circle-filled",
"unicode": "\ue65e"
},
{
"font_class": "clear",
"unicode": "\ue66d"
},
{
"font_class": "close",
"unicode": "\ue673"
},
{
"font_class": "closeempty",
"unicode": "\ue66c"
},
{
"font_class": "cloud-download",
"unicode": "\ue647"
},
{
"font_class": "cloud-download-filled",
"unicode": "\ue646"
},
{
"font_class": "cloud-upload",
"unicode": "\ue645"
},
{
"font_class": "cloud-upload-filled",
"unicode": "\ue648"
},
{
"font_class": "color",
"unicode": "\ue6cf"
},
{
"font_class": "color-filled",
"unicode": "\ue6c9"
},
{
"font_class": "compose",
"unicode": "\ue67f"
},
{
"font_class": "contact",
"unicode": "\ue693"
},
{
"font_class": "contact-filled",
"unicode": "\ue695"
},
{
"font_class": "down",
"unicode": "\ue6b8"
},
{
"font_class": "bottom",
"unicode": "\ue6b8"
},
{
"font_class": "download",
"unicode": "\ue68d"
},
{
"font_class": "download-filled",
"unicode": "\ue681"
},
{
"font_class": "email",
"unicode": "\ue69e"
},
{
"font_class": "email-filled",
"unicode": "\ue69a"
},
{
"font_class": "eye",
"unicode": "\ue651"
},
{
"font_class": "eye-filled",
"unicode": "\ue66a"
},
{
"font_class": "eye-slash",
"unicode": "\ue6b3"
},
{
"font_class": "eye-slash-filled",
"unicode": "\ue6b4"
},
{
"font_class": "fire",
"unicode": "\ue6a1"
},
{
"font_class": "fire-filled",
"unicode": "\ue6c5"
},
{
"font_class": "flag",
"unicode": "\ue65f"
},
{
"font_class": "flag-filled",
"unicode": "\ue660"
},
{
"font_class": "folder-add",
"unicode": "\ue6a9"
},
{
"font_class": "folder-add-filled",
"unicode": "\ue6c8"
},
{
"font_class": "font",
"unicode": "\ue6a3"
},
{
"font_class": "forward",
"unicode": "\ue6ba"
},
{
"font_class": "gear",
"unicode": "\ue664"
},
{
"font_class": "gear-filled",
"unicode": "\ue661"
},
{
"font_class": "gift",
"unicode": "\ue6a4"
},
{
"font_class": "gift-filled",
"unicode": "\ue6c4"
},
{
"font_class": "hand-down",
"unicode": "\ue63d"
},
{
"font_class": "hand-down-filled",
"unicode": "\ue63c"
},
{
"font_class": "hand-up",
"unicode": "\ue63f"
},
{
"font_class": "hand-up-filled",
"unicode": "\ue63e"
},
{
"font_class": "headphones",
"unicode": "\ue630"
},
{
"font_class": "heart",
"unicode": "\ue639"
},
{
"font_class": "heart-filled",
"unicode": "\ue641"
},
{
"font_class": "help",
"unicode": "\ue679"
},
{
"font_class": "help-filled",
"unicode": "\ue674"
},
{
"font_class": "home",
"unicode": "\ue662"
},
{
"font_class": "home-filled",
"unicode": "\ue663"
},
{
"font_class": "image",
"unicode": "\ue670"
},
{
"font_class": "image-filled",
"unicode": "\ue678"
},
{
"font_class": "images",
"unicode": "\ue650"
},
{
"font_class": "images-filled",
"unicode": "\ue64b"
},
{
"font_class": "info",
"unicode": "\ue669"
},
{
"font_class": "info-filled",
"unicode": "\ue649"
},
{
"font_class": "left",
"unicode": "\ue6b7"
},
{
"font_class": "link",
"unicode": "\ue6a5"
},
{
"font_class": "list",
"unicode": "\ue644"
},
{
"font_class": "location",
"unicode": "\ue6ae"
},
{
"font_class": "location-filled",
"unicode": "\ue6af"
},
{
"font_class": "locked",
"unicode": "\ue66b"
},
{
"font_class": "locked-filled",
"unicode": "\ue668"
},
{
"font_class": "loop",
"unicode": "\ue633"
},
{
"font_class": "mail-open",
"unicode": "\ue643"
},
{
"font_class": "mail-open-filled",
"unicode": "\ue63a"
},
{
"font_class": "map",
"unicode": "\ue667"
},
{
"font_class": "map-filled",
"unicode": "\ue666"
},
{
"font_class": "map-pin",
"unicode": "\ue6ad"
},
{
"font_class": "map-pin-ellipse",
"unicode": "\ue6ac"
},
{
"font_class": "medal",
"unicode": "\ue6a2"
},
{
"font_class": "medal-filled",
"unicode": "\ue6c3"
},
{
"font_class": "mic",
"unicode": "\ue671"
},
{
"font_class": "mic-filled",
"unicode": "\ue677"
},
{
"font_class": "micoff",
"unicode": "\ue67e"
},
{
"font_class": "micoff-filled",
"unicode": "\ue6b0"
},
{
"font_class": "minus",
"unicode": "\ue66f"
},
{
"font_class": "minus-filled",
"unicode": "\ue67d"
},
{
"font_class": "more",
"unicode": "\ue64d"
},
{
"font_class": "more-filled",
"unicode": "\ue64e"
},
{
"font_class": "navigate",
"unicode": "\ue66e"
},
{
"font_class": "navigate-filled",
"unicode": "\ue67a"
},
{
"font_class": "notification",
"unicode": "\ue6a6"
},
{
"font_class": "notification-filled",
"unicode": "\ue6c1"
},
{
"font_class": "paperclip",
"unicode": "\ue652"
},
{
"font_class": "paperplane",
"unicode": "\ue672"
},
{
"font_class": "paperplane-filled",
"unicode": "\ue675"
},
{
"font_class": "person",
"unicode": "\ue699"
},
{
"font_class": "person-filled",
"unicode": "\ue69d"
},
{
"font_class": "personadd",
"unicode": "\ue69f"
},
{
"font_class": "personadd-filled",
"unicode": "\ue698"
},
{
"font_class": "personadd-filled-copy",
"unicode": "\ue6d1"
},
{
"font_class": "phone",
"unicode": "\ue69c"
},
{
"font_class": "phone-filled",
"unicode": "\ue69b"
},
{
"font_class": "plus",
"unicode": "\ue676"
},
{
"font_class": "plus-filled",
"unicode": "\ue6c7"
},
{
"font_class": "plusempty",
"unicode": "\ue67b"
},
{
"font_class": "pulldown",
"unicode": "\ue632"
},
{
"font_class": "pyq",
"unicode": "\ue682"
},
{
"font_class": "qq",
"unicode": "\ue680"
},
{
"font_class": "redo",
"unicode": "\ue64a"
},
{
"font_class": "redo-filled",
"unicode": "\ue655"
},
{
"font_class": "refresh",
"unicode": "\ue657"
},
{
"font_class": "refresh-filled",
"unicode": "\ue656"
},
{
"font_class": "refreshempty",
"unicode": "\ue6bf"
},
{
"font_class": "reload",
"unicode": "\ue6b2"
},
{
"font_class": "right",
"unicode": "\ue6b5"
},
{
"font_class": "scan",
"unicode": "\ue62a"
},
{
"font_class": "search",
"unicode": "\ue654"
},
{
"font_class": "settings",
"unicode": "\ue653"
},
{
"font_class": "settings-filled",
"unicode": "\ue6ce"
},
{
"font_class": "shop",
"unicode": "\ue62f"
},
{
"font_class": "shop-filled",
"unicode": "\ue6cd"
},
{
"font_class": "smallcircle",
"unicode": "\ue67c"
},
{
"font_class": "smallcircle-filled",
"unicode": "\ue665"
},
{
"font_class": "sound",
"unicode": "\ue684"
},
{
"font_class": "sound-filled",
"unicode": "\ue686"
},
{
"font_class": "spinner-cycle",
"unicode": "\ue68a"
},
{
"font_class": "staff",
"unicode": "\ue6a7"
},
{
"font_class": "staff-filled",
"unicode": "\ue6cb"
},
{
"font_class": "star",
"unicode": "\ue688"
},
{
"font_class": "star-filled",
"unicode": "\ue68f"
},
{
"font_class": "starhalf",
"unicode": "\ue683"
},
{
"font_class": "trash",
"unicode": "\ue687"
},
{
"font_class": "trash-filled",
"unicode": "\ue685"
},
{
"font_class": "tune",
"unicode": "\ue6aa"
},
{
"font_class": "tune-filled",
"unicode": "\ue6ca"
},
{
"font_class": "undo",
"unicode": "\ue64f"
},
{
"font_class": "undo-filled",
"unicode": "\ue64c"
},
{
"font_class": "up",
"unicode": "\ue6b6"
},
{
"font_class": "top",
"unicode": "\ue6b6"
},
{
"font_class": "upload",
"unicode": "\ue690"
},
{
"font_class": "upload-filled",
"unicode": "\ue68e"
},
{
"font_class": "videocam",
"unicode": "\ue68c"
},
{
"font_class": "videocam-filled",
"unicode": "\ue689"
},
{
"font_class": "vip",
"unicode": "\ue6a8"
},
{
"font_class": "vip-filled",
"unicode": "\ue6c6"
},
{
"font_class": "wallet",
"unicode": "\ue6b1"
},
{
"font_class": "wallet-filled",
"unicode": "\ue6c2"
},
{
"font_class": "weibo",
"unicode": "\ue68b"
},
{
"font_class": "weixin",
"unicode": "\ue691"
}
]
// export const fontData = JSON.parse<IconsDataItem>(fontDataJson)

View File

@@ -0,0 +1,111 @@
{
"id": "uni-icons",
"displayName": "uni-icons 图标",
"version": "2.0.12",
"description": "图标组件,用于展示移动端常见的图标,可自定义颜色、大小。",
"keywords": [
"uni-ui",
"uniui",
"icon",
"图标"
],
"repository": "https://github.com/dcloudio/uni-ui",
"engines": {
"HBuilderX": "^3.2.14",
"uni-app": "^4.08",
"uni-app-x": "^4.61"
},
"directories": {
"example": "../../temps/example_temps"
},
"dcloudext": {
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
"type": "component-vue",
"darkmode": "x",
"i18n": "x",
"widescreen": "x"
},
"uni_modules": {
"dependencies": [
"uni-scss"
],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "x",
"aliyun": "x",
"alipay": "x"
},
"client": {
"uni-app": {
"vue": {
"vue2": "√",
"vue3": "√"
},
"web": {
"safari": "√",
"chrome": "√"
},
"app": {
"vue": "√",
"nvue": "-",
"android": {
"extVersion": "",
"minVersion": "29"
},
"ios": "√",
"harmony": "√"
},
"mp": {
"weixin": "√",
"alipay": "√",
"toutiao": "√",
"baidu": "√",
"kuaishou": "-",
"jd": "-",
"harmony": "-",
"qq": "√",
"lark": "-"
},
"quickapp": {
"huawei": "√",
"union": "√"
}
},
"uni-app-x": {
"web": {
"safari": "√",
"chrome": "√"
},
"app": {
"android": {
"extVersion": "",
"minVersion": "29"
},
"ios": "√",
"harmony": "√"
},
"mp": {
"weixin": "√"
}
}
}
}
}
}

View File

@@ -0,0 +1,8 @@
## Icons 图标
> **组件名uni-icons**
> 代码块: `uIcons`
用于展示 icons 图标 。
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-icons)
#### 如使用过程中有任何问题或者您对uni-ui有一些好的建议欢迎加入 uni-ui 交流群871950839

View File

@@ -0,0 +1,104 @@
## 1.9.122026-03-26
- 修复 uni-app x 下类型错误导致的编译问题
## 1.9.112025-08-20
- 修复 uni-popup-dialog组件设置 borderRadius 不生效的 Bug
## 1.9.102025-07-18
- 修复 nvue 下弹窗样式错乱的问题 ,更新依赖 uni-transition 组件
- 更新 示例取消 borderRadius 属性 ,如需内容圆角,用户应该直接在内容插槽中实现
## 1.9.92025-06-11
- 修复 uni-popup-dialog 中 setVal 方法报错的问题
- 修复 uni-popup-dialog 数据双向绑定问题。
## 1.9.82025-04-16
- 修复 更新组件示例 ,解决更新数据或保存项目导致弹窗消失的问题
## 1.9.72025-04-14
- 修复 uni-popup-dialog 弹出框在vue3中双向绑定问题
## 1.9.62025-01-08
- 修复 示例中过期图片地址
## 1.9.52024-10-15
- 修复 微信小程序中的getSystemInfo警告
## 1.9.22024-09-21
- 修复 uni-popup在android上的重复点击弹出位置不正确的bug
## 1.9.12024-04-02
- 修复 uni-popup-dialog vue3下使用value无法进行绑定的bug(双向绑定兼容旧写法)
## 1.9.02024-03-28
- 修复 uni-popup-dialog 双向绑定时初始化逻辑修正
## 1.8.92024-03-20
- 修复 uni-popup-dialog 数据输入时修正为双向绑定
## 1.8.82024-02-20
- 修复 uni-popup 在微信小程序下出现文字向上闪动的bug
## 1.8.72024-02-02
- 新增 uni-popup-dialog 新增属性focusinput模式下是否自动自动聚焦
## 1.8.62024-01-30
- 新增 uni-popup-dialog 新增属性maxLength:限制输入框字数
## 1.8.52024-01-26
- 新增 uni-popup-dialog 新增属性showClose:控制关闭按钮的显示
## 1.8.42023-11-15
- 新增 uni-popup 支持uni-app-x 注意暂时仅支持 `maskClick` `@open` `@close`
## 1.8.32023-04-17
- 修复 uni-popup 重复打开时的 bug
## 1.8.22023-02-02
- uni-popup-dialog 组件新增 inputType 属性
## 1.8.12022-12-01
- 修复 nvue 下 v-show 报错
## 1.8.02022-11-29
- 优化 主题样式
## 1.7.92022-04-02
- 修复 弹出层内部无法滚动的bug
## 1.7.82022-03-28
- 修复 小程序中高度错误的bug
## 1.7.72022-03-17
- 修复 快速调用open出现问题的Bug
## 1.7.62022-02-14
- 修复 safeArea 属性不能设置为false的bug
## 1.7.52022-01-19
- 修复 isMaskClick 失效的bug
## 1.7.42022-01-19
- 新增 cancelText \ confirmText 属性 ,可自定义文本
- 新增 maskBackgroundColor 属性 ,可以修改蒙版颜色
- 优化 maskClick属性 更新为 isMaskClick ,解决微信小程序警告的问题
## 1.7.32022-01-13
- 修复 设置 safeArea 属性不生效的bug
## 1.7.22021-11-26
- 优化 组件示例
## 1.7.12021-11-26
- 修复 vuedoc 文字错误
## 1.7.02021-11-19
- 优化 组件UI并提供设计资源详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-popup](https://uniapp.dcloud.io/component/uniui/uni-popup)
## 1.6.22021-08-24
- 新增 支持国际化
## 1.6.12021-07-30
- 优化 vue3下事件警告的问题
## 1.6.02021-07-13
- 组件兼容 vue3如何创建vue3项目详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
## 1.5.02021-06-23
- 新增 mask-click 遮罩层点击事件
## 1.4.52021-06-22
- 修复 nvue 平台中间弹出后点击内容再点击遮罩无法关闭的Bug
## 1.4.42021-06-18
- 修复 H5平台中间弹出后点击内容再点击遮罩无法关闭的Bug
## 1.4.32021-06-08
- 修复 错误的 watch 字段
- 修复 safeArea 属性不生效的问题
- 修复 点击内容再点击遮罩无法关闭的Bug
## 1.4.22021-05-12
- 新增 组件示例地址
## 1.4.12021-04-29
- 修复 组件内放置 input 、textarea 组件,无法聚焦的问题
## 1.4.0 2021-04-29
- 新增 type 属性的 left\right 值,支持左右弹出
- 新增 open(String:type) 方法参数 ,可以省略 type 属性 ,直接传入类型打开指定弹窗
- 新增 backgroundColor 属性,可定义主窗口背景色,默认不显示背景色
- 新增 safeArea 属性,是否适配底部安全区
- 修复 App\h5\微信小程序底部安全区占位不对的Bug
- 修复 App 端弹出等待的Bug
- 优化 提升低配设备性能,优化动画卡顿问题
- 优化 更简单的组件自定义方式
## 1.2.92021-02-05
- 优化 组件引用关系通过uni_modules引用组件
## 1.2.82021-02-05
- 调整为uni_modules目录规范
## 1.2.72021-02-05
- 调整为uni_modules目录规范
- 新增 支持 PC 端
- 新增 uni-popup-message 、uni-popup-dialog扩展组件支持 PC 端

View File

@@ -0,0 +1,45 @@
// #ifdef H5
export default {
name: 'Keypress',
props: {
disable: {
type: Boolean,
default: false
}
},
mounted () {
const keyNames = {
esc: ['Esc', 'Escape'],
tab: 'Tab',
enter: 'Enter',
space: [' ', 'Spacebar'],
up: ['Up', 'ArrowUp'],
left: ['Left', 'ArrowLeft'],
right: ['Right', 'ArrowRight'],
down: ['Down', 'ArrowDown'],
delete: ['Backspace', 'Delete', 'Del']
}
const listener = ($event) => {
if (this.disable) {
return
}
const keyName = Object.keys(keyNames).find(key => {
const keyName = $event.key
const value = keyNames[key]
return value === keyName || (Array.isArray(value) && value.includes(keyName))
})
if (keyName) {
// 避免和其他按键事件冲突
setTimeout(() => {
this.$emit(keyName, {})
}, 0)
}
}
document.addEventListener('keyup', listener)
this.$once('hook:beforeDestroy', () => {
document.removeEventListener('keyup', listener)
})
},
render: () => {}
}
// #endif

View File

@@ -0,0 +1,330 @@
<template>
<view class="uni-popup-dialog" :style="{ borderRadius }">
<view class="uni-dialog-title">
<text class="uni-dialog-title-text" :class="['uni-popup__'+dialogType]">{{titleText}}</text>
</view>
<view v-if="mode === 'base'" class="uni-dialog-content">
<slot>
<text class="uni-dialog-content-text">{{content}}</text>
</slot>
</view>
<view v-else class="uni-dialog-content">
<slot>
<input class="uni-dialog-input" :maxlength="maxlength" v-model="val" :type="inputType"
:placeholder="placeholderText" :focus="focus">
</slot>
</view>
<view class="uni-dialog-button-group">
<view class="uni-dialog-button" v-if="showClose" @click="closeDialog">
<text class="uni-dialog-button-text">{{closeText}}</text>
</view>
<view class="uni-dialog-button" :class="showClose?'uni-border-left':''" @click="onOk">
<text class="uni-dialog-button-text uni-button-color">{{okText}}</text>
</view>
</view>
</view>
</template>
<script>
import popup from '../uni-popup/popup.js'
import {
initVueI18n
} from '@dcloudio/uni-i18n'
import messages from '../uni-popup/i18n/index.js'
const {
t
} = initVueI18n(messages)
/**
* PopUp 弹出层-对话框样式
* @description 弹出层-对话框样式
* @tutorial https://ext.dcloud.net.cn/plugin?id=329
* @property {String} value input 模式下的默认值
* @property {String} placeholder input 模式下输入提示
* @property {Boolean} focus input模式下是否自动聚焦默认为true
* @property {String} type = [success|warning|info|error] 主题样式
* @value success 成功
* @value warning 提示
* @value info 消息
* @value error 错误
* @property {String} mode = [base|input] 模式、
* @value base 基础对话框
* @value input 可输入对话框
* @showClose {Boolean} 是否显示关闭按钮
* @property {String} content 对话框内容
* @property {Boolean} beforeClose 是否拦截取消事件
* @property {Number} maxlength 输入
* @event {Function} confirm 点击确认按钮触发
* @event {Function} close 点击取消按钮触发
*/
export default {
name: "uniPopupDialog",
mixins: [popup],
emits: ['confirm', 'close', 'update:modelValue', 'input'],
props: {
inputType: {
type: String,
default: 'text'
},
showClose: {
type: Boolean,
default: true
},
// #ifdef VUE2
value: {
type: [String, Number],
default: ''
},
// #endif
// #ifdef VUE3
modelValue: {
type: [Number, String],
default: ''
},
// #endif
placeholder: {
type: [String, Number],
default: ''
},
type: {
type: String,
default: 'error'
},
mode: {
type: String,
default: 'base'
},
title: {
type: String,
default: ''
},
content: {
type: String,
default: ''
},
beforeClose: {
type: Boolean,
default: false
},
cancelText: {
type: String,
default: ''
},
confirmText: {
type: String,
default: ''
},
maxlength: {
type: Number,
default: -1,
},
focus: {
type: Boolean,
default: true,
},
borderRadius: {
type: String,
default: '11px',
}
},
data() {
return {
dialogType: 'error',
val: ""
}
},
computed: {
okText() {
return this.confirmText || t("uni-popup.ok")
},
closeText() {
return this.cancelText || t("uni-popup.cancel")
},
placeholderText() {
return this.placeholder || t("uni-popup.placeholder")
},
titleText() {
return this.title || t("uni-popup.title")
}
},
watch: {
type(val) {
this.dialogType = val
},
mode(val) {
if (val === 'input') {
this.dialogType = 'info'
}
},
value(val) {
this.setVal(val)
},
// #ifdef VUE3
modelValue(val) {
this.setVal(val)
},
// #endif
val(val) {
// #ifdef VUE2
// TODO 兼容 vue2
this.$emit('input', val);
// #endif
// #ifdef VUE3
// TODO 兼容 vue3
this.$emit('update:modelValue', val);
// #endif
}
},
created() {
// 对话框遮罩不可点击
this.popup.disableMask()
// this.popup.closeMask()
if (this.mode === 'input') {
this.dialogType = 'info'
this.val = this.value;
// #ifdef VUE3
this.val = this.modelValue;
// #endif
} else {
this.dialogType = this.type
}
},
methods: {
/**
* 给val属性赋值
*/
setVal(val) {
if (this.maxlength != -1 && this.mode === 'input') {
this.val = val.slice(0, this.maxlength);
} else {
this.val = val
}
},
/**
* 点击确认按钮
*/
onOk() {
if (this.mode === 'input') {
this.$emit('confirm', this.val)
} else {
this.$emit('confirm')
}
if (this.beforeClose) return
this.popup.close()
},
/**
* 点击取消按钮
*/
closeDialog() {
this.$emit('close')
if (this.beforeClose) return
this.popup.close()
},
close() {
this.popup.close()
}
}
}
</script>
<style lang="scss">
.uni-popup-dialog {
width: 300px;
background-color: #fff;
}
.uni-dialog-title {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
justify-content: center;
padding-top: 25px;
}
.uni-dialog-title-text {
font-size: 16px;
font-weight: 500;
}
.uni-dialog-content {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
justify-content: center;
align-items: center;
padding: 20px;
}
.uni-dialog-content-text {
font-size: 14px;
color: #6C6C6C;
}
.uni-dialog-button-group {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
border-top-color: #f5f5f5;
border-top-style: solid;
border-top-width: 1px;
}
.uni-dialog-button {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex: 1;
flex-direction: row;
justify-content: center;
align-items: center;
height: 45px;
}
.uni-border-left {
border-left-color: #f0f0f0;
border-left-style: solid;
border-left-width: 1px;
}
.uni-dialog-button-text {
font-size: 16px;
color: #333;
}
.uni-button-color {
color: #007aff;
}
.uni-dialog-input {
flex: 1;
font-size: 14px;
border: 1px #eee solid;
height: 40px;
padding: 0 10px;
border-radius: 5px;
color: #555;
}
.uni-popup__success {
color: #4cd964;
}
.uni-popup__warn {
color: #f0ad4e;
}
.uni-popup__error {
color: #dd524d;
}
.uni-popup__info {
color: #909399;
}
</style>

View File

@@ -0,0 +1,143 @@
<template>
<view class="uni-popup-message">
<view class="uni-popup-message__box fixforpc-width" :class="'uni-popup__'+type">
<slot>
<text class="uni-popup-message-text" :class="'uni-popup__'+type+'-text'">{{message}}</text>
</slot>
</view>
</view>
</template>
<script>
import popup from '../uni-popup/popup.js'
/**
* PopUp 弹出层-消息提示
* @description 弹出层-消息提示
* @tutorial https://ext.dcloud.net.cn/plugin?id=329
* @property {String} type = [success|warning|info|error] 主题样式
* @value success 成功
* @value warning 提示
* @value info 消息
* @value error 错误
* @property {String} message 消息提示文字
* @property {String} duration 显示时间,设置为 0 则不会自动关闭
*/
export default {
name: 'uniPopupMessage',
mixins:[popup],
props: {
/**
* 主题 success/warning/info/error 默认 success
*/
type: {
type: String,
default: 'success'
},
/**
* 消息文字
*/
message: {
type: String,
default: ''
},
/**
* 显示时间,设置为 0 则不会自动关闭
*/
duration: {
type: Number,
default: 3000
},
maskShow:{
type:Boolean,
default:false
}
},
data() {
return {}
},
created() {
this.popup.maskShow = this.maskShow
this.popup.messageChild = this
},
methods: {
timerClose(){
if(this.duration === 0) return
clearTimeout(this.timer)
this.timer = setTimeout(()=>{
this.popup.close()
},this.duration)
}
}
}
</script>
<style lang="scss" >
.uni-popup-message {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
justify-content: center;
}
.uni-popup-message__box {
background-color: #e1f3d8;
padding: 10px 15px;
border-color: #eee;
border-style: solid;
border-width: 1px;
flex: 1;
}
@media screen and (min-width: 500px) {
.fixforpc-width {
margin-top: 20px;
border-radius: 4px;
flex: none;
min-width: 380px;
/* #ifndef APP-NVUE */
max-width: 50%;
/* #endif */
/* #ifdef APP-NVUE */
max-width: 500px;
/* #endif */
}
}
.uni-popup-message-text {
font-size: 14px;
padding: 0;
}
.uni-popup__success {
background-color: #e1f3d8;
}
.uni-popup__success-text {
color: #67C23A;
}
.uni-popup__warn {
background-color: #faecd8;
}
.uni-popup__warn-text {
color: #E6A23C;
}
.uni-popup__error {
background-color: #fde2e2;
}
.uni-popup__error-text {
color: #F56C6C;
}
.uni-popup__info {
background-color: #F2F6FC;
}
.uni-popup__info-text {
color: #909399;
}
</style>

View File

@@ -0,0 +1,188 @@
<template>
<view class="uni-popup-share">
<view class="uni-share-title"><text class="uni-share-title-text">{{shareTitleText}}</text></view>
<view class="uni-share-content">
<view class="uni-share-content-box">
<view class="uni-share-content-item" v-for="(item,index) in bottomData" :key="index" @click.stop="select(item,index)">
<image class="uni-share-image" :src="item.icon" mode="aspectFill"></image>
<text class="uni-share-text">{{item.text}}</text>
</view>
</view>
</view>
<view class="uni-share-button-box">
<button class="uni-share-button" @click="close">{{cancelText}}</button>
</view>
</view>
</template>
<script>
import popup from '../uni-popup/popup.js'
import {
initVueI18n
} from '@dcloudio/uni-i18n'
import messages from '../uni-popup/i18n/index.js'
const { t } = initVueI18n(messages)
export default {
name: 'UniPopupShare',
mixins:[popup],
emits:['select'],
props: {
title: {
type: String,
default: ''
},
beforeClose: {
type: Boolean,
default: false
}
},
data() {
return {
// TODO 替换为自己的图标
bottomData: [{
text: '微信',
icon: 'https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/unicloudlogo.png',
name: 'wx'
},
{
text: '支付宝',
icon: 'https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/unicloudlogo.png',
name: 'ali'
},
{
text: 'QQ',
icon: 'https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/unicloudlogo.png',
name: 'qq'
},
{
text: '新浪',
icon: 'https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/unicloudlogo.png',
name: 'sina'
},
// {
// text: '百度',
// icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/1ec6e920-50bf-11eb-8a36-ebb87efcf8c0.png',
// name: 'copy'
// },
// {
// text: '其他',
// icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/2e0fdfe0-50bf-11eb-b997-9918a5dda011.png',
// name: 'more'
// }
]
}
},
created() {},
computed: {
cancelText() {
return t("uni-popup.cancel")
},
shareTitleText() {
return this.title || t("uni-popup.shareTitle")
}
},
methods: {
/**
* 选择内容
*/
select(item, index) {
this.$emit('select', {
item,
index
})
this.close()
},
/**
* 关闭窗口
*/
close() {
if(this.beforeClose) return
this.popup.close()
}
}
}
</script>
<style lang="scss" >
.uni-popup-share {
background-color: #fff;
border-top-left-radius: 11px;
border-top-right-radius: 11px;
}
.uni-share-title {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
align-items: center;
justify-content: center;
height: 40px;
}
.uni-share-title-text {
font-size: 14px;
color: #666;
}
.uni-share-content {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
justify-content: center;
padding-top: 10px;
}
.uni-share-content-box {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
flex-wrap: wrap;
width: 360px;
}
.uni-share-content-item {
width: 90px;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
justify-content: center;
padding: 10px 0;
align-items: center;
}
.uni-share-content-item:active {
background-color: #f5f5f5;
}
.uni-share-image {
width: 30px;
height: 30px;
}
.uni-share-text {
margin-top: 10px;
font-size: 14px;
color: #3B4144;
}
.uni-share-button-box {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
padding: 10px 15px;
}
.uni-share-button {
flex: 1;
border-radius: 50px;
color: #666;
font-size: 16px;
}
.uni-share-button::after {
border-radius: 50px;
}
</style>

View File

@@ -0,0 +1,7 @@
{
"uni-popup.cancel": "cancel",
"uni-popup.ok": "ok",
"uni-popup.placeholder": "pleace enter",
"uni-popup.title": "Hint",
"uni-popup.shareTitle": "Share to"
}

View File

@@ -0,0 +1,8 @@
import en from './en.json'
import zhHans from './zh-Hans.json'
import zhHant from './zh-Hant.json'
export default {
en,
'zh-Hans': zhHans,
'zh-Hant': zhHant
}

View File

@@ -0,0 +1,7 @@
{
"uni-popup.cancel": "取消",
"uni-popup.ok": "确定",
"uni-popup.placeholder": "请输入",
"uni-popup.title": "提示",
"uni-popup.shareTitle": "分享到"
}

View File

@@ -0,0 +1,7 @@
{
"uni-popup.cancel": "取消",
"uni-popup.ok": "確定",
"uni-popup.placeholder": "請輸入",
"uni-popup.title": "提示",
"uni-popup.shareTitle": "分享到"
}

View File

@@ -0,0 +1,45 @@
// #ifdef H5
export default {
name: 'Keypress',
props: {
disable: {
type: Boolean,
default: false
}
},
mounted () {
const keyNames = {
esc: ['Esc', 'Escape'],
tab: 'Tab',
enter: 'Enter',
space: [' ', 'Spacebar'],
up: ['Up', 'ArrowUp'],
left: ['Left', 'ArrowLeft'],
right: ['Right', 'ArrowRight'],
down: ['Down', 'ArrowDown'],
delete: ['Backspace', 'Delete', 'Del']
}
const listener = ($event) => {
if (this.disable) {
return
}
const keyName = Object.keys(keyNames).find(key => {
const keyName = $event.key
const value = keyNames[key]
return value === keyName || (Array.isArray(value) && value.includes(keyName))
})
if (keyName) {
// 避免和其他按键事件冲突
setTimeout(() => {
this.$emit(keyName, {})
}, 0)
}
}
document.addEventListener('keyup', listener)
// this.$once('hook:beforeDestroy', () => {
// document.removeEventListener('keyup', listener)
// })
},
render: () => {}
}
// #endif

View File

@@ -0,0 +1,26 @@
export default {
data() {
return {
}
},
created(){
this.popup = this.getParent()
},
methods:{
/**
* 获取父元素实例
*/
getParent(name = 'uniPopup') {
let parent = this.$parent;
let parentName = parent.$options.name;
while (parentName !== name) {
parent = parent.$parent;
if (!parent) return false
parentName = parent.$options.name;
}
return parent;
},
}
}

View File

@@ -0,0 +1,90 @@
<template>
<view class="popup-root" v-if="isOpen" v-show="isShow" @click="clickMask">
<view @click.stop>
<slot></slot>
</view>
</view>
</template>
<script>
type CloseCallBack = ()=> void;
let closeCallBack:CloseCallBack = () :void => {};
export default {
emits:["close","clickMask"],
data() {
return {
isShow:false,
isOpen:false
}
},
props: {
maskClick: {
type: Boolean,
default: true
},
},
watch: {
// 设置show = true 时,如果没有 open 需要设置为 open
isShow:{
handler(isShow: boolean) {
// console.log("isShow",isShow)
if(isShow && this.isOpen == false){
this.isOpen = true
}
},
immediate:true
},
// 设置isOpen = true 时,如果没有 isShow 需要设置为 isShow
isOpen:{
handler(isOpen: boolean) {
// console.log("isOpen",isOpen)
if(isOpen && this.isShow == false){
this.isShow = true
}
},
immediate:true
}
},
methods:{
open(){
// ...funs : CloseCallBack[]
// if(funs.length > 0){
// closeCallBack = funs[0]
// }
this.isOpen = true;
},
clickMask(){
if(this.maskClick == true){
this.$emit('clickMask')
this.close()
}
},
close(): void{
this.isOpen = false;
this.$emit('close')
closeCallBack()
},
hiden(){
this.isShow = false
},
show(){
this.isShow = true
}
}
}
</script>
<style>
.popup-root {
position: fixed;
top: 0;
left: 0;
width: 750rpx;
height: 100%;
flex: 1;
background-color: rgba(0, 0, 0, 0.3);
justify-content: center;
align-items: center;
z-index: 99;
}
</style>

View File

@@ -0,0 +1,518 @@
<template>
<view v-if="showPopup" class="uni-popup" :class="[popupstyle, isDesktop ? 'fixforpc-z-index' : '']">
<view @touchstart="touchstart">
<uni-transition key="1" v-if="maskShow" name="mask" mode-class="fade" :styles="maskClass"
:duration="duration" :show="showTrans" @click="onTap" />
<uni-transition key="2" :mode-class="ani" name="content" :styles="transClass" :duration="duration"
:show="showTrans" @click="onTap">
<view class="uni-popup__wrapper" :style="getStyles" :class="[popupstyle]" @click="clear">
<slot />
</view>
</uni-transition>
</view>
<!-- #ifdef H5 -->
<keypress v-if="maskShow" @esc="onTap" />
<!-- #endif -->
</view>
</template>
<script>
// #ifdef H5
import keypress from './keypress.js'
// #endif
/**
* PopUp 弹出层
* @description 弹出层组件,为了解决遮罩弹层的问题
* @tutorial https://ext.dcloud.net.cn/plugin?id=329
* @property {String} type = [top|center|bottom|left|right|message|dialog|share] 弹出方式
* @value top 顶部弹出
* @value center 中间弹出
* @value bottom 底部弹出
* @value left 左侧弹出
* @value right 右侧弹出
* @value message 消息提示
* @value dialog 对话框
* @value share 底部分享示例
* @property {Boolean} animation = [true|false] 是否开启动画
* @property {Boolean} maskClick = [true|false] 蒙版点击是否关闭弹窗(废弃)
* @property {Boolean} isMaskClick = [true|false] 蒙版点击是否关闭弹窗
* @property {String} backgroundColor 主窗口背景色
* @property {String} maskBackgroundColor 蒙版颜色
* @property {String} borderRadius 设置圆角(左上、右上、右下和左下) 示例:"10px 10px 10px 10px"
* @property {Boolean} safeArea 是否适配底部安全区
* @event {Function} change 打开关闭弹窗触发e={show: false}
* @event {Function} maskClick 点击遮罩触发
*/
export default {
name: 'uniPopup',
components: {
// #ifdef H5
keypress
// #endif
},
emits: ['change', 'maskClick'],
props: {
// 开启动画
animation: {
type: Boolean,
default: true
},
// 弹出层类型可选值top: 顶部弹出层bottom底部弹出层center全屏弹出层
// message: 消息提示 ; dialog : 对话框
type: {
type: String,
default: 'center'
},
// maskClick
isMaskClick: {
type: Boolean,
default: null
},
// TODO 2 个版本后废弃属性 ,使用 isMaskClick
maskClick: {
type: Boolean,
default: null
},
backgroundColor: {
type: String,
default: 'none'
},
safeArea: {
type: Boolean,
default: true
},
maskBackgroundColor: {
type: String,
default: 'rgba(0, 0, 0, 0.4)'
},
borderRadius:{
type: String,
}
},
watch: {
/**
* 监听type类型
*/
type: {
handler: function(type) {
if (!this.config[type]) return
this[this.config[type]](true)
},
immediate: true
},
isDesktop: {
handler: function(newVal) {
if (!this.config[newVal]) return
this[this.config[this.type]](true)
},
immediate: true
},
/**
* 监听遮罩是否可点击
* @param {Object} val
*/
maskClick: {
handler: function(val) {
this.mkclick = val
},
immediate: true
},
isMaskClick: {
handler: function(val) {
this.mkclick = val
},
immediate: true
},
// H5 下禁止底部滚动
showPopup(show) {
// #ifdef H5
// fix by mehaotian 处理 h5 滚动穿透的问题
document.getElementsByTagName('body')[0].style.overflow = show ? 'hidden' : 'visible'
// #endif
}
},
data() {
return {
duration: 300,
ani: [],
showPopup: false,
showTrans: false,
popupWidth: 0,
popupHeight: 0,
config: {
top: 'top',
bottom: 'bottom',
center: 'center',
left: 'left',
right: 'right',
message: 'top',
dialog: 'center',
share: 'bottom'
},
maskClass: {
position: 'fixed',
bottom: 0,
top: 0,
left: 0,
right: 0,
backgroundColor: 'rgba(0, 0, 0, 0.4)'
},
transClass: {
backgroundColor: 'transparent',
borderRadius: this.borderRadius || "0",
position: 'fixed',
left: 0,
right: 0
},
maskShow: true,
mkclick: true,
popupstyle: 'top'
}
},
computed: {
getStyles() {
let res = { backgroundColor: this.bg };
if (this.borderRadius || "0") {
res = Object.assign(res, { borderRadius: this.borderRadius })
}
return res;
},
isDesktop() {
return this.popupWidth >= 500 && this.popupHeight >= 500
},
bg() {
if (this.backgroundColor === '' || this.backgroundColor === 'none') {
return 'transparent'
}
return this.backgroundColor
}
},
mounted() {
const fixSize = () => {
// #ifdef MP-WEIXIN
const {
windowWidth,
windowHeight,
windowTop,
safeArea,
screenHeight,
safeAreaInsets
} = uni.getWindowInfo()
// #endif
// #ifndef MP-WEIXIN
const {
windowWidth,
windowHeight,
windowTop,
safeArea,
screenHeight,
safeAreaInsets
} = uni.getSystemInfoSync()
// #endif
this.popupWidth = windowWidth
this.popupHeight = windowHeight + (windowTop || 0)
// TODO fix by mehaotian 是否适配底部安全区 ,目前微信ios 、和 app ios 计算有差异,需要框架修复
if (safeArea && this.safeArea) {
// #ifdef MP-WEIXIN
this.safeAreaInsets = screenHeight - safeArea.bottom
// #endif
// #ifndef MP-WEIXIN
this.safeAreaInsets = safeAreaInsets.bottom
// #endif
} else {
this.safeAreaInsets = 0
}
}
fixSize()
// #ifdef H5
// window.addEventListener('resize', fixSize)
// this.$once('hook:beforeDestroy', () => {
// window.removeEventListener('resize', fixSize)
// })
// #endif
},
// #ifndef VUE3
// TODO vue2
destroyed() {
this.setH5Visible()
},
// #endif
// #ifdef VUE3
// TODO vue3
unmounted() {
this.setH5Visible()
},
// #endif
activated() {
this.setH5Visible(!this.showPopup);
},
deactivated() {
this.setH5Visible(true);
},
created() {
// this.mkclick = this.isMaskClick || this.maskClick
if (this.isMaskClick === null && this.maskClick === null) {
this.mkclick = true
} else {
this.mkclick = this.isMaskClick !== null ? this.isMaskClick : this.maskClick
}
if (this.animation) {
this.duration = 300
} else {
this.duration = 0
}
// TODO 处理 message 组件生命周期异常的问题
this.messageChild = null
// TODO 解决头条冒泡的问题
this.clearPropagation = false
this.maskClass.backgroundColor = this.maskBackgroundColor
},
methods: {
setH5Visible(visible = true) {
// #ifdef H5
// fix by mehaotian 处理 h5 滚动穿透的问题
document.getElementsByTagName('body')[0].style.overflow = visible ? "visible" : "hidden";
// #endif
},
/**
* 公用方法,不显示遮罩层
*/
closeMask() {
this.maskShow = false
},
/**
* 公用方法,遮罩层禁止点击
*/
disableMask() {
this.mkclick = false
},
// TODO nvue 取消冒泡
clear(e) {
// #ifndef APP-NVUE
e.stopPropagation()
// #endif
this.clearPropagation = true
},
open(direction) {
// fix by mehaotian 处理快速打开关闭的情况
if (this.showPopup) {
return
}
let innerType = ['top', 'center', 'bottom', 'left', 'right', 'message', 'dialog', 'share']
if (!(direction && innerType.indexOf(direction) !== -1)) {
direction = this.type
}
if (!this.config[direction]) {
console.error('缺少类型:', direction)
return
}
this[this.config[direction]]()
this.$emit('change', {
show: true,
type: direction
})
},
close(type) {
this.showTrans = false
this.$emit('change', {
show: false,
type: this.type
})
clearTimeout(this.timer)
// // 自定义关闭事件
// this.customOpen && this.customClose()
this.timer = setTimeout(() => {
this.showPopup = false
}, 300)
},
// TODO 处理冒泡事件,头条的冒泡事件有问题 ,先这样兼容
touchstart() {
this.clearPropagation = false
},
onTap() {
if (this.clearPropagation) {
// fix by mehaotian 兼容 nvue
this.clearPropagation = false
return
}
this.$emit('maskClick')
if (!this.mkclick) return
this.close()
},
/**
* 顶部弹出样式处理
*/
top(type) {
this.popupstyle = this.isDesktop ? 'fixforpc-top' : 'top'
this.ani = ['slide-top']
this.transClass = {
position: 'fixed',
left: 0,
right: 0,
backgroundColor: this.bg,
borderRadius:this.borderRadius || "0"
}
// TODO 兼容 type 属性 ,后续会废弃
if (type) return
this.showPopup = true
this.showTrans = true
this.$nextTick(() => {
this.showPoptrans()
if (this.messageChild && this.type === 'message') {
this.messageChild.timerClose()
}
})
},
/**
* 底部弹出样式处理
*/
bottom(type) {
this.popupstyle = 'bottom'
this.ani = ['slide-bottom']
this.transClass = {
position: 'fixed',
left: 0,
right: 0,
bottom: 0,
paddingBottom: this.safeAreaInsets + 'px',
backgroundColor: this.bg,
borderRadius:this.borderRadius || "0",
}
// TODO 兼容 type 属性 ,后续会废弃
if (type) return
this.showPoptrans()
},
/**
* 中间弹出样式处理
*/
center(type) {
this.popupstyle = 'center'
//微信小程序下,组合动画会出现文字向上闪动问题,再此做特殊处理
// #ifdef MP-WEIXIN
this.ani = ['fade']
// #endif
// #ifndef MP-WEIXIN
this.ani = ['zoom-out', 'fade']
// #endif
this.transClass = {
position: 'fixed',
/* #ifndef APP-NVUE */
display: 'flex',
flexDirection: 'column',
/* #endif */
bottom: 0,
left: 0,
right: 0,
top: 0,
justifyContent: 'center',
alignItems: 'center',
borderRadius:this.borderRadius || "0"
}
// TODO 兼容 type 属性 ,后续会废弃
if (type) return
this.showPoptrans()
},
left(type) {
this.popupstyle = 'left'
this.ani = ['slide-left']
this.transClass = {
position: 'fixed',
left: 0,
bottom: 0,
top: 0,
backgroundColor: this.bg,
borderRadius:this.borderRadius || "0",
/* #ifndef APP-NVUE */
display: 'flex',
flexDirection: 'column'
/* #endif */
}
// TODO 兼容 type 属性 ,后续会废弃
if (type) return
this.showPoptrans()
},
right(type) {
this.popupstyle = 'right'
this.ani = ['slide-right']
this.transClass = {
position: 'fixed',
bottom: 0,
right: 0,
top: 0,
backgroundColor: this.bg,
borderRadius:this.borderRadius || "0",
/* #ifndef APP-NVUE */
display: 'flex',
flexDirection: 'column'
/* #endif */
}
// TODO 兼容 type 属性 ,后续会废弃
if (type) return
this.showPoptrans()
},
showPoptrans(){
this.$nextTick(()=>{
this.showPopup = true
this.showTrans = true
})
}
}
}
</script>
<style lang="scss">
.uni-popup {
position: fixed;
/* #ifndef APP-NVUE */
z-index: 99;
/* #endif */
&.top,
&.left,
&.right {
/* #ifdef H5 */
top: var(--window-top);
/* #endif */
/* #ifndef H5 */
top: 0;
/* #endif */
}
.uni-popup__wrapper {
/* #ifndef APP-NVUE */
display: block;
/* #endif */
position: relative;
/* iphonex 等安全区设置,底部安全区适配 */
/* #ifndef APP-NVUE */
// padding-bottom: constant(safe-area-inset-bottom);
// padding-bottom: env(safe-area-inset-bottom);
/* #endif */
&.left,
&.right {
/* #ifdef H5 */
padding-top: var(--window-top);
/* #endif */
/* #ifndef H5 */
padding-top: 0;
/* #endif */
flex: 1;
}
}
}
.fixforpc-z-index {
/* #ifndef APP-NVUE */
z-index: 999;
/* #endif */
}
.fixforpc-top {
top: 0;
}
</style>

View File

@@ -0,0 +1,108 @@
{
"id": "uni-popup",
"displayName": "uni-popup 弹出层",
"version": "1.9.12",
"description": " Popup 组件,提供常用的弹层",
"keywords": [
"uni-ui",
"弹出层",
"弹窗",
"popup",
"弹框"
],
"repository": "https://github.com/dcloudio/uni-ui",
"engines": {
"HBuilderX": "",
"uni-app": "^4.07",
"uni-app-x": "^5.0"
},
"directories": {
"example": "../../temps/example_temps"
},
"dcloudext": {
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
"type": "component-vue",
"darkmode": "x",
"i18n": "x",
"widescreen": "x"
},
"uni_modules": {
"dependencies": [
"uni-scss",
"uni-transition"
],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "x",
"aliyun": "x",
"alipay": "x"
},
"client": {
"uni-app": {
"vue": {
"vue2": "√",
"vue3": "√"
},
"web": {
"safari": "√",
"chrome": "√"
},
"app": {
"vue": "√",
"nvue": "√",
"android": "√",
"ios": "√",
"harmony": "√"
},
"mp": {
"weixin": "√",
"alipay": "√",
"toutiao": "√",
"baidu": "√",
"kuaishou": "-",
"jd": "-",
"harmony": "-",
"qq": "√",
"lark": "-",
"xhs": "-"
},
"quickapp": {
"huawei": "-",
"union": "-"
}
},
"uni-app-x": {
"web": {
"safari": "√",
"chrome": "√"
},
"app": {
"android": "√",
"ios": "√",
"harmony": "√"
},
"mp": {
"weixin": "√"
}
}
}
}
}
}

View File

@@ -0,0 +1,15 @@
## Popup 弹出层
> **组件名uni-popup**
> 代码块: `uPopup`
> 关联组件:`uni-transition`
弹出层组件,在应用中弹出一个消息提示窗口、提示框等
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-popup)

View File

@@ -0,0 +1,8 @@
## 1.0.32022-01-21
- 优化 组件示例
## 1.0.22021-11-22
- 修复 / 符号在 vue 不同版本兼容问题引起的报错问题
## 1.0.12021-11-22
- 修复 vue3中scss语法兼容问题
## 1.0.02021-11-18
- init

View File

@@ -0,0 +1 @@
@import './styles/index.scss';

View File

@@ -0,0 +1,82 @@
{
"id": "uni-scss",
"displayName": "uni-scss 辅助样式",
"version": "1.0.3",
"description": "uni-sass是uni-ui提供的一套全局样式 通过一些简单的类名和sass变量实现简单的页面布局操作比如颜色、边距、圆角等。",
"keywords": [
"uni-scss",
"uni-ui",
"辅助样式"
],
"repository": "https://github.com/dcloudio/uni-ui",
"engines": {
"HBuilderX": "^3.1.0"
},
"dcloudext": {
"category": [
"JS SDK",
"通用 SDK"
],
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "u"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y"
},
"快应用": {
"华为": "n",
"联盟": "n"
},
"Vue": {
"vue2": "y",
"vue3": "y"
}
}
}
}
}

View File

@@ -0,0 +1,4 @@
`uni-sass``uni-ui`提供的一套全局样式 ,通过一些简单的类名和`sass`变量,实现简单的页面布局操作,比如颜色、边距、圆角等。
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-sass)
#### 如使用过程中有任何问题或者您对uni-ui有一些好的建议欢迎加入 uni-ui 交流群871950839

View File

@@ -0,0 +1,7 @@
@import './setting/_variables.scss';
@import './setting/_border.scss';
@import './setting/_color.scss';
@import './setting/_space.scss';
@import './setting/_radius.scss';
@import './setting/_text.scss';
@import './setting/_styles.scss';

View File

@@ -0,0 +1,3 @@
.uni-border {
border: 1px $uni-border-1 solid;
}

View File

@@ -0,0 +1,66 @@
// TODO 暂时不需要 class ,需要用户使用变量实现 ,如果使用类名其实并不推荐
// @mixin get-styles($k,$c) {
// @if $k == size or $k == weight{
// font-#{$k}:#{$c}
// }@else{
// #{$k}:#{$c}
// }
// }
$uni-ui-color:(
// 主色
primary: $uni-primary,
primary-disable: $uni-primary-disable,
primary-light: $uni-primary-light,
// 辅助色
success: $uni-success,
success-disable: $uni-success-disable,
success-light: $uni-success-light,
warning: $uni-warning,
warning-disable: $uni-warning-disable,
warning-light: $uni-warning-light,
error: $uni-error,
error-disable: $uni-error-disable,
error-light: $uni-error-light,
info: $uni-info,
info-disable: $uni-info-disable,
info-light: $uni-info-light,
// 中性色
main-color: $uni-main-color,
base-color: $uni-base-color,
secondary-color: $uni-secondary-color,
extra-color: $uni-extra-color,
// 背景色
bg-color: $uni-bg-color,
// 边框颜色
border-1: $uni-border-1,
border-2: $uni-border-2,
border-3: $uni-border-3,
border-4: $uni-border-4,
// 黑色
black:$uni-black,
// 白色
white:$uni-white,
// 透明
transparent:$uni-transparent
) !default;
@each $key, $child in $uni-ui-color {
.uni-#{"" + $key} {
color: $child;
}
.uni-#{"" + $key}-bg {
background-color: $child;
}
}
.uni-shadow-sm {
box-shadow: $uni-shadow-sm;
}
.uni-shadow-base {
box-shadow: $uni-shadow-base;
}
.uni-shadow-lg {
box-shadow: $uni-shadow-lg;
}
.uni-mask {
background-color:$uni-mask;
}

View File

@@ -0,0 +1,55 @@
@mixin radius($r,$d:null ,$important: false){
$radius-value:map-get($uni-radius, $r) if($important, !important, null);
// Key exists within the $uni-radius variable
@if (map-has-key($uni-radius, $r) and $d){
@if $d == t {
border-top-left-radius:$radius-value;
border-top-right-radius:$radius-value;
}@else if $d == r {
border-top-right-radius:$radius-value;
border-bottom-right-radius:$radius-value;
}@else if $d == b {
border-bottom-left-radius:$radius-value;
border-bottom-right-radius:$radius-value;
}@else if $d == l {
border-top-left-radius:$radius-value;
border-bottom-left-radius:$radius-value;
}@else if $d == tl {
border-top-left-radius:$radius-value;
}@else if $d == tr {
border-top-right-radius:$radius-value;
}@else if $d == br {
border-bottom-right-radius:$radius-value;
}@else if $d == bl {
border-bottom-left-radius:$radius-value;
}
}@else{
border-radius:$radius-value;
}
}
@each $key, $child in $uni-radius {
@if($key){
.uni-radius-#{"" + $key} {
@include radius($key)
}
}@else{
.uni-radius {
@include radius($key)
}
}
}
@each $direction in t, r, b, l,tl, tr, br, bl {
@each $key, $child in $uni-radius {
@if($key){
.uni-radius-#{"" + $direction}-#{"" + $key} {
@include radius($key,$direction,false)
}
}@else{
.uni-radius-#{$direction} {
@include radius($key,$direction,false)
}
}
}
}

View File

@@ -0,0 +1,56 @@
@mixin fn($space,$direction,$size,$n) {
@if $n {
#{$space}-#{$direction}: #{$size*$uni-space-root}px
} @else {
#{$space}-#{$direction}: #{-$size*$uni-space-root}px
}
}
@mixin get-styles($direction,$i,$space,$n){
@if $direction == t {
@include fn($space, top,$i,$n);
}
@if $direction == r {
@include fn($space, right,$i,$n);
}
@if $direction == b {
@include fn($space, bottom,$i,$n);
}
@if $direction == l {
@include fn($space, left,$i,$n);
}
@if $direction == x {
@include fn($space, left,$i,$n);
@include fn($space, right,$i,$n);
}
@if $direction == y {
@include fn($space, top,$i,$n);
@include fn($space, bottom,$i,$n);
}
@if $direction == a {
@if $n {
#{$space}:#{$i*$uni-space-root}px;
} @else {
#{$space}:#{-$i*$uni-space-root}px;
}
}
}
@each $orientation in m,p {
$space: margin;
@if $orientation == m {
$space: margin;
} @else {
$space: padding;
}
@for $i from 0 through 16 {
@each $direction in t, r, b, l, x, y, a {
.uni-#{$orientation}#{$direction}-#{$i} {
@include get-styles($direction,$i,$space,true);
}
.uni-#{$orientation}#{$direction}-n#{$i} {
@include get-styles($direction,$i,$space,false);
}
}
}
}

View File

@@ -0,0 +1,167 @@
/* #ifndef APP-NVUE */
$-color-white:#fff;
$-color-black:#000;
@mixin base-style($color) {
color: #fff;
background-color: $color;
border-color: mix($-color-black, $color, 8%);
&:not([hover-class]):active {
background: mix($-color-black, $color, 10%);
border-color: mix($-color-black, $color, 20%);
color: $-color-white;
outline: none;
}
}
@mixin is-color($color) {
@include base-style($color);
&[loading] {
@include base-style($color);
&::before {
margin-right:5px;
}
}
&[disabled] {
&,
&[loading],
&:not([hover-class]):active {
color: $-color-white;
border-color: mix(darken($color,10%), $-color-white);
background-color: mix($color, $-color-white);
}
}
}
@mixin base-plain-style($color) {
color:$color;
background-color: mix($-color-white, $color, 90%);
border-color: mix($-color-white, $color, 70%);
&:not([hover-class]):active {
background: mix($-color-white, $color, 80%);
color: $color;
outline: none;
border-color: mix($-color-white, $color, 50%);
}
}
@mixin is-plain($color){
&[plain] {
@include base-plain-style($color);
&[loading] {
@include base-plain-style($color);
&::before {
margin-right:5px;
}
}
&[disabled] {
&,
&:active {
color: mix($-color-white, $color, 40%);
background-color: mix($-color-white, $color, 90%);
border-color: mix($-color-white, $color, 80%);
}
}
}
}
.uni-btn {
margin: 5px;
color: #393939;
border:1px solid #ccc;
font-size: 16px;
font-weight: 200;
background-color: #F9F9F9;
// TODO 暂时处理边框隐藏一边的问题
overflow: visible;
&::after{
border: none;
}
&:not([type]),&[type=default] {
color: #999;
&[loading] {
background: none;
&::before {
margin-right:5px;
}
}
&[disabled]{
color: mix($-color-white, #999, 60%);
&,
&[loading],
&:active {
color: mix($-color-white, #999, 60%);
background-color: mix($-color-white,$-color-black , 98%);
border-color: mix($-color-white, #999, 85%);
}
}
&[plain] {
color: #999;
background: none;
border-color: $uni-border-1;
&:not([hover-class]):active {
background: none;
color: mix($-color-white, $-color-black, 80%);
border-color: mix($-color-white, $-color-black, 90%);
outline: none;
}
&[disabled]{
&,
&[loading],
&:active {
background: none;
color: mix($-color-white, #999, 60%);
border-color: mix($-color-white, #999, 85%);
}
}
}
}
&:not([hover-class]):active {
color: mix($-color-white, $-color-black, 50%);
}
&[size=mini] {
font-size: 16px;
font-weight: 200;
border-radius: 8px;
}
&.uni-btn-small {
font-size: 14px;
}
&.uni-btn-mini {
font-size: 12px;
}
&.uni-btn-radius {
border-radius: 999px;
}
&[type=primary] {
@include is-color($uni-primary);
@include is-plain($uni-primary)
}
&[type=success] {
@include is-color($uni-success);
@include is-plain($uni-success)
}
&[type=error] {
@include is-color($uni-error);
@include is-plain($uni-error)
}
&[type=warning] {
@include is-color($uni-warning);
@include is-plain($uni-warning)
}
&[type=info] {
@include is-color($uni-info);
@include is-plain($uni-info)
}
}
/* #endif */

View File

@@ -0,0 +1,24 @@
@mixin get-styles($k,$c) {
@if $k == size or $k == weight{
font-#{$k}:#{$c}
}@else{
#{$k}:#{$c}
}
}
@each $key, $child in $uni-headings {
/* #ifndef APP-NVUE */
.uni-#{$key} {
@each $k, $c in $child {
@include get-styles($k,$c)
}
}
/* #endif */
/* #ifdef APP-NVUE */
.container .uni-#{$key} {
@each $k, $c in $child {
@include get-styles($k,$c)
}
}
/* #endif */
}

View File

@@ -0,0 +1,146 @@
// @use "sass:math";
@import '../tools/functions.scss';
// 间距基础倍数
$uni-space-root: 2 !default;
// 边框半径默认值
$uni-radius-root:5px !default;
$uni-radius: () !default;
// 边框半径断点
$uni-radius: map-deep-merge(
(
0: 0,
// TODO 当前版本暂时不支持 sm 属性
// 'sm': math.div($uni-radius-root, 2),
null: $uni-radius-root,
'lg': $uni-radius-root * 2,
'xl': $uni-radius-root * 6,
'pill': 9999px,
'circle': 50%
),
$uni-radius
);
// 字体家族
$body-font-family: 'Roboto', sans-serif !default;
// 文本
$heading-font-family: $body-font-family !default;
$uni-headings: () !default;
$letterSpacing: -0.01562em;
$uni-headings: map-deep-merge(
(
'h1': (
size: 32px,
weight: 300,
line-height: 50px,
// letter-spacing:-0.01562em
),
'h2': (
size: 28px,
weight: 300,
line-height: 40px,
// letter-spacing: -0.00833em
),
'h3': (
size: 24px,
weight: 400,
line-height: 32px,
// letter-spacing: normal
),
'h4': (
size: 20px,
weight: 400,
line-height: 30px,
// letter-spacing: 0.00735em
),
'h5': (
size: 16px,
weight: 400,
line-height: 24px,
// letter-spacing: normal
),
'h6': (
size: 14px,
weight: 500,
line-height: 18px,
// letter-spacing: 0.0125em
),
'subtitle': (
size: 12px,
weight: 400,
line-height: 20px,
// letter-spacing: 0.00937em
),
'body': (
font-size: 14px,
font-weight: 400,
line-height: 22px,
// letter-spacing: 0.03125em
),
'caption': (
'size': 12px,
'weight': 400,
'line-height': 20px,
// 'letter-spacing': 0.03333em,
// 'text-transform': false
)
),
$uni-headings
);
// 主色
$uni-primary: #2979ff !default;
$uni-primary-disable:lighten($uni-primary,20%) !default;
$uni-primary-light: lighten($uni-primary,25%) !default;
// 辅助色
// 除了主色外的场景色,需要在不同的场景中使用(例如危险色表示危险的操作)。
$uni-success: #18bc37 !default;
$uni-success-disable:lighten($uni-success,20%) !default;
$uni-success-light: lighten($uni-success,25%) !default;
$uni-warning: #f3a73f !default;
$uni-warning-disable:lighten($uni-warning,20%) !default;
$uni-warning-light: lighten($uni-warning,25%) !default;
$uni-error: #e43d33 !default;
$uni-error-disable:lighten($uni-error,20%) !default;
$uni-error-light: lighten($uni-error,25%) !default;
$uni-info: #8f939c !default;
$uni-info-disable:lighten($uni-info,20%) !default;
$uni-info-light: lighten($uni-info,25%) !default;
// 中性色
// 中性色用于文本、背景和边框颜色。通过运用不同的中性色,来表现层次结构。
$uni-main-color: #3a3a3a !default; // 主要文字
$uni-base-color: #6a6a6a !default; // 常规文字
$uni-secondary-color: #909399 !default; // 次要文字
$uni-extra-color: #c7c7c7 !default; // 辅助说明
// 边框颜色
$uni-border-1: #F0F0F0 !default;
$uni-border-2: #EDEDED !default;
$uni-border-3: #DCDCDC !default;
$uni-border-4: #B9B9B9 !default;
// 常规色
$uni-black: #000000 !default;
$uni-white: #ffffff !default;
$uni-transparent: rgba($color: #000000, $alpha: 0) !default;
// 背景色
$uni-bg-color: #f7f7f7 !default;
/* 水平间距 */
$uni-spacing-sm: 8px !default;
$uni-spacing-base: 15px !default;
$uni-spacing-lg: 30px !default;
// 阴影
$uni-shadow-sm:0 0 5px rgba($color: #d8d8d8, $alpha: 0.5) !default;
$uni-shadow-base:0 1px 8px 1px rgba($color: #a5a5a5, $alpha: 0.2) !default;
$uni-shadow-lg:0px 1px 10px 2px rgba($color: #a5a4a4, $alpha: 0.5) !default;
// 蒙版
$uni-mask: rgba($color: #000000, $alpha: 0.4) !default;

View File

@@ -0,0 +1,19 @@
// 合并 map
@function map-deep-merge($parent-map, $child-map){
$result: $parent-map;
@each $key, $child in $child-map {
$parent-has-key: map-has-key($result, $key);
$parent-value: map-get($result, $key);
$parent-type: type-of($parent-value);
$child-type: type-of($child);
$parent-is-map: $parent-type == map;
$child-is-map: $child-type == map;
@if (not $parent-has-key) or ($parent-type != $child-type) or (not ($parent-is-map and $child-is-map)){
$result: map-merge($result, ( $key: $child ));
}@else {
$result: map-merge($result, ( $key: map-deep-merge($parent-value, $child) ));
}
}
@return $result;
};

View File

@@ -0,0 +1,31 @@
// 间距基础倍数
$uni-space-root: 2;
// 边框半径默认值
$uni-radius-root:5px;
// 主色
$uni-primary: #2979ff;
// 辅助色
$uni-success: #4cd964;
// 警告色
$uni-warning: #f0ad4e;
// 错误色
$uni-error: #dd524d;
// 描述色
$uni-info: #909399;
// 中性色
$uni-main-color: #303133;
$uni-base-color: #606266;
$uni-secondary-color: #909399;
$uni-extra-color: #C0C4CC;
// 背景色
$uni-bg-color: #f5f5f5;
// 边框颜色
$uni-border-1: #DCDFE6;
$uni-border-2: #E4E7ED;
$uni-border-3: #EBEEF5;
$uni-border-4: #F2F6FC;
// 常规色
$uni-black: #000000;
$uni-white: #ffffff;
$uni-transparent: rgba($color: #000000, $alpha: 0);

View File

@@ -0,0 +1,62 @@
@import './styles/setting/_variables.scss';
// 间距基础倍数
$uni-space-root: 2;
// 边框半径默认值
$uni-radius-root:5px;
// 主色
$uni-primary: #2979ff;
$uni-primary-disable:mix(#fff,$uni-primary,50%);
$uni-primary-light: mix(#fff,$uni-primary,80%);
// 辅助色
// 除了主色外的场景色,需要在不同的场景中使用(例如危险色表示危险的操作)。
$uni-success: #18bc37;
$uni-success-disable:mix(#fff,$uni-success,50%);
$uni-success-light: mix(#fff,$uni-success,80%);
$uni-warning: #f3a73f;
$uni-warning-disable:mix(#fff,$uni-warning,50%);
$uni-warning-light: mix(#fff,$uni-warning,80%);
$uni-error: #e43d33;
$uni-error-disable:mix(#fff,$uni-error,50%);
$uni-error-light: mix(#fff,$uni-error,80%);
$uni-info: #8f939c;
$uni-info-disable:mix(#fff,$uni-info,50%);
$uni-info-light: mix(#fff,$uni-info,80%);
// 中性色
// 中性色用于文本、背景和边框颜色。通过运用不同的中性色,来表现层次结构。
$uni-main-color: #3a3a3a; // 主要文字
$uni-base-color: #6a6a6a; // 常规文字
$uni-secondary-color: #909399; // 次要文字
$uni-extra-color: #c7c7c7; // 辅助说明
// 边框颜色
$uni-border-1: #F0F0F0;
$uni-border-2: #EDEDED;
$uni-border-3: #DCDCDC;
$uni-border-4: #B9B9B9;
// 常规色
$uni-black: #000000;
$uni-white: #ffffff;
$uni-transparent: rgba($color: #000000, $alpha: 0);
// 背景色
$uni-bg-color: #f7f7f7;
/* 水平间距 */
$uni-spacing-sm: 8px;
$uni-spacing-base: 15px;
$uni-spacing-lg: 30px;
// 阴影
$uni-shadow-sm:0 0 5px rgba($color: #d8d8d8, $alpha: 0.5);
$uni-shadow-base:0 1px 8px 1px rgba($color: #a5a5a5, $alpha: 0.2);
$uni-shadow-lg:0px 1px 10px 2px rgba($color: #a5a4a4, $alpha: 0.5);
// 蒙版
$uni-mask: rgba($color: #000000, $alpha: 0.4);

View File

@@ -0,0 +1,47 @@
## 1.3.02024-04-22
- 修复 textColor默认值导致的文字不显示的bug
## 1.2.92024-04-17
- 修复 textColor不生效的bug
## 1.2.82024-02-22
- 修复 清空按钮emit值错误的bug
## 1.2.72024-02-21
- 新增 设置输入框字体颜色:textColor
## 1.2.62024-02-20
- 修复 uni-search-bar在支付宝小程序下样式兼容问题
## 1.2.52024-01-31
- 修复 uni-search-bar居中问题现在默认居左并修复样式偏移问题
## 1.2.42023-05-09
- 修复 i18n 国际化不正确的 Bug
## 1.2.32022-05-24
- 新增 readonly 属性,组件只读
## 1.2.22022-05-06
- 修复 vue3 input 事件不生效的bug
## 1.2.12022-05-06
- 修复 多余代码导致的bug
## 1.2.02021-11-19
- 优化 组件UI并提供设计资源详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-search-bar](https://uniapp.dcloud.io/component/uniui/uni-search-bar)
## 1.1.22021-08-30
- 修复 value 属性与 modelValue 属性不兼容的Bug
## 1.1.12021-08-24
- 新增 支持国际化
## 1.1.02021-07-30
- 组件兼容 vue3如何创建vue3项目详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
## 1.0.92021-05-12
- 新增 项目示例地址
## 1.0.82021-04-21
- 优化 添加依赖 uni-icons, 导入后自动下载依赖
## 1.0.72021-04-15
- uni-ui 新增 uni-search-bar 的 focus 事件
## 1.0.62021-02-05
- 优化 组件引用关系通过uni_modules引用组件
## 1.0.52021-02-05
- 调整为uni_modules目录规范
- 新增 支持双向绑定
- 更改 input 事件的返回值e={value:Number} --> e=value
- 新增 支持图标插槽
- 新增 支持 clear、blur 事件
- 新增 支持 focus 属性
- 去掉组件背景色

View File

@@ -0,0 +1,4 @@
{
"uni-search-bar.cancel": "cancel",
"uni-search-bar.placeholder": "Search enter content"
}

View File

@@ -0,0 +1,8 @@
import en from './en.json'
import zhHans from './zh-Hans.json'
import zhHant from './zh-Hant.json'
export default {
en,
'zh-Hans': zhHans,
'zh-Hant': zhHant
}

View File

@@ -0,0 +1,4 @@
{
"uni-search-bar.cancel": "取消",
"uni-search-bar.placeholder": "请输入搜索内容"
}

View File

@@ -0,0 +1,4 @@
{
"uni-search-bar.cancel": "取消",
"uni-search-bar.placeholder": "請輸入搜索內容"
}

Some files were not shown because too many files have changed in this diff Show More