去除unicloud空间绑定,修复已知错误
This commit is contained in:
@ -1,15 +0,0 @@
|
||||
{
|
||||
"version" : "1.0",
|
||||
"configurations" : [
|
||||
{
|
||||
"default" : {
|
||||
"launchtype" : "local"
|
||||
},
|
||||
"h5" : {
|
||||
"launchtype" : "local"
|
||||
},
|
||||
"provider" : "aliyun",
|
||||
"type" : "uniCloud"
|
||||
}
|
||||
]
|
||||
}
|
8
App.vue
8
App.vue
@ -1,12 +1,11 @@
|
||||
<script>
|
||||
import initApp from '@/common/appInit.js';
|
||||
// import initApp from '@/common/appInit.js';
|
||||
import openApp from '@/common/openApp.js';
|
||||
import sysconfig from './app.config.js';
|
||||
// #ifdef H5
|
||||
// openApp() //创建在h5端全局悬浮引导用户下载app的功能
|
||||
openApp() //创建在h5端全局悬浮引导用户下载app的功能
|
||||
// #endif
|
||||
// import checkIsAgree from '@/pages/uni-agree/utils/uni-agree.js';
|
||||
import uniIdPageInit from '@/uni_modules/uni-id-pages/init.js';
|
||||
|
||||
import utils from "@/utils/common.js" //自定义函数
|
||||
export default {
|
||||
@ -24,8 +23,7 @@
|
||||
this.globalData.$i18n = this.$i18n
|
||||
this.globalData.$t = str => this.$t(str)
|
||||
this.utils = utils;
|
||||
initApp();
|
||||
uniIdPageInit();
|
||||
// initApp();
|
||||
if (o.query) {
|
||||
var opt = o.query;
|
||||
//以下做裂变分销场景布置
|
||||
|
@ -1,38 +1,38 @@
|
||||
{
|
||||
"version": "1",
|
||||
"prompt": "template",
|
||||
"title": "服务协议和隐私政策",
|
||||
"message": " 请你务必审慎阅读、充分理解“服务协议”和“隐私政策”各条款,包括但不限于:为了更好的向你提供服务,我们需要收集你的设备标识、操作日志等信息用于分析、优化应用性能。<br/> 你可阅读<a href=\"https://public.hiluker.com/ctms/client/service.html\">《服务协议》</a>和<a href=\"https://public.hiluker.com/ctms/client/private.html\">《隐私政策》</a>了解详细信息。如果你同意,请点击下面按钮开始接受我们的服务。",
|
||||
"buttonAccept": "同意并接受",
|
||||
"buttonRefuse": "暂不同意",
|
||||
"hrefLoader": "system",
|
||||
"backToExit": "false",
|
||||
"second": {
|
||||
"title": "确认提示",
|
||||
"message": " 进入应用前,你需先同意<a href=\"https://public.hiluker.com/ctms/client/service.html\">《服务协议》</a>和<a href=\"https://public.hiluker.com/ctms/client/private.html\">《隐私政策》</a>,否则将退出应用。",
|
||||
"buttonAccept": "同意并继续",
|
||||
"buttonRefuse": "退出应用"
|
||||
"version" : "1",
|
||||
"prompt" : "template",
|
||||
"title" : "服务协议和隐私政策",
|
||||
"message" : " 请你务必审慎阅读、充分理解“服务协议”和“隐私政策”各条款,包括但不限于:为了更好的向你提供服务,我们需要收集你的设备标识、操作日志等信息用于分析、优化应用性能。<br/> 你可阅读<a href=\"https://public.hiluker.com/ctms/client/service.html\">《服务协议》</a>和<a href=\"https://public.hiluker.com/ctms/client/private.html\">《隐私政策》</a>了解详细信息。如果你同意,请点击下面按钮开始接受我们的服务。",
|
||||
"buttonAccept" : "同意并接受",
|
||||
"buttonRefuse" : "暂不同意",
|
||||
"hrefLoader" : "system",
|
||||
"backToExit" : "false",
|
||||
"second" : {
|
||||
"title" : "确认提示",
|
||||
"message" : " 进入应用前,你需先同意<a href=\"https://public.hiluker.com/ctms/client/service.html\">《服务协议》</a>和<a href=\"https://public.hiluker.com/ctms/client/private.html\">《隐私政策》</a>,否则将退出应用。",
|
||||
"buttonAccept" : "同意并继续",
|
||||
"buttonRefuse" : "退出应用"
|
||||
},
|
||||
"disagreeMode": {
|
||||
"support": true,
|
||||
"loadNativePlugins": false,
|
||||
"visitorEntry": false,
|
||||
"showAlways": false
|
||||
"disagreeMode" : {
|
||||
"support" : true,
|
||||
"loadNativePlugins" : false,
|
||||
"visitorEntry" : false,
|
||||
"showAlways" : false
|
||||
},
|
||||
"styles": {
|
||||
"backgroundColor": "#ffffff",
|
||||
"borderRadius": "5px",
|
||||
"title": {
|
||||
"color": "#000000"
|
||||
"styles" : {
|
||||
"backgroundColor" : "#ffffff",
|
||||
"borderRadius" : "5px",
|
||||
"title" : {
|
||||
"color" : "#000000"
|
||||
},
|
||||
"buttonAccept": {
|
||||
"color": "#0a5fff"
|
||||
"buttonAccept" : {
|
||||
"color" : "#0a5fff"
|
||||
},
|
||||
"buttonRefuse": {
|
||||
"color": "#7b7b81"
|
||||
"buttonRefuse" : {
|
||||
"color" : "#7b7b81"
|
||||
},
|
||||
"buttonVisitor": {
|
||||
"color": "#000000"
|
||||
"buttonVisitor" : {
|
||||
"color" : "#000000"
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +1,9 @@
|
||||
/*————接口预设————*/
|
||||
{
|
||||
"index": "/index/index",
|
||||
"IndexData": "/index/h5data",
|
||||
"AdsSplash": "/index/ads-splash",
|
||||
"AdsBanner": "/index/ads-banner",
|
||||
//获取短信验证码
|
||||
|
||||
"getVcode": "/sms/vcode",
|
||||
"getCwVcode": "/sms/caiwu",
|
||||
|
||||
|
@ -1,3 +1,11 @@
|
||||
/**
|
||||
* @Author: 嗨噜客(三亚)<fm453>
|
||||
* @Date: 2023-07-19 16:03:07
|
||||
* @FilePath: apis/ctms/fab.js
|
||||
* @Description:
|
||||
* @Email: 393213759@qq.com
|
||||
* Copyright (c) 2025 by www.hiluker.cn, All Rights Reserved.
|
||||
*/
|
||||
export default {
|
||||
// 登录方法
|
||||
login: function(username, password, smscode, uuid) {
|
||||
|
@ -1,5 +1,14 @@
|
||||
/**
|
||||
* @Author: 嗨噜客(三亚)<fm453>
|
||||
* @Date: 2023-07-19 16:03:07
|
||||
* @FilePath: apis/ctms/index.js
|
||||
* @Description:
|
||||
* @Email: 393213759@qq.com
|
||||
* Copyright (c) 2025 by www.hiluker.cn, All Rights Reserved.
|
||||
*/
|
||||
import user from './user.js';
|
||||
import ads from './ads.js';
|
||||
import datas from './datas.js';
|
||||
import order from './order.js';
|
||||
import orderpre from './orderpre.js';
|
||||
import notice from './notice.js';
|
||||
@ -42,6 +51,7 @@ const cache = {
|
||||
const ctms = {
|
||||
user,
|
||||
ads,
|
||||
datas,
|
||||
order,
|
||||
orderpre,
|
||||
notice,
|
||||
|
@ -1,3 +1,11 @@
|
||||
/**
|
||||
* @Author: 嗨噜客(三亚)<fm453>
|
||||
* @Date: 2023-07-19 16:03:07
|
||||
* @FilePath: apis/ctms/news.js
|
||||
* @Description:
|
||||
* @Email: 393213759@qq.com
|
||||
* Copyright (c) 2025 by www.hiluker.cn, All Rights Reserved.
|
||||
*/
|
||||
import request from './_utils/request.js'
|
||||
import apis from './apis.json'
|
||||
import constant from './_utils/constant.js'
|
||||
|
@ -1,3 +1,11 @@
|
||||
/**
|
||||
* @Author: 嗨噜客(三亚)<fm453>
|
||||
* @Date: 2023-07-19 16:03:07
|
||||
* @FilePath: apis/ctms/notice.js
|
||||
* @Description:
|
||||
* @Email: 393213759@qq.com
|
||||
* Copyright (c) 2025 by www.hiluker.cn, All Rights Reserved.
|
||||
*/
|
||||
import request from './_utils/request.js'
|
||||
import apis from './apis.json'
|
||||
import constant from './_utils/constant.js'
|
||||
|
@ -1,3 +1,11 @@
|
||||
/**
|
||||
* @Author: 嗨噜客(三亚)<fm453>
|
||||
* @Date: 2023-07-19 16:03:07
|
||||
* @FilePath: apis/ctms/orderpre.js
|
||||
* @Description:
|
||||
* @Email: 393213759@qq.com
|
||||
* Copyright (c) 2025 by www.hiluker.cn, All Rights Reserved.
|
||||
*/
|
||||
import request from './_utils/request.js'
|
||||
import apis from './apis.json'
|
||||
import constant from './_utils/constant.js'
|
||||
|
@ -1,3 +1,11 @@
|
||||
/**
|
||||
* @Author: 嗨噜客(三亚)<fm453>
|
||||
* @Date: 2023-07-19 16:03:07
|
||||
* @FilePath: apis/ctms/sync.js
|
||||
* @Description:
|
||||
* @Email: 393213759@qq.com
|
||||
* Copyright (c) 2025 by www.hiluker.cn, All Rights Reserved.
|
||||
*/
|
||||
// 对异步函数进行同步化模拟
|
||||
const Confirm = {
|
||||
modalPromise: function(title, content, editable) {
|
||||
|
@ -1,3 +1,11 @@
|
||||
/**
|
||||
* @Author: 嗨噜客(三亚)<fm453>
|
||||
* @Date: 2023-07-19 16:03:07
|
||||
* @FilePath: apis/ctms/user.js
|
||||
* @Description:
|
||||
* @Email: 393213759@qq.com
|
||||
* Copyright (c) 2025 by www.hiluker.cn, All Rights Reserved.
|
||||
*/
|
||||
import request from './_utils/request.js'
|
||||
import apis from './apis.json'
|
||||
import constant from './_utils/constant.js'
|
||||
@ -10,9 +18,13 @@ export default {
|
||||
checkLogin: function() {
|
||||
var user = store.state.user,
|
||||
isCloud = config.isUserUnicloud;
|
||||
if (user.hasLogin && !isCloud) {
|
||||
if (!isCloud) {
|
||||
if (user.hasLogin) {
|
||||
return user.info;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
var userCloud = store.state.userCloud;
|
||||
if (isCloud && userCloud.hasLogin) {
|
||||
var data = {
|
||||
@ -30,9 +42,12 @@ export default {
|
||||
getInfo: function() {
|
||||
var user = store.state.user,
|
||||
isCloud = config.isUserUnicloud;
|
||||
if (user.hasLogin && !isCloud) {
|
||||
if (!isCloud) {
|
||||
if (user.hasLogin) {
|
||||
return user.info;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
var userCloud = store.state.userCloud;
|
||||
if (isCloud && userCloud.hasLogin) {
|
||||
return {
|
||||
@ -66,7 +81,7 @@ export default {
|
||||
cancelText: '放弃',
|
||||
success() {
|
||||
uni.navigateTo({
|
||||
url: 'uni_modules/uni-id-pages/pages/login/login-withoutpwd'
|
||||
url: config.uniCloudLoginUrl
|
||||
})
|
||||
}
|
||||
})
|
||||
|
@ -1,3 +1,11 @@
|
||||
/**
|
||||
* @Author: 嗨噜客(三亚)<fm453>
|
||||
* @Date: 2023-07-19 16:03:07
|
||||
* @FilePath: apis/ctms/vcode.js
|
||||
* @Description:
|
||||
* @Email: 393213759@qq.com
|
||||
* Copyright (c) 2025 by www.hiluker.cn, All Rights Reserved.
|
||||
*/
|
||||
import request from './_utils/request.js'
|
||||
import apis from './apis.json'
|
||||
import constant from './_utils/constant.js'
|
||||
|
@ -5,7 +5,7 @@ export default {
|
||||
//开启调试
|
||||
"isDebug": false,
|
||||
//定义开放平台
|
||||
"openplat": 'uniCloud',
|
||||
// "openplat": 'uniCloud',
|
||||
//关于应用
|
||||
"about": {
|
||||
//应用名称
|
||||
@ -19,7 +19,7 @@ export default {
|
||||
//应用的链接,用于分享到第三方平台和生成关于我们页的二维码
|
||||
"download": "https://ctms.hiluker.cn",
|
||||
//version
|
||||
"version": "1.20240808.006", //用于非app端显示,app端自动获取
|
||||
"version": "1.20250701.007", //用于非app端显示,app端自动获取
|
||||
"agreements": {
|
||||
serviceUrl: 'https://public.hiluker.com/ctms/client/service.html',
|
||||
privacyUrl: 'https://public.hiluker.com/ctms/client/private.html'
|
||||
|
@ -1,166 +1,3 @@
|
||||
import _app_Config from '@/app.config.js';
|
||||
//应用初始化页
|
||||
// #ifdef APP-PLUS
|
||||
import checkUpdate from '@/uni_modules/uni-upgrade-center-app/utils/check-update';
|
||||
import callCheckVersion from '@/uni_modules/uni-upgrade-center-app/utils/call-check-version';
|
||||
|
||||
// 实现,路由拦截。当应用无访问摄像头/相册权限,引导跳到设置界面 https://ext.dcloud.net.cn/plugin?id=5095
|
||||
import interceptorChooseImage from '@/uni_modules/json-interceptor-chooseImage/js_sdk/main.js';
|
||||
interceptorChooseImage()
|
||||
|
||||
// #endif
|
||||
const db = uniCloud.database()
|
||||
export default async function() {
|
||||
const debug = _app_Config.debug;
|
||||
|
||||
// _app_Config挂载到getApp().globalData.config
|
||||
setTimeout(() => {
|
||||
getApp({
|
||||
allowDefault: true
|
||||
}).globalData.config = _app_Config;
|
||||
}, 1)
|
||||
|
||||
|
||||
// 初始化appVersion(仅app生效)
|
||||
initAppVersion();
|
||||
|
||||
//clientDB的错误提示
|
||||
function onDBError({
|
||||
code, // 错误码详见https://uniapp.dcloud.net.cn/uniCloud/clientdb?id=returnvalue
|
||||
message
|
||||
}) {
|
||||
console.log('onDBError', {
|
||||
code,
|
||||
message
|
||||
});
|
||||
// 处理错误
|
||||
console.error(code, message);
|
||||
}
|
||||
// 绑定clientDB错误事件
|
||||
db.on('error', onDBError)
|
||||
|
||||
|
||||
//拦截云对象请求
|
||||
uniCloud.interceptObject({
|
||||
async invoke({
|
||||
objectName, // 云对象名称
|
||||
methodName, // 云对象的方法名称
|
||||
params // 参数列表
|
||||
}) {
|
||||
// console.log('interceptObject',{
|
||||
// objectName, // 云对象名称
|
||||
// methodName, // 云对象的方法名称
|
||||
// params // 参数列表
|
||||
// });
|
||||
if (objectName == "uni-id-co" && (methodName.includes('loginBy') || ['login',
|
||||
'registerUser'
|
||||
].includes(methodName))) {
|
||||
// console.log('执行登录相关云对象');
|
||||
params[0].inviteCode = await new Promise((callBack) => {
|
||||
uni.getClipboardData({
|
||||
success: function(res) {
|
||||
// console.log('剪切板内容:' + res.data);
|
||||
if (res.data.slice(0, 18) == 'uniInvitationCode:') {
|
||||
let uniInvitationCode = res.data.slice(18, 38)
|
||||
// console.log('当前用户是其他用户推荐下载的,推荐者的code是:' +uniInvitationCode);
|
||||
// uni.showModal({
|
||||
// content: '当前用户是其他用户推荐下载的,推荐者的code是:'+uniInvitationCode,
|
||||
// showCancel: false
|
||||
// });
|
||||
callBack(uniInvitationCode)
|
||||
//当前用户是其他用户推荐下载的。这里登记他的推荐者id 为当前用户的myInviteCode。判断如果是注册
|
||||
} else {
|
||||
callBack()
|
||||
}
|
||||
},
|
||||
fail() {
|
||||
// console.log('error--');
|
||||
callBack()
|
||||
},
|
||||
complete() {
|
||||
// #ifdef MP-WEIXIN
|
||||
uni.hideToast()
|
||||
// #endif
|
||||
}
|
||||
});
|
||||
})
|
||||
// console.log(params);
|
||||
}
|
||||
// console.log(params);
|
||||
},
|
||||
success(e) {
|
||||
// console.log(e);
|
||||
},
|
||||
complete() {
|
||||
|
||||
},
|
||||
fail(e) {
|
||||
// console.error(e);
|
||||
// if (debug) {
|
||||
// uni.showModal({
|
||||
// content: JSON.stringify(e),
|
||||
// showCancel: false
|
||||
// });
|
||||
// }else{
|
||||
// uni.showToast({
|
||||
// title: '系统错误请稍后再试',
|
||||
// icon:'error'
|
||||
// });
|
||||
// }
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
// #ifdef APP-PLUS
|
||||
// 监听并提示设备网络状态变化
|
||||
uni.onNetworkStatusChange(res => {
|
||||
// console.log(res.isConnected);
|
||||
// console.log(res.networkType);
|
||||
if (res.networkType != 'none') {
|
||||
uni.showToast({
|
||||
title: '当前网络类型:' + res.networkType,
|
||||
icon: 'none',
|
||||
duration: 3000
|
||||
})
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '网络类型:' + res.networkType,
|
||||
icon: 'none',
|
||||
duration: 3000
|
||||
})
|
||||
}
|
||||
});
|
||||
// #endif
|
||||
|
||||
}
|
||||
/**
|
||||
* // 初始化appVersion
|
||||
*/
|
||||
function initAppVersion() {
|
||||
// #ifdef APP-PLUS
|
||||
let appid = plus.runtime.appid;
|
||||
plus.runtime.getProperty(appid, (wgtInfo) => {
|
||||
let appVersion = plus.runtime;
|
||||
let currentVersion = appVersion.versionCode > wgtInfo.versionCode ? appVersion : wgtInfo;
|
||||
getApp({
|
||||
allowDefault: true
|
||||
}).appVersion = {
|
||||
...currentVersion,
|
||||
appid,
|
||||
hasNew: false
|
||||
}
|
||||
// 检查更新小红点
|
||||
callCheckVersion().then(res => {
|
||||
// console.log('检查是否有可以更新的版本', res);
|
||||
if (res.result.code > 0) {
|
||||
// 有新版本
|
||||
getApp({
|
||||
allowDefault: true
|
||||
}).appVersion.hasNew = true;
|
||||
// console.log(checkUpdate());
|
||||
}
|
||||
})
|
||||
});
|
||||
// 检查更新
|
||||
// #endif
|
||||
export default {
|
||||
Tips: '本函数尚未启用'
|
||||
}
|
@ -1,3 +1,11 @@
|
||||
/**
|
||||
* @Author: 嗨噜客(三亚)<fm453>
|
||||
* @Date: 2022-12-29 11:05:40
|
||||
* @FilePath: common/util.js
|
||||
* @Description:
|
||||
* @Email: 393213759@qq.com
|
||||
* Copyright (c) 2025 by www.hiluker.cn, All Rights Reserved.
|
||||
*/
|
||||
import permission from "./permission"
|
||||
|
||||
function formatTime(time) {
|
||||
|
@ -1,3 +1,11 @@
|
||||
/**
|
||||
* @Author: 嗨噜客(三亚)<fm453>
|
||||
* @Date: 2023-07-19 16:03:07
|
||||
* @FilePath: config/ctms.config.js
|
||||
* @Description:
|
||||
* @Email: 393213759@qq.com
|
||||
* Copyright (c) 2025 by www.hiluker.cn, All Rights Reserved.
|
||||
*/
|
||||
// 应用子项目配置
|
||||
export default {
|
||||
/*接口设置*/
|
||||
@ -20,19 +28,19 @@ export default {
|
||||
Authorization: 'hiCtmsClientXXXXXXXXXXXXXX', //请求授权的token示范
|
||||
params: [], //TODO,暂未想好如何配置
|
||||
},
|
||||
// loginPage: 'uni_modules/uni-id-pages/pages/login/login-withoutpwd',
|
||||
loginPage: 'pages/ctms/login/loginSms',
|
||||
pageDir: "/pages/ctms/", //子项目页面目录
|
||||
kfPhone: "13211111058", //客服手机号
|
||||
"version": "1.20240808.008", //内置版本号
|
||||
version: "1.20250701.007", //内置版本号
|
||||
isUserUnicloud: false,
|
||||
//是否使用 用户uni云服务
|
||||
uniCloudLoginUrl: 'uni_modules/uni-id-pages/pages/login/login-withoutpwd',
|
||||
demoCarno: '皖ABBBBB',
|
||||
//示例车牌号
|
||||
'poweredBy': '安徽安邮车联运输有限公司',
|
||||
poweredBy: '安徽安邮车联运输有限公司',
|
||||
//版权归属
|
||||
'supportedBy': 'Hiluker & Fm453',
|
||||
supportedBy: 'Hiluker & Fm453',
|
||||
//技术支持
|
||||
'thanksFor': ['北京数字天堂科技 DCloud', '阿里云 aliyun.com'],
|
||||
thanksFor: ['北京数字天堂科技 DCloud', '阿里云 aliyun.com'],
|
||||
//鸣谢
|
||||
}
|
16
main.js
16
main.js
@ -2,20 +2,7 @@ import App from './App'
|
||||
import i18n from './lang/i18n'
|
||||
import utils from "@/utils/common.js" //自定义函数
|
||||
|
||||
// #ifdef VUE2
|
||||
import Vue from 'vue'
|
||||
Vue.config.productionTip = false
|
||||
Vue.mixin(utils); //vue2方式混入 //未测试可用性
|
||||
App.mpType = 'app'
|
||||
const app = new Vue({
|
||||
i18n,
|
||||
...App
|
||||
})
|
||||
app.$mount()
|
||||
// #endif
|
||||
|
||||
|
||||
// #ifdef VUE3
|
||||
//VUE3方式引用
|
||||
import {
|
||||
createSSRApp
|
||||
} from 'vue'
|
||||
@ -27,4 +14,3 @@ export function createApp() {
|
||||
app
|
||||
}
|
||||
}
|
||||
// #endif
|
342
manifest.json
342
manifest.json
@ -1,31 +1,31 @@
|
||||
{
|
||||
"name" : "运车助手",
|
||||
"appid" : "__UNI__B63B6BD",
|
||||
"description" : "ctms运车平台用户前端,为用户提供下单、查询及相关售后跟进等服务",
|
||||
"versionName" : "1.20240808.006",
|
||||
"versionCode" : 106,
|
||||
"transformPx" : false,
|
||||
"app-plus" : {
|
||||
"usingComponents" : true,
|
||||
"nvueCompiler" : "uni-app",
|
||||
"splashscreen" : {
|
||||
"alwaysShowBeforeRender" : true,
|
||||
"waiting" : true,
|
||||
"autoclose" : true,
|
||||
"delay" : 0
|
||||
"name": "运车助手",
|
||||
"appid": "__UNI__B63B6BD",
|
||||
"description": "ctms运车平台用户前端,为用户提供下单、查询及相关售后跟进等服务",
|
||||
"versionName": "1.20250701.007",
|
||||
"versionCode": 107,
|
||||
"transformPx": false,
|
||||
"app-plus": {
|
||||
"usingComponents": true,
|
||||
"nvueCompiler": "uni-app",
|
||||
"splashscreen": {
|
||||
"alwaysShowBeforeRender": true,
|
||||
"waiting": true,
|
||||
"autoclose": true,
|
||||
"delay": 0
|
||||
},
|
||||
"modules" : {
|
||||
"Barcode" : {},
|
||||
"Camera" : {},
|
||||
"Geolocation" : {},
|
||||
"Maps" : {},
|
||||
"Share" : {},
|
||||
"OAuth" : {},
|
||||
"Push" : {}
|
||||
"modules": {
|
||||
"Barcode": {},
|
||||
"Camera": {},
|
||||
"Geolocation": {},
|
||||
"Maps": {},
|
||||
"Share": {},
|
||||
"OAuth": {},
|
||||
"Push": {}
|
||||
},
|
||||
"distribute" : {
|
||||
"android" : {
|
||||
"permissions" : [
|
||||
"distribute": {
|
||||
"android": {
|
||||
"permissions": [
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
|
||||
@ -46,209 +46,209 @@
|
||||
"<uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CALL_PHONE\"/>"
|
||||
],
|
||||
"schemes" : "ctms,ctms-client",
|
||||
"minSdkVersion" : 26,
|
||||
"targetSdkVersion" : 33,
|
||||
"abiFilters" : [ "armeabi-v7a", "arm64-v8a" ]
|
||||
"schemes": "ctms,ctms-client",
|
||||
"minSdkVersion": 26,
|
||||
"targetSdkVersion": 33,
|
||||
"abiFilters": ["armeabi-v7a", "arm64-v8a"]
|
||||
},
|
||||
"ios" : {
|
||||
"urltypes" : "ctms,ctms-client",
|
||||
"capabilities" : {
|
||||
"entitlements" : {
|
||||
"com.apple.developer.associated-domains" : []
|
||||
"ios": {
|
||||
"urltypes": "ctms,ctms-client",
|
||||
"capabilities": {
|
||||
"entitlements": {
|
||||
"com.apple.developer.associated-domains": []
|
||||
}
|
||||
},
|
||||
"UIBackgroundModes" : "location",
|
||||
"dSYMs" : false,
|
||||
"idfa" : false
|
||||
"UIBackgroundModes": "location",
|
||||
"dSYMs": false,
|
||||
"idfa": false
|
||||
},
|
||||
"sdkConfigs" : {
|
||||
"geolocation" : {
|
||||
"system" : {
|
||||
"__platform__" : [ "ios", "android" ]
|
||||
"sdkConfigs": {
|
||||
"geolocation": {
|
||||
"system": {
|
||||
"__platform__": ["ios", "android"]
|
||||
},
|
||||
"amap" : {
|
||||
"name" : "map_18608981880QdibHebq",
|
||||
"__platform__" : [ "ios", "android" ],
|
||||
"appkey_ios" : "f83067a97f0523331c3b06cf4ea28775",
|
||||
"appkey_android" : "0467567b45ec78d05357615209c7e69d"
|
||||
"amap": {
|
||||
"name": "map_18608981880QdibHebq",
|
||||
"__platform__": ["ios", "android"],
|
||||
"appkey_ios": "f83067a97f0523331c3b06cf4ea28775",
|
||||
"appkey_android": "0467567b45ec78d05357615209c7e69d"
|
||||
}
|
||||
},
|
||||
"maps" : {
|
||||
"amap" : {
|
||||
"name" : "map_18608981880QdibHebq",
|
||||
"appkey_ios" : "f83067a97f0523331c3b06cf4ea28775",
|
||||
"appkey_android" : "0467567b45ec78d05357615209c7e69d"
|
||||
"maps": {
|
||||
"amap": {
|
||||
"name": "map_18608981880QdibHebq",
|
||||
"appkey_ios": "f83067a97f0523331c3b06cf4ea28775",
|
||||
"appkey_android": "0467567b45ec78d05357615209c7e69d"
|
||||
}
|
||||
},
|
||||
"push" : {
|
||||
"unipush" : {
|
||||
"version" : "2",
|
||||
"offline" : false,
|
||||
"icons" : {
|
||||
"small" : {
|
||||
"hdpi" : "unpackage/res/push/icon-36.png"
|
||||
"push": {
|
||||
"unipush": {
|
||||
"version": "2",
|
||||
"offline": false,
|
||||
"icons": {
|
||||
"small": {
|
||||
"hdpi": "unpackage/res/push/icon-36.png"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"share" : {},
|
||||
"speech" : {},
|
||||
"statics" : {},
|
||||
"ad" : {},
|
||||
"oauth" : {}
|
||||
"share": {},
|
||||
"speech": {},
|
||||
"statics": {},
|
||||
"ad": {},
|
||||
"oauth": {}
|
||||
},
|
||||
"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"
|
||||
"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"
|
||||
"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"
|
||||
"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"
|
||||
}
|
||||
}
|
||||
},
|
||||
"splashscreen" : {
|
||||
"androidStyle" : "default",
|
||||
"android" : {
|
||||
"hdpi" : "unpackage/res/splash/splash-480X762.png",
|
||||
"xhdpi" : "unpackage/res/splash/splash-720X1242.png",
|
||||
"xxhdpi" : "unpackage/res/splash/splash-1080X1882.png"
|
||||
"splashscreen": {
|
||||
"androidStyle": "default",
|
||||
"android": {
|
||||
"hdpi": "unpackage/res/splash/splash-480X762.png",
|
||||
"xhdpi": "unpackage/res/splash/splash-720X1242.png",
|
||||
"xxhdpi": "unpackage/res/splash/splash-1080X1882.png"
|
||||
},
|
||||
"useOriginalMsgbox" : true
|
||||
"useOriginalMsgbox": true
|
||||
}
|
||||
},
|
||||
"error" : {
|
||||
"url" : "hybrid/html/404.html"
|
||||
"error": {
|
||||
"url": "hybrid/html/404.html"
|
||||
},
|
||||
"uniStatistics" : {
|
||||
"enable" : true
|
||||
"uniStatistics": {
|
||||
"enable": false
|
||||
}
|
||||
},
|
||||
"quickapp" : {},
|
||||
"mp-weixin" : {
|
||||
"appid" : "wxccd7e2a0911b3397",
|
||||
"setting" : {
|
||||
"urlCheck" : false,
|
||||
"es6" : false,
|
||||
"minified" : true,
|
||||
"postcss" : true
|
||||
"quickapp": {},
|
||||
"mp-weixin": {
|
||||
"appid": "wxccd7e2a0911b3397",
|
||||
"setting": {
|
||||
"urlCheck": false,
|
||||
"es6": false,
|
||||
"minified": true,
|
||||
"postcss": true
|
||||
},
|
||||
"optimization" : {
|
||||
"subPackages" : true
|
||||
"optimization": {
|
||||
"subPackages": true
|
||||
},
|
||||
"usingComponents" : true,
|
||||
"uniStatistics" : {
|
||||
"enable" : false
|
||||
"usingComponents": true,
|
||||
"uniStatistics": {
|
||||
"enable": false
|
||||
},
|
||||
"unipush" : {
|
||||
"enable" : true
|
||||
"unipush": {
|
||||
"enable": true
|
||||
}
|
||||
},
|
||||
"vueVersion" : "3",
|
||||
"h5" : {
|
||||
"template" : "static/index.html",
|
||||
"devServer" : {
|
||||
"port" : 9090,
|
||||
"https" : false
|
||||
"vueVersion": "3",
|
||||
"h5": {
|
||||
"template": "static/index.html",
|
||||
"devServer": {
|
||||
"port": 9090,
|
||||
"https": false
|
||||
},
|
||||
"title" : "汽车托运助手",
|
||||
"router" : {
|
||||
"mode" : "hash",
|
||||
"base" : "./"
|
||||
"title": "汽车托运助手",
|
||||
"router": {
|
||||
"mode": "hash",
|
||||
"base": "./"
|
||||
},
|
||||
"unipush" : {
|
||||
"enable" : true
|
||||
"unipush": {
|
||||
"enable": true
|
||||
},
|
||||
"sdkConfigs" : {
|
||||
"maps" : {
|
||||
"amap" : {
|
||||
"key" : "e3df95513a8c0ca18fdecbac3c4c7bc4",
|
||||
"securityJsCode" : "d21c9d60fe573e0ceb8e23396fe29233",
|
||||
"serviceHost" : ""
|
||||
"sdkConfigs": {
|
||||
"maps": {
|
||||
"amap": {
|
||||
"key": "e3df95513a8c0ca18fdecbac3c4c7bc4",
|
||||
"securityJsCode": "d21c9d60fe573e0ceb8e23396fe29233",
|
||||
"serviceHost": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
"uniStatistics" : {
|
||||
"enable" : true
|
||||
"uniStatistics": {
|
||||
"enable": false
|
||||
},
|
||||
"optimization" : {
|
||||
"treeShaking" : {
|
||||
"enable" : true
|
||||
"optimization": {
|
||||
"treeShaking": {
|
||||
"enable": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"locale" : "zh-Hans",
|
||||
"fallbackLocale" : "zh-Hans",
|
||||
"uniStatistics" : {
|
||||
"version" : "2",
|
||||
"enable" : false
|
||||
"locale": "zh-Hans",
|
||||
"fallbackLocale": "zh-Hans",
|
||||
"uniStatistics": {
|
||||
"version": "2",
|
||||
"enable": false
|
||||
},
|
||||
"mp-alipay" : {
|
||||
"uniStatistics" : {
|
||||
"enable" : false
|
||||
"mp-alipay": {
|
||||
"uniStatistics": {
|
||||
"enable": false
|
||||
}
|
||||
},
|
||||
"mp-baidu" : {
|
||||
"uniStatistics" : {
|
||||
"enable" : false
|
||||
"mp-baidu": {
|
||||
"uniStatistics": {
|
||||
"enable": false
|
||||
}
|
||||
},
|
||||
"mp-jd" : {
|
||||
"uniStatistics" : {
|
||||
"enable" : false
|
||||
"mp-jd": {
|
||||
"uniStatistics": {
|
||||
"enable": false
|
||||
}
|
||||
},
|
||||
"mp-kuaishou" : {
|
||||
"uniStatistics" : {
|
||||
"enable" : false
|
||||
"mp-kuaishou": {
|
||||
"uniStatistics": {
|
||||
"enable": false
|
||||
}
|
||||
},
|
||||
"mp-lark" : {
|
||||
"uniStatistics" : {
|
||||
"enable" : false
|
||||
"mp-lark": {
|
||||
"uniStatistics": {
|
||||
"enable": false
|
||||
}
|
||||
},
|
||||
"mp-qq" : {
|
||||
"uniStatistics" : {
|
||||
"enable" : false
|
||||
"mp-qq": {
|
||||
"uniStatistics": {
|
||||
"enable": false
|
||||
}
|
||||
},
|
||||
"mp-toutiao" : {
|
||||
"uniStatistics" : {
|
||||
"enable" : false
|
||||
"mp-toutiao": {
|
||||
"uniStatistics": {
|
||||
"enable": false
|
||||
}
|
||||
},
|
||||
"quickapp-webview-huawei" : {
|
||||
"uniStatistics" : {
|
||||
"enable" : false
|
||||
"quickapp-webview-huawei": {
|
||||
"uniStatistics": {
|
||||
"enable": false
|
||||
}
|
||||
},
|
||||
"quickapp-webview-union" : {
|
||||
"uniStatistics" : {
|
||||
"enable" : false
|
||||
"quickapp-webview-union": {
|
||||
"uniStatistics": {
|
||||
"enable": false
|
||||
}
|
||||
}
|
||||
}
|
12
package.json
12
package.json
@ -9,12 +9,12 @@
|
||||
},
|
||||
"repository": "https://gitea.hiluker.com/lukegzs/ctms-client",
|
||||
"keywords": [
|
||||
"hello-uniapp",
|
||||
"uni-app",
|
||||
"uni-ui",
|
||||
"示例工程"
|
||||
"汽车拖运",
|
||||
"运车",
|
||||
"安邮车联",
|
||||
"anyouchelian"
|
||||
],
|
||||
"author": "",
|
||||
"author": "fm453",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://gitea.hiluker.com/lukegzs/ctms-client"
|
||||
@ -60,7 +60,7 @@
|
||||
"联盟": "u"
|
||||
},
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue2": "n",
|
||||
"vue3": "y"
|
||||
}
|
||||
}
|
||||
|
244
pages.json
244
pages.json
@ -38,21 +38,6 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
}, {
|
||||
"path": "uni_modules/uni-upgrade-center-app/pages/upgrade-popup",
|
||||
"style": {
|
||||
"disableScroll": true,
|
||||
"app-plus": {
|
||||
"backgroundColorTop": "transparent",
|
||||
"background": "transparent",
|
||||
"titleNView": false,
|
||||
"scrollIndicator": false,
|
||||
"popGesture": "none",
|
||||
"animationType": "fade-in",
|
||||
"animationDuration": 200
|
||||
|
||||
}
|
||||
}
|
||||
}, {
|
||||
"path": "pages/uni-agree/uni-agree",
|
||||
"style": {
|
||||
@ -111,230 +96,6 @@
|
||||
"needLogin": false
|
||||
}],
|
||||
"subPackages": [{
|
||||
"root": "pages/uni-starter",
|
||||
"pages": [{
|
||||
"path": "list/list",
|
||||
"style": {
|
||||
// #ifndef APP-PLUS
|
||||
"enablePullDownRefresh": true
|
||||
// #endif
|
||||
// "navigationStyle": "custom"
|
||||
}
|
||||
}, {
|
||||
"path": "list/search/search",
|
||||
"style": {
|
||||
"navigationBarTitleText": "搜索"
|
||||
}
|
||||
}, {
|
||||
"path": "list/detail",
|
||||
"style": {
|
||||
"app-plus": {
|
||||
"titleNView": {
|
||||
"buttons": [{
|
||||
"type": "share"
|
||||
}],
|
||||
"type": "transparent"
|
||||
}
|
||||
},
|
||||
"h5": {
|
||||
"titleNView": {
|
||||
"type": "transparent"
|
||||
}
|
||||
},
|
||||
"navigationBarTitleText": "文章详情"
|
||||
}
|
||||
}, {
|
||||
"path": "news/list/list",
|
||||
"style": {
|
||||
// #ifndef APP-PLUS
|
||||
"enablePullDownRefresh": true
|
||||
// #endif
|
||||
// "navigationStyle": "custom"
|
||||
}
|
||||
}, {
|
||||
"path": "news/search/search",
|
||||
"style": {
|
||||
"navigationBarTitleText": "搜索"
|
||||
}
|
||||
}, {
|
||||
"path": "news/detail/detail",
|
||||
"style": {
|
||||
"app-plus": {
|
||||
"titleNView": {
|
||||
"buttons": [{
|
||||
"type": "share"
|
||||
}],
|
||||
"type": "transparent"
|
||||
}
|
||||
},
|
||||
"h5": {
|
||||
"titleNView": {
|
||||
"type": "transparent"
|
||||
}
|
||||
},
|
||||
"navigationBarTitleText": "文章详情"
|
||||
}
|
||||
}, {
|
||||
"path": "ucenter/ucenter",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
}, {
|
||||
"path": "ucenter/settings/settings",
|
||||
"style": {
|
||||
"navigationBarTitleText": "设置"
|
||||
}
|
||||
}, {
|
||||
"path": "ucenter/read-news-log/read-news-log",
|
||||
"style": {
|
||||
"navigationBarTitleText": "阅读记录",
|
||||
"enablePullDownRefresh": true
|
||||
}
|
||||
}
|
||||
// #ifdef APP-PLUS
|
||||
, {
|
||||
"path": "ucenter/about/about",
|
||||
"style": {
|
||||
"navigationBarTitleText": "关于",
|
||||
"app-plus": {
|
||||
"titleNView": {
|
||||
"buttons": [{
|
||||
"type": "share"
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "ucenter/invite/invite",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
]
|
||||
}, {
|
||||
"root": "uni_modules/uni-feedback",
|
||||
"pages": [{
|
||||
"path": "pages/opendb-feedback/opendb-feedback",
|
||||
"style": {
|
||||
"navigationBarTitleText": "意见反馈",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
}]
|
||||
}, {
|
||||
"root": "uni_modules/uni-id-pages/pages",
|
||||
"pages": [{
|
||||
"path": "userinfo/userinfo",
|
||||
"style": {
|
||||
"navigationBarTitleText": "个人资料"
|
||||
}
|
||||
}, {
|
||||
"path": "userinfo/realname-verify/realname-verify",
|
||||
"style": {
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationBarTitleText": "实名认证"
|
||||
}
|
||||
}, {
|
||||
"path": "login/login-withoutpwd"
|
||||
}, {
|
||||
"path": "login/login-withpwd"
|
||||
}, {
|
||||
"path": "userinfo/deactivate/deactivate",
|
||||
"style": {
|
||||
"navigationBarTitleText": "注销账号"
|
||||
}
|
||||
}, {
|
||||
"path": "userinfo/bind-mobile/bind-mobile",
|
||||
"style": {
|
||||
"navigationBarTitleText": "绑定手机号码"
|
||||
}
|
||||
}, {
|
||||
"path": "login/login-smscode",
|
||||
"style": {
|
||||
"navigationBarTitleText": "手机验证码登录"
|
||||
}
|
||||
}, {
|
||||
"path": "register/register",
|
||||
"style": {
|
||||
"navigationBarTitleText": "注册"
|
||||
}
|
||||
}, {
|
||||
"path": "retrieve/retrieve",
|
||||
"style": {
|
||||
"navigationBarTitleText": "重置密码"
|
||||
}
|
||||
}, {
|
||||
"path": "common/webview/webview",
|
||||
"style": {
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationBarTitleText": ""
|
||||
}
|
||||
}, {
|
||||
"path": "userinfo/change_pwd/change_pwd",
|
||||
"style": {
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationBarTitleText": "修改密码"
|
||||
}
|
||||
}, {
|
||||
"path": "register/register-by-email",
|
||||
"style": {
|
||||
"navigationBarTitleText": "邮箱验证码注册"
|
||||
}
|
||||
}, {
|
||||
"path": "retrieve/retrieve-by-email",
|
||||
"style": {
|
||||
"navigationBarTitleText": "通过邮箱重置密码"
|
||||
}
|
||||
}, {
|
||||
"path": "userinfo/set-pwd/set-pwd",
|
||||
"style": {
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationBarTitleText": "设置密码"
|
||||
}
|
||||
}
|
||||
// #ifdef H5
|
||||
, {
|
||||
"path": "userinfo/cropImage/cropImage"
|
||||
}, {
|
||||
"path": "register/register-admin",
|
||||
"style": {
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationBarTitleText": "注册管理员账号"
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
]
|
||||
}, {
|
||||
"root": "uni_modules/uni-cms-article/pages",
|
||||
"pages": [{
|
||||
"path": "list/list",
|
||||
"style": {
|
||||
"backgroundColor": "#FFFFFF",
|
||||
"disableScroll": true
|
||||
// "navigationStyle": "custom"
|
||||
}
|
||||
}, {
|
||||
"path": "search/search",
|
||||
"style": {
|
||||
"navigationBarTitleText": "搜索"
|
||||
}
|
||||
}, {
|
||||
"path": "detail/detail",
|
||||
"style": {
|
||||
"backgroundColor": "#FFFFFF",
|
||||
"navigationBarTitleText": "详情"
|
||||
}
|
||||
}, {
|
||||
"path": "detail/preview",
|
||||
"style": {
|
||||
"backgroundColor": "#FFFFFF",
|
||||
"navigationBarTitleText": "预览"
|
||||
}
|
||||
}]
|
||||
}, {
|
||||
"root": "pages/ctms",
|
||||
"pages": [{
|
||||
"path": "index/index",
|
||||
@ -538,14 +299,11 @@
|
||||
},
|
||||
"uniIdRouter": {
|
||||
//自动路由
|
||||
// "loginPage": "uni_modules/uni-id-pages/pages/login/login-withoutpwd",
|
||||
"loginPage": "pages/ctms/login/loginSms",
|
||||
|
||||
// 需要登录的页面路径
|
||||
"needLogin": [
|
||||
// 需要登录才可访问的页面列表,可以使用正则语法
|
||||
"uni_modules/uni-id-pages/pages/userinfo/userinfo",
|
||||
"pages/uni-starter/.*",
|
||||
"pages/ctms/order/.*",
|
||||
//order目录下全部需要登陆
|
||||
"pages/ctms/orderpre/.*",
|
||||
@ -553,7 +311,7 @@
|
||||
"pages/ctms/me/.*"
|
||||
],
|
||||
// 客户端未登录或登录状态过期的判断: uni_id_token失效
|
||||
"resToLogin": true
|
||||
"resToLogin": false
|
||||
// 自动解析云对象及clientDB的错误码,如果是客户端token不正确或token过期则自动跳转配置的登录页面
|
||||
}
|
||||
}
|
@ -106,11 +106,6 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.uni-padding-wrap {
|
||||
width: 550rpx;
|
||||
padding: 0 100rpx;
|
||||
}
|
||||
|
||||
/*轮播幻灯*/
|
||||
.swiper {
|
||||
height: 300rpx;
|
||||
@ -123,11 +118,12 @@
|
||||
}
|
||||
|
||||
.swiper-item {
|
||||
width: 100%;
|
||||
width: 96%;
|
||||
display: block;
|
||||
height: 300rpx;
|
||||
line-height: 300rpx;
|
||||
text-align: center;
|
||||
margin-left: 2%;
|
||||
}
|
||||
|
||||
.swiper-image {
|
||||
|
@ -51,7 +51,7 @@
|
||||
<view class="uni-form-item ">
|
||||
<view class="title">持久登陆</view>
|
||||
<view>
|
||||
<switch name="isLong" :checked="isLong==1?true:false" />
|
||||
<switch name="isLong" :checked="isLong===1" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="uni-form-item">
|
||||
@ -219,7 +219,7 @@
|
||||
return false;
|
||||
}
|
||||
let timer = setInterval(() => {
|
||||
if (this.leftSecond == 0) {
|
||||
if (this.leftSecond === 0) {
|
||||
clearInterval(this.timer)
|
||||
this.leftSecond = this.vcode_time;
|
||||
this.vcode_again = false;
|
||||
|
@ -70,6 +70,7 @@
|
||||
|
||||
<uni-notice-bar
|
||||
text="温馨提示: 请不要随车放置 贵重小件物品(如 眼镜\无线充电器\数据线\U盘\手表\Zipporr火机等)、精密仪器设备(如 电脑等)、易燃易爆物品,车内不得放置违规违禁物品(如 燃料油\火机\酒精\散装酒等),否则司机有权拒载、平台有权拒单。" />
|
||||
<uni-notice-bar text="有安装了ETC设备的,请务必关闭或移除ETC,避免扣费" />
|
||||
<uni-notice-bar text="炎热天气,不要随车装运水果,一定会闷坏的。" />
|
||||
<text class="uniui-h6 help-block"></text>
|
||||
</view>
|
||||
|
@ -85,7 +85,7 @@
|
||||
);
|
||||
},
|
||||
formReset: function(e) {
|
||||
// utils.debug('清空数据')
|
||||
utils.debug('清空数据')
|
||||
},
|
||||
goTo(page) {
|
||||
page = config.pageDir + page;
|
||||
@ -96,8 +96,8 @@
|
||||
|
||||
},
|
||||
onLoad() {
|
||||
var user = ctms.user.checkLogin();
|
||||
var user = store.state.userCloud;
|
||||
var user = ctms.user.getInfo();
|
||||
// var user = store.state.userCloud;
|
||||
this.search.phone = user.mobile;
|
||||
},
|
||||
onShow: function() {}
|
||||
|
@ -68,9 +68,7 @@
|
||||
:direction="direction" @trigger="trigger" @fabClick="fabClick" />
|
||||
</view>
|
||||
|
||||
<uni-notice-bar
|
||||
text="温馨提示: 请不要随车放置 贵重小件物品(如 眼镜\无线充电器\数据线\U盘\手表\Zipporr火机等)、精密仪器设备(如 电脑等)、易燃易爆物品,车内不得放置违规违禁物品(如 燃料油\火机\酒精\散装酒等),否则司机有权拒载、平台有权拒单。" />
|
||||
<uni-notice-bar text="炎热天气,不要随车装运水果,一定会闷坏的。" />
|
||||
<uni-notice-bar text="温馨提示:请填写真实信息以便获取确切报价反馈。" />
|
||||
<text class="uniui-h6 help-block"></text>
|
||||
</view>
|
||||
|
||||
@ -78,10 +76,6 @@
|
||||
|
||||
<script>
|
||||
import province from '@/common/province.js';
|
||||
import letter from '@/common/letter.js';
|
||||
import carP from '@/common/car-p.js';
|
||||
import config from "@/config/ctms.config.js";
|
||||
import store from '@/store/index.js';
|
||||
import utils from "@/utils/common.js";
|
||||
import ctms from '@/apis/ctms/index.js';
|
||||
export default {
|
||||
|
@ -1,3 +1,11 @@
|
||||
<!--
|
||||
* @Author: 嗨噜客(三亚)<fm453>
|
||||
* @Date: 2021-09-06 11:48:18
|
||||
* @FilePath: pages/ctms/tabbar/index/index.vue
|
||||
* @Description:
|
||||
* @Email: 393213759@qq.com
|
||||
* Copyright (c) 2025 by www.hiluker.cn, All Rights Reserved.
|
||||
-->
|
||||
<template>
|
||||
<view class="content">
|
||||
<!-- 轮播图 -->
|
||||
@ -11,14 +19,22 @@
|
||||
</swiper>
|
||||
</view>
|
||||
|
||||
<image class="logo" src="@/static/logo.png"></image>
|
||||
<!--计数器 -->
|
||||
<uni-notice-bar color="#2979FF" background-color="#EAF2FF" :text="h5Data.welcomeTip" />
|
||||
<view class="text-area">
|
||||
<text class="title">安邮车联</text>
|
||||
<view class="numCounter">
|
||||
<view class="div title">累计运单:</view>
|
||||
<view class="div" v-for="(num, index) in totalOrdersNum" :key="index">
|
||||
<text :data-value="num" class="text">{{num}}</text>
|
||||
</view>
|
||||
<view class="text-area">
|
||||
<text class="title">运车助手</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<uni-section title="近期热门" subTitle="最近咨询、下单的路段及车型信息" type="line" class="recent">
|
||||
<uni-notice-bar show-icon='false' scrollable v-for="(str, index) in h5Data.recent" :key="index"
|
||||
:text="str" />
|
||||
</uni-section>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@ -32,7 +48,13 @@
|
||||
banner: [{
|
||||
image: '/static/img/banner/banner.jpg',
|
||||
link: ""
|
||||
}]
|
||||
}],
|
||||
h5Data: {
|
||||
welcomeTip: '安邮车联汽车托运平台致力于为客户提供多样化、专业化的优质托运服务承运商信息,让客户省心、省钱地找到合适的汽车托运服务。',
|
||||
orderTotal: 1234567,
|
||||
recent: ['王女士,三亚=>哈尔滨,一台比亚迪宋新能源车型,日期:6月15日', '刘先生,万宁=>常德,路虎揽胜,日期:6月18日']
|
||||
},
|
||||
totalOrdersNum: [1, 2, 3, 4, 5, 6]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@ -55,6 +77,24 @@
|
||||
}
|
||||
});
|
||||
},
|
||||
getH5datas() {
|
||||
ctms.datas.h5().then((res) => {
|
||||
var _data = res;
|
||||
if (!_data) {
|
||||
return false;
|
||||
}
|
||||
console.log(_data);
|
||||
if (_data.welcomeTip) {
|
||||
this.h5Data.welcomeTip = _data.welcomeTip;
|
||||
}
|
||||
if (_data.orderTotal) {
|
||||
this.h5Data.orderTotal = _data.orderTotal;
|
||||
}
|
||||
if (_data.recent) {
|
||||
this.h5Data.recent = _data.recent;
|
||||
}
|
||||
});
|
||||
},
|
||||
checkSplash() {
|
||||
var ls = "splashShowed";
|
||||
var a = uni.getStorageSync(ls);
|
||||
@ -63,13 +103,23 @@
|
||||
url: "/pages/index/index"
|
||||
})
|
||||
}
|
||||
},
|
||||
numToArr(num) {
|
||||
var _num = num ?? this.h5Data.orderTotal;
|
||||
_num = _num.toString();
|
||||
var arr = Array.from(_num);
|
||||
return arr;
|
||||
}
|
||||
},
|
||||
onLoad: function() {
|
||||
this.checkSplash();
|
||||
this.getH5datas();
|
||||
this.totalOrdersNum = this.numToArr();
|
||||
},
|
||||
onShow: function() {
|
||||
this.getBanner();
|
||||
this.getH5datas();
|
||||
this.totalOrdersNum = this.numToArr();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -102,15 +152,12 @@
|
||||
}
|
||||
</style>
|
||||
<style lang="scss">
|
||||
@import url("../../index/counter.css");
|
||||
|
||||
.uni-margin-wrap {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.uni-padding-wrap {
|
||||
width: 550rpx;
|
||||
padding: 0 100rpx;
|
||||
}
|
||||
|
||||
/*轮播幻灯*/
|
||||
.swiper {
|
||||
height: 300rpx;
|
||||
@ -145,4 +192,10 @@
|
||||
.swiper-box .wx-swiper-dots.wx-swiper-dots-horizontal {
|
||||
padding-bottom: 10rpx;
|
||||
}
|
||||
|
||||
/*最近热门*/
|
||||
.recent {
|
||||
margin-top: 1rem;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
@ -1,3 +1,11 @@
|
||||
<!--
|
||||
* @Author: 嗨噜客(三亚)<fm453>
|
||||
* @Date: 2021-09-06 11:48:18
|
||||
* @FilePath: pages/ctms/tabbar/me/index.vue
|
||||
* @Description:
|
||||
* @Email: 393213759@qq.com
|
||||
* Copyright (c) 2025 by www.hiluker.cn, All Rights Reserved.
|
||||
-->
|
||||
<template>
|
||||
<view class="container">
|
||||
<view class="about">
|
||||
|
@ -1,3 +1,11 @@
|
||||
<!--
|
||||
* @Author: 嗨噜客(三亚)<fm453>
|
||||
* @Date: 2021-09-06 11:48:18
|
||||
* @FilePath: pages/ctms/tabbar/notice/index.vue
|
||||
* @Description:
|
||||
* @Email: 393213759@qq.com
|
||||
* Copyright (c) 2025 by www.hiluker.cn, All Rights Reserved.
|
||||
-->
|
||||
<template>
|
||||
<view class="container">
|
||||
<view v-if="!totalCount" class="content">
|
||||
|
@ -1,3 +1,11 @@
|
||||
<!--
|
||||
* @Author: 嗨噜客(三亚)<fm453>
|
||||
* @Date: 2022-04-22 13:22:50
|
||||
* @FilePath: pages/ctms/tabbar/order/index.vue
|
||||
* @Description:
|
||||
* @Email: 393213759@qq.com
|
||||
* Copyright (c) 2025 by www.hiluker.cn, All Rights Reserved.
|
||||
-->
|
||||
<template>
|
||||
<view class="content">
|
||||
<view class="uni-common-mt uni-form">
|
||||
|
@ -1,385 +0,0 @@
|
||||
<template>
|
||||
<view class="article">
|
||||
<!-- #ifdef APP-PLUS -->
|
||||
<uni-nav-bar :statusBar="true" :border="false"></uni-nav-bar>
|
||||
<!-- #endif -->
|
||||
<view class="article-title">{{ title }}</view>
|
||||
<unicloud-db v-slot:default="{data, loading, error, options}" :options="formData"
|
||||
collection="uni-cms-articles,uni-id-users" :field="field" :getone="true" :where="where" :manual="true"
|
||||
ref="detail" foreignKey="uni-cms-articles.user_id" @load="loadData">
|
||||
<template v-if="!loading && data">
|
||||
<uni-list :border="false">
|
||||
<uni-list-item thumbSize="lg" :thumb="data.image">
|
||||
<!-- 通过body插槽定义作者信息内容 -->
|
||||
<template v-slot:body>
|
||||
<view class="header-content">
|
||||
<view class="uni-title">
|
||||
{{data.user_id && data.user_id[0] && data.user_id[0].nickname || '未知'}}
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<template v-slot:footer>
|
||||
<view class="footer">
|
||||
<view class="uni-note">更新于
|
||||
<uni-dateformat :date="data.last_modify_date" format="yyyy-MM-dd hh:mm"
|
||||
:threshold="[60000, 2592000000]" />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</uni-list-item>
|
||||
</uni-list>
|
||||
<view class="banner">
|
||||
<!-- 文章开头,缩略图 -->
|
||||
<image class="banner-img" :src="data.thumbnail" mode="widthFix"></image>
|
||||
<!-- 文章摘要 -->
|
||||
<view class="banner-title">
|
||||
<text class="uni-ellipsis">{{data.excerpt}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="article-content">
|
||||
<rich-text :nodes="data.content"></rich-text>
|
||||
</view>
|
||||
</template>
|
||||
</unicloud-db>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// #ifdef APP
|
||||
import UniShare from '@/uni_modules/uni-share/js_sdk/uni-share.js';
|
||||
import uniNavBar from '@/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-nav-bar.vue';
|
||||
const uniShare = new UniShare()
|
||||
// #endif
|
||||
const db = uniCloud.database();
|
||||
const readNewsLog = db.collection('read-news-log')
|
||||
export default {
|
||||
// #ifdef APP
|
||||
components: {
|
||||
"uni-nav-bar": uniNavBar
|
||||
},
|
||||
onBackPress({
|
||||
from
|
||||
}) {
|
||||
if (from == 'backbutton') {
|
||||
if (uniShare.isShow) {
|
||||
this.$nextTick(function() {
|
||||
console.log(uniShare);
|
||||
uniShare.hide()
|
||||
})
|
||||
}
|
||||
return uniShare.isShow;
|
||||
}
|
||||
},
|
||||
// #endif
|
||||
data() {
|
||||
return {
|
||||
// 当前显示 _id
|
||||
id: "",
|
||||
title: 'title',
|
||||
// 数据表名
|
||||
// 查询字段,多个字段用 , 分割
|
||||
field: 'user_id.nickname,user_id._id,avatar,excerpt,last_modify_date,comment_count,like_count,title,content',
|
||||
formData: {
|
||||
noData: '<p style="text-align:center;color:#666">详情加载中...</p>'
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
uniStarterConfig() {
|
||||
return getApp().globalData.config
|
||||
},
|
||||
where() {
|
||||
//拼接where条件 查询条件 ,更多详见 :https://uniapp.dcloud.net.cn/uniCloud/unicloud-db?id=jsquery
|
||||
return `_id =="${this.id}"`
|
||||
}
|
||||
},
|
||||
onLoad(event) {
|
||||
//获取真实新闻id,通常 id 来自上一个页面
|
||||
if (event.id) {
|
||||
this.id = event.id
|
||||
}
|
||||
//若上一页传递了标题过来,则设置导航栏标题
|
||||
if (event.title) {
|
||||
this.title = event.title
|
||||
uni.setNavigationBarTitle({
|
||||
title: event.title
|
||||
})
|
||||
}
|
||||
},
|
||||
onReady() {
|
||||
// 开始加载数据,修改 where 条件后才开始去加载 clinetDB 的数据 ,需要等组件渲染完毕后才开始执行 loadData,所以不能再 onLoad 中执行
|
||||
if (this.id) { // ID 不为空,则发起查询
|
||||
this.$refs.detail.loadData()
|
||||
} else {
|
||||
uni.showToast({
|
||||
icon: 'none',
|
||||
title: this.$t('listDetail.newsErr')
|
||||
})
|
||||
}
|
||||
},
|
||||
onNavigationBarButtonTap(event) {
|
||||
if (event.type == 'share') {
|
||||
this.shareClick();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
$log(...args) {
|
||||
console.log('args', ...args, this.id)
|
||||
},
|
||||
setReadNewsLog() {
|
||||
let item = {
|
||||
"article_id": this.id,
|
||||
"last_time": Date.now()
|
||||
},
|
||||
readNewsLog = uni.getStorageSync('readNewsLog') || [],
|
||||
index = -1;
|
||||
readNewsLog.forEach(({
|
||||
article_id
|
||||
}, i) => {
|
||||
if (article_id == item.article_id) {
|
||||
index = i
|
||||
}
|
||||
})
|
||||
if (index === -1) {
|
||||
readNewsLog.push(item)
|
||||
} else {
|
||||
readNewsLog.splice(index, 1, item)
|
||||
}
|
||||
uni.setStorageSync('readNewsLog', readNewsLog)
|
||||
console.log(readNewsLog);
|
||||
},
|
||||
setFavorite() {
|
||||
if (uniCloud.getCurrentUserInfo().tokenExpired < Date.now()) {
|
||||
return console.log('未登录用户');
|
||||
}
|
||||
let article_id = this.id,
|
||||
last_time = Date.now();
|
||||
console.log({
|
||||
article_id,
|
||||
last_time
|
||||
});
|
||||
readNewsLog.where(`"article_id" == "${article_id}" && "user_id"==$env.uid`)
|
||||
.update({
|
||||
last_time
|
||||
})
|
||||
.then(({
|
||||
result: {
|
||||
updated
|
||||
}
|
||||
}) => {
|
||||
console.log('updated', updated);
|
||||
if (!updated) {
|
||||
readNewsLog.add({
|
||||
article_id
|
||||
}).then(e => {
|
||||
console.log(e);
|
||||
}).catch(err => {
|
||||
console.log(err);
|
||||
})
|
||||
}
|
||||
}).catch(err => {
|
||||
console.log(err);
|
||||
})
|
||||
},
|
||||
loadData(data) {
|
||||
//如果上一页未传递标题过来(如搜索直达详情),则从新闻详情中读取标题
|
||||
if (this.title == '' && data[0].title) {
|
||||
this.title = data[0].title
|
||||
uni.setNavigationBarTitle({
|
||||
title: data[0].title
|
||||
});
|
||||
|
||||
}
|
||||
this.setReadNewsLog();
|
||||
},
|
||||
/**
|
||||
* followClick
|
||||
* 点击关注
|
||||
*/
|
||||
followClick() {
|
||||
uni.showToast({
|
||||
title: this.$t('listDetail.follow'),
|
||||
icon: 'none'
|
||||
});
|
||||
},
|
||||
/**
|
||||
* 分享该文章
|
||||
*/
|
||||
// #ifdef APP
|
||||
shareClick() {
|
||||
let {
|
||||
_id,
|
||||
title,
|
||||
excerpt,
|
||||
avatar
|
||||
} = this.$refs.detail.dataList
|
||||
console.log(JSON.stringify({
|
||||
_id,
|
||||
title,
|
||||
excerpt,
|
||||
avatar
|
||||
}));
|
||||
uniShare.show({
|
||||
content: { //公共的分享类型(type)、链接(herf)、标题(title)、summary(描述)、imageUrl(缩略图)
|
||||
type: 0,
|
||||
href: this.uniStarterConfig.h5.url +
|
||||
`/#/pages/uni-starter/list/detail?id=${_id}&title=${title}`,
|
||||
title: this.title,
|
||||
summary: excerpt,
|
||||
imageUrl: avatar +
|
||||
'?x-oss-process=image/resize,m_fill,h_100,w_100' //压缩图片解决,在ios端分享图过大导致的图片失效问题
|
||||
},
|
||||
menus: [{
|
||||
"img": "/static/app-plus/sharemenu/wechatfriend.png",
|
||||
"text": this.$t('common.wechatFriends'),
|
||||
"share": {
|
||||
"provider": "weixin",
|
||||
"scene": "WXSceneSession"
|
||||
}
|
||||
},
|
||||
{
|
||||
"img": "/static/app-plus/sharemenu/wechatmoments.png",
|
||||
"text": this.$t('common.wechatBbs'),
|
||||
"share": {
|
||||
"provider": "weixin",
|
||||
"scene": "WXSceneTimeline"
|
||||
}
|
||||
},
|
||||
{
|
||||
"img": "/static/app-plus/sharemenu/mp_weixin.png",
|
||||
"text": this.$t('common.wechatApplet'),
|
||||
"share": {
|
||||
provider: "weixin",
|
||||
scene: "WXSceneSession",
|
||||
type: 5,
|
||||
miniProgram: {
|
||||
id: this.uniStarterConfig.mp.weixin.id,
|
||||
path: `/pages/uni-starter/list/detail?id=${_id}&title=${title}`,
|
||||
webUrl: this.uniStarterConfig.h5.url +
|
||||
`/#/pages/uni-starter/list/detail?id=${_id}&title=${title}`,
|
||||
type: 0
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
"img": "/static/app-plus/sharemenu/weibo.png",
|
||||
"text": this.$t('common.weibo'),
|
||||
"share": {
|
||||
"provider": "sinaweibo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"img": "/static/app-plus/sharemenu/qq.png",
|
||||
"text": "QQ",
|
||||
"share": {
|
||||
"provider": "qq"
|
||||
}
|
||||
},
|
||||
{
|
||||
"img": "/static/app-plus/sharemenu/copyurl.png",
|
||||
"text": this.$t('common.copy'),
|
||||
"share": "copyurl"
|
||||
},
|
||||
{
|
||||
"img": "/static/app-plus/sharemenu/more.png",
|
||||
"text": this.$t('common.more'),
|
||||
"share": "shareSystem"
|
||||
}
|
||||
],
|
||||
cancelText: this.$t('common.cancelShare'),
|
||||
}, e => { //callback
|
||||
console.log(e);
|
||||
})
|
||||
}
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.header-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* 标题 */
|
||||
.uni-title {
|
||||
display: flex;
|
||||
margin-bottom: 5px;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
color: #3b4144;
|
||||
}
|
||||
|
||||
/* 描述 额外文本 */
|
||||
.uni-note {
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.footer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.footer-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 12px;
|
||||
height: 30px;
|
||||
color: #fff;
|
||||
background-color: #ff5a5f;
|
||||
}
|
||||
|
||||
.banner {
|
||||
position: relative;
|
||||
margin: 0 15px;
|
||||
height: 180px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.banner-img {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.banner-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
padding: 0 15px;
|
||||
width: 100%;
|
||||
bottom: 0;
|
||||
height: 30px;
|
||||
font-size: 14px;
|
||||
color: #fff;
|
||||
background: rgba(0, 0, 0, 0.4);
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.uni-ellipsis {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.article-title {
|
||||
padding: 20px 15px;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.article-content {
|
||||
padding: 15px;
|
||||
font-size: 15px;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
@ -1,256 +0,0 @@
|
||||
<template>
|
||||
<view class="pages">
|
||||
<!-- #ifndef H5 -->
|
||||
<statusBar></statusBar>
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- 搜索功能 -->
|
||||
<view class="uni-search-box">
|
||||
<uni-search-bar v-model="keyword" ref="searchBar" radius="100" cancelButton="none" disabled
|
||||
:placeholder="inputPlaceholder" />
|
||||
<view class="cover-search-bar" @click="searchClick"></view>
|
||||
</view>
|
||||
|
||||
<unicloud-db ref='udb' v-slot:default="{data,pagination,hasMore, loading, error, options}" @error="onqueryerror"
|
||||
:collection="colList" :page-size="10">
|
||||
<!-- 基于 uni-list 的页面布局 field="user_id.nickname"-->
|
||||
<uni-list class="uni-list" :border="false" :style="{height:listHight}">
|
||||
|
||||
<!-- 作用于app端nvue页面的下拉加载 -->
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
<refreshBox @refresh="refresh" :loading="loading"></refreshBox>
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- 列表渲染 -->
|
||||
<uni-list-item :to="'./detail?id='+item._id+'&title='+item.title" v-for="(item,index) in data"
|
||||
:key="index">
|
||||
<!-- 通过header插槽定义列表左侧图片 -->
|
||||
<template v-slot:header>
|
||||
<image class="avatar" :src="item.avatar" mode="aspectFill"></image>
|
||||
</template>
|
||||
<!-- 通过body插槽定义布局 -->
|
||||
<template v-slot:body>
|
||||
<view class="main">
|
||||
<text class="title">{{item.title}}</text>
|
||||
<view class="info">
|
||||
<text class="author">{{item.user_id[0]?item.user_id[0].nickname:''}}</text>
|
||||
<uni-dateformat class="last_modify_date" :date="item.last_modify_date"
|
||||
format="yyyy-MM-dd" :threshold="[60000, 2592000000]" />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</uni-list-item>
|
||||
<!-- 加载状态:上拉加载更多,加载中,没有更多数据了,加载错误 -->
|
||||
<!-- #ifdef APP-PLUS -->
|
||||
<uni-list-item>
|
||||
<template v-slot:body>
|
||||
<!-- #endif -->
|
||||
<uni-load-state @networkResume="refresh" :state="{data,pagination,hasMore, loading, error}"
|
||||
@loadMore="loadMore">
|
||||
</uni-load-state>
|
||||
<!-- #ifdef APP-PLUS -->
|
||||
</template>
|
||||
</uni-list-item>
|
||||
<!-- #endif -->
|
||||
</uni-list>
|
||||
</unicloud-db>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
let cdbRef;
|
||||
import statusBar from "@/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-status-bar";
|
||||
|
||||
import Gps from '@/uni_modules/json-gps/js_sdk/gps.js';
|
||||
const gps = new Gps();
|
||||
|
||||
const db = uniCloud.database();
|
||||
const articleDBName = 'opendb-news-articles';
|
||||
const userDBName = 'uni-id-users';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
statusBar,
|
||||
},
|
||||
computed: {
|
||||
// 根据当前语言返回不同的搜索框占位符
|
||||
inputPlaceholder(e) {
|
||||
if (uni.getStorageSync('CURRENT_LANG') == "en") {
|
||||
return 'Please enter the search content'
|
||||
} else {
|
||||
return '请输入搜索内容'
|
||||
}
|
||||
},
|
||||
// 连表查询,返回两个集合的查询结果
|
||||
colList() {
|
||||
return [
|
||||
db.collection(articleDBName).where(this.where).field('thumbnail,title,publish_date,user_id')
|
||||
.getTemp(), // 文章集合
|
||||
db.collection(userDBName).field('_id,nickname').getTemp() // 用户集合
|
||||
]
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
where: '"article_status" == 1',
|
||||
keyword: "",
|
||||
showRefresh: false,
|
||||
listHight: 0
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
keyword(keyword, oldValue) {
|
||||
let where = '"article_status" == 1 '
|
||||
if (keyword) {
|
||||
this.where = where + `&& /${keyword}/.test(title)`;
|
||||
} else {
|
||||
this.where = where;
|
||||
}
|
||||
}
|
||||
},
|
||||
async onReady() {
|
||||
// #ifdef APP-NVUE
|
||||
/* 可用窗口高度 - 搜索框高 - 状态栏高 */
|
||||
this.listHight = uni.getSystemInfoSync().windowHeight - uni.getSystemInfoSync().statusBarHeight - 50 +
|
||||
'px';
|
||||
// #endif
|
||||
// #ifndef APP-NVUE
|
||||
this.listHight = 'auto'
|
||||
// #endif
|
||||
cdbRef = this.$refs.udb
|
||||
},
|
||||
async onShow() {
|
||||
this.keyword = getApp().globalData.searchText
|
||||
getApp().globalData.searchText = ''
|
||||
//这里仅演示如何,在onShow生命周期获取设备位置,并在设备或者应用没有权限时自动引导。设置完毕自动重新获取。
|
||||
//你可以基于他做自己的业务,比如:根据距离由近到远排序列表数据等
|
||||
// uni.showLoading({
|
||||
// title:"获取定位中"
|
||||
// });
|
||||
//默认h5端不获取定位
|
||||
// #ifndef H5
|
||||
let location = await gps.getLocation({
|
||||
geocode: true
|
||||
})
|
||||
// console.log(location);
|
||||
// #endif
|
||||
// if(location){
|
||||
// uni.showToast({
|
||||
// title: JSON.stringify(location),
|
||||
// icon: 'none'
|
||||
// });
|
||||
// }
|
||||
// uni.hideLoading()
|
||||
},
|
||||
methods: {
|
||||
searchClick(e) { //点击搜索框
|
||||
uni.hideKeyboard();
|
||||
uni.navigateTo({
|
||||
url: './search/search',
|
||||
animationType: 'fade-in'
|
||||
});
|
||||
},
|
||||
retry() {
|
||||
this.refresh()
|
||||
},
|
||||
refresh() {
|
||||
cdbRef.loadData({
|
||||
clear: true
|
||||
}, () => {
|
||||
uni.stopPullDownRefresh()
|
||||
// #ifdef APP-NVUE
|
||||
this.showRefresh = false
|
||||
// #endif
|
||||
console.log('end');
|
||||
})
|
||||
console.log('refresh');
|
||||
},
|
||||
loadMore() {
|
||||
cdbRef.loadMore()
|
||||
},
|
||||
onqueryerror(e) {
|
||||
console.error(e);
|
||||
},
|
||||
onpullingdown(e) {
|
||||
console.log(e);
|
||||
this.showRefresh = true
|
||||
if (e.pullingDistance > 100) {
|
||||
this.refresh()
|
||||
}
|
||||
}
|
||||
},
|
||||
// #ifndef APP-NVUE
|
||||
onPullDownRefresh() {
|
||||
this.refresh()
|
||||
},
|
||||
onReachBottom() {
|
||||
this.loadMore()
|
||||
}
|
||||
// #endif
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* #ifndef APP-NVUE */
|
||||
view {
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
.pages {
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
.main {
|
||||
justify-content: space-between;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.info {
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.author,
|
||||
.last_modify_date {
|
||||
font-size: 14px;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.uni-search-box {
|
||||
background-color: #FFFFFF;
|
||||
position: sticky;
|
||||
height: 50px;
|
||||
top: 0;
|
||||
left: 0;
|
||||
/* #ifndef APP-PLUS */
|
||||
z-index: 9;
|
||||
/* #endif */
|
||||
/* #ifdef MP-WEIXIN */
|
||||
width: 580rpx;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.cover-search-bar {
|
||||
height: 50px;
|
||||
position: relative;
|
||||
top: -50px;
|
||||
margin-bottom: -50px;
|
||||
/* #ifndef APP-NVUE */
|
||||
z-index: 999;
|
||||
/* #endif */
|
||||
}
|
||||
</style>
|
@ -1,505 +0,0 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<view class="search-container">
|
||||
<!-- 搜索框 -->
|
||||
<view class="search-container-bar">
|
||||
<!-- #ifdef APP-PLUS -->
|
||||
<uni-icons class="search-icons" :color="iconColor" size="22" type="mic-filled" @click="speech" />
|
||||
<!-- #endif -->
|
||||
<!-- :cancelText="keyBoardPopup ? '取消' : '搜索'" -->
|
||||
<uni-search-bar ref="searchBar" style="flex:1;" radius="100" v-model="searchText" :focus="focus" :placeholder="hotWorld"
|
||||
clearButton="auto" cancelButton="always" @clear="clear" @confirm="confirm" @cancel="cancel" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="search-body">
|
||||
<!-- 搜索历史 -->
|
||||
<view class="word-container" v-if="localSearchList.length">
|
||||
<view class="word-container_header">
|
||||
<text class="word-container_header-text">搜索历史</text>
|
||||
<uni-icons v-if="!localSearchListDel" @click="localSearchListDel = true" class="search-icons" style="padding-right: 0;"
|
||||
:color="iconColor" size="18" type="trash"></uni-icons>
|
||||
<view v-else class="flex-center flex-row" style="font-weight: 500;justify-content: space-between;">
|
||||
<text style="font-size: 22rpx;color: #666;padding-top:4rpx;padding-bottom:4rpx;padding-right:20rpx;" @click="LocalSearchListClear">全部删除</text>
|
||||
<text style="font-size: 22rpx;color: #c0402b;padding-top:4rpx;padding-bottom:4rpx;padding-left:20rpx;" @click="localSearchListDel = false">完成</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="word-container_body">
|
||||
<view class="flex-center flex-row word-container_body-text" v-for="(word,index) in localSearchList" :key="index"
|
||||
@click="LocalSearchlistItemClick(word,index)">
|
||||
<text class="word-display" :key="word">{{word}}</text>
|
||||
<uni-icons v-if="localSearchListDel" size="12" type="closeempty" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 搜索发现 -->
|
||||
<view class="word-container">
|
||||
<view class="word-container_header">
|
||||
<view class="flex-center flex-row">
|
||||
<text class="word-container_header-text">搜索发现</text>
|
||||
<uni-icons v-if="!netHotListIsHide" class="search-icons" :color="iconColor" size="14" type="reload" @click="searchHotRefresh"></uni-icons>
|
||||
</view>
|
||||
<uni-icons class="search-icons" style="padding-right: 0;" :color="iconColor" size="18" :type="netHotListIsHide ? 'eye-slash' : 'eye'"
|
||||
@click="netHotListIsHide = !netHotListIsHide"></uni-icons>
|
||||
</view>
|
||||
|
||||
<unicloud-db ref="udb" #default="{data, loading, error, options}" field="content" collection="opendb-search-hot"
|
||||
orderby="create_date desc,count desc" page-data="replace" :page-size="10">
|
||||
<text v-if="loading && !netHotListIsHide" class="word-container_body-info">正在加载...</text>
|
||||
<view v-else class="word-container_body">
|
||||
<template v-if="!netHotListIsHide">
|
||||
<text v-if="error" class="word-container_body-info">{{error.message}}</text>
|
||||
<template v-else>
|
||||
<text v-for="(word,index) in data" class="word-container_body-text" :key="index" @click="search(word.content)">{{word.content}}</text>
|
||||
</template>
|
||||
</template>
|
||||
<view v-else style="flex:1;">
|
||||
<text class="word-container_body-info">当前搜索发现已隐藏</text>
|
||||
</view>
|
||||
</view>
|
||||
</unicloud-db>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 搜索联想 -->
|
||||
<view class="search-associative" v-if="associativeShow">
|
||||
<uni-list>
|
||||
<uni-list-item v-for="(item,index) in associativeList" :key="item._id" :ellipsis="1" :title="item.name" @click="associativeClick(item)" show-extra-icon
|
||||
clickable :extra-icon="{size:18,color:iconColor,type:'search'}" >
|
||||
</uni-list-item>
|
||||
</uni-list>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* 云端一体搜索模板
|
||||
* @description uniCloud云端一体搜索模板,自带下拉候选、历史搜索、热搜。无需再开发服务器代码
|
||||
*/
|
||||
const searchLogDbName = 'opendb-search-log'; // 搜索记录数据库
|
||||
const mallGoodsDbName = 'opendb-news-articles'; // 文章数据库
|
||||
const associativeSearchField = 'title'; // 联想时,搜索框值检索数据库字段名
|
||||
const associativeField = '_id,title'; // 联想列表每一项携带的字段
|
||||
const localSearchListKey = '__local_search_history'; // 本地历史存储字段名
|
||||
|
||||
// 数组去重
|
||||
const arrUnique = arr => {
|
||||
for (let i = arr.length - 1; i >= 0; i--) {
|
||||
const curIndex = arr.indexOf(arr[i]);
|
||||
const lastIndex = arr.lastIndexOf(arr[i])
|
||||
curIndex != lastIndex && arr.splice(lastIndex, 1)
|
||||
}
|
||||
return arr
|
||||
} // 节流
|
||||
// 防抖
|
||||
function debounce(fn, interval, isFirstAutoRun) {
|
||||
/**
|
||||
*
|
||||
* @param {要执行的函数} fn
|
||||
* @param {在操作多长时间后可再执行,第一次立即执行} interval
|
||||
*/
|
||||
var _self = fn;
|
||||
var timer = null;
|
||||
var first = true;
|
||||
|
||||
if (isFirstAutoRun) {
|
||||
_self();
|
||||
}
|
||||
|
||||
return function() {
|
||||
var args = arguments;
|
||||
var _me = this;
|
||||
if (first) {
|
||||
first = false;
|
||||
_self.apply(_me, args);
|
||||
}
|
||||
|
||||
if (timer) {
|
||||
clearTimeout(timer)
|
||||
// return false;
|
||||
}
|
||||
|
||||
timer = setTimeout(function() {
|
||||
clearTimeout(timer);
|
||||
timer = null;
|
||||
_self.apply(_me, args);
|
||||
}, interval || 200);
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
mallGoodsDbName,
|
||||
searchLogDbName,
|
||||
statusBarHeight:'0px',
|
||||
localSearchList: uni.getStorageSync(localSearchListKey),
|
||||
localSearchListDel: false,
|
||||
netHotListIsHide: false,
|
||||
searchText: '',
|
||||
iconColor: '#999999',
|
||||
associativeList: [],
|
||||
keyBoardPopup: false,
|
||||
hotWorld: 'DCloud', // 搜索热词,如果没有输入即回车,则搜索热词,但是不会加入搜索记录
|
||||
focus: true, // 是否自动聚焦
|
||||
speechEngine: 'iFly' // 语音识别引擎 iFly 讯飞 baidu 百度
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.db = uniCloud.database();
|
||||
this.searchLogDb = this.db.collection(this.searchLogDbName);
|
||||
this.mallGoodsDb = this.db.collection(this.mallGoodsDbName);
|
||||
// #ifndef H5
|
||||
uni.onKeyboardHeightChange((res) => {
|
||||
this.keyBoardPopup = res.height !== 0;
|
||||
})
|
||||
// #endif
|
||||
|
||||
this.searchText = getApp().globalData.searchText;
|
||||
},
|
||||
computed: {
|
||||
associativeShow() {
|
||||
return this.searchText && this.associativeList.length;
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
//#ifdef APP-PLUS
|
||||
this.statusBarHeight = `${uni.getSystemInfoSync().statusBarHeight}px`;
|
||||
//#endif
|
||||
},
|
||||
methods: {
|
||||
clear(res) {
|
||||
console.log("res: ", res);
|
||||
},
|
||||
confirm(res) {
|
||||
// 键盘确认
|
||||
this.search(res.value);
|
||||
},
|
||||
cancel(res) {
|
||||
uni.hideKeyboard();
|
||||
this.searchText = '';
|
||||
this.loadList();
|
||||
},
|
||||
search(value) {
|
||||
if (!value && !this.hotWorld) {
|
||||
return;
|
||||
}
|
||||
if (value) {
|
||||
if (this.searchText !== value) {
|
||||
this.searchText = value
|
||||
}
|
||||
|
||||
this.localSearchListManage(value);
|
||||
|
||||
this.searchLogDbAdd(value)
|
||||
} else if (this.hotWorld) {
|
||||
this.searchText = this.hotWorld
|
||||
}
|
||||
|
||||
uni.hideKeyboard();
|
||||
this.loadList(this.searchText);
|
||||
},
|
||||
localSearchListManage(word) {
|
||||
let list = uni.getStorageSync(localSearchListKey);
|
||||
if (list.length) {
|
||||
this.localSearchList.unshift(word);
|
||||
arrUnique(this.localSearchList);
|
||||
if (this.localSearchList.length > 10) {
|
||||
this.localSearchList.pop();
|
||||
}
|
||||
} else {
|
||||
this.localSearchList = [word];
|
||||
}
|
||||
uni.setStorageSync(localSearchListKey, this.localSearchList);
|
||||
},
|
||||
LocalSearchListClear() {
|
||||
uni.showModal({
|
||||
content: "确认清空搜索历史吗",
|
||||
confirmText: "删除",
|
||||
confirmColor: 'red',
|
||||
cancelColor: '#808080',
|
||||
success: res => {
|
||||
if (res.confirm) {
|
||||
this.localSearchListDel = false;
|
||||
this.localSearchList = [];
|
||||
uni.removeStorageSync(localSearchListKey)
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
LocalSearchlistItemClick(word, index) {
|
||||
if (this.localSearchListDel) {
|
||||
this.localSearchList.splice(index, 1);
|
||||
uni.setStorageSync(localSearchListKey, this.localSearchList);
|
||||
if (!this.localSearchList.length) {
|
||||
this.localSearchListDel = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.search(word);
|
||||
},
|
||||
searchHotRefresh() {
|
||||
this.$refs.udb.refresh();
|
||||
},
|
||||
speech() {
|
||||
// #ifdef APP-PLUS
|
||||
plus.speech.startRecognize({
|
||||
engine: this.speechEngine,
|
||||
punctuation: false, // 标点符号
|
||||
timeout: 10000
|
||||
}, word => {
|
||||
word = word instanceof Array ? word[0] : word;
|
||||
this.search(word)
|
||||
}, err => {
|
||||
console.error("语音识别错误: ", err);
|
||||
});
|
||||
// #endif
|
||||
},
|
||||
searchLogDbAdd(value) {
|
||||
/*
|
||||
在此处存搜索记录,如果登录则需要存 user_id,若未登录则存device_id
|
||||
*/
|
||||
this.getDeviceId().then(device_id => {
|
||||
this.searchLogDb.add({
|
||||
// user_id: device_id,
|
||||
device_id,
|
||||
content: value,
|
||||
create_date: Date.now()
|
||||
})
|
||||
})
|
||||
},
|
||||
getDeviceId() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const uniId = uni.getStorageSync('uni_id');
|
||||
if (!uniId) {
|
||||
// #ifdef APP-PLUS
|
||||
plus.device.getInfo({
|
||||
success: (deviceInfo) => {
|
||||
resolve(deviceInfo.uuid)
|
||||
},
|
||||
fail: () => {
|
||||
resolve(uni.getSystemInfoSync().system + '_' + Math.random().toString(36).substr(2))
|
||||
}
|
||||
});
|
||||
// #endif
|
||||
// #ifndef APP-PLUS
|
||||
resolve(uni.getSystemInfoSync().system + '_' + Math.random().toString(36).substr(2))
|
||||
// #endif
|
||||
} else {
|
||||
resolve(uniId)
|
||||
}
|
||||
})
|
||||
},
|
||||
associativeClick(item) {
|
||||
/**
|
||||
* 注意:这里用户根据自己的业务需要,选择跳转的页面即可
|
||||
*/
|
||||
console.log("associativeClick: ", item);
|
||||
this.loadList(item.title);
|
||||
},
|
||||
loadList(text = '') {
|
||||
getApp().globalData.searchText = text;
|
||||
uni.switchTab({
|
||||
url:'/pages/list/list'
|
||||
})
|
||||
},
|
||||
backPage(){
|
||||
uni.navigateBack();
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
searchText: debounce(function(value) {
|
||||
if (value) {
|
||||
this.mallGoodsDb.where({
|
||||
[associativeSearchField]: new RegExp(value, 'gi'),
|
||||
}).field(associativeField).get().then(res => {
|
||||
this.associativeList = res.result.data;
|
||||
})
|
||||
} else {
|
||||
this.associativeList.length = 0;
|
||||
getApp().globalData.searchText = '';
|
||||
}
|
||||
}, 100)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/* #ifndef APP-NVUE */
|
||||
page {
|
||||
height: 100%;
|
||||
flex: 1;
|
||||
}
|
||||
/* #endif */
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$search-bar-height:52px;
|
||||
$word-container_header-height:72rpx;
|
||||
.status-bar{
|
||||
background-color: #fff;
|
||||
}
|
||||
.container {
|
||||
/* #ifndef APP-NVUE */
|
||||
height: 100%;
|
||||
/* #endif */
|
||||
flex: 1;
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
|
||||
.search-body {
|
||||
background-color: #fff;
|
||||
border-bottom-right-radius: 10px;
|
||||
border-bottom-left-radius: 10px;
|
||||
}
|
||||
|
||||
@mixin uni-flex {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
@mixin words-display {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.flex-center {
|
||||
@include uni-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.flex-row {
|
||||
@include uni-flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
/* #ifdef APP-PLUS */
|
||||
/* #ifndef APP-NVUE || VUE3*/
|
||||
::v-deep
|
||||
/* #endif */
|
||||
.uni-searchbar {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
|
||||
/* #ifndef APP-NVUE || VUE3*/
|
||||
::v-deep
|
||||
/* #endif */
|
||||
.uni-searchbar__box {
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
/* #ifndef APP-NVUE || VUE3 */
|
||||
::v-deep
|
||||
/* #endif */
|
||||
.uni-input-placeholder {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.search-container {
|
||||
height: $search-bar-height;
|
||||
@include uni-flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
background-color: #fff;
|
||||
|
||||
@at-root {
|
||||
#{&}-bar {
|
||||
@include uni-flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.search-associative {
|
||||
/* #ifndef APP-NVUE */
|
||||
overflow-y: auto;
|
||||
/* #endif */
|
||||
position: absolute;
|
||||
top: $search-bar-height;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: #fff;
|
||||
margin-top: 10rpx;
|
||||
padding-left: 10rpx;
|
||||
padding-right: 10rpx;
|
||||
}
|
||||
|
||||
.search-icons {
|
||||
padding: 16rpx;
|
||||
}
|
||||
|
||||
.word-display {
|
||||
@include words-display;
|
||||
}
|
||||
|
||||
.word-container {
|
||||
padding: 20rpx;
|
||||
|
||||
@at-root {
|
||||
#{&}_header {
|
||||
@include uni-flex;
|
||||
height: $word-container_header-height;
|
||||
line-height: $word-container_header-height;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
@at-root {
|
||||
#{&}-text {
|
||||
color: #3e3e3e;
|
||||
font-size: 30rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#{&}_body {
|
||||
@include uni-flex;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: row;
|
||||
|
||||
@at-root {
|
||||
#{&}-text {
|
||||
@include uni-flex;
|
||||
@include words-display;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: #f6f6f6;
|
||||
padding: 10rpx 20rpx;
|
||||
margin: 20rpx 30rpx 0 0;
|
||||
border-radius: 30rpx;
|
||||
/* #ifndef APP-NVUE */
|
||||
box-sizing: border-box;
|
||||
/* #endif */
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#{&}-info {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: block;
|
||||
/* #endif */
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
font-size: 26rpx;
|
||||
color: #808080;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,223 +0,0 @@
|
||||
<template>
|
||||
<scroll-view :scroll-y="true" v-if="!loading">
|
||||
<view class="meta">
|
||||
<view class="title">
|
||||
<text class="text">{{ articleDetail.title }}</text>
|
||||
</view>
|
||||
<view class="excerpt">
|
||||
<text class="text">{{ articleDetail.excerpt }}</text>
|
||||
</view>
|
||||
<view class="author">
|
||||
<template v-if="articleDetail.user_id != null">
|
||||
<text class="at">{{ articleDetail.user_id?.nickname ?? '' }}</text>
|
||||
<text class="split">·</text>
|
||||
</template>
|
||||
<text class="date">{{ publishTime(articleDetail.publish_date as number) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="content" v-if="articleDetail.content != null">
|
||||
<template v-for="(block, index) in articleDetail.content" :key="index">
|
||||
<view v-if="block.type == 'mediaVideo'">
|
||||
<video
|
||||
style="width: 300px; height: 200px; margin: 0 auto 20px;"
|
||||
:src="(block.data as UTSJSONObject).getJSON('attributes')!.getString('src')!"
|
||||
:poster="(block.data as UTSJSONObject).getJSON('attributes')!.getString('poster')!"
|
||||
></video>
|
||||
</view>
|
||||
<view v-if="block.type == 'divider'" class="divider"></view>
|
||||
<view v-if="block.type == 'unlockContent'" class="unlock-content">
|
||||
<button @click="unlockContent">请观看广告后解锁全文</button>
|
||||
</view>
|
||||
<rich-text v-if="block.type == 'rich-text'" :selectable="false" :nodes="block.data" @itemclick="richTextItemClick"></rich-text>
|
||||
<render-image-component v-if="block.type == 'image'" :deltaOp="block.data" @image-preview="onImagePreview"></render-image-component>
|
||||
</template>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</template>
|
||||
|
||||
<script lang="uts">
|
||||
import translatePublishTime from "@/uni_modules/uni-cms-article/common/publish-time";
|
||||
import RenderImageComponent from '@/uni_modules/uni-cms-article/components/render-article-detail/image.uvue'
|
||||
|
||||
type Author = {
|
||||
_id: string
|
||||
nickname: string
|
||||
}
|
||||
type Content = {
|
||||
type: string
|
||||
data: any
|
||||
}
|
||||
type Article = {
|
||||
_id: string | null
|
||||
title: string | null
|
||||
content: Content[] | null
|
||||
excerpt: string | null
|
||||
publish_date: number | null
|
||||
user_id: Author | null
|
||||
thumbnail: string[] | null
|
||||
content_images: string[] | null
|
||||
}
|
||||
|
||||
const db = uniCloud.databaseForJQL()
|
||||
const articleDBName = 'uni-cms-articles'
|
||||
const userDBName = 'uni-id-users'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
RenderImageComponent
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: true,
|
||||
id: "", // 文章ID
|
||||
title: "", // 文章标题
|
||||
articleDetail: {} as Article, // 文章详情
|
||||
// 广告相关配置
|
||||
adpId: "", // TODO: 请填写广告位ID
|
||||
watchAdUniqueType: "device" // TODO: 观看广告的唯一标识类型,可选值为 user 或者 device,user 表示用户唯一,device 表示设备唯一
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
where(): string {
|
||||
//拼接where条件 查询条件 ,更多详见 :https://uniapp.dcloud.net.cn/uniCloud/unicloud-db?id=jsquery
|
||||
return `_id =="${this.id}"`
|
||||
},
|
||||
collection(): any[] {
|
||||
return [
|
||||
db.collection(articleDBName).where(this.where).field('user_id,thumbnail,excerpt,publish_date,title,content').getTemp(),
|
||||
db.collection(userDBName).field('_id, nickname').getTemp()
|
||||
]
|
||||
}
|
||||
},
|
||||
onLoad(event: OnLoadOptions) {
|
||||
if (event.has('id')) {
|
||||
this.id = event.get('id') as string
|
||||
this.load()
|
||||
}
|
||||
|
||||
if (event.has('title')) {
|
||||
uni.setNavigationBarTitle({
|
||||
title: event.get('title') as string
|
||||
})
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async load (): Promise<void> {
|
||||
uni.showLoading({
|
||||
title: "加载中..."
|
||||
})
|
||||
const articledb = db.collection(articleDBName).where(this.where).field('user_id,thumbnail,excerpt,publish_date,title,content').getTemp()
|
||||
const userdb = db.collection(userDBName).field('_id, nickname').getTemp()
|
||||
const res = await db.collection(articledb, userdb).get()
|
||||
|
||||
this.loadData(res.data)
|
||||
this.loading = false
|
||||
uni.hideLoading()
|
||||
},
|
||||
// 格式化发布时间
|
||||
publishTime(timestamp: number): string {
|
||||
return translatePublishTime(timestamp)
|
||||
},
|
||||
loadData(data: UTSJSONObject[]) {
|
||||
if (data.length <= 0) return
|
||||
const detail = data[0]
|
||||
|
||||
const user_id = detail.getArray<Author>('user_id')!;
|
||||
|
||||
this.articleDetail = {
|
||||
title: detail.getString('title'),
|
||||
content: detail.getArray<Content>('content'),
|
||||
excerpt: detail.getString('excerpt'),
|
||||
publish_date: detail.getNumber('publish_date'),
|
||||
thumbnail: detail.getArray<string>('thumbnail'),
|
||||
user_id: user_id.length > 0 ? user_id[0]: null,
|
||||
content_images: detail.getArray<string>('content_images')
|
||||
} as Article
|
||||
|
||||
this.title = detail.getString('title')!
|
||||
|
||||
uni.setNavigationBarTitle({
|
||||
title: this.title
|
||||
})
|
||||
},
|
||||
unlockContent () {
|
||||
uni.showModal({
|
||||
content: 'uni-app-x 暂不支持观看广告解锁全文',
|
||||
showCancel: false
|
||||
})
|
||||
},
|
||||
richTextItemClick (e: RichTextItemClickEvent) {
|
||||
if (e.detail.href != null) {
|
||||
uni.navigateTo({
|
||||
url: `/uni_modules/uni-cms-article/pages/webview/webview?url=${encodeURIComponent(e.detail.href as string)}`
|
||||
})
|
||||
}
|
||||
},
|
||||
onImagePreview (url: string) {
|
||||
const contentImages = this.articleDetail.content_images != null ? this.articleDetail.content_images: [] as string[]
|
||||
|
||||
uni.previewImage({
|
||||
current: url, // 当前显示图片的http链接
|
||||
urls: contentImages as string[] // 需要预览的图片http链接列表
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.meta {
|
||||
padding: 20rpx 30rpx 0;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
|
||||
.title {
|
||||
.text {
|
||||
font-size: 40rpx;
|
||||
line-height: 66rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.excerpt {
|
||||
margin-top: 10rpx;
|
||||
|
||||
.text {
|
||||
font-size: 26rpx;
|
||||
line-height: 40rpx;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.author {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
flex-direction: row;
|
||||
margin-top: 20rpx;
|
||||
|
||||
.at,
|
||||
.split,
|
||||
.date {
|
||||
font-size: 26rpx;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.split {
|
||||
margin: 0 10rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
.content {
|
||||
margin-top: 40rpx;
|
||||
padding: 0 30rpx 80rpx;
|
||||
}
|
||||
.divider {
|
||||
height: 1px;
|
||||
width: 100%;
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
</style>
|
||||
|
@ -1,217 +0,0 @@
|
||||
<template>
|
||||
<unicloud-db v-slot:default="{data, loading, error, options}" :collection="collection" :options="formData"
|
||||
:getone="true" :where="where" :manual="true" ref="detail" foreignKey="uni-cms-articles.user_id"
|
||||
@load="loadData"
|
||||
class="article">
|
||||
<template v-if="!loading && data">
|
||||
<view class="meta">
|
||||
<view class="title">
|
||||
<text class="text">{{ data.title }}</text>
|
||||
</view>
|
||||
<view class="excerpt">
|
||||
<text class="text">{{ data.excerpt }}</text>
|
||||
</view>
|
||||
<view class="author">
|
||||
<template v-if="data.user_id[0]">
|
||||
<text class="at">{{ data.user_id[0].nickname || '' }}</text>
|
||||
<text class="split">·</text>
|
||||
</template>
|
||||
<text class="date">{{ publishTime(data.publish_date) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<render-article-detail
|
||||
:content="data.content"
|
||||
:content-images="data.content_images"
|
||||
:ad-config="{ adpId, watchAdUniqueType }"
|
||||
></render-article-detail>
|
||||
</template>
|
||||
<view class="detail-loading" v-else>
|
||||
<uni-icons type="spinner-cycle" size="35px"/>
|
||||
</view>
|
||||
</unicloud-db>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import uniNavBar from '@/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-nav-bar.vue';
|
||||
import renderArticleDetail from "@/uni_modules/uni-cms-article/components/render-article-detail/index.vue";
|
||||
import translatePublishTime from "@/uni_modules/uni-cms-article/common/publish-time";
|
||||
|
||||
const db = uniCloud.database()
|
||||
const articleDBName = 'uni-cms-articles'
|
||||
const userDBName = 'uni-id-users'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
uniNavBar,
|
||||
renderArticleDetail
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
id: "", // 文章ID
|
||||
title: "", // 文章标题
|
||||
formData: {}, // 表单数据
|
||||
|
||||
// 广告相关配置
|
||||
adpId: "", // TODO: 请填写广告位ID
|
||||
watchAdUniqueType: "device" // TODO: 观看广告的唯一标识类型,可选值为 user 或者 device,user 表示用户唯一,device 表示设备唯一
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
where() {
|
||||
//拼接where条件 查询条件 ,更多详见 :https://uniapp.dcloud.net.cn/uniCloud/unicloud-db?id=jsquery
|
||||
return `_id =="${this.id}"`
|
||||
},
|
||||
collection() {
|
||||
return [
|
||||
db.collection(articleDBName).where(this.where).field('user_id,thumbnail,excerpt,publish_date,title,content').getTemp(),
|
||||
db.collection(userDBName).field('_id, nickname').getTemp()
|
||||
]
|
||||
}
|
||||
},
|
||||
onReady() {
|
||||
// 开始加载数据,修改 where 条件后才开始去加载 clinetDB 的数据 ,需要等组件渲染完毕后才开始执行 loadData,所以不能再 onLoad 中执行
|
||||
if (this.id) { // ID 不为空,则发起查询
|
||||
this.$refs.detail.loadData()
|
||||
} else {
|
||||
uni.showToast({
|
||||
icon: 'none',
|
||||
title: 'id 不能为空'
|
||||
})
|
||||
}
|
||||
},
|
||||
onLoad(event) {
|
||||
//获取文章id,通常 id 来自上一个页面
|
||||
if (event.id) {
|
||||
this.id = event.id
|
||||
}
|
||||
|
||||
// 监听解锁内容事件
|
||||
uni.$on('onUnlockContent', this.onUnlockContent)
|
||||
},
|
||||
onUnload() {
|
||||
// 页面卸载时,移除监听事件
|
||||
uni.$off('onUnlockContent', this.onUnlockContent)
|
||||
},
|
||||
onPageScroll(e) {
|
||||
// 根据滚动位置判断是否显示导航栏
|
||||
if (e.scrollTop > 100) {
|
||||
uni.setNavigationBarTitle({
|
||||
title: this.title
|
||||
})
|
||||
} else {
|
||||
uni.setNavigationBarTitle({
|
||||
title: ''
|
||||
})
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 将时间戳转换为可读的时间格式
|
||||
publishTime(timestamp) {
|
||||
return translatePublishTime(timestamp)
|
||||
},
|
||||
// 将文章加入阅读历史
|
||||
setReadHistory() {
|
||||
// 获取阅读历史缓存,如果不存在则为空数组
|
||||
const historyCache = uni.getStorageSync('readHistory') || []
|
||||
// 过滤掉当前文章的阅读历史
|
||||
const readHistory = historyCache.filter(item => item.article_id !== this.id)
|
||||
// 将当前文章的阅读历史添加到数组最前面
|
||||
readHistory.unshift({
|
||||
article_id: this.id,
|
||||
last_time: Date.now()
|
||||
})
|
||||
// 将更新后的阅读历史缓存到本地
|
||||
uni.setStorageSync('readHistory', readHistory)
|
||||
|
||||
},
|
||||
// 加载数据
|
||||
loadData(data) {
|
||||
// 设置文章标题
|
||||
this.title = data.title
|
||||
|
||||
// 将文章添加进阅读历史
|
||||
this.setReadHistory()
|
||||
},
|
||||
// 监听解锁内容事件,解锁内容后重新加载数据
|
||||
async onUnlockContent() {
|
||||
this.$refs.detail.loadData()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
/* #ifdef APP-NVUE */
|
||||
.article {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
|
||||
@mixin cp {
|
||||
padding: 0 30rpx;
|
||||
}
|
||||
|
||||
.detail-loading {
|
||||
margin: 100rpx auto 0;
|
||||
width: 35px;
|
||||
height: 35px;
|
||||
animation: rotate360 2s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes rotate360 {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
transform-origin: center center;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
transform-origin: center center;
|
||||
}
|
||||
}
|
||||
|
||||
.meta {
|
||||
@include cp;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
padding-top: 20rpx;
|
||||
.title {
|
||||
.text {
|
||||
font-size: 40rpx;
|
||||
line-height: 66rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.excerpt {
|
||||
margin-top: 10rpx;
|
||||
.text {
|
||||
font-size: 26rpx;
|
||||
line-height: 40rpx;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.author {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
flex-direction: row;
|
||||
margin-top: 20rpx;
|
||||
|
||||
.at,
|
||||
.split,
|
||||
.date {
|
||||
font-size: 26rpx;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.split {
|
||||
margin: 0 10rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,255 +0,0 @@
|
||||
<template>
|
||||
<unicloud-db v-slot:default="{loading, error, options}" :collection="collection" :options="formData"
|
||||
:getone="true" :where="where" :manual="true" ref="detail" foreignKey="uni-cms-articles.user_id"
|
||||
@load="loadData"
|
||||
class="article">
|
||||
<template v-if="!loading && articleData">
|
||||
<view class="preview-tip">此页面仅用于临时预览文章,链接将会在短期内失效。</view>
|
||||
<view class="meta">
|
||||
<view class="title">
|
||||
<text class="text">{{ articleData.title }}</text>
|
||||
</view>
|
||||
<view class="excerpt">
|
||||
<text class="text">{{ articleData.excerpt }}</text>
|
||||
</view>
|
||||
<view class="author">
|
||||
<template v-if="articleData.user_id && articleData.user_id[0]">
|
||||
<text class="at">{{ articleData.user_id[0].nickname || '' }}</text>
|
||||
<text class="split">·</text>
|
||||
</template>
|
||||
<text class="date">{{ publishTime(articleData.publish_date) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<render-article-detail
|
||||
:content="articleData.content"
|
||||
:content-images="articleData.content_images"
|
||||
:ad-config="{ adpId, watchAdUniqueType }"
|
||||
></render-article-detail>
|
||||
</template>
|
||||
<view class="detail-loading" v-else>
|
||||
<uni-icons type="spinner-cycle" size="35px"/>
|
||||
</view>
|
||||
</unicloud-db>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import uniNavBar from '@/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-nav-bar.vue';
|
||||
import renderArticleDetail from "@/uni_modules/uni-cms-article/components/render-article-detail/index.vue";
|
||||
import translatePublishTime from "@/uni_modules/uni-cms-article/common/publish-time";
|
||||
|
||||
const db = uniCloud.database()
|
||||
const articleDBName = 'uni-cms-articles'
|
||||
const userDBName = 'uni-id-users'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
uniNavBar,
|
||||
renderArticleDetail
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
id: "", // 文章ID
|
||||
title: "", // 文章标题
|
||||
secret: "", // 文章预览密钥
|
||||
formData: {}, // 表单数据
|
||||
articleData: null, // 文章数据
|
||||
|
||||
// 广告相关配置
|
||||
adpId: "", // TODO: 请填写广告位ID
|
||||
watchAdUniqueType: "device" // TODO: 观看广告的唯一标识类型,可选值为 user 或者 device,user 表示用户唯一,device 表示设备唯一
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
where() {
|
||||
//拼接where条件 查询条件 ,更多详见 :https://uniapp.dcloud.net.cn/uniCloud/unicloud-db?id=jsquery
|
||||
return `_id =="${this.id}" && preview_secret =="${this.secret}"`
|
||||
},
|
||||
collection() {
|
||||
return [
|
||||
db.collection(articleDBName).where(this.where).field('user_id,thumbnail,excerpt,publish_date,title,content,preview_secret,preview_expired,article_status').getTemp(),
|
||||
db.collection(userDBName).field('_id, nickname').getTemp()
|
||||
]
|
||||
}
|
||||
},
|
||||
onReady() {
|
||||
// 开始加载数据,修改 where 条件后才开始去加载 clinetDB 的数据 ,需要等组件渲染完毕后才开始执行 loadData,所以不能再 onLoad 中执行
|
||||
if (this.id) { // ID 不为空,则发起查询
|
||||
this.$refs.detail.loadData()
|
||||
} else {
|
||||
uni.showToast({
|
||||
icon: 'none',
|
||||
title: 'id 不能为空'
|
||||
})
|
||||
}
|
||||
},
|
||||
onLoad(event) {
|
||||
//获取文章id,通常 id 来自上一个页面
|
||||
if (event.id) {
|
||||
this.id = event.id
|
||||
this.secret = event.secret
|
||||
}
|
||||
|
||||
// 监听解锁内容事件
|
||||
uni.$on('onUnlockContent', this.onUnlockContent)
|
||||
},
|
||||
onUnload() {
|
||||
// 页面卸载时,移除监听事件
|
||||
uni.$off('onUnlockContent', this.onUnlockContent)
|
||||
},
|
||||
onPageScroll(e) {
|
||||
// 根据滚动位置判断是否显示导航栏
|
||||
if (e.scrollTop > 100) {
|
||||
uni.setNavigationBarTitle({
|
||||
title: this.title
|
||||
})
|
||||
} else {
|
||||
uni.setNavigationBarTitle({
|
||||
title: ''
|
||||
})
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 将时间戳转换为可读的时间格式
|
||||
publishTime(timestamp) {
|
||||
return translatePublishTime(timestamp)
|
||||
},
|
||||
// 加载数据
|
||||
loadData(data) {
|
||||
if (!data) {
|
||||
return uni.showModal({
|
||||
content: "文章不存在/预览密钥不存在",
|
||||
showCancel: false,
|
||||
success: () => {
|
||||
// #ifdef H5
|
||||
window.close()
|
||||
// #endif
|
||||
|
||||
// #ifndef H5
|
||||
uni.navigateBack()
|
||||
// #endif
|
||||
}
|
||||
})
|
||||
}
|
||||
// 文章已发布,跳转到文章详情页
|
||||
if (data.article_status === 1) {
|
||||
uni.showToast({
|
||||
icon: 'none',
|
||||
title: '文章已发布'
|
||||
})
|
||||
uni.redirectTo({
|
||||
url: `/uni_modules/uni-cms-article/pages/detail/detail?id=${this.id}`
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 预览已过期,提示用户
|
||||
if (data.preview_expired < Date.now()) {
|
||||
return uni.showModal({
|
||||
content: "预览已失效",
|
||||
showCancel: false,
|
||||
success: () => {
|
||||
// #ifdef H5
|
||||
window.close()
|
||||
// #endif
|
||||
|
||||
// #ifndef H5
|
||||
uni.navigateBack()
|
||||
// #endif
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 设置文章标题
|
||||
this.title = data.title
|
||||
this.articleData = data
|
||||
},
|
||||
// 监听解锁内容事件,解锁内容后重新加载数据
|
||||
async onUnlockContent() {
|
||||
this.$refs.detail.loadData()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
/* #ifdef APP-NVUE */
|
||||
.article {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
|
||||
@mixin cp {
|
||||
padding: 0 30rpx;
|
||||
}
|
||||
|
||||
.detail-loading {
|
||||
margin: 100rpx auto 0;
|
||||
width: 35px;
|
||||
height: 35px;
|
||||
animation: rotate360 2s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes rotate360 {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
transform-origin: center center;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
transform-origin: center center;
|
||||
}
|
||||
}
|
||||
|
||||
.meta {
|
||||
@include cp;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
padding-top: 20rpx;
|
||||
.title {
|
||||
.text {
|
||||
font-size: 40rpx;
|
||||
line-height: 66rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.excerpt {
|
||||
margin-top: 10rpx;
|
||||
.text {
|
||||
font-size: 26rpx;
|
||||
line-height: 40rpx;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.author {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
flex-direction: row;
|
||||
margin-top: 20rpx;
|
||||
|
||||
.at,
|
||||
.split,
|
||||
.date {
|
||||
font-size: 26rpx;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.split {
|
||||
margin: 0 10rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.preview-tip {
|
||||
font-size: 13px;
|
||||
color: #333;
|
||||
background: #fcd791;
|
||||
padding: 10px;
|
||||
}
|
||||
</style>
|
@ -1,295 +0,0 @@
|
||||
<template>
|
||||
<view class="pages">
|
||||
<view class="placeholder-bar">
|
||||
<statusBar></statusBar>
|
||||
<view :style="{ height: `${navBarHeight}px` }"></view>
|
||||
</view>
|
||||
|
||||
<view class="nav-box">
|
||||
<!-- #ifndef H5 -->
|
||||
<statusBar></statusBar>
|
||||
<!-- #endif -->
|
||||
<view class="nav" :style="{ height: `${navBarHeight}px` }">
|
||||
<!-- #ifdef MP -->
|
||||
<view class="mp-button-left-placeholder" :style="{ width: `${mpButtonLeftPlaceholderSize}px` }"></view>
|
||||
<!-- #endif -->
|
||||
<!-- 搜索功能 -->
|
||||
<view class="uni-search-box">
|
||||
<uni-search-bar ref="searchBar" radius="100" cancelButton="none" disabled
|
||||
:placeholder="inputPlaceholder" />
|
||||
<view class="cover-search-bar" @click="searchClick"></view>
|
||||
</view>
|
||||
<!-- #ifdef MP -->
|
||||
<view class="mp-button-placeholder" :style="{ width: `${mpButtonPlaceholderSize}px` }"></view>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<unicloud-db ref='udb' v-slot:default="{ pagination, hasMore, loading, error, options }" @error="onqueryerror"
|
||||
:collection="colList" :page-size="10" orderby="publish_date desc" @load="listLoad">
|
||||
<!-- 基于 uni-list 的页面布局 field="user_id.nickname"-->
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
<list class="uni-list" :border="false" :style="{ height: listHeight }">
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef APP-NVUE -->
|
||||
<scroll-view scroll-y class="uni-list" refresher-enabled :refresher-triggered="loadType=== 'refresh'"
|
||||
:style="{ height: listHeight }" @refresherrefresh="refresh" @scrolltolower="loadMore">
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
<refresh-box :loading="loading" @refresh="refresh"></refresh-box>
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- 列表渲染 -->
|
||||
<template v-for="item in listData">
|
||||
<not-cover v-if="item.thumbnail && item.thumbnail.length === 0" :data="item"></not-cover>
|
||||
<right-small-cover v-else-if="item.thumbnail && item.thumbnail.length === 1"
|
||||
:data="item"></right-small-cover>
|
||||
<three-cover v-else-if="item.thumbnail && item.thumbnail.length === 3"
|
||||
:data="item"></three-cover>
|
||||
</template>
|
||||
|
||||
<!-- 加载状态:上拉加载更多,加载中,没有更多数据了,加载错误 -->
|
||||
<!-- #ifdef APP-PLUS -->
|
||||
<uni-list-item>
|
||||
<template v-slot:body>
|
||||
<!-- #endif -->
|
||||
<uni-load-state @networkResume="refresh"
|
||||
:state="{ data: listData, pagination, hasMore, loading, error }" @loadMore="loadMore">
|
||||
</uni-load-state>
|
||||
<!-- #ifdef APP-PLUS -->
|
||||
</template>
|
||||
</uni-list-item>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef APP-NVUE -->
|
||||
</scroll-view>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
</list>
|
||||
<!-- #endif -->
|
||||
</unicloud-db>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import statusBar from "@/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-status-bar";
|
||||
import translatePublishTime from "@/uni_modules/uni-cms-article/common/publish-time";
|
||||
import refreshBox from "@/uni_modules/uni-cms-article/components/refresh-box/refreshBox.nvue";
|
||||
|
||||
import notCover from "@/uni_modules/uni-cms-article/components/list-template/not-cover.vue";
|
||||
import rightSmallCover from "@/uni_modules/uni-cms-article/components/list-template/right-small-cover.vue";
|
||||
import threeCover from "@/uni_modules/uni-cms-article/components/list-template/three-cover.vue";
|
||||
import {
|
||||
parseImageUrl
|
||||
} from "@/uni_modules/uni-cms-article/common/parse-image-url";
|
||||
|
||||
const db = uniCloud.database();
|
||||
const articleDBName = 'uni-cms-articles'
|
||||
const userDBName = 'uni-id-users'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
statusBar,
|
||||
refreshBox,
|
||||
notCover,
|
||||
rightSmallCover,
|
||||
threeCover
|
||||
},
|
||||
computed: {
|
||||
// 根据当前语言返回不同的搜索框占位符
|
||||
inputPlaceholder(e) {
|
||||
if (uni.getStorageSync('CURRENT_LANG') == "en") {
|
||||
return 'Please enter the search content' // 英文
|
||||
} else {
|
||||
return '请输入搜索内容' // 中文
|
||||
}
|
||||
},
|
||||
// 连表查询,返回两个集合的查询结果
|
||||
colList() {
|
||||
return [
|
||||
db.collection(articleDBName).where(this.where).field('thumbnail,title,publish_date,user_id')
|
||||
.getTemp(), // 文章集合
|
||||
db.collection(userDBName).field('_id,nickname').getTemp() // 用户集合
|
||||
]
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
where: '"article_status" == 1', // 查询条件
|
||||
showRefresh: false, // 是否显示刷新按钮
|
||||
listHeight: 0, // 列表高度
|
||||
mpButtonLeftPlaceholderSize: 0, // 小程序左侧icon占位大小
|
||||
mpButtonPlaceholderSize: 87, // 小程序导航栏按钮占位大小
|
||||
navBarHeight: 44, // 导航栏高度
|
||||
refreshStatus: 0, // 刷新状态 0: 未刷新 1: 刷新中 2: 刷新完成
|
||||
listData: [], // 列表数据
|
||||
loadType: null
|
||||
}
|
||||
},
|
||||
async onReady() {
|
||||
// #ifdef MP
|
||||
this.initNavBarSize() // 初始化导航栏大小
|
||||
// #endif
|
||||
/* 可用窗口高度 - 搜索框高 - 状态栏高 */
|
||||
this.listHeight = uni.getSystemInfoSync().windowHeight - uni.getSystemInfoSync().statusBarHeight - this
|
||||
.navBarHeight + 'px'; // 计算列表高度
|
||||
},
|
||||
methods: {
|
||||
async listLoad(data) {
|
||||
const listData = data.map(item => {
|
||||
if (typeof item.thumbnail === 'string') {
|
||||
item.thumbnail = [item.thumbnail]
|
||||
}
|
||||
|
||||
return item
|
||||
})
|
||||
|
||||
// 处理腾讯云文件链接
|
||||
for (const article of listData) {
|
||||
const parseImages = await parseImageUrl(article.thumbnail)
|
||||
|
||||
article.thumbnail = parseImages ? parseImages.map(image => image.src) : []
|
||||
}
|
||||
|
||||
this.listData = this.loadType === 'loadMore' ? this.listData.concat(listData) : listData
|
||||
this.loadType = null
|
||||
},
|
||||
// 初始化导航栏大小
|
||||
initNavBarSize() {
|
||||
// 获取小程序导航栏按钮信息
|
||||
// #ifdef MP-TOUTIAO
|
||||
let menuButtonInfo = tt.getCustomButtonBoundingClientRect()
|
||||
menuButtonInfo.width = menuButtonInfo.capsule.width // 小程序按钮区域中使用的按钮宽度
|
||||
this.mpButtonLeftPlaceholderSize = menuButtonInfo.leftIcon.width + 10
|
||||
// #endif
|
||||
// #ifndef MP-TOUTIAO
|
||||
let menuButtonInfo = uni.getMenuButtonBoundingClientRect()
|
||||
// #endif
|
||||
// 计算小程序导航栏按钮占位大小
|
||||
this.mpButtonPlaceholderSize = menuButtonInfo.width + 10
|
||||
// 获取系统信息,判断是否为 iOS 系统,设置导航栏高度
|
||||
this.navBarHeight = uni.getSystemInfoSync().system.toLowerCase().includes('ios') ? 44 : 48
|
||||
},
|
||||
// 格式化时间戳
|
||||
publishTime(timestamp) {
|
||||
return translatePublishTime(timestamp)
|
||||
},
|
||||
// 点击搜索框
|
||||
searchClick(e) {
|
||||
uni.hideKeyboard();
|
||||
uni.navigateTo({
|
||||
url: '../search/search'
|
||||
});
|
||||
},
|
||||
// 重试
|
||||
retry() {
|
||||
this.refresh()
|
||||
},
|
||||
// 刷新
|
||||
refresh() {
|
||||
this.loadType = 'refresh'
|
||||
this.$refs.udb.loadData({
|
||||
clear: true
|
||||
}, () => {
|
||||
uni.stopPullDownRefresh()
|
||||
// #ifdef APP-NVUE
|
||||
this.showRefresh = false
|
||||
// #endif
|
||||
})
|
||||
},
|
||||
// 加载更多
|
||||
loadMore() {
|
||||
this.loadType = 'loadMore'
|
||||
this.$refs.udb.loadMore()
|
||||
},
|
||||
// 查询出错
|
||||
onqueryerror(e) {
|
||||
console.error(e);
|
||||
}
|
||||
},
|
||||
// #ifdef H5
|
||||
// 下拉刷新
|
||||
onPullDownRefresh() {
|
||||
this.refresh()
|
||||
},
|
||||
// #endif
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* #ifndef APP-NVUE */
|
||||
.pages view {
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
|
||||
.pages {
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
|
||||
.refresh {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.nav-box {
|
||||
background-color: #FFFFFF;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
|
||||
/* #ifndef APP-PLUS */
|
||||
z-index: 9;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.pages .nav {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.uni-search-box {
|
||||
flex: 1;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.uni-search-box ::v-deep .uni-searchbar {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.uni-search-box ::v-deep .uni-searchbar__box {
|
||||
height: 32px;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.cover-search-bar {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
top: 0;
|
||||
/* #ifndef APP-NVUE */
|
||||
z-index: 999;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.pages .uni-list ::v-deep .uni-list-item__container {
|
||||
flex-direction: row;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.pages .uni-list ::v-deep .uni-list-item {
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.pages .uni-list ::v-deep .uni-load-more {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.pages .uni-list ::v-deep .uni-list--border:after {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
</style>
|
@ -1,33 +0,0 @@
|
||||
<template>
|
||||
<view class="page">
|
||||
<uni-cms-article-search-bar :show-placeholder="true"></uni-cms-article-search-bar>
|
||||
<uni-cms-article-list
|
||||
:collectionList="colList"
|
||||
:refresherEnabled="true"
|
||||
style="flex: 1;"
|
||||
></uni-cms-article-list>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="uts">
|
||||
const db = uniCloud.databaseForJQL()
|
||||
|
||||
export default {
|
||||
computed: {
|
||||
colList(): any[] {
|
||||
return [
|
||||
db.collection('uni-cms-articles').where("\"article_status\" == 1").field('thumbnail,title,publish_date,user_id').getTemp(), // 文章集合
|
||||
db.collection('uni-id-users').field('_id,nickname').getTemp() // 用户集合
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.page {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
@ -1,738 +0,0 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<view class="search-container">
|
||||
<!-- 搜索框 -->
|
||||
<view class="search-container-bar">
|
||||
<!-- #ifdef APP-PLUS -->
|
||||
<uni-icons class="search-icons" :color="iconColor" size="22" type="mic-filled" @click="speech" />
|
||||
<!-- #endif -->
|
||||
<!-- :cancelText="keyBoardPopup ? '取消' : '搜索'" -->
|
||||
<uni-search-bar ref="searchBar" style="flex:1;" radius="100" v-model="searchText" :focus="focus"
|
||||
:placeholder="hotWorld" clearButton="auto" cancelButton="none" @clear="clear" @confirm="confirm"
|
||||
@cancel="cancel" />
|
||||
<uni-icons class="scan-icons" :color="iconColor" size="22" type="scan" @click="scanEvent"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
<view class="search-body">
|
||||
<unicloud-db ref='listUdb' v-slot:default="{ data, pagination, hasMore, loading, error, options }"
|
||||
@error="onqueryerror" :collection="colList" :page-size="10" orderby="publish_date desc" @load="onDbLoad"
|
||||
loadtime="manual">
|
||||
<template v-if="!isLoadData">
|
||||
<!-- 搜索历史 -->
|
||||
<view class="word-container" v-if="localSearchList.length">
|
||||
<view class="word-container_header">
|
||||
<text class="word-container_header-text">搜索历史</text>
|
||||
<uni-icons v-if="!localSearchListDel" @click="localSearchListDel = true" class="search-icons"
|
||||
style="padding-right: 0;" :color="iconColor" size="18" type="trash"></uni-icons>
|
||||
<view v-else class="flex-center flex-row"
|
||||
style="font-weight: 500;justify-content: space-between;">
|
||||
<text
|
||||
style="font-size: 22rpx;color: #666;padding-top:4rpx;padding-bottom:4rpx;padding-right:20rpx;"
|
||||
@click="LocalSearchListClear">全部删除</text>
|
||||
<text
|
||||
style="font-size: 22rpx;color: #c0402b;padding-top:4rpx;padding-bottom:4rpx;padding-left:20rpx;"
|
||||
@click="localSearchListDel = false">完成</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="word-container_body">
|
||||
<view class="flex-center flex-row word-container_body-text"
|
||||
v-for="(word, index) in localSearchList" :key="index"
|
||||
@click="LocalSearchlistItemClick(word, index)">
|
||||
<text class="word-display" :key="word">{{ word }}</text>
|
||||
<uni-icons v-if="localSearchListDel" size="12" type="closeempty" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 搜索发现 -->
|
||||
<view class="word-container">
|
||||
<view class="word-container_header">
|
||||
<view class="flex-center flex-row">
|
||||
<text class="word-container_header-text">搜索发现</text>
|
||||
<uni-icons v-if="!netHotListIsHide" class="search-icons" :color="iconColor" size="14"
|
||||
type="reload" @click="searchHotRefresh"></uni-icons>
|
||||
</view>
|
||||
<uni-icons class="search-icons" style="padding-right: 0;" :color="iconColor" size="18"
|
||||
:type="netHotListIsHide ? 'eye-slash' : 'eye'"
|
||||
@click="netHotListIsHide = !netHotListIsHide"></uni-icons>
|
||||
</view>
|
||||
<unicloud-db ref="udb" #default="{ data, loading, error, options }" field="content"
|
||||
collection="opendb-search-hot" orderby="create_date desc,count desc" page-data="replace"
|
||||
:page-size="10">
|
||||
<text v-if="loading && !netHotListIsHide" class="word-container_body-info">正在加载...</text>
|
||||
<view v-else class="word-container_body">
|
||||
<template v-if="!netHotListIsHide">
|
||||
<text v-if="error" class="word-container_body-info">{{ error.message }}</text>
|
||||
<template v-else>
|
||||
<text v-for="(word, index) in data" class="word-container_body-text" :key="index"
|
||||
@click="search(word.content)">{{ word.content }}</text>
|
||||
</template>
|
||||
</template>
|
||||
<view v-else style="flex:1;">
|
||||
<text class="word-container_body-info">当前搜索发现已隐藏</text>
|
||||
</view>
|
||||
</view>
|
||||
</unicloud-db>
|
||||
</view>
|
||||
</template>
|
||||
<uni-list v-else class="uni-list" :border="false" :style="{ height: listHeight }">
|
||||
<!-- 列表渲染 -->
|
||||
<uni-list-item :to="'/uni_modules/uni-cms-article/pages/detail/detail?id=' + item._id"
|
||||
v-for="(item, index) in data" :key="index">
|
||||
<!-- 通过header插槽定义列表左侧图片 -->
|
||||
<template v-slot:header>
|
||||
<image class="thumbnail" :src="typeof item.thumbnail === 'string' ? item.thumbnail: item.thumbnail[0]" mode="aspectFill"></image>
|
||||
</template>
|
||||
<!-- 通过body插槽定义布局 -->
|
||||
<template v-slot:body>
|
||||
<view class="main">
|
||||
<text class="title">{{ item.title }}</text>
|
||||
<view class="info">
|
||||
<text class="author">{{ item.user_id[0] ? item.user_id[0].nickname : '' }}</text>
|
||||
<text class="publish_date">{{ publishTime(item.publish_date) }}</text>
|
||||
<!-- -->
|
||||
<!-- <uni-dateformat class="publish_date" :date="item.publish_date"-->
|
||||
<!-- format="yyyy-MM-dd" :threshold="[60000, 2592000000]"/>-->
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</uni-list-item>
|
||||
<!-- 加载状态:上拉加载更多,加载中,没有更多数据了,加载错误 -->
|
||||
<!-- #ifdef APP-PLUS -->
|
||||
<uni-list-item>
|
||||
<template v-slot:body>
|
||||
<!-- #endif -->
|
||||
<uni-load-state @networkResume="refresh" :state="{ data, pagination, hasMore, loading, error }"
|
||||
@loadMore="loadMore">
|
||||
</uni-load-state>
|
||||
<!-- #ifdef APP-PLUS -->
|
||||
</template>
|
||||
</uni-list-item>
|
||||
<!-- #endif -->
|
||||
</uni-list>
|
||||
</unicloud-db>
|
||||
</view>
|
||||
<!-- 搜索联想 -->
|
||||
<view class="search-associative" v-if="associativeShow">
|
||||
<uni-list>
|
||||
<uni-list-item v-for="(item, index) in associativeList" :key="item._id" :ellipsis="1" :title="item.title"
|
||||
@click="associativeClick(item)" show-extra-icon clickable
|
||||
:extra-icon="{ size: 18, color: iconColor, type: 'search' }">
|
||||
</uni-list-item>
|
||||
</uni-list>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* 云端一体搜索模板
|
||||
* @description uniCloud云端一体搜索模板,自带下拉候选、历史搜索、热搜。无需再开发服务器代码
|
||||
*/
|
||||
|
||||
import translatePublishTime from "@/uni_modules/uni-cms-article/common/publish-time";
|
||||
import parseScanResult from "@/uni_modules/uni-cms-article/common/parse-scan-result";
|
||||
|
||||
const searchLogDbName = 'opendb-search-log'; // 搜索记录数据库
|
||||
const articleDbName = 'uni-cms-articles'; // 文章数据库
|
||||
const associativeSearchField = 'title'; // 联想时,搜索框值检索数据库字段名
|
||||
const associativeField = '_id,title'; // 联想列表每一项携带的字段
|
||||
const localSearchListKey = '__local_search_history'; // 本地历史存储字段名
|
||||
|
||||
const db = uniCloud.database();
|
||||
const articleDBName = 'uni-cms-articles'
|
||||
const userDBName = 'uni-id-users'
|
||||
|
||||
// 数组去重
|
||||
const arrUnique = arr => {
|
||||
for (let i = arr.length - 1; i >= 0; i--) {
|
||||
const curIndex = arr.indexOf(arr[i]);
|
||||
const lastIndex = arr.lastIndexOf(arr[i])
|
||||
curIndex != lastIndex && arr.splice(lastIndex, 1)
|
||||
}
|
||||
return arr
|
||||
} // 节流
|
||||
// 防抖
|
||||
function debounce(fn, interval, isFirstAutoRun) {
|
||||
/**
|
||||
*
|
||||
* @param {要执行的函数} fn
|
||||
* @param {在操作多长时间后可再执行,第一次立即执行} interval
|
||||
*/
|
||||
var _self = fn;
|
||||
var timer = null;
|
||||
var first = true;
|
||||
|
||||
if (isFirstAutoRun) {
|
||||
_self();
|
||||
}
|
||||
|
||||
return function () {
|
||||
var args = arguments;
|
||||
var _me = this;
|
||||
if (first) {
|
||||
first = false;
|
||||
_self.apply(_me, args);
|
||||
}
|
||||
|
||||
if (timer) {
|
||||
clearTimeout(timer)
|
||||
// return false;
|
||||
}
|
||||
|
||||
timer = setTimeout(function () {
|
||||
clearTimeout(timer);
|
||||
timer = null;
|
||||
_self.apply(_me, args);
|
||||
}, interval || 200);
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
// 组件数据
|
||||
data() {
|
||||
return {
|
||||
// 文章数据库名称
|
||||
articleDbName,
|
||||
// 搜索记录数据库名称
|
||||
searchLogDbName,
|
||||
// 状态栏高度
|
||||
statusBarHeight: '0px',
|
||||
// 本地搜索列表
|
||||
localSearchList: uni.getStorageSync(localSearchListKey),
|
||||
// 是否删除本地搜索列表
|
||||
localSearchListDel: false,
|
||||
// 是否隐藏网络热搜列表
|
||||
netHotListIsHide: false,
|
||||
// 搜索文本
|
||||
searchText: '',
|
||||
// 图标颜色
|
||||
iconColor: '#999999',
|
||||
// 联想列表
|
||||
associativeList: [],
|
||||
// 是否弹出键盘
|
||||
keyBoardPopup: false,
|
||||
// 搜索热词
|
||||
hotWorld: 'DCloud', // 搜索热词,如果没有输入即回车,则搜索热词,但是不会加入搜索记录
|
||||
// 是否自动聚焦
|
||||
focus: true,
|
||||
// 语音识别引擎
|
||||
speechEngine: 'iFly', // 语音识别引擎 iFly 讯飞 baidu 百度
|
||||
// 是否正在加载数据
|
||||
isLoadData: false,
|
||||
// 数据库查询条件
|
||||
where: '"article_status" == 1',
|
||||
// 列表高度
|
||||
listHeight: 0,
|
||||
// 是否显示联想列表
|
||||
associativeShow: false,
|
||||
// 是否显示无联想列表
|
||||
noAssociativeShow: false
|
||||
}
|
||||
},
|
||||
// 组件创建时执行
|
||||
created() {
|
||||
// 初始化数据库
|
||||
this.db = uniCloud.database();
|
||||
this.searchLogDb = this.db.collection(this.searchLogDbName);
|
||||
this.articleDbName = this.db.collection(this.articleDbName);
|
||||
// #ifndef H5
|
||||
// 监听键盘高度变化
|
||||
uni.onKeyboardHeightChange((res) => {
|
||||
this.keyBoardPopup = res.height !== 0;
|
||||
})
|
||||
// #endif
|
||||
},
|
||||
// 计算属性
|
||||
computed: {
|
||||
colList() {
|
||||
// 返回文章和用户列表
|
||||
return [
|
||||
db.collection(articleDBName).where(this.where).field('thumbnail,title,publish_date,user_id').getTemp(),
|
||||
db.collection(userDBName).field('_id,nickname').getTemp()
|
||||
]
|
||||
}
|
||||
},
|
||||
// 页面初次渲染完成时执行
|
||||
onReady() {
|
||||
// #ifdef APP-NVUE
|
||||
/* 可用窗口高度 - 搜索框高 - 状态栏高 */
|
||||
this.listHeight = uni.getSystemInfoSync().windowHeight + 'px';
|
||||
// #endif
|
||||
// #ifndef APP-NVUE
|
||||
this.listHeight = 'auto'
|
||||
// #endif
|
||||
},
|
||||
// 页面加载时执行
|
||||
onLoad() {
|
||||
//#ifdef APP-PLUS
|
||||
// 获取状态栏高度
|
||||
this.statusBarHeight = `${uni.getSystemInfoSync().statusBarHeight}px`;
|
||||
//#endif
|
||||
},
|
||||
// 组件方法
|
||||
methods: {
|
||||
// 清空搜索框
|
||||
clear(res) {
|
||||
console.log("res: ", res);
|
||||
},
|
||||
// 确认搜索
|
||||
confirm(res) {
|
||||
// 键盘确认
|
||||
this.search(res.value);
|
||||
},
|
||||
// 取消搜索
|
||||
cancel(res) {
|
||||
uni.hideKeyboard();
|
||||
this.searchText = '';
|
||||
this.isLoadData = false
|
||||
this.associativeShow = false
|
||||
// this.loadList();
|
||||
},
|
||||
// 执行搜索
|
||||
search(value) {
|
||||
if (!value && !this.hotWorld) {
|
||||
return;
|
||||
}
|
||||
if (value) {
|
||||
if (this.searchText !== value) {
|
||||
this.searchText = value
|
||||
}
|
||||
|
||||
this.localSearchListManage(value);
|
||||
|
||||
this.searchLogDbAdd(value)
|
||||
} else if (this.hotWorld) {
|
||||
this.searchText = this.hotWorld
|
||||
}
|
||||
|
||||
uni.hideKeyboard();
|
||||
this.loadList(this.searchText);
|
||||
},
|
||||
// 管理本地搜索列表
|
||||
localSearchListManage(word) {
|
||||
let list = uni.getStorageSync(localSearchListKey);
|
||||
if (list.length) {
|
||||
this.localSearchList.unshift(word);
|
||||
arrUnique(this.localSearchList);
|
||||
if (this.localSearchList.length > 10) {
|
||||
this.localSearchList.pop();
|
||||
}
|
||||
} else {
|
||||
this.localSearchList = [word];
|
||||
}
|
||||
uni.setStorageSync(localSearchListKey, this.localSearchList);
|
||||
},
|
||||
// 清空本地搜索列表
|
||||
LocalSearchListClear() {
|
||||
uni.showModal({
|
||||
content: "确认清空搜索历史吗",
|
||||
confirmText: "删除",
|
||||
confirmColor: 'red',
|
||||
cancelColor: '#808080',
|
||||
success: res => {
|
||||
if (res.confirm) {
|
||||
this.localSearchListDel = false;
|
||||
this.localSearchList = [];
|
||||
uni.removeStorageSync(localSearchListKey)
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
// 点击本地搜索列表项
|
||||
LocalSearchlistItemClick(word, index) {
|
||||
if (this.localSearchListDel) {
|
||||
this.localSearchList.splice(index, 1);
|
||||
uni.setStorageSync(localSearchListKey, this.localSearchList);
|
||||
if (!this.localSearchList.length) {
|
||||
this.localSearchListDel = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.noAssociativeShow = true;
|
||||
this.search(word);
|
||||
},
|
||||
// 刷新搜索热词
|
||||
searchHotRefresh() {
|
||||
this.$refs.udb.refresh();
|
||||
},
|
||||
// 语音搜索
|
||||
speech() {
|
||||
// #ifdef APP-PLUS
|
||||
plus.speech.startRecognize({
|
||||
engine: this.speechEngine,
|
||||
punctuation: false, // 标点符号
|
||||
timeout: 10000
|
||||
}, word => {
|
||||
word = word instanceof Array ? word[0] : word;
|
||||
this.search(word)
|
||||
}, err => {
|
||||
console.error("语音识别错误: ", err);
|
||||
});
|
||||
// #endif
|
||||
},
|
||||
// 添加搜索记录
|
||||
searchLogDbAdd(value) {
|
||||
/*
|
||||
在此处存搜索记录,如果登录则需要存 user_id,若未登录则存device_id
|
||||
*/
|
||||
this.getDeviceId().then(device_id => {
|
||||
this.searchLogDb.add({
|
||||
// user_id: device_id,
|
||||
device_id,
|
||||
content: value,
|
||||
create_date: Date.now()
|
||||
})
|
||||
})
|
||||
},
|
||||
// 获取设备ID
|
||||
getDeviceId() {
|
||||
return new Promise((resolve, reject) => {
|
||||
// 从本地缓存中获取uni_id
|
||||
const uniId = uni.getStorageSync('uni_id');
|
||||
// 如果uni_id不存在,则获取设备信息
|
||||
if (!uniId) {
|
||||
// #ifdef APP-PLUS
|
||||
plus.device.getInfo({
|
||||
success: (deviceInfo) => {
|
||||
resolve(deviceInfo.uuid)
|
||||
},
|
||||
fail: () => {
|
||||
// 如果获取设备信息失败,则返回一个随机字符串
|
||||
resolve(uni.getSystemInfoSync().system + '_' + Math.random().toString(36).substr(2))
|
||||
}
|
||||
});
|
||||
// #endif
|
||||
// #ifndef APP-PLUS
|
||||
// 如果不是APP-PLUS,则返回一个随机字符串
|
||||
resolve(uni.getSystemInfoSync().system + '_' + Math.random().toString(36).substr(2))
|
||||
// #endif
|
||||
} else {
|
||||
// 如果uni_id存在,则直接返回uni_id
|
||||
resolve(uniId)
|
||||
}
|
||||
})
|
||||
},
|
||||
// 点击联想词
|
||||
associativeClick(item) {
|
||||
/**
|
||||
* 注意:这里用户根据自己的业务需要,选择跳转的页面即可
|
||||
*/
|
||||
console.log("associativeClick: ", item, item.title);
|
||||
// 隐藏联想词
|
||||
this.noAssociativeShow = true;
|
||||
// 将搜索框的文本设置为联想词的标题
|
||||
this.searchText = item.title;
|
||||
// 加载列表
|
||||
this.loadList(item.title);
|
||||
},
|
||||
// 加载列表
|
||||
loadList(text = '') {
|
||||
// 设置查询条件
|
||||
let where = '"article_status" == 1 '
|
||||
if (text) {
|
||||
this.where = where + `&& /${text}/.test(title)`;
|
||||
} else {
|
||||
this.where = where;
|
||||
}
|
||||
|
||||
// 隐藏联想词
|
||||
this.associativeList = [];
|
||||
this.associativeShow = false;
|
||||
|
||||
// 延迟0ms后加载数据
|
||||
setTimeout(() => {
|
||||
this.$refs.listUdb.loadData({
|
||||
clear: true
|
||||
})
|
||||
}, 0)
|
||||
},
|
||||
// 数据库加载完成
|
||||
onDbLoad() {
|
||||
console.log('onDbLoad')
|
||||
// 设置数据已加载标志
|
||||
this.isLoadData = true
|
||||
// 显示联想词
|
||||
this.noAssociativeShow = false;
|
||||
},
|
||||
// 查询错误
|
||||
onqueryerror(e) {
|
||||
console.error(e);
|
||||
},
|
||||
// 刷新
|
||||
refresh() {
|
||||
// 刷新数据
|
||||
this.$refs.listUdb.loadData({
|
||||
clear: true
|
||||
}, () => {
|
||||
// 停止下拉刷新
|
||||
uni.stopPullDownRefresh()
|
||||
// #ifdef APP-NVUE
|
||||
// 隐藏刷新按钮
|
||||
this.showRefresh = false
|
||||
// #endif
|
||||
})
|
||||
},
|
||||
// 加载更多
|
||||
loadMore() {
|
||||
// 加载更多数据
|
||||
this.$refs.listUdb.loadMore()
|
||||
},
|
||||
// 格式化发布时间
|
||||
publishTime(timestamp) {
|
||||
return translatePublishTime(timestamp)
|
||||
},
|
||||
scanEvent () {
|
||||
uni.scanCode({
|
||||
onlyFromCamera: true,
|
||||
scanType: ["qrCode"],
|
||||
success: (e) => parseScanResult(e.result),
|
||||
fail: (e) => {
|
||||
console.error(e)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
onReachBottom() {
|
||||
// 当滚动到底部时,加载更多数据
|
||||
this.loadMore()
|
||||
},
|
||||
watch: {
|
||||
searchText: debounce(function (value, oldValue) {
|
||||
// 当搜索框的文本发生变化时,执行以下操作
|
||||
if (value === oldValue) return
|
||||
if (this.noAssociativeShow) return
|
||||
|
||||
if (value) {
|
||||
// 根据搜索框的文本,查询联想词
|
||||
this.articleDbName.where({
|
||||
[associativeSearchField]: new RegExp(value, 'gi'),
|
||||
}).field(associativeField).get().then(res => {
|
||||
// 将查询结果赋值给联想词列表,并显示联想词
|
||||
this.associativeList = res.result.data;
|
||||
this.associativeShow = true
|
||||
})
|
||||
} else {
|
||||
// 如果搜索框的文本为空,则清空联想词列表
|
||||
this.associativeList = [];
|
||||
}
|
||||
|
||||
}, 100)
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/* #ifndef APP-NVUE */
|
||||
page {
|
||||
height: 100%;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$search-bar-height: 52px;
|
||||
$word-container_header-height: 72rpx;
|
||||
|
||||
.status-bar {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.container {
|
||||
/* #ifndef APP-NVUE */
|
||||
height: 100%;
|
||||
/* #endif */
|
||||
flex: 1;
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
|
||||
.search-body {
|
||||
background-color: #fff;
|
||||
border-bottom-right-radius: 10px;
|
||||
border-bottom-left-radius: 10px;
|
||||
}
|
||||
|
||||
@mixin uni-flex {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
@mixin words-display {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.flex-center {
|
||||
@include uni-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.flex-row {
|
||||
@include uni-flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
/* #ifdef APP-PLUS */
|
||||
/* #ifndef APP-NVUE || VUE3*/
|
||||
::v-deep
|
||||
|
||||
/* #endif */
|
||||
.uni-searchbar {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
|
||||
/* #ifndef APP-NVUE || VUE3*/
|
||||
::v-deep
|
||||
|
||||
/* #endif */
|
||||
.uni-searchbar__box {
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
/* #ifndef APP-NVUE || VUE3 */
|
||||
::v-deep
|
||||
|
||||
/* #endif */
|
||||
.uni-input-placeholder {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.search-container {
|
||||
height: $search-bar-height;
|
||||
@include uni-flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
background-color: #fff;
|
||||
|
||||
@at-root {
|
||||
#{&}-bar {
|
||||
@include uni-flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.search-associative {
|
||||
/* #ifndef APP-NVUE */
|
||||
overflow-y: auto;
|
||||
/* #endif */
|
||||
position: absolute;
|
||||
top: $search-bar-height;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: #fff;
|
||||
margin-top: 10rpx;
|
||||
padding-left: 10rpx;
|
||||
padding-right: 10rpx;
|
||||
}
|
||||
|
||||
.search-icons, .scan-icons {
|
||||
padding: 16rpx;
|
||||
}
|
||||
.scan-icons {
|
||||
padding-left: 0;
|
||||
}
|
||||
.word-display {
|
||||
@include words-display;
|
||||
}
|
||||
|
||||
.word-container {
|
||||
padding: 20rpx;
|
||||
|
||||
@at-root {
|
||||
#{&}_header {
|
||||
@include uni-flex;
|
||||
height: $word-container_header-height;
|
||||
line-height: $word-container_header-height;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
@at-root {
|
||||
#{&}-text {
|
||||
color: #3e3e3e;
|
||||
font-size: 30rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#{&}_body {
|
||||
@include uni-flex;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: row;
|
||||
|
||||
@at-root {
|
||||
#{&}-text {
|
||||
@include uni-flex;
|
||||
@include words-display;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: #f6f6f6;
|
||||
padding: 10rpx 20rpx;
|
||||
margin: 20rpx 30rpx 0 0;
|
||||
border-radius: 30rpx;
|
||||
/* #ifndef APP-NVUE */
|
||||
box-sizing: border-box;
|
||||
/* #endif */
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#{&}-info {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: block;
|
||||
/* #endif */
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
font-size: 26rpx;
|
||||
color: #808080;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.thumbnail {
|
||||
width: 240rpx;
|
||||
height: 160rpx;
|
||||
margin-right: 20rpx;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
|
||||
.main {
|
||||
justify-content: space-between;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.info {
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.author,
|
||||
.publish_date {
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
}
|
||||
</style>
|
@ -1,363 +0,0 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<view class="search">
|
||||
<uni-cms-article-search-bar
|
||||
ref="searchBar"
|
||||
v-model="searchVal"
|
||||
:show-placeholder="false"
|
||||
:focus="true"
|
||||
@clear="showSearchResultPanel = false"
|
||||
@confirm="search"
|
||||
></uni-cms-article-search-bar>
|
||||
</view>
|
||||
<view class="search-result" v-if="showSearchResultPanel">
|
||||
<uni-cms-article-list
|
||||
ref="articleList"
|
||||
:collectionList="colList"
|
||||
:refresherEnabled="false"
|
||||
loadTime="manual"
|
||||
style="flex: 1;"
|
||||
></uni-cms-article-list>
|
||||
</view>
|
||||
<template v-else>
|
||||
<view class="panel history-panel" v-if="searchHistory.length > 0">
|
||||
<view class="panel__title">
|
||||
<view class="panel__title-text">
|
||||
<text class="text">搜索历史</text>
|
||||
</view>
|
||||
|
||||
<view class="delete-history-btns" v-if="deleteHistoryLoading">
|
||||
<text class="text" @click="deleteAllSearchHistory">全部删除</text>
|
||||
<text class="text danger" @click="deleteHistoryLoading = false">完成</text>
|
||||
</view>
|
||||
<uni-cms-article-icons
|
||||
class="panel__after-icon"
|
||||
type="trash"
|
||||
:size="18"
|
||||
color="#999"
|
||||
@click="deleteHistoryLoading = true"
|
||||
v-else
|
||||
></uni-cms-article-icons>
|
||||
</view>
|
||||
<view class="panel__list">
|
||||
<view class="panel__list-item" v-for="text in searchHistory">
|
||||
<text class="text" @click="search(text)">{{text}}</text>
|
||||
<uni-cms-article-icons
|
||||
class="icon"
|
||||
type="closeempty"
|
||||
:size="12"
|
||||
color="#999"
|
||||
v-if="deleteHistoryLoading"
|
||||
@click="deleteSearchHistory(text)"
|
||||
></uni-cms-article-icons>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<unicloud-db ref="udb" #default="{ data, loading, error }" field="content"
|
||||
collection="opendb-search-hot" orderby="create_date desc,count desc" page-data="replace"
|
||||
:page-size="10">
|
||||
<view class="panel recommend-panel">
|
||||
<view class="panel__title">
|
||||
<view class="panel__title-text">
|
||||
<text class="text">搜索发现</text>
|
||||
<uni-cms-article-icons
|
||||
class="icon"
|
||||
type="reload"
|
||||
:size="14"
|
||||
color="#999"
|
||||
v-if="!hideSearchRecommend"
|
||||
@click="reLoadSearchRecommend"
|
||||
></uni-cms-article-icons>
|
||||
</view>
|
||||
<uni-cms-article-icons
|
||||
class="panel__after-icon"
|
||||
:type="hideSearchRecommend ? 'eye-slash': 'eye'"
|
||||
:size="18"
|
||||
color="#999"
|
||||
@click="hideSearchRecommend = !hideSearchRecommend"
|
||||
></uni-cms-article-icons>
|
||||
</view>
|
||||
<view class="panel__list">
|
||||
<view class="panel__list-tip" v-if="loading">
|
||||
<text class="text">正在加载...</text>
|
||||
</view>
|
||||
<view class="panel__list-tip" v-else-if="error != null">
|
||||
<text class="text">{{error.message}}</text>
|
||||
</view>
|
||||
<view class="panel__list-tip" v-else-if="hideSearchRecommend">
|
||||
<text class="text">当前搜索发现已隐藏</text>
|
||||
</view>
|
||||
<template v-else>
|
||||
<view
|
||||
class="panel__list-item"
|
||||
v-for="(word, index) in data"
|
||||
:key="index"
|
||||
@click="search(word.getString('content')!)"
|
||||
>
|
||||
<text class="text">{{ word.getString('content') }}</text>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</view>
|
||||
</unicloud-db>
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="uts">
|
||||
type ArticleAuthor = {
|
||||
_id: string
|
||||
nickname: string
|
||||
}
|
||||
type ArticleItem = {
|
||||
_id: string
|
||||
title: string
|
||||
publish_date: number
|
||||
thumbnail: string[]
|
||||
user_id: ArticleAuthor[]
|
||||
}
|
||||
|
||||
const db = uniCloud.databaseForJQL()
|
||||
const searchLogDB = db.collection('opendb-search-log')
|
||||
const cmsArticleDB = db.collection('uni-cms-articles')
|
||||
const uniIdUsersDB = db.collection('uni-id-users')
|
||||
const localSearchHistoryKey = '__local_search_history'; // 本地历史存储字段名
|
||||
const localSearchRecommendHiddenKey = '__local_search_recommend_hidden'; // 本地搜索发现开关字段名
|
||||
const localSearchHistoryMax = 10; // 本地历史存储最大值
|
||||
export default {
|
||||
data() {
|
||||
const localSearchRecommendHidden = uni.getStorageSync(localSearchRecommendHiddenKey)
|
||||
|
||||
return {
|
||||
searchVal: "",
|
||||
searchHistory: [] as string[],
|
||||
searchRecommend: [] as string[],
|
||||
deleteHistoryLoading: false,
|
||||
hideSearchRecommend: (localSearchRecommendHidden == "" ? false : localSearchRecommendHidden) as boolean,
|
||||
showSearchResultPanel: false,
|
||||
searchResult: [] as ArticleItem[]
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
hideSearchRecommend(newValue) {
|
||||
uni.setStorageSync(localSearchRecommendHiddenKey, newValue)
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
hasSearchValue(): boolean {
|
||||
return this.searchVal != ""
|
||||
},
|
||||
where(): string {
|
||||
let where = "\"article_status\" == 1"
|
||||
|
||||
if (this.searchVal != "") {
|
||||
where += `&& /${this.searchVal}/.test(title)`
|
||||
}
|
||||
|
||||
return where
|
||||
},
|
||||
colList(): any[] {
|
||||
// 返回文章和用户列表
|
||||
return [
|
||||
cmsArticleDB.where(this.where).field('thumbnail,title,publish_date,user_id').getTemp(),
|
||||
uniIdUsersDB.field('_id,nickname').getTemp()
|
||||
]
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// 本地历史存储
|
||||
const localSearchHistory = uni.getStorageSync(localSearchHistoryKey)
|
||||
this.searchHistory = (localSearchHistory == "" ? [] as string[] : localSearchHistory) as string[]
|
||||
},
|
||||
methods: {
|
||||
deleteAllSearchHistory() {
|
||||
uni.showModal({
|
||||
title: "确定清空搜索历史吗",
|
||||
confirmText: "删除",
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
this.deleteSearchHistory(null)
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
deleteSearchHistory(searchText: string | null) {
|
||||
let history: string[] = []
|
||||
if (searchText != null) {
|
||||
history = this.searchHistory.filter((item: string): boolean => item != searchText)
|
||||
}
|
||||
|
||||
this.searchHistory = history
|
||||
uni.setStorageSync(localSearchHistoryKey, history)
|
||||
|
||||
console.log(history.length, 'history.length')
|
||||
if (history.length <= 0) {
|
||||
this.deleteHistoryLoading = false
|
||||
}
|
||||
},
|
||||
search(searchText: string) {
|
||||
searchText = searchText.trim()
|
||||
|
||||
if (searchText == "" || this.deleteHistoryLoading) return
|
||||
// 隐藏键盘
|
||||
;(this.$refs['searchBar'] as UniCmsArticleSearchBarComponentPublicInstance)!.hideKeyboard()
|
||||
|
||||
// 保存搜索历史
|
||||
this.setLocalSearchHistory(searchText)
|
||||
// 显示搜索结果Panel
|
||||
this.showSearchResultPanel = true
|
||||
// 搜索
|
||||
this.loadSearchResult(searchText)
|
||||
// 添加搜索记录
|
||||
this.addSearchRecord(searchText)
|
||||
},
|
||||
loadSearchResult(searchText: string) {
|
||||
// 设置查询条件
|
||||
this.searchVal = searchText
|
||||
|
||||
// 延迟0ms后加载数据
|
||||
setTimeout(() => {
|
||||
(this.$refs['articleList'] as UniCmsArticleListComponentPublicInstance)!.reLoadList()
|
||||
}, 0)
|
||||
},
|
||||
addSearchRecord(searchText: string) {
|
||||
const systemInfo = uni.getSystemInfoSync()
|
||||
/*
|
||||
在此处存搜索记录,如果登录则需要存 user_id,若未登录则存device_id
|
||||
*/
|
||||
searchLogDB.add({
|
||||
// user_id: device_id,
|
||||
device_id: systemInfo.deviceId,
|
||||
// device_uuid: systemInfo.deviceId,
|
||||
content: searchText,
|
||||
create_date: Date.now()
|
||||
})
|
||||
},
|
||||
setLocalSearchHistory(searchText: string) {
|
||||
const history = this.searchHistory.filter((item: string): boolean => item != searchText)
|
||||
|
||||
history.unshift(searchText)
|
||||
|
||||
if (history.length > localSearchHistoryMax) {
|
||||
history.pop()
|
||||
}
|
||||
|
||||
this.searchHistory = history
|
||||
this.deleteHistoryLoading = false
|
||||
uni.setStorageSync(localSearchHistoryKey, history)
|
||||
},
|
||||
reLoadSearchRecommend() {
|
||||
(this.$refs['udb'] as UniCloudDBElement)!.loadData({
|
||||
clear: true
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
|
||||
.search-result {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
.panel {
|
||||
margin-top: 40rpx;
|
||||
padding: 10rpx 20rpx;
|
||||
|
||||
&__title {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
&-text {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
.text {
|
||||
color: #3e3e3e;
|
||||
font-size: 30rpx;
|
||||
line-height: 36rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.icon {
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__after-icon {
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
|
||||
&__list {
|
||||
margin-top: 30rpx;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
|
||||
&-item {
|
||||
background-color: #f6f6f6;
|
||||
border-radius: 30rpx;
|
||||
padding: 10rpx 20rpx;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 10rpx;
|
||||
margin-bottom: 10rpx;
|
||||
|
||||
.text {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.icon {
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
}
|
||||
|
||||
&-tip {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
flex: 1;
|
||||
margin-top: 20rpx;
|
||||
|
||||
.text {
|
||||
font-size: 26rpx;
|
||||
color: #808080;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.delete-history-btns {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.text {
|
||||
color: #666;
|
||||
font-size: 22rpx;
|
||||
margin-left: 20rpx;
|
||||
|
||||
&.danger {
|
||||
color: #c0402b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
@ -1,246 +0,0 @@
|
||||
<template>
|
||||
<view class="about">
|
||||
<view class="box">
|
||||
<image class="logoImg" :src="about.logo"></image>
|
||||
<text class="tip appName">{{about.appName}}</text>
|
||||
<text class="tip">Version {{version}}</text>
|
||||
<view class="qrcode">
|
||||
<!--uqrcode 组件来源,插件Sansnn-uQRCode 链接地址:https://ext.dcloud.net.cn/plugin?id=1287-->
|
||||
<uqrcode :size="100" canvas-id="qrcode" :value="about.download"></uqrcode>
|
||||
</view>
|
||||
|
||||
<text class="tip">{{$t('about.sacnQR')}} {{about.appName}} {{$t('about.client')}}</text>
|
||||
</view>
|
||||
<view class="copyright">
|
||||
<view class="agreement-box" v-for="(agreement,index) in agreements" :key="index">
|
||||
<text class="agreement" @click="navigateTo(agreement)">《{{agreement.title}}》</text>
|
||||
<text class="hint" v-if="agreements.length-1>index">{{$t('about.and')}}</text>
|
||||
</view>
|
||||
<text class="hint">Copyright © {{year}}</text>
|
||||
<text class="hint">{{about.company}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
// #ifdef APP
|
||||
import UniShare from '@/uni_modules/uni-share/js_sdk/uni-share.js';
|
||||
const uniShare = new UniShare()
|
||||
// #endif
|
||||
import uniIdPagesConfig from '@/uni_modules/uni-id-pages/config.js';
|
||||
import uqrcode from "@/uni_modules/Sansnn-uQRCode/components/uqrcode/uqrcode"
|
||||
import extConfig from "@/app.config.js";
|
||||
export default {
|
||||
components: {
|
||||
uqrcode
|
||||
},
|
||||
// #ifdef APP
|
||||
onBackPress({
|
||||
from
|
||||
}) {
|
||||
if (from == 'backbutton') {
|
||||
this.$nextTick(function() {
|
||||
uniShare.hide()
|
||||
})
|
||||
return uniShare.isShow;
|
||||
}
|
||||
},
|
||||
// #endif
|
||||
onLoad() {
|
||||
// #ifdef APP-PLUS
|
||||
this.version = plus.runtime.version
|
||||
// #endif
|
||||
},
|
||||
computed: {
|
||||
uniStarterConfig() {
|
||||
let config = getApp().globalData.config;
|
||||
config.about = extConfig.about;
|
||||
return config
|
||||
},
|
||||
agreements() {
|
||||
if (!uniIdPagesConfig.agreements) {
|
||||
return []
|
||||
}
|
||||
let {
|
||||
serviceUrl,
|
||||
privacyUrl
|
||||
} = uniIdPagesConfig.agreements
|
||||
return [{
|
||||
url: serviceUrl,
|
||||
title: "用户服务协议"
|
||||
},
|
||||
{
|
||||
url: privacyUrl,
|
||||
title: "隐私政策条款"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
version: "V1.0.0",
|
||||
year: "2020",
|
||||
about: {}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.about = this.uniStarterConfig.about
|
||||
uni.setNavigationBarTitle({
|
||||
title: this.$t('about.about') + " " + this.about.appName
|
||||
})
|
||||
this.year = (new Date).getFullYear()
|
||||
},
|
||||
onNavigationBarButtonTap() {
|
||||
let {
|
||||
download,
|
||||
appName,
|
||||
slogan,
|
||||
logo
|
||||
} = this.about
|
||||
uniShare.show({
|
||||
content: { //公共的分享类型(type)、链接(herf)、标题(title)、summary(描述)、imageUrl(缩略图)
|
||||
type: 0,
|
||||
href: download,
|
||||
title: appName,
|
||||
summary: slogan,
|
||||
imageUrl: logo +
|
||||
'?x-oss-process=image/resize,m_fill,h_100,w_100' //压缩图片解决,在ios端分享图过大导致的图片失效问题
|
||||
},
|
||||
menus: [{
|
||||
"img": "/static/app-plus/sharemenu/wechatfriend.png",
|
||||
"text": this.$t('common.wechatFriends'),
|
||||
"share": {
|
||||
"provider": "weixin",
|
||||
"scene": "WXSceneSession"
|
||||
}
|
||||
},
|
||||
{
|
||||
"img": "/static/app-plus/sharemenu/wechatmoments.png",
|
||||
"text": this.$t('common.wechatBbs'),
|
||||
"share": {
|
||||
"provider": "weixin",
|
||||
"scene": "WXSceneTimeline"
|
||||
}
|
||||
},
|
||||
{
|
||||
"img": "/static/app-plus/sharemenu/weibo.png",
|
||||
"text": this.$t('common.weibo'),
|
||||
"share": {
|
||||
"provider": "sinaweibo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"img": "/static/app-plus/sharemenu/qq.png",
|
||||
"text": "QQ",
|
||||
"share": {
|
||||
"provider": "qq"
|
||||
}
|
||||
},
|
||||
{
|
||||
"img": "/static/app-plus/sharemenu/copyurl.png",
|
||||
"text": this.$t('common.copy'),
|
||||
"share": "copyurl"
|
||||
},
|
||||
{
|
||||
"img": "/static/app-plus/sharemenu/more.png",
|
||||
"text": this.$t('common.more'),
|
||||
"share": "shareSystem"
|
||||
}
|
||||
],
|
||||
cancelText: this.$t('common.cancelShare'),
|
||||
}, e => { //callback
|
||||
console.log(e);
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
navigateTo({
|
||||
url,
|
||||
title
|
||||
}) {
|
||||
uni.navigateTo({
|
||||
url: '/pages/common/webview/index?url=' + url + '&title=' +
|
||||
title,
|
||||
success: res => {},
|
||||
fail: () => {},
|
||||
complete: () => {}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
/* #ifndef APP-NVUE */
|
||||
view {
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
.about {
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.box {
|
||||
margin-top: 60px;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.logoImg {
|
||||
margin-bottom: 10rpx;
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
border-radius: 15px;
|
||||
}
|
||||
|
||||
.tip {
|
||||
text-align: center;
|
||||
font-size: 24rpx;
|
||||
margin-top: 10px;
|
||||
padding: 10rpx;
|
||||
}
|
||||
|
||||
.appName {
|
||||
margin-top: 20px;
|
||||
font-size: 42rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.qrcode,
|
||||
.qrcode .uqrcode {
|
||||
margin: 10px 0;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: block;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.copyright {
|
||||
font-size: 32rpx;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
bottom: 20px;
|
||||
// left: 0;
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
.agreement-box {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.agreement {
|
||||
color: #2285ff;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.hint {
|
||||
text-align: center;
|
||||
color: #999999;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
</style>
|
@ -1,179 +0,0 @@
|
||||
<template>
|
||||
<view class="about">
|
||||
<view class="box">
|
||||
<image class="logoImg" :src="about.logo"></image>
|
||||
<text class="tip appName">{{about.appName}}</text>
|
||||
<text class="tip">{{about.slogan}}</text>
|
||||
<view @click="download" id="download">
|
||||
<image v-if="isIos" class="icon" src="@/static/h5/download-app/ios.png" mode="widthFix"></image>
|
||||
<image v-else class="icon" src="@/static/h5/download-app/android.png" mode="widthFix"></image>
|
||||
<text class="download-text">{{$t('invite.download')}}</text>
|
||||
</view>
|
||||
<text class="tip">version {{about.version}}</text>
|
||||
</view>
|
||||
<view class="copyright">
|
||||
<text class="hint">{{about.company}}</text>
|
||||
</view>
|
||||
<view class="mask" v-if="showMask">
|
||||
<image src="@/static/h5/download-app/openImg.png" mode="widthFix"></image>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
computed: {
|
||||
uniStarterConfig() {
|
||||
return getApp().globalData.config
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
about: {},
|
||||
code: "",
|
||||
isIos: "",
|
||||
showMask: false,
|
||||
downloadUrl: {
|
||||
"ios": "",
|
||||
"android": ""
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.about = this.uniStarterConfig.about
|
||||
this.downloadUrl = this.uniStarterConfig.download
|
||||
this.year = (new Date).getFullYear()
|
||||
|
||||
//判断是否在微信中打开
|
||||
var userAgent = navigator.userAgent;
|
||||
var ua = userAgent.toLowerCase();
|
||||
this.isWeixin = ua.indexOf('micromessenger') != -1;
|
||||
//判断是否在ios或者安卓打开
|
||||
this.isIos = !!userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
|
||||
},
|
||||
onLoad({
|
||||
code
|
||||
}) {
|
||||
this.code = code
|
||||
document.getElementById("openApp").style.display = 'none'
|
||||
document.getElementsByTagName("body")[0].style = ""
|
||||
},
|
||||
methods: {
|
||||
download() {
|
||||
if (this.code) {
|
||||
uni.setClipboardData({
|
||||
data: this.code,
|
||||
complete: (e) => {
|
||||
console.log(e);
|
||||
uni.hideToast()
|
||||
/* 以下临时解决setClipboardData h5端样式和键盘弹出端错误解决方案,后续会直接内置*/
|
||||
document.getElementById("#clipboard").style.top = '-999px';
|
||||
uni.hideKeyboard()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (this.isIos) {
|
||||
window.location.href = this.downloadUrl.ios
|
||||
} else {
|
||||
if (this.isWeixin) {
|
||||
//显示浮层
|
||||
this.showMask = true
|
||||
} else {
|
||||
window.location.href = this.downloadUrl.android
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
/* #ifndef APP-NVUE */
|
||||
view {
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
.about {
|
||||
width: 750rpx;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.box {
|
||||
margin-top: 100px;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.logoImg {
|
||||
margin-bottom: 10upx;
|
||||
width: 160upx;
|
||||
height: 160upx;
|
||||
border-radius: 15px;
|
||||
}
|
||||
|
||||
.tip {
|
||||
font-size: 24rpx;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.appName {
|
||||
margin-top: 20px;
|
||||
font-size: 42rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.copyright {
|
||||
width: 750upx;
|
||||
font-size: 32rpx;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
bottom: 20px;
|
||||
left: 0;
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
.hint {
|
||||
color: #999999;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.icon {
|
||||
width: 34rpx;
|
||||
}
|
||||
|
||||
#download {
|
||||
background-color: #2A9839;
|
||||
color: #FFFFFF;
|
||||
margin: 55rpx;
|
||||
padding: 5px;
|
||||
height: 30px;
|
||||
width: 160rpx;
|
||||
border-radius: 100px;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.download-text {
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.mask {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 750rpx;
|
||||
height: 100vh;
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
background-color: rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
.mask image {
|
||||
width: 600rpx;
|
||||
}
|
||||
</style>
|
@ -1,77 +0,0 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<unicloud-db ref="udb" v-slot:default="{data, pagination, loading, hasMore, error}" :where="udbWhere"
|
||||
collection="opendb-news-articles" @load="isLoading == false" @error="isLoading == false"
|
||||
field="title,_id" :page-size="10">
|
||||
<uni-list>
|
||||
<uni-list-item v-for="(item, index) in data" :key="index" :clickable="true"
|
||||
@click="handleItemClick(item)">
|
||||
<template v-slot:body>
|
||||
<view class="item">
|
||||
<text>{{item.title}}</text>
|
||||
<uni-dateformat class="article-date" :date="readNewsLog[index].last_time" format="yyyy-MM-dd hh:mm"
|
||||
:threshold="[0, 0]" />
|
||||
</view>
|
||||
</template>
|
||||
</uni-list-item>
|
||||
</uni-list>
|
||||
<uni-load-state @networkResume="refreshData" :state="{data,pagination,hasMore, loading, error}"></uni-load-state>
|
||||
</unicloud-db>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
isLoading: true,
|
||||
loadMore: {
|
||||
contentdown: '',
|
||||
contentrefresh: '',
|
||||
contentnomore: '',
|
||||
},
|
||||
readNewsLog:[],
|
||||
udbWhere:''
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
this.readNewsLog = uni.getStorageSync('readNewsLog')||[];
|
||||
let readNewsLogIds = this.readNewsLog.map(({article_id})=>article_id)
|
||||
console.log(typeof readNewsLogIds,readNewsLogIds);
|
||||
this.udbWhere = `"_id" in ${JSON.stringify(readNewsLogIds)}`
|
||||
uni.setNavigationBarTitle({
|
||||
title: this.$t('newsLog.navigationBarTitle')
|
||||
})
|
||||
},
|
||||
onPullDownRefresh() {
|
||||
this.refreshData();
|
||||
},
|
||||
onReachBottom() {
|
||||
this.$refs.udb.loadMore()
|
||||
},
|
||||
methods: {
|
||||
refreshData() {
|
||||
this.$refs.udb.loadData({
|
||||
clear: true
|
||||
}, (res) => {
|
||||
uni.stopPullDownRefresh()
|
||||
})
|
||||
},
|
||||
handleItemClick(item) {
|
||||
uni.navigateTo({
|
||||
url: '/pages/list/detail?id=' + item._id + '&title=' + item.title
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.item{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.article-date {
|
||||
color: #C8C7CC;
|
||||
}
|
||||
</style>
|
@ -1,118 +0,0 @@
|
||||
/**
|
||||
* 判断Push是否开启
|
||||
*/
|
||||
function isTurnedOnPush(){
|
||||
var isOn = undefined;
|
||||
try{
|
||||
if('iOS' == plus.os.name){
|
||||
var types = 0;
|
||||
var app = plus.ios.invoke('UIApplication', 'sharedApplication');
|
||||
var settings = plus.ios.invoke(app, 'currentUserNotificationSettings');
|
||||
if(settings){
|
||||
types = settings.plusGetAttribute('types');
|
||||
plus.ios.deleteObject(settings);
|
||||
}else{
|
||||
types = plus.ios.invoke(app, 'enabledRemoteNotificationTypes');
|
||||
}
|
||||
plus.ios.deleteObject(app);
|
||||
isOn = (0!=types);
|
||||
}else{
|
||||
var main = plus.android.runtimeMainActivity();
|
||||
var manager = plus.android.invoke('com.igexin.sdk.PushManager', 'getInstance');
|
||||
isOn = plus.android.invoke(manager, 'isPushTurnedOn', main);
|
||||
}
|
||||
}catch(e){
|
||||
console.error('exception in isTurnedOnPush@dc-push!!');
|
||||
}
|
||||
return isOn;
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开Push
|
||||
* Android平台 - 打开个推(UniPush)的推送通道
|
||||
* iOS平台 - 如果开启通知功能,则打开应用的设置页面引导用户开启通知
|
||||
*/
|
||||
function turnOnPush(){
|
||||
try{
|
||||
if('iOS' == plus.os.name){
|
||||
// 如果设置中没有开启通知,则打开应用的设置界面
|
||||
if(!isTurnedOnPush()){
|
||||
settingInIos();
|
||||
}
|
||||
}else{
|
||||
var main = plus.android.runtimeMainActivity();
|
||||
var manager = plus.android.invoke('com.igexin.sdk.PushManager', 'getInstance');
|
||||
plus.android.invoke(manager, 'turnOnPush', main);
|
||||
}
|
||||
}catch(e){
|
||||
console.error('exception in turnOnPush@dc-push!!');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭Push
|
||||
* Android平台 - 关闭个推(UniPush)的推送通道
|
||||
* iOS平台 - 不做任何操作
|
||||
*/
|
||||
function trunOffPush(){
|
||||
try{
|
||||
if('iOS' == plus.os.name){
|
||||
// 这里不做任何操作(不引导用户关闭应用的推送能力),应该通知业务服务器不向此用户下发推送消息
|
||||
}else{
|
||||
var main = plus.android.runtimeMainActivity();
|
||||
var manager = plus.android.invoke('com.igexin.sdk.PushManager', 'getInstance');
|
||||
plus.android.invoke(manager, 'turnOffPush', main);
|
||||
}
|
||||
}catch(e){
|
||||
console.error('exception in trunOffPush@dc-push!!');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* iOS平台打开应用设置界面
|
||||
*/
|
||||
function settingInIos(){
|
||||
try{
|
||||
if('iOS' == plus.os.name){
|
||||
var app = plus.ios.invoke('UIApplication', 'sharedApplication');
|
||||
var setting = plus.ios.invoke('NSURL', 'URLWithString:', 'app-settings:');
|
||||
plus.ios.invoke(app, 'openURL:', setting);
|
||||
plus.ios.deleteObject(setting);
|
||||
plus.ios.deleteObject(app);
|
||||
}
|
||||
}catch(e){
|
||||
console.error('exception in settingInIos@dc-push!!');
|
||||
}
|
||||
}
|
||||
/**
|
||||
* android打开应用设置页面
|
||||
*/
|
||||
function settingInAndroid(){
|
||||
if (uni.getSystemInfoSync().platform == "android") {
|
||||
var main = plus.android.runtimeMainActivity();
|
||||
var Intent = plus.android.importClass('android.content.Intent');
|
||||
var Settings = plus.android.importClass('android.provider.Settings');
|
||||
var intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
||||
// 安卓跳转设置页面详细查看(https://ask.dcloud.net.cn/question/14732)
|
||||
main.startActivity(intent);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 打开应用设置界面
|
||||
*/
|
||||
function setting(){
|
||||
if (uni.getSystemInfoSync().platform == "ios") {
|
||||
settingInIos();
|
||||
}
|
||||
if (uni.getSystemInfoSync().platform == "android") {
|
||||
settingInAndroid();
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
isOn: isTurnedOnPush,
|
||||
iosSetting: settingInIos,
|
||||
on: turnOnPush,
|
||||
off: trunOffPush,
|
||||
setting:setting
|
||||
}
|
@ -1,325 +0,0 @@
|
||||
<template>
|
||||
<view class="content">
|
||||
<!-- 功能列表 -->
|
||||
<uni-list class="mt10" :border="false">
|
||||
<uni-list-item :title="$t('settings.userInfo')" to="/uni_modules/uni-id-pages/pages/userinfo/userinfo"
|
||||
link="navigateTo"></uni-list-item>
|
||||
<uni-list-item v-if="userInfo.mobile" :title="$t('settings.changePassword')"
|
||||
:to="'/pages/ucenter/login-page/pwd-retrieve/pwd-retrieve?phoneNumber='+ userInfo.mobile"
|
||||
link="navigateTo"></uni-list-item>
|
||||
</uni-list>
|
||||
<uni-list class="mt10" :border="false">
|
||||
<!-- #ifndef H5 -->
|
||||
<!-- #ifdef APP-PLUS -->
|
||||
<!-- 检查push过程未结束不显示,push设置项 -->
|
||||
<uni-list-item :title="$t('settings.clearTmp')" @click="clearTmp" link></uni-list-item>
|
||||
<uni-list-item v-show="pushIsOn != 'wait'" :title="$t('settings.pushServer')"
|
||||
@click.native="pushIsOn?pushServer.off():pushServer.on()" showSwitch
|
||||
:switchChecked="pushIsOn"></uni-list-item>
|
||||
<!-- #endif -->
|
||||
<uni-list-item v-if="supportMode.includes('fingerPrint')" :title="$t('settings.fingerPrint')"
|
||||
@click.native="startSoterAuthentication('fingerPrint')" link></uni-list-item>
|
||||
<uni-list-item v-if="supportMode.includes('facial')" :title="$t('settings.facial')"
|
||||
@click="startSoterAuthentication('facial')" link></uni-list-item>
|
||||
<!-- #endif -->
|
||||
<uni-list-item v-if="i18nEnable" :title="$t('settings.changeLanguage')" @click="changeLanguage"
|
||||
:rightText="currentLanguage" link></uni-list-item>
|
||||
</uni-list>
|
||||
|
||||
<!-- 退出/登录 按钮 -->
|
||||
<view class="bottom-back" @click="changeLoginState">
|
||||
<text class="bottom-back-text" v-if="hasLogin">{{$t('settings.logOut')}}</text>
|
||||
<text class="bottom-back-text" v-else>{{$t('settings.login')}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import pushServer from './dc-push/push.js';
|
||||
import {
|
||||
store,
|
||||
mutations
|
||||
} from '@/uni_modules/uni-id-pages/common/store.js'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
pushServer: pushServer,
|
||||
supportMode: [],
|
||||
pushIsOn: "wait",
|
||||
currentLanguage: "",
|
||||
userInfo: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
hasLogin() {
|
||||
return store.hasLogin
|
||||
},
|
||||
i18nEnable() {
|
||||
return getApp().globalData.config.i18n.enable
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
this.currentLanguage = uni.getStorageSync('CURRENT_LANG') == "en" ? 'English' : '简体中文'
|
||||
|
||||
uni.setNavigationBarTitle({
|
||||
title: this.$t('settings.navigationBarTitle')
|
||||
})
|
||||
// #ifdef APP-PLUS || MP-WEIXIN
|
||||
uni.checkIsSupportSoterAuthentication({
|
||||
success: (res) => {
|
||||
this.supportMode = res.supportMode
|
||||
},
|
||||
fail: (err) => {
|
||||
console.log(err);
|
||||
}
|
||||
})
|
||||
// #endif
|
||||
},
|
||||
onShow() {
|
||||
// 检查手机端获取推送是否开启
|
||||
//#ifdef APP-PLUS
|
||||
setTimeout(() => {
|
||||
this.pushIsOn = pushServer.isOn();
|
||||
}, 300)
|
||||
//#endif
|
||||
},
|
||||
methods: {
|
||||
async changeLoginState() {
|
||||
if (this.hasLogin) {
|
||||
await mutations.logout()
|
||||
} else {
|
||||
uni.redirectTo({
|
||||
url: '/uni_modules/uni-id-pages/pages/login/login-withoutpwd',
|
||||
});
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 开始生物认证
|
||||
*/
|
||||
startSoterAuthentication(checkAuthMode) {
|
||||
console.log(checkAuthMode);
|
||||
let title = {
|
||||
"fingerPrint": this.$t('settings.fingerPrint'),
|
||||
"facial": this.$t('settings.facial')
|
||||
} [checkAuthMode]
|
||||
// 检查是否开启认证
|
||||
this.checkIsSoterEnrolledInDevice({
|
||||
checkAuthMode,
|
||||
title
|
||||
})
|
||||
.then(() => {
|
||||
console.log(checkAuthMode, title);
|
||||
// 开始认证
|
||||
uni.startSoterAuthentication({
|
||||
requestAuthModes: [checkAuthMode],
|
||||
challenge: '123456', // 微信端挑战因子
|
||||
authContent: this.$t('settings.please') + " " + `${title}`,
|
||||
complete: (res) => {
|
||||
console.log(res);
|
||||
},
|
||||
success: (res) => {
|
||||
console.log(res);
|
||||
if (res.errCode == 0) {
|
||||
/**
|
||||
* 验证成功后开启自己的业务逻辑
|
||||
*
|
||||
* app端以此为依据 验证成功
|
||||
*
|
||||
* 微信小程序需要再次通过后台验证resultJSON与resultJSONSignature获取最终结果
|
||||
*/
|
||||
return uni.showToast({
|
||||
title: `${title}` + this.$t('settings.successText'),
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
uni.showToast({
|
||||
title: this.$t('settings.failTip'),
|
||||
icon: 'none'
|
||||
});
|
||||
},
|
||||
fail: (err) => {
|
||||
console.log(err);
|
||||
console.log(`认证失败:${err.errCode}`);
|
||||
uni.showToast({
|
||||
title: this.$t('settings.authFailed'),
|
||||
// title: `认证失败`,
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
checkIsSoterEnrolledInDevice({
|
||||
checkAuthMode,
|
||||
title
|
||||
}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.checkIsSoterEnrolledInDevice({
|
||||
checkAuthMode,
|
||||
success: (res) => {
|
||||
console.log(res);
|
||||
if (res.isEnrolled) {
|
||||
return resolve(res);
|
||||
}
|
||||
uni.showToast({
|
||||
title: this.$t('settings.deviceNoOpen') + `${title}`,
|
||||
icon: 'none'
|
||||
});
|
||||
reject(res);
|
||||
},
|
||||
fail: (err) => {
|
||||
console.log(err);
|
||||
uni.showToast({
|
||||
title: `${title}` + this.$t('settings.fail'),
|
||||
icon: 'none'
|
||||
});
|
||||
reject(err);
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
clearTmp() {
|
||||
uni.showLoading({
|
||||
title: this.$t('settings.clearing'),
|
||||
mask: true
|
||||
});
|
||||
/*
|
||||
任何临时存储或删除不直接影响程序运行逻辑(清除缓存必定造成业务逻辑的变化,如:打开页面的图片不从缓存中读取而从网络请求)的内容都可以视为缓存。主要有storage、和file写入。
|
||||
缓存分为三部分
|
||||
原生层(如:webview、x5播放器的、第三方sdk的、地图组件等)
|
||||
前端框架(重启就会自动清除)
|
||||
开发者自己的逻辑(如:
|
||||
本示例的 检测更新功能下载了apk安装包,
|
||||
其他逻辑需要根据开发者自己的业务设计
|
||||
比如:有聊天功能的应用,聊天记录是否视为缓存,还是单独提供清除聊天记录的功能由开发者自己设计
|
||||
)
|
||||
*/
|
||||
uni.getSavedFileList({
|
||||
success: res => {
|
||||
if (res.fileList.length > 0) {
|
||||
uni.removeSavedFile({
|
||||
filePath: res.fileList[0].filePath,
|
||||
complete: res => {
|
||||
console.log(res);
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
title: this.$t('settings.clearedSuccessed'),
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
title: this.$t('settings.clearedSuccessed'),
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
},
|
||||
complete: e => {
|
||||
console.log(e);
|
||||
}
|
||||
});
|
||||
},
|
||||
changeLanguage() {
|
||||
console.log('语言切换')
|
||||
uni.showActionSheet({
|
||||
itemList: ["English", "简体中文"],
|
||||
success: res => {
|
||||
console.log(res.tapIndex);
|
||||
let language = uni.getStorageSync('CURRENT_LANG')
|
||||
if (
|
||||
!res.tapIndex && language == 'zh-Hans' || res.tapIndex && language == 'en'
|
||||
) {
|
||||
const globalData = getApp().globalData
|
||||
if (language === 'en') {
|
||||
language = globalData.locale = 'zh-Hans'
|
||||
} else {
|
||||
language = globalData.locale = 'en'
|
||||
}
|
||||
uni.setStorageSync('CURRENT_LANG', language)
|
||||
getApp().globalData.$i18n.locale = language
|
||||
this.currentLanguage = res.tapIndex ? '简体中文' : 'English'
|
||||
if (uni.setLocale) {
|
||||
uni.setLocale(language)
|
||||
}
|
||||
uni.reLaunch({
|
||||
url: '/pages/index/index',
|
||||
complete: () => {
|
||||
uni.$emit("changeLanguage", language)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
fail: () => {},
|
||||
complete: () => {}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/* #ifndef APP-NVUE */
|
||||
page {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
uni-button:after {
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
.content {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
width: 750rpx;
|
||||
height: 100vh;
|
||||
/* #endif */
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
background-color: #F9F9F9;
|
||||
}
|
||||
|
||||
.bottom-back {
|
||||
margin-top: 10px;
|
||||
width: 750rpx;
|
||||
height: 44px;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
/* #ifndef APP-NVUE */
|
||||
border: none;
|
||||
/* #endif */
|
||||
border-width: 0;
|
||||
border-radius: 0;
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
|
||||
.bottom-back-text {
|
||||
font-size: 33rpx;
|
||||
}
|
||||
|
||||
.mt10 {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
/* #ifndef APP-NVUE || VUE3 */
|
||||
.content ::v-deep .uni-list {
|
||||
background-color: #F9F9F9;
|
||||
}
|
||||
|
||||
.content ::v-deep .uni-list-item--disabled,
|
||||
.list-item {
|
||||
height: 50px;
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
</style>
|
@ -1,506 +0,0 @@
|
||||
<template>
|
||||
<view class="center">
|
||||
<uni-sign-in ref="signIn"></uni-sign-in>
|
||||
<view class="userInfo" @click.capture="toUserInfo">
|
||||
<cloud-image width="150rpx" height="150rpx" v-if="hasLogin&&userInfo.avatar_file&&userInfo.avatar_file.url"
|
||||
:src="userInfo.avatar_file.url"></cloud-image>
|
||||
|
||||
<view v-else class="defaultAvatarUrl">
|
||||
<uni-icons color="#ffffff" size="50" type="person-filled" />
|
||||
</view>
|
||||
|
||||
<view class="logo-title">
|
||||
<text class="uer-name" v-if="hasLogin">{{userInfo.nickname||userInfo.username||userInfo.mobile}}</text>
|
||||
<text class="uer-name" v-else>{{$t('mine.notLogged')}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<uni-grid class="grid" :column="4" :showBorder="false" :square="true">
|
||||
<uni-grid-item class="item" v-for="(item,index) in gridList" @click.native="tapGrid(index)" :key="index">
|
||||
<uni-icons class="icon" color="#007AFF" :type="item.icon" size="26"></uni-icons>
|
||||
<text class="text">{{item.text}}</text>
|
||||
</uni-grid-item>
|
||||
</uni-grid>
|
||||
<uni-list class="center-list" v-for="(sublist , index) in ucenterList" :key="index">
|
||||
<uni-list-item v-for="(item,i) in sublist" :title="item.title" link :rightText="item.rightText" :key="i"
|
||||
:clickable="true" :to="item.to" @click="ucenterListClick(item)" :show-extra-icon="true"
|
||||
:extraIcon="{type:item.icon,color:'#999'}">
|
||||
<template v-slot:footer>
|
||||
<view v-if="item.showBadge" class="item-footer">
|
||||
<text class="item-footer-text">{{item.rightText}}</text>
|
||||
<view class="item-footer-badge"></view>
|
||||
</view>
|
||||
</template>
|
||||
</uni-list-item>
|
||||
</uni-list>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import checkUpdate from '@/uni_modules/uni-upgrade-center-app/utils/check-update';
|
||||
import callCheckVersion from '@/uni_modules/uni-upgrade-center-app/utils/call-check-version';
|
||||
// #ifdef APP
|
||||
import UniShare from '@/uni_modules/uni-share/js_sdk/uni-share.js';
|
||||
const uniShare = new UniShare()
|
||||
// #endif
|
||||
const db = uniCloud.database();
|
||||
import {
|
||||
store,
|
||||
mutations
|
||||
} from '@/uni_modules/uni-id-pages/common/store.js'
|
||||
export default {
|
||||
// #ifdef APP
|
||||
onBackPress({
|
||||
from
|
||||
}) {
|
||||
if (from == 'backbutton') {
|
||||
this.$nextTick(function() {
|
||||
uniShare.hide()
|
||||
})
|
||||
return uniShare.isShow;
|
||||
}
|
||||
},
|
||||
// #endif
|
||||
data() {
|
||||
return {
|
||||
gridList: [{
|
||||
"text": this.$t('mine.noticeText'),
|
||||
"icon": "email"
|
||||
},
|
||||
{
|
||||
"text": this.$t('mine.appsText'),
|
||||
"icon": "cloud-upload"
|
||||
},
|
||||
{
|
||||
"text": this.$t('mine.scanText'),
|
||||
"event": "toScan",
|
||||
"icon": "scan"
|
||||
},
|
||||
{
|
||||
"text": this.$t('mine.scoreText'),
|
||||
"icon": "shop"
|
||||
}
|
||||
],
|
||||
ucenterList: [
|
||||
[
|
||||
// #ifdef APP-PLUS
|
||||
{
|
||||
"title": this.$t('mine.signInByAd'),
|
||||
"event": 'signInByAd',
|
||||
"icon": "compose"
|
||||
},
|
||||
// #endif
|
||||
{
|
||||
"title": this.$t('mine.signIn'),
|
||||
"event": 'signIn',
|
||||
"icon": "compose"
|
||||
},
|
||||
// #ifdef APP-PLUS
|
||||
{
|
||||
"title": this.$t('mine.toEvaluate'),
|
||||
"event": 'gotoMarket',
|
||||
"icon": "star"
|
||||
},
|
||||
//#endif
|
||||
{
|
||||
"title": this.$t('mine.readArticles'),
|
||||
"to": './read-news-log/read-news-log',
|
||||
"icon": "flag"
|
||||
},
|
||||
{
|
||||
"title": this.$t('mine.myScore'),
|
||||
"to": '',
|
||||
"event": 'getScore',
|
||||
"icon": "paperplane"
|
||||
}
|
||||
// #ifdef APP-PLUS
|
||||
, {
|
||||
"title": this.$t('mine.invite'),
|
||||
"event": 'share',
|
||||
"icon": "redo"
|
||||
}
|
||||
// #endif
|
||||
],
|
||||
[{
|
||||
"title": this.$t('mine.feedback'),
|
||||
"to": '/uni_modules/uni-feedback/pages/opendb-feedback/opendb-feedback',
|
||||
"icon": "help"
|
||||
}, {
|
||||
"title": this.$t('mine.newsList'),
|
||||
"to": '/uni_modules/uni-cms-article/pages/list/list',
|
||||
"icon": "list"
|
||||
}, {
|
||||
"title": this.$t('mine.articleList'),
|
||||
"to": '/pages/uni-starter/list/list',
|
||||
"icon": "settings"
|
||||
}, {
|
||||
"title": this.$t('mine.settings'),
|
||||
"to": './settings/settings',
|
||||
"icon": "gear"
|
||||
}]
|
||||
// #ifdef APP-PLUS
|
||||
,
|
||||
[{
|
||||
"title": this.$t('mine.about'),
|
||||
"to": './about/about',
|
||||
"icon": "info"
|
||||
}]
|
||||
// #endif
|
||||
],
|
||||
listStyles: {
|
||||
"height": "150rpx", // 边框高度
|
||||
"width": "150rpx", // 边框宽度
|
||||
"border": { // 如果为 Boolean 值,可以控制边框显示与否
|
||||
"color": "#eee", // 边框颜色
|
||||
"width": "1px", // 边框宽度
|
||||
"style": "solid", // 边框样式
|
||||
"radius": "100%" // 边框圆角,支持百分比
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
//#ifdef APP-PLUS
|
||||
this.ucenterList[this.ucenterList.length - 2].unshift({
|
||||
title: this.$t('mine.checkUpdate'), // this.this.$t('mine.checkUpdate')"检查更新"
|
||||
rightText: this.appVersion.version + '-' + this.appVersion.versionCode,
|
||||
event: 'checkVersion',
|
||||
icon: 'loop',
|
||||
showBadge: this.appVersion.hasNew
|
||||
})
|
||||
//#endif
|
||||
},
|
||||
onShow() {},
|
||||
computed: {
|
||||
userInfo() {
|
||||
return store.userInfo
|
||||
},
|
||||
hasLogin() {
|
||||
return store.hasLogin
|
||||
},
|
||||
// #ifdef APP-PLUS
|
||||
appVersion() {
|
||||
return getApp().appVersion
|
||||
},
|
||||
// #endif
|
||||
appConfig() {
|
||||
return getApp().globalData.config
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toSettings() {
|
||||
uni.navigateTo({
|
||||
url: "./settings/settings"
|
||||
})
|
||||
},
|
||||
signIn() { //普通签到
|
||||
this.$refs.signIn.open()
|
||||
},
|
||||
signInByAd() { //看激励视频广告签到
|
||||
this.$refs.signIn.showRewardedVideoAd()
|
||||
},
|
||||
/**
|
||||
* 个人中心项目列表点击事件
|
||||
*/
|
||||
ucenterListClick(item) {
|
||||
if (!item.to && item.event) {
|
||||
this[item.event]();
|
||||
}
|
||||
},
|
||||
async checkVersion() {
|
||||
let res = await callCheckVersion()
|
||||
console.log(res);
|
||||
if (res.result.code > 0) {
|
||||
checkUpdate()
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: res.result.message,
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
},
|
||||
toUserInfo() {
|
||||
uni.navigateTo({
|
||||
url: '/uni_modules/uni-id-pages/pages/userinfo/userinfo'
|
||||
})
|
||||
},
|
||||
//TODO,扫码识别后的相应操作
|
||||
toScan() {
|
||||
uni.scanCode({
|
||||
onlyFromCamera: true,
|
||||
scanType: ["qrCode"],
|
||||
success: (e) => {
|
||||
console.log(e.result)
|
||||
},
|
||||
fail: (e) => {
|
||||
console.error(e)
|
||||
}
|
||||
})
|
||||
},
|
||||
tapGrid(index) {
|
||||
if (!this.gridList[index].event) {
|
||||
uni.showToast({
|
||||
// title: '你点击了,第' + (index + 1) + '个',
|
||||
title: this.$t('mine.clicked') + " " + (index + 1),
|
||||
icon: 'none'
|
||||
});
|
||||
} else {
|
||||
// console.log(this.gridList[index]);
|
||||
this[this.gridList[index].event]();
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 去应用市场评分
|
||||
*/
|
||||
gotoMarket() {
|
||||
// #ifdef APP-PLUS
|
||||
if (uni.getSystemInfoSync().platform == "ios") {
|
||||
// 这里填写appstore应用id
|
||||
let appstoreid = this.appConfig.marketId.ios; // 'id1417078253';
|
||||
console.log({
|
||||
appstoreid
|
||||
});
|
||||
plus.runtime.openURL("itms-apps://" + 'itunes.apple.com/cn/app/wechat/' + appstoreid + '?mt=8',
|
||||
err => {
|
||||
console.log('plus.runtime.openURL err:' + JSON.stringify(err));
|
||||
});
|
||||
}
|
||||
if (uni.getSystemInfoSync().platform == "android") {
|
||||
var Uri = plus.android.importClass("android.net.Uri");
|
||||
var uri = Uri.parse("market://details?id=" + this.appConfig.marketId.android);
|
||||
var Intent = plus.android.importClass('android.content.Intent');
|
||||
var intent = new Intent(Intent.ACTION_VIEW, uri);
|
||||
var main = plus.android.runtimeMainActivity();
|
||||
main.startActivity(intent);
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
/**
|
||||
* 获取积分信息
|
||||
*/
|
||||
getScore() {
|
||||
if (!this.userInfo) return uni.showToast({
|
||||
title: this.$t('mine.checkScore'),
|
||||
icon: 'none'
|
||||
});
|
||||
uni.showLoading({
|
||||
mask: true
|
||||
})
|
||||
db.collection("uni-id-scores")
|
||||
.where('"user_id" == $env.uid')
|
||||
.field('score,balance')
|
||||
.orderBy("create_date", "desc")
|
||||
.limit(1)
|
||||
.get()
|
||||
.then((res) => {
|
||||
console.log(res);
|
||||
const data = res.result.data[0];
|
||||
let msg = '';
|
||||
msg = data ? (this.$t('mine.currentScore') + data.balance) : this.$t('mine.noScore');
|
||||
uni.showToast({
|
||||
title: msg,
|
||||
icon: 'none'
|
||||
});
|
||||
}).finally(() => {
|
||||
uni.hideLoading()
|
||||
})
|
||||
},
|
||||
async share() {
|
||||
let {
|
||||
result
|
||||
} = await db.collection('uni-id-users').where("'_id' == $cloudEnv_uid").field('my_invite_code')
|
||||
.get()
|
||||
let myInviteCode = result.data[0].my_invite_code
|
||||
if (!myInviteCode) {
|
||||
return uni.showToast({
|
||||
title: '请检查uni-config-center中uni-id配置,是否已启用 autoSetInviteCode',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
console.log({
|
||||
myInviteCode
|
||||
});
|
||||
let {
|
||||
appName,
|
||||
logo,
|
||||
company,
|
||||
slogan
|
||||
} = this.appConfig.about
|
||||
// #ifdef APP-PLUS
|
||||
uniShare.show({
|
||||
content: { //公共的分享类型(type)、链接(herf)、标题(title)、summary(描述)、imageUrl(缩略图)
|
||||
type: 0,
|
||||
href: this.appConfig.h5.url +
|
||||
`/#/pages/ucenter/invite/invite?code=uniInvitationCode:${myInviteCode}`,
|
||||
title: appName,
|
||||
summary: slogan,
|
||||
imageUrl: logo +
|
||||
'?x-oss-process=image/resize,m_fill,h_100,w_100' //压缩图片解决,在ios端分享图过大导致的图片失效问题
|
||||
},
|
||||
menus: [{
|
||||
"img": "/static/app-plus/sharemenu/wechatfriend.png",
|
||||
"text": this.$t('common.wechatFriends'),
|
||||
"share": {
|
||||
"provider": "weixin",
|
||||
"scene": "WXSceneSession"
|
||||
}
|
||||
},
|
||||
{
|
||||
"img": "/static/app-plus/sharemenu/wechatmoments.png",
|
||||
"text": this.$t('common.wechatBbs'),
|
||||
"share": {
|
||||
"provider": "weixin",
|
||||
"scene": "WXSceneTimeline"
|
||||
}
|
||||
},
|
||||
{
|
||||
"img": "/static/app-plus/sharemenu/weibo.png",
|
||||
"text": this.$t('common.weibo'),
|
||||
"share": {
|
||||
"provider": "sinaweibo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"img": "/static/app-plus/sharemenu/qq.png",
|
||||
"text": "QQ",
|
||||
"share": {
|
||||
"provider": "qq"
|
||||
}
|
||||
},
|
||||
{
|
||||
"img": "/static/app-plus/sharemenu/copyurl.png",
|
||||
"text": this.$t('common.copy'),
|
||||
"share": "copyurl"
|
||||
},
|
||||
{
|
||||
"img": "/static/app-plus/sharemenu/more.png",
|
||||
"text": this.$t('common.more'),
|
||||
"share": "shareSystem"
|
||||
}
|
||||
],
|
||||
cancelText: this.$t('common.cancelShare'),
|
||||
}, e => { //callback
|
||||
console.log(e);
|
||||
})
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* #ifndef APP-NVUE */
|
||||
view {
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
page {
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
|
||||
/* #endif*/
|
||||
|
||||
.center {
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
|
||||
.userInfo {
|
||||
// padding: 20rpx;
|
||||
padding-top: 60px;
|
||||
background-image: url(@/static/uni-center/headers.png);
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.defaultAvatarUrl {
|
||||
width: 150rpx;
|
||||
height: 150rpx;
|
||||
background-color: #007aff;
|
||||
border-radius: 100%;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.logo-title {
|
||||
flex: 1;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.uer-name {
|
||||
height: 100rpx;
|
||||
line-height: 100rpx;
|
||||
font-size: 38rpx;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.center-list {
|
||||
margin-bottom: 30rpx;
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
.center-list-cell {
|
||||
width: 750rpx;
|
||||
background-color: #007AFF;
|
||||
height: 40rpx;
|
||||
}
|
||||
|
||||
.grid {
|
||||
background-color: #FFFFFF;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.uni-grid .text {
|
||||
font-size: 16px;
|
||||
height: 25px;
|
||||
line-height: 25px;
|
||||
color: #817f82;
|
||||
}
|
||||
|
||||
.uni-grid .item ::v-deep .uni-grid-item__box {
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
|
||||
/*修改边线粗细示例*/
|
||||
/* #ifndef APP-NVUE */
|
||||
.center-list ::v-deep .uni-list--border:after {
|
||||
-webkit-transform: scaleY(0.2);
|
||||
transform: scaleY(0.2);
|
||||
margin-left: 80rpx;
|
||||
}
|
||||
|
||||
.center-list ::v-deep .uni-list--border-top,
|
||||
.center-list ::v-deep .uni-list--border-bottom {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
.item-footer {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.item-footer-text {
|
||||
color: #999;
|
||||
font-size: 24rpx;
|
||||
padding-right: 10rpx;
|
||||
}
|
||||
|
||||
.item-footer-badge {
|
||||
width: 20rpx;
|
||||
height: 20rpx;
|
||||
/* #ifndef APP-NVUE */
|
||||
border-radius: 50%;
|
||||
/* #endif */
|
||||
/* #ifdef APP-NVUE */
|
||||
border-radius: 10rpx;
|
||||
/* #endif */
|
||||
background-color: #DD524D;
|
||||
}
|
||||
</style>
|
@ -1,5 +1,13 @@
|
||||
/**
|
||||
* @Author: 嗨噜客(三亚)<fm453>
|
||||
* @Date: 2023-07-19 16:03:07
|
||||
* @FilePath: store/index.js
|
||||
* @Description:
|
||||
* @Email: 393213759@qq.com
|
||||
* Copyright (c) 2025 by www.hiluker.cn, All Rights Reserved.
|
||||
*/
|
||||
import user from '@/store/modules/user.js' //主项目的user信息及操作
|
||||
import userCloud from '@/store/modules/userCloud.js' //unistarter云端处理的用户信息
|
||||
// import userCloud from '@/store/modules/userCloud.js' //unistarter云端处理的用户信息
|
||||
let store;
|
||||
|
||||
// #ifndef VUE3
|
||||
@ -9,7 +17,7 @@ Vue.use(Vuex)
|
||||
store = new Vuex.Store({
|
||||
modules: {
|
||||
user,
|
||||
userCloud
|
||||
// userCloud
|
||||
},
|
||||
strict: true
|
||||
})
|
||||
@ -22,7 +30,7 @@ import {
|
||||
store = createStore({
|
||||
modules: {
|
||||
user,
|
||||
userCloud
|
||||
// userCloud
|
||||
}
|
||||
})
|
||||
// #endif
|
||||
|
@ -1,49 +0,0 @@
|
||||
## 0.7.5(2023-12-18)
|
||||
- 修复 在uni-app x项目,部分情况下,执行uni-captcha组件的setFocus无效的问题
|
||||
## 0.7.4(2023-12-18)
|
||||
- 更新 `package.json` -> `dependencies` 增加 `uni-popup`
|
||||
## 0.7.3(2023-11-15)
|
||||
- 更新 uni-popup-captcha.uvue依赖的popup组件,直接使用uni_modules下的uni-popup组件
|
||||
## 0.7.2(2023-11-07)
|
||||
- 新增 前端组件:uni-captcha.uvue、uni-popup-captcha
|
||||
## 0.7.1(2023-11-07)
|
||||
- 新增 前端组件:uni-captcha.uvue、uni-popup-captcha
|
||||
## 0.7.0(2023-10-10)
|
||||
- 新增 支持在`uni-config-center`中配置mode,可选值为svg和bmp,配置成bmp后可以在uniappx的uvue页面正常显示验证码(uvue不支持显示svg验证码)
|
||||
## 0.6.4(2023-01-16)
|
||||
- 修复 部分情况下APP端无法获取验证码的问题
|
||||
## 0.6.3(2023-01-11)
|
||||
- 修复 抖音小程序无法显示的Bug
|
||||
- 修复 刷新时兼容 device_uuid
|
||||
## 0.6.1(2022-06-23)
|
||||
- 修复:部分返回值,不符合响应体规范的问题
|
||||
## 0.6.0(2022-05-27)
|
||||
- 新增:支持在`uni-config-center`中根据场景值配置
|
||||
- 修复:弹窗式验证码,输入内容后点击取消,重新打开验证码的值仍然存在的问题
|
||||
## 0.5.2(2022-05-19)
|
||||
- 修复在Vue3的兼容问题
|
||||
## 0.5.1(2022-05-18)
|
||||
- 修复在某些情况下微信小程序端验证码显示错误的问题
|
||||
## 0.5.0(2022-05-17)
|
||||
- 新增支持在`uni-captcha-co`->`config`配置验证码
|
||||
## 0.4.1(2022-05-16)
|
||||
- 新增示例项目
|
||||
## 0.4.0(2022-05-16)
|
||||
- 集成创建、刷新、显示验证码的云端一体验证码组件
|
||||
- 云对象`uni-captcha-co`集成获取验证码的api,`getImageCaptcha`
|
||||
## 0.3.1(2022-05-13)
|
||||
- 新增 返回值符合响应体规范
|
||||
## 0.3.0(2022-05-13)
|
||||
- 新增 支持 uni-config-center 配置
|
||||
## 0.2.2(2022-04-25)
|
||||
- 修复 0.2.1 版本引起的使用 image 组件验证码不显示的Bug
|
||||
## 0.2.1(2022-04-18)
|
||||
- 更新 优化字体
|
||||
## 0.2.0(2022-04-14)
|
||||
- 新增 使用 svg 表现形式更好
|
||||
- 新增 使用字体,可以任意替换默认字体
|
||||
- 新增 支持设置字体大小
|
||||
- 新增 支持忽略某些字符
|
||||
- 注意 更新之后请重新上传公共模块
|
||||
## 0.1.0(2021-03-01)
|
||||
- 调整为uni_modules目录规范
|
@ -1,180 +0,0 @@
|
||||
<template>
|
||||
<view class="captcha-box">
|
||||
<view class="captcha-img-box">
|
||||
<image class="loding" src="/uni_modules/uni-captcha/static/run.gif" v-if="loging" mode="widthFix" />
|
||||
<image class="captcha-img" :class="{opacity:loging}" @click="getImageCaptcha(true)" :src="captchaBase64" mode="widthFix" />
|
||||
</view>
|
||||
<input @blur="focusCaptchaInput = false" @focus="focusCaptchaInput = true" :focus="focusCaptchaInput" type="digit" class="captcha" :inputBorder="false"
|
||||
maxlength="4" v-model="val" placeholder="请输入验证码" :cursor-spacing="cursorSpacing" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
emits: ["modelValue"],
|
||||
props: {
|
||||
cursorSpacing: {
|
||||
type: Number,
|
||||
default: 100
|
||||
},
|
||||
modelValue: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
value: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
scene: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
focus: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
focusCaptchaInput: false,
|
||||
captchaBase64: "" as string,
|
||||
loging: false,
|
||||
val: ""
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
value: {
|
||||
handler(value : string) {
|
||||
// console.log('setvue', value);
|
||||
this.val = value
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
modelValue: {
|
||||
handler(modelValue : string) {
|
||||
// console.log('setvue', modelValue);
|
||||
this.val = modelValue
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
scene: {
|
||||
handler(scene : string) {
|
||||
if (scene.length != 0) {
|
||||
this.getImageCaptcha(this.focus)
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: 'scene不能为空',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
val(value : string) {
|
||||
// console.log('setvue', value);
|
||||
// TODO 兼容 vue2
|
||||
// #ifdef VUE2
|
||||
this.$emit('input', value);
|
||||
// #endif
|
||||
// TODO 兼容 vue3
|
||||
// #ifdef VUE3
|
||||
this.$emit('update:modelValue', value)
|
||||
// #endif
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setFocus(state:boolean){
|
||||
this.focusCaptchaInput = state
|
||||
},
|
||||
getImageCaptcha(focus : boolean) {
|
||||
this.loging = true
|
||||
if (focus) {
|
||||
this.val = ''
|
||||
this.focusCaptchaInput = true
|
||||
}
|
||||
const uniIdCo = uniCloud.importObject("uni-captcha-co", {
|
||||
customUI: true
|
||||
})
|
||||
uniIdCo.getImageCaptcha({
|
||||
scene: this.scene,
|
||||
isUniAppX:true
|
||||
}).then((result : UTSJSONObject) => {
|
||||
this.captchaBase64 = (result.getString('captchaBase64') as string)
|
||||
})
|
||||
.catch<void>((err : any | null) : void => {
|
||||
const error = err as UniCloudError
|
||||
console.error(error)
|
||||
console.error(error.code)
|
||||
uni.showToast({
|
||||
title: error.message,
|
||||
icon: 'none'
|
||||
});
|
||||
})
|
||||
.finally(()=> {
|
||||
this.loging = false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.captcha-box {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.captcha-img-box,
|
||||
.captcha {
|
||||
height: 44px;
|
||||
}
|
||||
|
||||
.captcha {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.captcha-img-box {
|
||||
position: relative;
|
||||
background-color: #FEFAE7;
|
||||
}
|
||||
|
||||
.captcha {
|
||||
background-color: #F8F8F8;
|
||||
font-size: 14px;
|
||||
flex: 1;
|
||||
padding: 0 20rpx;
|
||||
margin-left: 20rpx;
|
||||
/* #ifndef APP-NVUE */
|
||||
box-sizing: border-box;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.captcha-img-box,
|
||||
.captcha-img,
|
||||
.loding {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.captcha-img {
|
||||
/* #ifdef WEB */
|
||||
cursor: pointer;
|
||||
/* #endif */
|
||||
height: 44px;
|
||||
}
|
||||
|
||||
.loding {
|
||||
z-index: 9;
|
||||
position: absolute;
|
||||
width: 30px;
|
||||
margin:7px 35px;
|
||||
}
|
||||
|
||||
.opacity {
|
||||
opacity: 0.5;
|
||||
}
|
||||
</style>
|
@ -1,167 +0,0 @@
|
||||
<template>
|
||||
<view class="captcha-box">
|
||||
<view class="captcha-img-box">
|
||||
<uni-icons class="loding" size="20px" color="#BBB" v-if="loging" type="spinner-cycle"></uni-icons>
|
||||
<image class="captcha-img" :class="{opacity:loging}" @click="getImageCaptcha" :src="captchaBase64"
|
||||
mode="widthFix"></image>
|
||||
</view>
|
||||
<input @blur="focusCaptchaInput = false" :focus="focusCaptchaInput" type="text" class="captcha"
|
||||
:inputBorder="false" maxlength="4" v-model="val" placeholder="请输入验证码">
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
modelValue:String,
|
||||
value:String,
|
||||
scene: {
|
||||
type: String,
|
||||
default () {
|
||||
return ""
|
||||
}
|
||||
},
|
||||
focus: {
|
||||
type: Boolean,
|
||||
default () {
|
||||
return false
|
||||
}
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
val:{
|
||||
get(){
|
||||
return this.value||this.modelValue
|
||||
},
|
||||
set(value){
|
||||
// console.log(value);
|
||||
// TODO 兼容 vue2
|
||||
// #ifdef VUE2
|
||||
this.$emit('input', value);
|
||||
// #endif
|
||||
|
||||
// TODO 兼容 vue3
|
||||
// #ifdef VUE3
|
||||
this.$emit('update:modelValue', value)
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
focusCaptchaInput: false,
|
||||
captchaBase64: "",
|
||||
loging: false
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
scene: {
|
||||
handler(scene) {
|
||||
if (scene) {
|
||||
this.getImageCaptcha(this.focus)
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: 'scene不能为空',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
},
|
||||
immediate:true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getImageCaptcha(focus = true) {
|
||||
this.loging = true
|
||||
if (focus) {
|
||||
this.val = ''
|
||||
this.focusCaptchaInput = true
|
||||
}
|
||||
const uniIdCo = uniCloud.importObject("uni-captcha-co", {
|
||||
customUI: true
|
||||
})
|
||||
uniIdCo.getImageCaptcha({
|
||||
scene: this.scene
|
||||
}).then(result => {
|
||||
// console.log(result);
|
||||
this.captchaBase64 = result.captchaBase64
|
||||
})
|
||||
.catch(e => {
|
||||
uni.showToast({
|
||||
title: e.message,
|
||||
icon: 'none'
|
||||
});
|
||||
}).finally(e => {
|
||||
this.loging = false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.captcha-box {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.captcha-img-box,
|
||||
.captcha {
|
||||
height: 44px;
|
||||
line-height: 44px;
|
||||
}
|
||||
|
||||
.captcha-img-box {
|
||||
position: relative;
|
||||
background-color: #FEFAE7;
|
||||
}
|
||||
|
||||
.captcha {
|
||||
background-color: #F8F8F8;
|
||||
font-size: 14px;
|
||||
flex: 1;
|
||||
padding: 0 20rpx;
|
||||
margin-left: 20rpx;
|
||||
/* #ifndef APP-NVUE */
|
||||
box-sizing: border-box;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.captcha-img-box,
|
||||
.captcha-img,
|
||||
.loding {
|
||||
height: 44px !important;
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.captcha-img{
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.loding {
|
||||
z-index: 9;
|
||||
color: #bbb;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
line-height: 45px;
|
||||
animation: rotate 1s linear infinite;
|
||||
}
|
||||
|
||||
.opacity {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
@keyframes rotate {
|
||||
from {
|
||||
transform: rotate(0deg)
|
||||
}
|
||||
|
||||
to {
|
||||
transform: rotate(360deg)
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,130 +0,0 @@
|
||||
<template>
|
||||
<uni-popup ref="popup" @clickMask="cancel">
|
||||
<view class="popup-captcha">
|
||||
<view class="content">
|
||||
<text class="title">{{title}}</text>
|
||||
<uni-captcha ref="captcha" :focus="focus" :scene="scene" v-model="val" :cursorSpacing="150"></uni-captcha>
|
||||
</view>
|
||||
<view class="button-box">
|
||||
<text @click="cancel" class="btn cancel">取消</text>
|
||||
<text @click="confirm" class="btn confirm">确认</text>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
let confirmCallBack = ():void=>console.log('未传入回调函数')
|
||||
export default {
|
||||
emits:["modelValue","confirm","cancel"],
|
||||
data() {
|
||||
return {
|
||||
focus: false,
|
||||
val:""
|
||||
}
|
||||
},
|
||||
props: {
|
||||
modelValue: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
value: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
scene: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: "默认标题"
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
val(val:string) {
|
||||
// console.log(val);
|
||||
// TODO 兼容 vue2
|
||||
// #ifdef VUE2
|
||||
this.$emit('input', val);
|
||||
// #endif
|
||||
|
||||
// TODO 兼容 vue3
|
||||
// #ifdef VUE3
|
||||
this.$emit('update:modelValue', val)
|
||||
// #endif
|
||||
|
||||
if(val.length == 4){
|
||||
this.confirm()
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {},
|
||||
methods: {
|
||||
open(callback: () => void) {
|
||||
// console.log('callback',callback);
|
||||
confirmCallBack = callback;
|
||||
this.focus = true
|
||||
this.val = "";
|
||||
(this.$refs['popup'] as ComponentPublicInstance).$callMethod("open");
|
||||
this.$nextTick(()=>{
|
||||
(this.$refs['captcha'] as ComponentPublicInstance).$callMethod("getImageCaptcha",true);
|
||||
})
|
||||
},
|
||||
close() {
|
||||
this.focus = false;
|
||||
(this.$refs['popup'] as ComponentPublicInstance).$callMethod("close");
|
||||
},
|
||||
cancel(){
|
||||
this.close()
|
||||
this.$emit("cancel")
|
||||
},
|
||||
confirm() {
|
||||
if (this.val.length != 4) {
|
||||
return uni.showToast({
|
||||
title: '请填写验证码',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
this.close()
|
||||
this.$emit('confirm')
|
||||
confirmCallBack()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.popup-captcha {
|
||||
background-color: #fff;
|
||||
flex-direction: column;
|
||||
width: 600rpx;
|
||||
padding:10px 15px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.popup-captcha .title {
|
||||
text-align: center;
|
||||
font-weight: 700;
|
||||
margin: 5px 0;
|
||||
}
|
||||
.popup-captcha .button-box {
|
||||
flex-direction: row;
|
||||
justify-content: space-around;
|
||||
margin-top: 5px;
|
||||
}
|
||||
.popup-captcha .button-box .btn {
|
||||
flex: 1;
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
text-align: center;
|
||||
}
|
||||
.popup-captcha .button-box .cancel {
|
||||
border: 1px solid #eee;
|
||||
color: #666;
|
||||
}
|
||||
.confirm {
|
||||
background-color: #0070ff;
|
||||
color: #fff;
|
||||
margin-left: 5px;
|
||||
}
|
||||
</style>
|
@ -1,140 +0,0 @@
|
||||
<template>
|
||||
<uni-popup ref="popup" type="center">
|
||||
<view class="popup-captcha">
|
||||
<view class="content">
|
||||
<text class="title">{{title}}</text>
|
||||
<uni-captcha :focus="focus" :scene="scene" v-model="val"></uni-captcha>
|
||||
</view>
|
||||
<view class="button-box">
|
||||
<view @click="close" class="btn">取消</view>
|
||||
<view @click="confirm" class="btn confirm">确认</view>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
focus: false
|
||||
}
|
||||
},
|
||||
props: {
|
||||
modelValue:String,
|
||||
value:String,
|
||||
scene: {
|
||||
type: String,
|
||||
default () {
|
||||
return ""
|
||||
}
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default () {
|
||||
return ""
|
||||
}
|
||||
},
|
||||
},
|
||||
computed:{
|
||||
val:{
|
||||
get(){
|
||||
return this.value||this.modelValue
|
||||
},
|
||||
set(value){
|
||||
// console.log(value);
|
||||
// TODO 兼容 vue2
|
||||
// #ifdef VUE2
|
||||
this.$emit('input', value);
|
||||
// #endif
|
||||
|
||||
// TODO 兼容 vue3
|
||||
// #ifdef VUE3
|
||||
this.$emit('update:modelValue', value)
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
open() {
|
||||
this.focus = true
|
||||
this.val = ""
|
||||
this.$refs.popup.open()
|
||||
},
|
||||
close() {
|
||||
this.focus = false
|
||||
this.$refs.popup.close()
|
||||
},
|
||||
confirm() {
|
||||
if(!this.val){
|
||||
return uni.showToast({
|
||||
title: '请填写验证码',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
this.close()
|
||||
this.$emit('confirm')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* #ifndef APP-NVUE */
|
||||
view {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
.popup-captcha {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
max-width: 600px;
|
||||
/* #endif */
|
||||
width: 600rpx;
|
||||
padding-bottom: 0;
|
||||
background-color: #FFF;
|
||||
border-radius: 10px;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.popup-captcha .content {
|
||||
padding: 1.3em 0.8em;
|
||||
}
|
||||
|
||||
.popup-captcha .title {
|
||||
text-align: center;
|
||||
word-wrap: break-word;
|
||||
word-break: break-all;
|
||||
white-space: pre-wrap;
|
||||
font-weight: 400;
|
||||
font-size: 18px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
color: #111;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.button-box {
|
||||
height: 44px;
|
||||
border-top: solid 1px #eee;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
}
|
||||
.button-box ,.btn{
|
||||
height: 44px;
|
||||
line-height: 44px;
|
||||
}
|
||||
.button-box .btn{
|
||||
flex: 1;
|
||||
margin: 1px;
|
||||
text-align: center;
|
||||
}
|
||||
.button-box .confirm{
|
||||
color: #007aff;
|
||||
border-left: solid 1px #eee;
|
||||
}
|
||||
</style>
|
@ -1,83 +0,0 @@
|
||||
{
|
||||
"id": "uni-captcha",
|
||||
"displayName": "uni-captcha",
|
||||
"version": "0.7.5",
|
||||
"description": "云端一体图形验证码组件",
|
||||
"keywords": [
|
||||
"captcha",
|
||||
"图形验证码",
|
||||
"人机验证",
|
||||
"防刷",
|
||||
"防脚本"
|
||||
],
|
||||
"repository": "https://gitee.com/dcloud/uni-captcha",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.1.0"
|
||||
},
|
||||
"dcloudext": {
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "无",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": "",
|
||||
"type": "unicloud-template-function"
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [
|
||||
"uni-popup"
|
||||
],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"App": {
|
||||
"app-vue": "u",
|
||||
"app-nvue": "u"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "u",
|
||||
"Android Browser": "u",
|
||||
"微信浏览器(Android)": "u",
|
||||
"QQ浏览器(Android)": "u"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "u",
|
||||
"IE": "u",
|
||||
"Edge": "u",
|
||||
"Firefox": "u",
|
||||
"Safari": "u"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "u",
|
||||
"阿里": "u",
|
||||
"百度": "u",
|
||||
"字节跳动": "u",
|
||||
"QQ": "u"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
},
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "u"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
<h2>
|
||||
文档已移至 <a href="https://uniapp.dcloud.io/uniCloud/uni-captcha.html" target="_blank">uni-captcha文档</a>
|
||||
</h2>
|
Binary file not shown.
Before Width: | Height: | Size: 30 KiB |
@ -1,201 +0,0 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
Binary file not shown.
File diff suppressed because one or more lines are too long
@ -1,16 +0,0 @@
|
||||
{
|
||||
"name": "uni-captcha",
|
||||
"version": "0.7.0",
|
||||
"description": "uni-captcha",
|
||||
"main": "index.js",
|
||||
"homepage": "https://ext.dcloud.net.cn/plugin?id=4048",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://gitee.com/dcloud/uni-captcha"
|
||||
},
|
||||
"author": "DCloud",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"uni-config-center": "file:../../../../../uni-config-center/uniCloud/cloudfunctions/common/uni-config-center"
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
module.exports = {
|
||||
"image-captcha":{
|
||||
"width": 150, //图片宽度
|
||||
"height": 44, //图片高度
|
||||
"background": "#FFFAE8", //验证码背景色,设置空字符`''`不使用背景颜色
|
||||
// "size": 4, //验证码长度,最多 6 个字符
|
||||
// "noise": 4, //验证码干扰线条数
|
||||
// "color": false, //字体是否使用随机颜色,当设置`background`后恒为`true`
|
||||
// "fontSize": 40, //字体大小
|
||||
// "ignoreChars": '', //忽略那些字符
|
||||
// "mathExpr": false, //是否使用数学表达式
|
||||
// "mathMin": 1, //表达式所使用的最小数字
|
||||
// "mathMax": 9, //表达式所使用的最大数字
|
||||
// "mathOperator": '' //表达式所使用的运算符,支持 `+`、`-`。不传随机使用
|
||||
// "expiresDate":180 //验证码过期时间(s)
|
||||
}
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
// 开发文档: https://uniapp.dcloud.net.cn/uniCloud/cloud-obj
|
||||
//导入验证码公共模块
|
||||
const uniCaptcha = require('uni-captcha')
|
||||
//获取数据库对象
|
||||
const db = uniCloud.database();
|
||||
//获取数据表opendb-verify-codes对象
|
||||
const verifyCodes = db.collection('opendb-verify-codes')
|
||||
module.exports = {
|
||||
async getImageCaptcha({
|
||||
scene,isUniAppX
|
||||
}) {
|
||||
//获取设备id
|
||||
let {
|
||||
deviceId,
|
||||
platform
|
||||
} = this.getClientInfo();
|
||||
//根据:设备id、场景值、状态,查找记录是否存在
|
||||
let res = await verifyCodes.where({
|
||||
scene,
|
||||
deviceId,
|
||||
state: 0
|
||||
}).limit(1).get()
|
||||
//如果已存在则调用刷新接口,反之调用插件接口
|
||||
let action = res.data.length ? 'refresh' : 'create'
|
||||
//执行并返回结果
|
||||
let option = {
|
||||
scene, //来源客户端传递,表示:使用场景值,用于防止不同功能的验证码混用
|
||||
uniPlatform: platform
|
||||
}
|
||||
if(isUniAppX){
|
||||
option.mode = "bmp"
|
||||
}
|
||||
return await uniCaptcha[action](option)
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
{
|
||||
"name": "uni-captcha-co",
|
||||
"dependencies": {
|
||||
"uni-captcha": "file:../common/uni-captcha",
|
||||
"uni-config-center": "file:../../../../uni-config-center/uniCloud/cloudfunctions/common/uni-config-center"
|
||||
},
|
||||
"extensions": {
|
||||
"uni-cloud-jql": {}
|
||||
}
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
{
|
||||
"bsonType": "object",
|
||||
"properties": {
|
||||
"_id": {
|
||||
"description": "ID,系统自动生成"
|
||||
},
|
||||
"code": {
|
||||
"bsonType": "string",
|
||||
"description": "验证码"
|
||||
},
|
||||
"create_date": {
|
||||
"bsonType": "timestamp",
|
||||
"description": "创建时间"
|
||||
},
|
||||
"device_uuid": {
|
||||
"bsonType": "string",
|
||||
"description": "设备UUID,常用于图片验证码"
|
||||
},
|
||||
"email": {
|
||||
"bsonType": "string",
|
||||
"description": "邮箱"
|
||||
},
|
||||
"expired_date": {
|
||||
"bsonType": "timestamp",
|
||||
"description": "过期时间"
|
||||
},
|
||||
"ip": {
|
||||
"bsonType": "string",
|
||||
"description": "请求时客户端IP地址"
|
||||
},
|
||||
"mobile": {
|
||||
"bsonType": "string",
|
||||
"description": "手机号码"
|
||||
},
|
||||
"scene": {
|
||||
"bsonType": "string",
|
||||
"description": "使用验证码的场景,如:login, bind, unbind, pay"
|
||||
},
|
||||
"state": {
|
||||
"bsonType": "int",
|
||||
"description": "验证状态:0 未验证、1 已验证、2 已作废"
|
||||
}
|
||||
},
|
||||
"required": []
|
||||
}
|
@ -1,2 +0,0 @@
|
||||
## 1.0.1(2023-03-02)
|
||||
- 修复 方法名错误
|
@ -1,83 +0,0 @@
|
||||
{
|
||||
"id": "uni-cloud-s2s",
|
||||
"displayName": "服务空间与服务器安全通讯模块",
|
||||
"version": "1.0.1",
|
||||
"description": "用于解决服务空间与服务器通讯时互相信任问题",
|
||||
"keywords": [
|
||||
"安全通讯",
|
||||
"服务器请求云函数",
|
||||
"云函数请求服务器"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.1.0"
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "unicloud-template-function",
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "无",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": ""
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
"vue2": "u",
|
||||
"vue3": "u"
|
||||
},
|
||||
"App": {
|
||||
"app-vue": "u",
|
||||
"app-nvue": "u"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "u",
|
||||
"Android Browser": "u",
|
||||
"微信浏览器(Android)": "u",
|
||||
"QQ浏览器(Android)": "u"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "u",
|
||||
"IE": "u",
|
||||
"Edge": "u",
|
||||
"Firefox": "u",
|
||||
"Safari": "u"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "u",
|
||||
"阿里": "u",
|
||||
"百度": "u",
|
||||
"字节跳动": "u",
|
||||
"QQ": "u",
|
||||
"钉钉": "u",
|
||||
"快手": "u",
|
||||
"飞书": "u",
|
||||
"京东": "u"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
# uni-cloud-s2s
|
||||
|
||||
文档见:[外部服务器如何与uniCloud安全通讯](https://uniapp.dcloud.net.cn/uniCloud/uni-cloud-s2s.html)
|
File diff suppressed because one or more lines are too long
@ -1,11 +0,0 @@
|
||||
{
|
||||
"name": "uni-cloud-s2s",
|
||||
"version": "1.0.1",
|
||||
"description": "",
|
||||
"keywords": [],
|
||||
"author": "DCloud",
|
||||
"main": "index.js",
|
||||
"dependencies": {
|
||||
"uni-config-center": "file:../../../../../uni-config-center/uniCloud/cloudfunctions/common/uni-config-center"
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
## 1.0.16(2024-06-21)
|
||||
- 修复 小程序发布时无法上传的Bug
|
||||
## 1.0.15(2024-06-20)
|
||||
- 修复 小程序访问文章列表报错的Bug
|
||||
## 1.0.14(2024-06-12)
|
||||
- 修复 客户端无法显示文章详情问题的Bug
|
||||
## 1.0.13(2023-12-09)
|
||||
- 新增 支持uni-app-x,需要[uni-cms](https://ext.dcloud.net.cn/plugin?id=11700)插件版本>=1.0.17
|
||||
## 1.0.12(2023-10-17)
|
||||
- 修复 使用腾讯云服务空间时无法加载封面图及正文图片的问题
|
||||
## 1.0.11(2023-08-07)
|
||||
- 修复 Vue3下因`parse-scen-result.js`文件导出问题导致无法打包编译的bug
|
||||
## 1.0.10(2023-07-14)
|
||||
- 新增 文章预览功能,详见[文档](https://uniapp.dcloud.net.cn/uniCloud/uni-cms.html#article-preview)(需要uni-cms版本>=1.0.14)
|
||||
- 修复 文章详情页换行重复问题
|
||||
- 修复 文章列表在数据量小时下拉刷新数据会重复的问题
|
||||
## 1.0.9(2023-07-10)
|
||||
- 优化 文章详情页正文可以渲染多个换行
|
||||
## 1.0.8(2023-06-21)
|
||||
- 增加 文章列表无图、三图封面样式(需要uni-cms版本>=1.0.12)
|
||||
- 优化 文章详情页样式
|
||||
- 修复 在Vue3下出现 require is not defined 问题
|
||||
## 1.0.7(2023-06-07)
|
||||
- 新增 文章详情页面支持播放视频(发布视频需要uni-cms版本>=1.0.11)
|
||||
- 优化 文章正文渲染逻辑
|
||||
- 优化 文章详情页面样式
|
||||
- 修复 在文章详情页下点击返回按钮无响应问题
|
||||
## 1.0.6(2023-04-28)
|
||||
- 修复 文章详情只存在列表时无法渲染的问题
|
||||
## 1.0.5(2023-04-24)
|
||||
- 增加 license 文件
|
||||
## 1.0.4(2023-04-21)
|
||||
- 优化代码结构,增加代码注释,提高可读性
|
||||
## 1.0.3(2023-04-17)
|
||||
- 移除无用schema文件
|
||||
## 1.0.2(2023-04-12)
|
||||
- 优化看广告解锁文章交互
|
||||
## 1.0.1(2023-04-12)
|
||||
- 优化页面逻辑
|
||||
## 1.0.0(2023-04-11)
|
||||
- 插件发布,支持图文内容展示、广告解锁全文功能 [详见文档](https://uniapp.dcloud.net.cn/uniCloud/uni-cms.html)
|
@ -1,68 +0,0 @@
|
||||
function parseEditorImage (blocks = []) {
|
||||
const images = []
|
||||
|
||||
if (!Array.isArray(blocks)) {
|
||||
blocks = [blocks]
|
||||
}
|
||||
|
||||
for (const block of blocks) {
|
||||
const {insert = {}, attributes = {}} = block
|
||||
const {'data-custom': custom = ""} = attributes
|
||||
|
||||
let parseCustom = custom.split('&').reduce((obj, item) => {
|
||||
const [key, value] = item.split('=')
|
||||
|
||||
if (key && value) {
|
||||
obj[key] = value
|
||||
}
|
||||
return obj
|
||||
}, {})
|
||||
|
||||
images.push({
|
||||
src: insert.image,
|
||||
source: parseCustom.source ? parseCustom.source: insert.image
|
||||
})
|
||||
}
|
||||
|
||||
return images
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析媒体库/编辑器中的图片
|
||||
* @param images 图片地址
|
||||
* @param type {string} 解析类型 media: 媒体库, editor: 编辑器
|
||||
* @returns {Promise<{src: *, source: *}[]|{src, source: *}[]>}
|
||||
*/
|
||||
export async function parseImageUrl (images = [], type = "media") {
|
||||
if (type === "editor") {
|
||||
images = parseEditorImage(images).map(item => item.source)
|
||||
} else {
|
||||
if (!Array.isArray(images)) {
|
||||
images = [images]
|
||||
}
|
||||
}
|
||||
|
||||
if (!images) return null
|
||||
|
||||
const tcbFiles = images.filter(item => item.startsWith("cloud://"))
|
||||
|
||||
if (tcbFiles.length) {
|
||||
const res = await uniCloud.getTempFileURL({
|
||||
fileList: tcbFiles
|
||||
})
|
||||
|
||||
return images.map(image => {
|
||||
const file = res.fileList.find(item => item.fileID === image)
|
||||
|
||||
return {
|
||||
src: file ? file.tempFileURL : image,
|
||||
source: image
|
||||
}
|
||||
})
|
||||
} else {
|
||||
return images.map(image => ({
|
||||
src: image,
|
||||
source: image
|
||||
}))
|
||||
}
|
||||
}
|
@ -1,80 +0,0 @@
|
||||
export type ParseImageUrlResult = {
|
||||
src: string
|
||||
source: string
|
||||
}
|
||||
function parseEditorImage (_blocks: any): UTSJSONObject[] {
|
||||
const images: UTSJSONObject[] = []
|
||||
let blocks: UTSJSONObject[]
|
||||
|
||||
if (!Array.isArray(_blocks)) {
|
||||
blocks = [_blocks as UTSJSONObject] as UTSJSONObject[]
|
||||
} else {
|
||||
blocks = _blocks as UTSJSONObject[]
|
||||
}
|
||||
|
||||
blocks.forEach((block: UTSJSONObject) => {
|
||||
const insert = block.getJSON('insert')
|
||||
const attributes = block.getJSON('attributes')
|
||||
const custom = attributes!.getString('data-custom')
|
||||
|
||||
let parseCustom = custom && custom.split('&') ? custom.split('&').reduce((obj: UTSJSONObject, item: string): UTSJSONObject => {
|
||||
const kv = item.split('=')
|
||||
|
||||
if (kv.length > 1) {
|
||||
obj[kv[0]] = kv[1]
|
||||
}
|
||||
|
||||
return obj
|
||||
}, {} as UTSJSONObject) : {}
|
||||
|
||||
images.push({
|
||||
src: insert!.getString('image'),
|
||||
source: parseCustom.getString('source') != null ? parseCustom.getString('source') : insert!.getString('image')
|
||||
})
|
||||
})
|
||||
|
||||
return images
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析媒体库/编辑器中的图片
|
||||
* @param images 图片地址
|
||||
* @param type {string} 解析类型 media: 媒体库, editor: 编辑器
|
||||
* @returns {Promise<{src: *, source: *}[]|{src, source: *}[]>}
|
||||
*/
|
||||
export async function parseImageUrl (images: any, type: string = "media"): Promise<ParseImageUrlResult[] | null> {
|
||||
let imagePaths: string[] = []
|
||||
if (type === "editor") {
|
||||
imagePaths = parseEditorImage(images).map((item: UTSJSONObject): string => item.getString('source')!)
|
||||
} else {
|
||||
if (!Array.isArray(images)) {
|
||||
imagePaths = [images as string] as string[]
|
||||
} else {
|
||||
imagePaths = images
|
||||
}
|
||||
}
|
||||
|
||||
if (imagePaths.length <= 0) return null
|
||||
|
||||
const tcbFiles = imagePaths.filter((item: string): boolean => item.startsWith("cloud://"))
|
||||
|
||||
if (tcbFiles.length > 0) {
|
||||
const res: UniCloudGetTempFileURLResult = await uniCloud.getTempFileURL({
|
||||
fileList: tcbFiles
|
||||
})
|
||||
|
||||
return imagePaths.map((image: string): ParseImageUrlResult => {
|
||||
const file = res.fileList.find((item: UniCloudGetTempFileURLResultItem): boolean => item.fileID === image)
|
||||
|
||||
return {
|
||||
src: file ? file.tempFileURL : image,
|
||||
source: image
|
||||
} as ParseImageUrlResult
|
||||
})
|
||||
} else {
|
||||
return imagePaths.map((image: string): ParseImageUrlResult => ({
|
||||
src: image,
|
||||
source: image
|
||||
} as ParseImageUrlResult))
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
function parseScanResult (scanText) {
|
||||
const match = scanText.match(/^(.*?):\/\/(.*)/)
|
||||
|
||||
if (!match || match.length < 1) {
|
||||
uni.showToast({
|
||||
icon: 'none',
|
||||
title: '未能识别到有效信息'
|
||||
})
|
||||
}
|
||||
|
||||
const [, protocol, path] = match
|
||||
|
||||
switch (protocol) {
|
||||
case "internallink":
|
||||
uni.navigateTo({
|
||||
url: `/${path.replace(/^\//, '')}`,
|
||||
fail: () => {
|
||||
uni.showToast({
|
||||
icon: "none",
|
||||
title: "访问的路径不存在"
|
||||
})
|
||||
}
|
||||
})
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
export default parseScanResult
|
@ -1,28 +0,0 @@
|
||||
function parseScanResult (scanText: string): void {
|
||||
const match = scanText.match(/^(.*?):\/\/(.*)/)
|
||||
|
||||
if (!match || match.length < 1) {
|
||||
uni.showToast({
|
||||
icon: 'none',
|
||||
title: '未能识别到有效信息'
|
||||
})
|
||||
}
|
||||
|
||||
const [, protocol, path] = match
|
||||
|
||||
switch (protocol) {
|
||||
case "internallink":
|
||||
uni.navigateTo({
|
||||
url: `/${path.replace(/^\//, '')}`,
|
||||
fail: () => {
|
||||
uni.showToast({
|
||||
icon: "none",
|
||||
title: "访问的路径不存在"
|
||||
})
|
||||
}
|
||||
})
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
export default parseScanResult
|
@ -1,93 +0,0 @@
|
||||
export default function translatePublishTime(timestamp) {
|
||||
let result = ''
|
||||
// 获取当前时间
|
||||
const currentData = new Date()
|
||||
// 获取发布时间
|
||||
const date = new Date(timestamp)
|
||||
// 获取发布年份
|
||||
const year = date.getFullYear()
|
||||
// 获取发布月份
|
||||
const mouth = date.getMonth() + 1
|
||||
// 获取发布日期
|
||||
const day = date.getDate()
|
||||
// 获取发布小时
|
||||
const hours = date.getHours()
|
||||
// 获取发布分钟
|
||||
const minute = date.getMinutes()
|
||||
// 获取发布秒数
|
||||
const second = date.getSeconds()
|
||||
// 获取发布时间戳
|
||||
const timer = date.getTime()
|
||||
// 获取当前年份
|
||||
const currentYear = currentData.getFullYear()
|
||||
// 获取当前月份
|
||||
const currentMonth = currentData.getMonth() + 1
|
||||
// 获取当前日期
|
||||
const currentDay = currentData.getDate()
|
||||
// 获取当前小时
|
||||
const currentHours = currentData.getHours()
|
||||
// 获取当前分钟
|
||||
let currentMinute = currentData.getMinutes()
|
||||
// 获取当前秒数
|
||||
const currentSecond = currentData.getSeconds()
|
||||
// 获取当前时间戳
|
||||
const currentTimer = currentData.getTime()
|
||||
|
||||
// 如果时间差小于10秒
|
||||
if ((currentTimer - timer) < 1000 * 10) {
|
||||
// 显示刚刚
|
||||
result = `刚刚`;
|
||||
// 如果时间差小于60秒
|
||||
} else if ((currentTimer - timer) < 1000 * 60) {
|
||||
// 如果当前分钟大于发布分钟
|
||||
if (currentMinute > minute) {
|
||||
// 显示秒数差
|
||||
result = `${(((currentMinute - minute) * 60) + currentSecond - second)}秒前`;
|
||||
} else {
|
||||
// 显示秒数差
|
||||
result = `${(currentSecond - second)}秒前`;
|
||||
}
|
||||
// 如果时间差小于1小时
|
||||
} else if ((currentTimer - timer) < 1000 * (60 * 60)) {
|
||||
// 如果当前小时大于发布小时
|
||||
if (currentHours > hours) {
|
||||
// 显示分钟差
|
||||
result = `${(((currentHours - hours) * 60) + currentMinute - minute)}分钟前`;
|
||||
} else {
|
||||
// 修改 昨天发布的文章时间会出现负数
|
||||
// 如果当前分钟小于发布分钟
|
||||
if (currentMinute < minute) {
|
||||
// 当前分钟加60
|
||||
currentMinute += 60
|
||||
}
|
||||
// 显示分钟差
|
||||
result = `${(currentMinute - minute)}分钟前`;
|
||||
}
|
||||
// 如果时间差小于1天
|
||||
} else if ((currentTimer - timer) < 1000 * (24 * 60 * 60)) {
|
||||
// 如果当前日期大于发布日期
|
||||
if (currentDay > day) {
|
||||
// 显示小时差
|
||||
result = `${((currentDay - day) * 24 + currentHours - hours)}小时前`;
|
||||
} else {
|
||||
// 修改 跨月-昨天发布的文章时间会出现负数
|
||||
// 如果当前月份不等于发布月份
|
||||
if (currentMonth !== mouth) {
|
||||
// 显示小时差
|
||||
result = `${(24 + currentHours - hours)}小时前`;
|
||||
} else {
|
||||
// 显示小时差
|
||||
result = `${(currentHours - hours)}小时前`;
|
||||
}
|
||||
}
|
||||
// 如果发布年份等于当前年份
|
||||
} else if (currentYear === year) {
|
||||
// 显示月份和日期
|
||||
result = `${mouth}月${day}日`;
|
||||
} else {
|
||||
// 显示年份、月份和日期
|
||||
result = `${year}年${mouth}月${day}日`;
|
||||
}
|
||||
return result // 返回结果
|
||||
}
|
||||
|
@ -1,93 +0,0 @@
|
||||
export default function translatePublishTime(timestamp: number): string {
|
||||
let result: string
|
||||
// 获取当前时间
|
||||
const currentData = new Date()
|
||||
// 获取发布时间
|
||||
const date = new Date(timestamp)
|
||||
// 获取发布年份
|
||||
const year = date.getFullYear()
|
||||
// 获取发布月份
|
||||
const mouth = date.getMonth() + 1
|
||||
// 获取发布日期
|
||||
const day = date.getDate()
|
||||
// 获取发布小时
|
||||
const hours = date.getHours()
|
||||
// 获取发布分钟
|
||||
const minute = date.getMinutes()
|
||||
// 获取发布秒数
|
||||
const second = date.getSeconds()
|
||||
// 获取发布时间戳
|
||||
const timer = date.getTime()
|
||||
// 获取当前年份
|
||||
const currentYear = currentData.getFullYear()
|
||||
// 获取当前月份
|
||||
const currentMonth = currentData.getMonth() + 1
|
||||
// 获取当前日期
|
||||
const currentDay = currentData.getDate()
|
||||
// 获取当前小时
|
||||
const currentHours = currentData.getHours()
|
||||
// 获取当前分钟
|
||||
let currentMinute = currentData.getMinutes()
|
||||
// 获取当前秒数
|
||||
const currentSecond = currentData.getSeconds()
|
||||
// 获取当前时间戳
|
||||
const currentTimer = currentData.getTime()
|
||||
|
||||
// 如果时间差小于10秒
|
||||
if ((currentTimer - timer) < 1000 * 10) {
|
||||
// 显示刚刚
|
||||
result = `刚刚`;
|
||||
// 如果时间差小于60秒
|
||||
} else if ((currentTimer - timer) < 1000 * 60) {
|
||||
// 如果当前分钟大于发布分钟
|
||||
if (currentMinute > minute) {
|
||||
// 显示秒数差
|
||||
result = `${(((currentMinute - minute) * 60) + currentSecond - second)}秒前`;
|
||||
} else {
|
||||
// 显示秒数差
|
||||
result = `${(currentSecond - second)}秒前`;
|
||||
}
|
||||
// 如果时间差小于1小时
|
||||
} else if ((currentTimer - timer) < 1000 * (60 * 60)) {
|
||||
// 如果当前小时大于发布小时
|
||||
if (currentHours > hours) {
|
||||
// 显示分钟差
|
||||
result = `${(((currentHours - hours) * 60) + currentMinute - minute)}分钟前`;
|
||||
} else {
|
||||
// 修改 昨天发布的文章时间会出现负数
|
||||
// 如果当前分钟小于发布分钟
|
||||
if (currentMinute < minute) {
|
||||
// 当前分钟加60
|
||||
currentMinute += 60
|
||||
}
|
||||
// 显示分钟差
|
||||
result = `${(currentMinute - minute)}分钟前`;
|
||||
}
|
||||
// 如果时间差小于1天
|
||||
} else if ((currentTimer - timer) < 1000 * (24 * 60 * 60)) {
|
||||
// 如果当前日期大于发布日期
|
||||
if (currentDay > day) {
|
||||
// 显示小时差
|
||||
result = `${((currentDay - day) * 24 + currentHours - hours)}小时前`;
|
||||
} else {
|
||||
// 修改 跨月-昨天发布的文章时间会出现负数
|
||||
// 如果当前月份不等于发布月份
|
||||
if (currentMonth !== mouth) {
|
||||
// 显示小时差
|
||||
result = `${(24 + currentHours - hours)}小时前`;
|
||||
} else {
|
||||
// 显示小时差
|
||||
result = `${(currentHours - hours)}小时前`;
|
||||
}
|
||||
}
|
||||
// 如果发布年份等于当前年份
|
||||
} else if (currentYear === year) {
|
||||
// 显示月份和日期
|
||||
result = `${mouth}月${day}日`;
|
||||
} else {
|
||||
// 显示年份、月份和日期
|
||||
result = `${year}年${mouth}月${day}日`;
|
||||
}
|
||||
return result // 返回结果
|
||||
}
|
||||
|
@ -1,55 +0,0 @@
|
||||
<template>
|
||||
<view
|
||||
:to="'/uni_modules/uni-cms-article/pages/detail/detail?id=' + data?._id"
|
||||
:key="data?._id"
|
||||
class="list-item not-cover"
|
||||
direction="column"
|
||||
>
|
||||
<view class="main">
|
||||
<view>
|
||||
<text class="title">{{ data?.title }}</text>
|
||||
</view>
|
||||
<view class="info">
|
||||
<text class="author">{{ data!.user_id!.length > 0 ? data!.user_id[0]!.nickname : '' }}</text>
|
||||
<text class="publish_date">{{ publishTime(data?.publish_date ?? 0) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="uts">
|
||||
import { type PropType } from 'vue'
|
||||
|
||||
import translatePublishTime from "@/uni_modules/uni-cms-article/common/publish-time.uts";
|
||||
|
||||
type ArticleAuthor = {
|
||||
_id: string
|
||||
nickname: string
|
||||
}
|
||||
type ArticleItem = {
|
||||
_id: string
|
||||
title: string
|
||||
publish_date: number
|
||||
thumbnail: string[]
|
||||
user_id: ArticleAuthor[]
|
||||
}
|
||||
|
||||
export default {
|
||||
name: "not-cover",
|
||||
props: {
|
||||
data: {
|
||||
type: Object as PropType<ArticleItem>
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 格式化时间戳
|
||||
publishTime(timestamp: number): string {
|
||||
return translatePublishTime(timestamp)
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "./style.scss";
|
||||
</style>
|
@ -1,46 +0,0 @@
|
||||
<template>
|
||||
<uni-list-item
|
||||
:to="'/uni_modules/uni-cms-article/pages/detail/detail?id=' + data._id"
|
||||
:key="data._id"
|
||||
class="list-item not-cover"
|
||||
direction="column"
|
||||
>
|
||||
<template v-slot:body>
|
||||
<view class="main">
|
||||
<view>
|
||||
<text class="title">{{ data.title }}</text>
|
||||
</view>
|
||||
<view class="info">
|
||||
<text class="author">{{ data.user_id[0] ? data.user_id[0].nickname : '' }}</text>
|
||||
<text class="publish_date">{{ publishTime(data.publish_date) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</uni-list-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import translatePublishTime from "@/uni_modules/uni-cms-article/common/publish-time";
|
||||
|
||||
export default {
|
||||
name: "not-cover",
|
||||
props: {
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 格式化时间戳
|
||||
publishTime(timestamp) {
|
||||
return translatePublishTime(timestamp)
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "./style.scss";
|
||||
</style>
|
@ -1,50 +0,0 @@
|
||||
<template>
|
||||
<view
|
||||
:to="'/uni_modules/uni-cms-article/pages/detail/detail?id=' + data?._id"
|
||||
:key="data?._id"
|
||||
class="list-item"
|
||||
>
|
||||
<view class="main">
|
||||
<text class="title">{{ data?.title }}</text>
|
||||
<view class="info">
|
||||
<text class="author">{{ data!.user_id!.length > 0 ? data!.user_id[0]!.nickname : '' }}</text>
|
||||
<text class="publish_date">{{ publishTime(data?.publish_date ?? 0) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<image class="thumbnail" :src="data!.thumbnail[0]" mode="aspectFill"></image>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="uts">
|
||||
import { type PropType } from 'vue'
|
||||
import translatePublishTime from "@/uni_modules/uni-cms-article/common/publish-time.uts";
|
||||
type ArticleAuthor = {
|
||||
_id: string
|
||||
nickname: string
|
||||
}
|
||||
type ArticleItem = {
|
||||
_id: string
|
||||
title: string
|
||||
publish_date: number
|
||||
thumbnail: string[]
|
||||
user_id: ArticleAuthor[]
|
||||
}
|
||||
export default {
|
||||
name: "right-small-cover",
|
||||
props: {
|
||||
data: {
|
||||
type: Object as PropType<ArticleItem>
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 格式化时间戳
|
||||
publishTime(timestamp: number): string {
|
||||
return translatePublishTime(timestamp)
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "./style.scss";
|
||||
</style>
|
@ -1,46 +0,0 @@
|
||||
<template>
|
||||
<uni-list-item
|
||||
:to="'/uni_modules/uni-cms-article/pages/detail/detail?id=' + data._id"
|
||||
:key="data._id"
|
||||
class="list-item"
|
||||
>
|
||||
<template v-slot:body>
|
||||
<view class="main">
|
||||
<text class="title">{{ data.title }}</text>
|
||||
<view class="info">
|
||||
<text class="author">{{ data.user_id[0] ? data.user_id[0].nickname : '' }}</text>
|
||||
<text class="publish_date">{{ publishTime(data.publish_date) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<template v-slot:footer>
|
||||
<image class="thumbnail" :src="data.thumbnail[0]" mode="aspectFill"></image>
|
||||
</template>
|
||||
</uni-list-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import translatePublishTime from "@/uni_modules/uni-cms-article/common/publish-time";
|
||||
|
||||
export default {
|
||||
name: "right-small-cover",
|
||||
props: {
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 格式化时间戳
|
||||
publishTime(timestamp) {
|
||||
return translatePublishTime(timestamp)
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "./style.scss";
|
||||
</style>
|
@ -1,63 +0,0 @@
|
||||
.list-item {
|
||||
&.not-cover {
|
||||
.main {
|
||||
.info {
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
.main {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
.title {
|
||||
font-size: 30rpx;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.thumbnails {
|
||||
margin: 20rpx 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
.img {
|
||||
flex: 1;
|
||||
/* #ifndef APP-NVUE */
|
||||
width: auto;
|
||||
/* #endif */
|
||||
height: 200rpx;
|
||||
border-radius: 8rpx;
|
||||
margin: 0 10rpx;
|
||||
&:first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.info {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.author,
|
||||
.publish_date {
|
||||
font-size: 24rpx;
|
||||
color: #bbbbbb;
|
||||
}
|
||||
|
||||
.publish_date {
|
||||
margin-left: 14rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.thumbnail {
|
||||
width: 240rpx;
|
||||
height: 160rpx;
|
||||
margin-left: 20rpx;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
<template>
|
||||
<view
|
||||
:to="'/uni_modules/uni-cms-article/pages/detail/detail?id=' + data?._id"
|
||||
:key="data?._id"
|
||||
class="list-item"
|
||||
direction="column"
|
||||
>
|
||||
<view class="main">
|
||||
<text class="title">{{ data?.title }}</text>
|
||||
<view class="thumbnails">
|
||||
<image
|
||||
v-for="image in data?.thumbnail"
|
||||
:src="image"
|
||||
mode="aspectFill"
|
||||
class="img"
|
||||
></image>
|
||||
</view>
|
||||
<view class="info">
|
||||
<text class="author">{{ data!.user_id!.length > 0 ? data!.user_id[0]!.nickname : '' }}</text>
|
||||
<text class="publish_date">{{ publishTime(data?.publish_date ?? 0) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="uts">
|
||||
import { type PropType } from 'vue'
|
||||
import translatePublishTime from "@/uni_modules/uni-cms-article/common/publish-time.uts";
|
||||
type ArticleAuthor = {
|
||||
_id: string
|
||||
nickname: string
|
||||
}
|
||||
type ArticleItem = {
|
||||
_id: string
|
||||
title: string
|
||||
publish_date: number
|
||||
thumbnail: string[]
|
||||
user_id: ArticleAuthor[]
|
||||
}
|
||||
export default {
|
||||
name: "three-cover",
|
||||
props: {
|
||||
data: {
|
||||
type: Object as PropType<ArticleItem>
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 格式化时间戳
|
||||
publishTime(timestamp: number): string {
|
||||
return translatePublishTime(timestamp)
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "./style.scss";
|
||||
</style>
|
@ -1,52 +0,0 @@
|
||||
<template>
|
||||
<uni-list-item
|
||||
:to="'/uni_modules/uni-cms-article/pages/detail/detail?id=' + data._id"
|
||||
:key="data._id"
|
||||
class="list-item"
|
||||
direction="column"
|
||||
>
|
||||
<template v-slot:body>
|
||||
<view class="main">
|
||||
<text class="title">{{ data.title }}</text>
|
||||
<view class="thumbnails">
|
||||
<image
|
||||
v-for="image in data.thumbnail"
|
||||
:src="image"
|
||||
mode="aspectFill"
|
||||
class="img"
|
||||
></image>
|
||||
</view>
|
||||
<view class="info">
|
||||
<text class="author">{{ data.user_id[0] ? data.user_id[0].nickname : '' }}</text>
|
||||
<text class="publish_date">{{ publishTime(data.publish_date) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</uni-list-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import translatePublishTime from "@/uni_modules/uni-cms-article/common/publish-time";
|
||||
|
||||
export default {
|
||||
name: "three-cover",
|
||||
props: {
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 格式化时间戳
|
||||
publishTime(timestamp) {
|
||||
return translatePublishTime(timestamp)
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "./style.scss";
|
||||
</style>
|
@ -1,99 +0,0 @@
|
||||
<template>
|
||||
<refresh @refresh="refresh" @pullingdown="onpullingdown" :display="showRefresh ? 'show' : 'hide'">
|
||||
<view class="refreshBox">
|
||||
<!-- 可以自己添加图片路径或base64实现图片 <image class="refreshImg" :src="config[state].img" mode="widthFix" resize="cover"></image> -->
|
||||
<text class="refreshText">{{config[state].text}}</text>
|
||||
</view>
|
||||
</refresh>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
showRefresh:false, // 是否显示刷新
|
||||
state:0 // 刷新状态,0:继续下拉执行刷新,1:释放立即刷新,2:正在加载中,3:加载成功
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
// 下拉刷新回调函数
|
||||
onpullingdown({pullingDistance,viewHeight}) {
|
||||
if(pullingDistance < viewHeight){
|
||||
this.state = 0 // 继续下拉执行刷新
|
||||
}else{
|
||||
this.state = 1 // 释放立即刷新
|
||||
}
|
||||
},
|
||||
// 执行刷新
|
||||
refresh(){
|
||||
// console.log('refresh');
|
||||
this.showRefresh = true // 显示刷新
|
||||
this.state = 2 // 正在加载中
|
||||
this.$emit('refresh') // 触发refresh事件
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
// 监听loading变化
|
||||
loading(loading, oldValue) {
|
||||
if(!loading){
|
||||
this.showRefresh = false // 隐藏刷新
|
||||
this.state = 3 // 加载成功
|
||||
}
|
||||
}
|
||||
},
|
||||
props: {
|
||||
loading: {
|
||||
type:Boolean,
|
||||
default(){
|
||||
return false
|
||||
}
|
||||
},
|
||||
config: {
|
||||
type: Array,
|
||||
default(){
|
||||
return [
|
||||
{
|
||||
text:"继续下拉执行刷新",
|
||||
img:""//可以自己添加图片路径或base64实现图片
|
||||
},
|
||||
{
|
||||
text:"释放立即刷新",
|
||||
img:""//可以自己添加图片路径或base64实现图片
|
||||
},
|
||||
{
|
||||
text:"正在加载中",
|
||||
img:""//可以自己添加图片路径或base64实现图片
|
||||
},
|
||||
{
|
||||
text:"加载成功",
|
||||
img:""//可以自己添加图片路径或base64实现图片
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.refreshBox{
|
||||
width: 750rpx;
|
||||
height: 50px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
/* #ifndef APP-PLUS */
|
||||
margin-top: -50px;
|
||||
/* #endif */
|
||||
}
|
||||
.refreshImg{
|
||||
width: 55rpx;
|
||||
height: 55rpx;
|
||||
z-index: 111;
|
||||
}
|
||||
.refreshText{
|
||||
font-size: 26rpx;
|
||||
color: #999999;
|
||||
padding-left: 6rpx;
|
||||
}
|
||||
</style>
|
@ -1,99 +0,0 @@
|
||||
<template>
|
||||
<refresh @refresh="refresh" @pullingdown="onpullingdown" :display="showRefresh ? 'show' : 'hide'">
|
||||
<view class="refreshBox">
|
||||
<!-- 可以自己添加图片路径或base64实现图片 <image class="refreshImg" :src="config[state].img" mode="widthFix" resize="cover"></image> -->
|
||||
<text class="refreshText">{{config[state].text}}</text>
|
||||
</view>
|
||||
</refresh>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
showRefresh:false, // 是否显示刷新
|
||||
state:0 // 刷新状态,0:继续下拉执行刷新,1:释放立即刷新,2:正在加载中,3:加载成功
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
// 下拉刷新回调函数
|
||||
onpullingdown({pullingDistance,viewHeight}) {
|
||||
if(pullingDistance < viewHeight){
|
||||
this.state = 0 // 继续下拉执行刷新
|
||||
}else{
|
||||
this.state = 1 // 释放立即刷新
|
||||
}
|
||||
},
|
||||
// 执行刷新
|
||||
refresh(){
|
||||
// console.log('refresh');
|
||||
this.showRefresh = true // 显示刷新
|
||||
this.state = 2 // 正在加载中
|
||||
this.$emit('refresh') // 触发refresh事件
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
// 监听loading变化
|
||||
loading(loading, oldValue) {
|
||||
if(!loading){
|
||||
this.showRefresh = false // 隐藏刷新
|
||||
this.state = 3 // 加载成功
|
||||
}
|
||||
}
|
||||
},
|
||||
props: {
|
||||
loading: {
|
||||
type:Boolean,
|
||||
default(){
|
||||
return false
|
||||
}
|
||||
},
|
||||
config: {
|
||||
type: Array,
|
||||
default(){
|
||||
return [
|
||||
{
|
||||
text:"继续下拉执行刷新",
|
||||
img:""//可以自己添加图片路径或base64实现图片
|
||||
},
|
||||
{
|
||||
text:"释放立即刷新",
|
||||
img:""//可以自己添加图片路径或base64实现图片
|
||||
},
|
||||
{
|
||||
text:"正在加载中",
|
||||
img:""//可以自己添加图片路径或base64实现图片
|
||||
},
|
||||
{
|
||||
text:"加载成功",
|
||||
img:""//可以自己添加图片路径或base64实现图片
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.refreshBox{
|
||||
width: 750rpx;
|
||||
height: 50px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
/* #ifndef APP-PLUS */
|
||||
margin-top: -50px;
|
||||
/* #endif */
|
||||
}
|
||||
.refreshImg{
|
||||
width: 55rpx;
|
||||
height: 55rpx;
|
||||
z-index: 111;
|
||||
}
|
||||
.refreshText{
|
||||
font-size: 26rpx;
|
||||
color: #999999;
|
||||
padding-left: 6rpx;
|
||||
}
|
||||
</style>
|
@ -1,167 +0,0 @@
|
||||
<template>
|
||||
<view
|
||||
:class="classList"
|
||||
v-if="imageData.image != ''"
|
||||
>
|
||||
<image
|
||||
:src="imagePath"
|
||||
:style="styles"
|
||||
:alt="imageData.attributes.alt"
|
||||
class="img"
|
||||
mode="aspectFill"
|
||||
@load="imageLoad"
|
||||
@click="imagePreview"
|
||||
></image>
|
||||
</view>
|
||||
</template>
|
||||
<script lang="uts">
|
||||
import {parseImageUrl} from "@/uni_modules/uni-cms-article/common/parse-image-url.uts";
|
||||
import type {ParseImageUrlResult} from '@/uni_modules/uni-cms-article/common/parse-image-url.uts';
|
||||
type ImageAttributes = {
|
||||
customParams: string | null
|
||||
width: number | null
|
||||
height: number | null
|
||||
alt: string | null
|
||||
}
|
||||
type ImageData = {
|
||||
image: string
|
||||
attributes: ImageAttributes
|
||||
}
|
||||
type ImageCalResult = {
|
||||
width: number
|
||||
height: number
|
||||
}
|
||||
|
||||
export default {
|
||||
name: "render-image",
|
||||
emits: ['imagePreview'],
|
||||
props: {
|
||||
deltaOp: {
|
||||
type: Object as UTSJSONObject,
|
||||
default (): UTSJSONObject {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
reset: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
width: 0,
|
||||
height: 0,
|
||||
imagePath: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
imageData (): ImageData {
|
||||
const insert = this.deltaOp!.getJSON('insert')! as UTSJSONObject
|
||||
const attributes: UTSJSONObject | null = this.deltaOp!.getJSON('attributes')
|
||||
console.log(insert, attributes)
|
||||
return {
|
||||
image: insert.getString('image')!,
|
||||
attributes: {
|
||||
customParams: attributes != null ? attributes.getString('data-custom'): null,
|
||||
width: attributes != null ? attributes!.getNumber('width'): null,
|
||||
height: attributes != null ? attributes!.getNumber('height'): null,
|
||||
alt: attributes != null ? attributes!.getString('alt'): null,
|
||||
}
|
||||
} as ImageData
|
||||
},
|
||||
classList (): string[] {
|
||||
return [
|
||||
'image',
|
||||
this.reset ? 'reset': ''
|
||||
] as string[]
|
||||
},
|
||||
styles (): string {
|
||||
let style = ""
|
||||
|
||||
if (this.width != 0) {
|
||||
style += `;width:${this.width}px`
|
||||
}
|
||||
if (this.height != 0) {
|
||||
style += `;height:${this.height}px`
|
||||
}
|
||||
return style
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.loadImagePath()
|
||||
},
|
||||
methods: {
|
||||
async loadImagePath (): Promise<void> {
|
||||
const {image, attributes} = this.imageData
|
||||
const parseImages = await parseImageUrl({
|
||||
insert: {image},
|
||||
attributes: {
|
||||
'data-custom': attributes.customParams != null ? attributes.customParams : ""
|
||||
}
|
||||
}, "editor")
|
||||
|
||||
if (parseImages != null) {
|
||||
this.imagePath = parseImages[0].src
|
||||
}
|
||||
},
|
||||
imagePreview () {
|
||||
this.$emit('imagePreview', this.imageData.image)
|
||||
},
|
||||
// 图片加载完成
|
||||
imageLoad(e: ImageLoadEvent) {
|
||||
const recal = this.wxAutoImageCal(e.detail.width, e.detail.height, 15) // 计算图片宽高
|
||||
// const image = this.imageData
|
||||
|
||||
// ::TODO 关注一下在多端得表现情况
|
||||
// if (!image.data.attributes.width || Number(image.data.attributes.width) > recal.imageWidth) {
|
||||
// 如果图片宽度不存在或者图片宽度大于计算出来的宽度,则设置图片宽高
|
||||
this.width = recal.width
|
||||
this.height = recal.height
|
||||
// }
|
||||
},
|
||||
|
||||
// 计算图片宽高
|
||||
wxAutoImageCal(originalWidth: number, originalHeight: number, imagePadding: number): ImageCalResult {
|
||||
// 获取系统信息
|
||||
const systemInfo = uni.getSystemInfoSync()
|
||||
let windowWidth: number;
|
||||
// let windowHeight: number;
|
||||
let autoWidth: number;
|
||||
let autoHeight: number;
|
||||
|
||||
let results: ImageCalResult = {
|
||||
width: 0,
|
||||
height: 0
|
||||
};
|
||||
// 计算图片宽度
|
||||
windowWidth = systemInfo.windowWidth - 2 * imagePadding;
|
||||
// windowHeight = systemInfo.windowHeight;
|
||||
if (originalWidth > windowWidth) {//在图片width大于手机屏幕width时候
|
||||
autoWidth = windowWidth;
|
||||
autoHeight = (autoWidth * originalHeight) / originalWidth;
|
||||
results.width = autoWidth;
|
||||
results.height = autoHeight;
|
||||
} else {//否则展示原来的数据
|
||||
results.width = originalWidth;
|
||||
results.height = originalHeight;
|
||||
}
|
||||
return results;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.image {
|
||||
margin-bottom: 40rpx;
|
||||
&.reset {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.img {
|
||||
display: flex;
|
||||
border-radius: 12rpx;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,131 +0,0 @@
|
||||
<template>
|
||||
<view
|
||||
:class="classList"
|
||||
v-if="data.data"
|
||||
>
|
||||
<image
|
||||
:src="imagePath"
|
||||
:class="data.data.class"
|
||||
:style="styles"
|
||||
:alt="data.data.attributes.alt || ''"
|
||||
class="img"
|
||||
mode="aspectFill"
|
||||
@load="imageLoad"
|
||||
@click="imagePreview"
|
||||
></image>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import {parseImageUrl} from "@/uni_modules/uni-cms-article/common/parse-image-url.js";
|
||||
|
||||
export default {
|
||||
name: "render-image",
|
||||
props: {
|
||||
data: {
|
||||
type: Object,
|
||||
default () {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
className: String,
|
||||
reset: false
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
width: 0,
|
||||
height: 0,
|
||||
imagePath: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
classList () {
|
||||
return [
|
||||
'image',
|
||||
this.reset ? 'reset': '',
|
||||
this.className
|
||||
]
|
||||
},
|
||||
styles () {
|
||||
let style = this.data.data.style
|
||||
|
||||
if (this.width) {
|
||||
style += `;width:${this.width}px`
|
||||
}
|
||||
if (this.height) {
|
||||
style += `;height:${this.height}px`
|
||||
}
|
||||
return style
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.loadImagePath()
|
||||
},
|
||||
methods: {
|
||||
async loadImagePath () {
|
||||
const parseImages = await parseImageUrl({
|
||||
insert: {image: this.data.data.value},
|
||||
attributes: this.data.data.attributes,
|
||||
}, "editor")
|
||||
|
||||
this.imagePath = parseImages[0].src
|
||||
},
|
||||
imagePreview () {
|
||||
uni.$emit('imagePreview', this.data.data.value)
|
||||
},
|
||||
// 图片加载完成
|
||||
imageLoad(e) {
|
||||
const recal = this.wxAutoImageCal(e.detail.width, e.detail.height, 15) // 计算图片宽高
|
||||
// const image = this.data
|
||||
|
||||
// ::TODO 关注一下在多端得表现情况
|
||||
// if (!image.data.attributes.width || Number(image.data.attributes.width) > recal.imageWidth) {
|
||||
// 如果图片宽度不存在或者图片宽度大于计算出来的宽度,则设置图片宽高
|
||||
this.width = recal.imageWidth
|
||||
this.height = recal.imageHeight
|
||||
// }
|
||||
},
|
||||
|
||||
// 计算图片宽高
|
||||
wxAutoImageCal(originalWidth, originalHeight, imagePadding = 0) {
|
||||
// 获取系统信息
|
||||
const systemInfo = uni.getSystemInfoSync()
|
||||
let windowWidth = 0, windowHeight = 0;
|
||||
let autoWidth = 0, autoHeight = 0;
|
||||
let results = {};
|
||||
// 计算图片宽度
|
||||
windowWidth = systemInfo.windowWidth - 2 * imagePadding;
|
||||
windowHeight = systemInfo.windowHeight;
|
||||
if (originalWidth > windowWidth) {//在图片width大于手机屏幕width时候
|
||||
autoWidth = windowWidth;
|
||||
autoHeight = (autoWidth * originalHeight) / originalWidth;
|
||||
results.imageWidth = autoWidth;
|
||||
results.imageHeight = autoHeight;
|
||||
} else {//否则展示原来的数据
|
||||
results.imageWidth = originalWidth;
|
||||
results.imageHeight = originalHeight;
|
||||
}
|
||||
return results;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.image {
|
||||
margin-bottom: 40rpx;
|
||||
&.reset {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.img {
|
||||
// #ifdef APP-PLUS
|
||||
display: block;
|
||||
// #endif
|
||||
// #ifndef APP-PLUS
|
||||
display: flex;
|
||||
// #endif
|
||||
border-radius: 12rpx;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,129 +0,0 @@
|
||||
<template>
|
||||
<view class="content">
|
||||
<template v-for="op in content">
|
||||
<render-text
|
||||
v-if="op.type === 'paragraph'"
|
||||
:data="op.data"
|
||||
:className="op.class"
|
||||
:style="op.style"
|
||||
></render-text>
|
||||
<render-image
|
||||
v-else-if="op.type === 'image' && op.data.length > 0"
|
||||
:data="op.data[0]"
|
||||
:className="op.class"
|
||||
:style="op.style"
|
||||
></render-image>
|
||||
<render-list
|
||||
v-else-if="op.type === 'list'"
|
||||
:data="op.data"
|
||||
:style="op.style"
|
||||
></render-list>
|
||||
<view
|
||||
v-else-if="op.type === 'divider'"
|
||||
class="divider"
|
||||
></view>
|
||||
<render-video
|
||||
v-else-if="op.type === 'mediaVideo'"
|
||||
:data="op.data"
|
||||
></render-video>
|
||||
<render-unlock-content
|
||||
v-else-if="op.type === 'unlockContent'"
|
||||
:adp-id="adConfig.adpId"
|
||||
:watch-ad-unique-type="adConfig.watchAdUniqueType"
|
||||
></render-unlock-content>
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {parseImageUrl} from "@/uni_modules/uni-cms-article/common/parse-image-url"
|
||||
|
||||
import text from './text.vue'
|
||||
import image from './image.vue'
|
||||
import video from './video.vue'
|
||||
import list from './list.vue'
|
||||
import unlockContent from './unlock-content.vue'
|
||||
|
||||
export default {
|
||||
name: "render-article-detail",
|
||||
props: {
|
||||
content: {
|
||||
type: Array,
|
||||
default () {
|
||||
return []
|
||||
}
|
||||
},
|
||||
contentImages: {
|
||||
type: Array,
|
||||
default () {
|
||||
return []
|
||||
}
|
||||
},
|
||||
adConfig: {
|
||||
type: Object,
|
||||
default: {}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
articleImages: []
|
||||
}
|
||||
},
|
||||
components: {
|
||||
renderUnlockContent: unlockContent,
|
||||
renderText: text,
|
||||
renderImage: image,
|
||||
renderList: list,
|
||||
renderVideo: video
|
||||
},
|
||||
mounted() {
|
||||
this.initImage()
|
||||
},
|
||||
beforeDestroy() {
|
||||
uni.$off('imagePreview')
|
||||
},
|
||||
methods: {
|
||||
// 初始化图片
|
||||
async initImage() {
|
||||
// 获取所有图片
|
||||
const parseImages = await parseImageUrl(this.contentImages)
|
||||
|
||||
if (parseImages != null) {
|
||||
this.articleImages = parseImages.map(image => image.src)
|
||||
}
|
||||
|
||||
// 监听图片预览
|
||||
uni.$on('imagePreview', this.imagePreview)
|
||||
},
|
||||
// 点击图片预览
|
||||
imagePreview(src) {
|
||||
if (src) {
|
||||
uni.previewImage({
|
||||
current: src.split('?')[0], // 当前显示图片的http链接
|
||||
urls: this.articleImages // 需要预览的图片http链接列表
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.content {
|
||||
line-height: 1.75;
|
||||
font-size: 32rpx;
|
||||
margin-top: 40rpx;
|
||||
padding: 0 30rpx 80rpx;
|
||||
word-break: break-word;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.divider {
|
||||
height: 1px;
|
||||
background: #d8d8d8;
|
||||
width: 100%;
|
||||
margin: 40rpx 0;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
@ -1,50 +0,0 @@
|
||||
<template>
|
||||
<view :class="['list', data.type]">
|
||||
<view class="list-item" v-for="(item, index) in data.items">
|
||||
<text class="dot">{{data.type === 'ordered' ? `${index + 1}.` : '•'}}</text>
|
||||
<render-text :data="item.data" reset class="reset-default"></render-text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import text from './text.vue'
|
||||
|
||||
export default {
|
||||
name: "render-list",
|
||||
props: {
|
||||
data: {
|
||||
type: Object,
|
||||
default () {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
renderText: text
|
||||
},
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.list {
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
.list-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 20rpx;
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.dot {
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
}
|
||||
.reset-default {
|
||||
text-indent: 0;
|
||||
flex: 1;
|
||||
}
|
||||
</style>
|
@ -1,160 +0,0 @@
|
||||
<template>
|
||||
<view :class="classList">
|
||||
<template v-for="item in data">
|
||||
<text
|
||||
v-if="item.type === 'text'"
|
||||
:class="item.data.class"
|
||||
:style="item.data.style"
|
||||
class="text"
|
||||
>
|
||||
{{item.data.value}}
|
||||
</text>
|
||||
<text
|
||||
v-if="item.type === 'link'"
|
||||
:class="item.data.class"
|
||||
:style="item.data.style"
|
||||
class="link"
|
||||
@click="goLink(item.data.attributes.link)"
|
||||
>
|
||||
{{item.data.value}}
|
||||
</text>
|
||||
<image-item v-else-if="item.type === 'image'" :data="item"></image-item>
|
||||
<!-- #ifdef H5 -->
|
||||
<br v-else-if="item.type === 'br'" class="br"/>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef H5 -->
|
||||
<text v-else-if="item.type === 'br'" class="br">\n</text>
|
||||
<!-- #endif -->
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import ImageItem from './image.vue'
|
||||
|
||||
export default {
|
||||
name: "render-text",
|
||||
props: {
|
||||
data: {
|
||||
type: Array,
|
||||
default () {
|
||||
return []
|
||||
}
|
||||
},
|
||||
className: String,
|
||||
reset: Boolean
|
||||
},
|
||||
computed: {
|
||||
classList () {
|
||||
return [
|
||||
'row-text',
|
||||
this.className,
|
||||
this.reset ? 'reset': ''
|
||||
]
|
||||
}
|
||||
},
|
||||
components: {
|
||||
ImageItem
|
||||
},
|
||||
methods: {
|
||||
show () {
|
||||
uni.showToast({
|
||||
title: 'test',
|
||||
icon: 'none'
|
||||
})
|
||||
},
|
||||
// 点击链接跳转
|
||||
goLink(link) {
|
||||
// 如果链接为空,则返回
|
||||
if (!link) return
|
||||
|
||||
// #ifdef H5
|
||||
// 在新窗口中打开链接
|
||||
window.open(link, '_blank')
|
||||
// #endif
|
||||
|
||||
// #ifdef MP
|
||||
// 微信小程序不支持打开外链,复制链接到剪贴板
|
||||
uni.setClipboardData({
|
||||
data: link,
|
||||
success: () => {
|
||||
uni.showToast({
|
||||
title: '链接已复制',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
})
|
||||
// #endif
|
||||
|
||||
// #ifdef APP
|
||||
// 在webview中打开链接
|
||||
uni.navigateTo({
|
||||
url: `/uni_modules/uni-cms-article/pages/webview/webview?url=${encodeURIComponent(link)}`
|
||||
})
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
.row-text, .br {
|
||||
margin-bottom: 40rpx;
|
||||
&.reset {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
.header-1,
|
||||
.header-2,
|
||||
.header-3,
|
||||
.header-4,
|
||||
.header-5,
|
||||
.header-6 {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.header-1 {
|
||||
font-size: 44rpx;
|
||||
}
|
||||
|
||||
.header-2 {
|
||||
font-size: 40rpx;
|
||||
}
|
||||
|
||||
.header-3 {
|
||||
font-size: 38rpx;
|
||||
}
|
||||
|
||||
.header-4 {
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.header-5 {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.header-6 {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.italic {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.strike {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.underline {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.link {
|
||||
color: #0064f9;
|
||||
text-decoration: underline;
|
||||
}
|
||||
</style>
|
@ -1,216 +0,0 @@
|
||||
<template>
|
||||
<view class="unlock-content">
|
||||
<!-- #ifdef H5 -->
|
||||
<!-- 等广告支持H5后优化-->
|
||||
<button class="text" @click="callAd">请观看广告后解锁全文</button>
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- #ifndef H5 -->
|
||||
<ad-rewarded-video ref="rewardedVideo" :adpid="adpId" :preload="false" :disabled="true" :loadnext="true"
|
||||
:url-callback="urlCallback" @load="onAdLoad" @close="onAdClose" @error="onAdError"
|
||||
v-slot:default="{ loading, error }">
|
||||
<text v-if="error" class="text">广告加载失败</text>
|
||||
</ad-rewarded-video>
|
||||
<button v-if="!isLoadError" class="text" @click="callAd" :loading="adLoading">请观看广告后解锁全文</button>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 实例化数据库
|
||||
const db = uniCloud.database()
|
||||
// 定义解锁记录表名
|
||||
const unlockContentDBName = 'uni-cms-unlock-record'
|
||||
|
||||
export default {
|
||||
name: "ad",
|
||||
props: {
|
||||
adpId: String,
|
||||
watchAdUniqueType: {
|
||||
type: String,
|
||||
default: 'device'
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentArticleId: '',
|
||||
currentPageRoute: '',
|
||||
adLoading: false,
|
||||
isLoadError: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 回调URL
|
||||
urlCallback() {
|
||||
return {
|
||||
extra: JSON.stringify({
|
||||
article_id: this.currentArticleId,
|
||||
unique_id: this.uniqueId,
|
||||
unique_type: this.watchAdUniqueType
|
||||
})
|
||||
}
|
||||
},
|
||||
// 是否通过设备观看
|
||||
watchByDevice() {
|
||||
return this.watchAdUniqueType === 'device'
|
||||
},
|
||||
// 是否通过用户观看
|
||||
watchByUser() {
|
||||
return this.watchAdUniqueType === 'user'
|
||||
},
|
||||
// 获取唯一ID
|
||||
uniqueId() {
|
||||
return this.watchByDevice ? uni.getSystemInfoSync().deviceId : uniCloud.getCurrentUserInfo().uid
|
||||
}
|
||||
},
|
||||
// #ifndef H5
|
||||
mounted() {
|
||||
// 获取当前页面信息
|
||||
const pages = getCurrentPages()
|
||||
const currentPage = pages[pages.length - 1]
|
||||
this.currentArticleId = currentPage.options.id
|
||||
this.currentPageRoute = currentPage.route
|
||||
|
||||
// 如果广告位ID未设置,则提示广告无法正常加载
|
||||
if (!this.adpId) {
|
||||
uni.showModal({
|
||||
content: '广告位ID未设置,广告无法正常加载',
|
||||
showCancel: false
|
||||
})
|
||||
} else {
|
||||
// 加载广告
|
||||
this.$refs.rewardedVideo.load()
|
||||
}
|
||||
},
|
||||
// #endif
|
||||
methods: {
|
||||
// 调用广告
|
||||
callAd() {
|
||||
// #ifdef H5
|
||||
// 如果在浏览器中,则提示需在App或小程序中操作
|
||||
return uni.showModal({
|
||||
content: '需观看广告解锁内容, 但浏览器不支持广告播放, 请在App或小程序中操作',
|
||||
showCancel: false
|
||||
})
|
||||
// #endif
|
||||
|
||||
if (this.watchByUser) {
|
||||
// 登录跳转URL 请根据实际情况修改
|
||||
const redirectUrl = '/uni_modules/uni-id-pages/pages/login/login-withoutpwd' + (this.currentPageRoute ? '?uniIdRedirectUrl=' + this.currentPageRoute + '?id=' + this.currentArticleId : '')
|
||||
|
||||
//::TODO 支持设备与用户
|
||||
// 如果用户未登录,则提示需要登录
|
||||
if (uniCloud.getCurrentUserInfo().tokenExpired < Date.now()) {
|
||||
uni.showModal({
|
||||
content: '请登录后操作',
|
||||
success: ({ confirm }) => {
|
||||
confirm && uni.redirectTo({
|
||||
url: redirectUrl
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 显示广告
|
||||
this.adLoading = true
|
||||
this.$refs.rewardedVideo.show()
|
||||
},
|
||||
// 广告加载成功
|
||||
onAdLoad() {
|
||||
this.adLoading && this.$refs.rewardedVideo.show()
|
||||
console.log('广告数据加载成功');
|
||||
},
|
||||
// 广告关闭
|
||||
onAdClose(e) {
|
||||
console.log('close', e)
|
||||
const detail = e.detail
|
||||
// 轮询3次,每次1秒,如果3秒内没有查询到解锁记录,就提示解锁失败
|
||||
let i = 3
|
||||
uni.hideLoading()
|
||||
this.adLoading = false
|
||||
|
||||
// detail.isEnded 为true 说明用户观看了完整视频
|
||||
if (detail && detail.isEnded) {
|
||||
uni.showLoading({
|
||||
title: '正在解锁全文',
|
||||
timeout: 7000
|
||||
})
|
||||
let queryResult = setInterval(async () => {
|
||||
i--;
|
||||
|
||||
// 查询解锁记录
|
||||
const res = await db.collection(unlockContentDBName).where({
|
||||
unique_id: this.uniqueId,
|
||||
article_id: this.currentArticleId,
|
||||
}).get()
|
||||
|
||||
// 1. result.data.length 为0 说明没有解锁记录
|
||||
// 2. i <= 0 说明已经轮询了3次,还是没有解锁记录,说明解锁失败
|
||||
// 3. result.data.length && i > 0 说明已经解锁成功
|
||||
if (i <= 0) {
|
||||
console.log('解锁失败', i)
|
||||
clearInterval(queryResult)
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
title: '解锁失败!',
|
||||
icon: 'error',
|
||||
duration: 2000
|
||||
});
|
||||
} else if (res.result && res.result.data.length) {
|
||||
console.log('解锁成功', i)
|
||||
|
||||
clearInterval(queryResult)
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
title: '解锁成功!',
|
||||
icon: 'success',
|
||||
duration: 2000
|
||||
});
|
||||
uni.$emit('onUnlockContent')
|
||||
}
|
||||
}, 1500);
|
||||
} else {
|
||||
uni.showModal({
|
||||
content: "请观看完整视频后解锁全文",
|
||||
showCancel: false
|
||||
})
|
||||
}
|
||||
},
|
||||
onAdError(e) {
|
||||
// uni.hideLoading()
|
||||
// this.isLoadError = true
|
||||
console.error('onaderror: ', e)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<style scoped lang="scss">
|
||||
.unlock-content {
|
||||
text-align: center;
|
||||
padding: 160rpx 0 60rpx;
|
||||
position: relative;
|
||||
margin-top: -140rpx;
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 160rpx;
|
||||
background: linear-gradient(to bottom, transparent, #fff);
|
||||
}
|
||||
|
||||
.text {
|
||||
border: #f0f0f0 solid 1px;
|
||||
display: inline-block;
|
||||
background: #f6f6f6;
|
||||
border-radius: 10rpx;
|
||||
font-size: 34rpx;
|
||||
color: #222;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,44 +0,0 @@
|
||||
<template>
|
||||
<view class="video">
|
||||
<video
|
||||
class="v"
|
||||
:src="data.attributes.src"
|
||||
:poster="data.attributes.poster"
|
||||
></video>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: "render-video",
|
||||
props: {
|
||||
data: {
|
||||
type: Object,
|
||||
default () {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
width: 0,
|
||||
height: 0,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.video {
|
||||
margin-bottom: 40rpx;
|
||||
.v {
|
||||
display: block;
|
||||
width: 100%;
|
||||
max-width: 500px;
|
||||
margin: 0 auto;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,54 +0,0 @@
|
||||
<template>
|
||||
<view>
|
||||
<text class="uni-cms-article-icon" :style="{color, 'fontSize': size + 'px', lineHeight: size + 'px'}">{{iconCode}}</text>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="uts">
|
||||
const icons: UTSJSONObject = {
|
||||
search: "\ue654",
|
||||
back: "\ue6b9",
|
||||
scan: "\ue62a",
|
||||
closeempty: "\ue66c",
|
||||
trash: "\ue687",
|
||||
reload: "\ue6b2",
|
||||
eye: "\ue651",
|
||||
'eye-slash': '\ue6b3'
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'uni-cms-article-icons',
|
||||
props: {
|
||||
type: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: '#333333'
|
||||
},
|
||||
size: {
|
||||
type: Number,
|
||||
default: 16
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
iconCode(): string {
|
||||
return icons.getString(this.type) as string
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: "uni-cms-article-icons";
|
||||
src: url('/uni_modules/uni-cms-article/static/uniicons.ttf');
|
||||
}
|
||||
|
||||
.uni-cms-article-icon {
|
||||
font-family: "uni-cms-article-icons";
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
</style>
|
@ -1,371 +0,0 @@
|
||||
<template>
|
||||
<unicloud-db
|
||||
ref='udb'
|
||||
v-slot:default="{ data, pagination, hasMore, loading, error }"
|
||||
:collection="collectionList"
|
||||
:page-size="10"
|
||||
:loadtime="loadTime"
|
||||
orderby="publish_date desc"
|
||||
@load="onListLoad"
|
||||
@error="onListLoadError"
|
||||
>
|
||||
<view
|
||||
v-if="networkType == 'none'"
|
||||
class="error-box"
|
||||
@click="checkNetwork"
|
||||
>
|
||||
<image class="disconnect-icon" src="/uni_modules/uni-cms-article/static/disconnection.png" mode="widthFix"></image>
|
||||
<text class="tip-text">当前网络不可用,请点击重试</text>
|
||||
</view>
|
||||
<list-view
|
||||
v-else
|
||||
class="list-view"
|
||||
:scroll-y="true"
|
||||
:refresher-enabled="refresherEnabled"
|
||||
refresher-default-style="none"
|
||||
:refresher-triggered="refresherTriggered"
|
||||
@refresherpulling="refresherpulling"
|
||||
@refresherrefresh="refresherrefresh"
|
||||
@scrolltolower="scrolltolower"
|
||||
>
|
||||
<list-item slot="refresher" class="refresh-box">
|
||||
<text class="text">{{ refreshText[refreshState] }}</text>
|
||||
</list-item>
|
||||
|
||||
<!-- 列表渲染 -->
|
||||
<list-item
|
||||
v-for="item in articleList"
|
||||
:class="['list-item', `list-item__thumbnail-${item.thumbnail.length}`]"
|
||||
:key="item._id"
|
||||
@click="goToDetailPage(item)"
|
||||
>
|
||||
<template v-if="item.thumbnail.length == 0">
|
||||
<view class="list-item__content">
|
||||
<view class="list-item__content-title">
|
||||
<text class="text">{{ item.title }}</text>
|
||||
</view>
|
||||
<view class="list-item__content-info">
|
||||
<view class="list-item__author">
|
||||
<text class="text">{{ item!.user_id!.length > 0 ? item.user_id[0].nickname : '' }}</text>
|
||||
</view>
|
||||
<view class="list-item__publish-date">
|
||||
<text class="text">{{ publishTime(item.publish_date) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<template v-if="item.thumbnail.length == 1">
|
||||
<view class="list-item__content">
|
||||
<view class="list-item__content-title">
|
||||
<text class="text">{{ item.title }}</text>
|
||||
</view>
|
||||
<view class="list-item__content-info">
|
||||
<view class="list-item__author">
|
||||
<text class="text">{{ item!.user_id!.length > 0 ? item.user_id[0].nickname : '' }}</text>
|
||||
</view>
|
||||
<view class="list-item__publish-date">
|
||||
<text class="text">{{ publishTime(item.publish_date) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="list-item__thumbnails">
|
||||
<image
|
||||
v-for="image in item.thumbnail"
|
||||
:src="image"
|
||||
mode="aspectFill"
|
||||
class="list-item__img"
|
||||
></image>
|
||||
</view>
|
||||
</template>
|
||||
<template v-if="item.thumbnail.length == 3">
|
||||
<view class="list-item__content">
|
||||
<view class="list-item__content-title">
|
||||
<text>{{ item.title }}</text>
|
||||
</view>
|
||||
<view class="list-item__thumbnails">
|
||||
<image
|
||||
v-for="image in item.thumbnail"
|
||||
:src="image"
|
||||
mode="aspectFill"
|
||||
class="list-item__img"
|
||||
></image>
|
||||
</view>
|
||||
<view class="list-item__content-info">
|
||||
<view class="list-item__author">
|
||||
<text class="text">{{ item!.user_id!.length > 0 ? item.user_id[0].nickname : '' }}</text>
|
||||
</view>
|
||||
<view class="list-item__publish-date">
|
||||
<text class="text">{{ publishTime(item.publish_date) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</list-item>
|
||||
<list-item class="load-state">
|
||||
<text class="text">{{ loading ? '加载中...' : (hasMore ? '上拉加载更多' : '没有更多数据了') }}</text>
|
||||
</list-item>
|
||||
</list-view>
|
||||
</unicloud-db>
|
||||
</template>
|
||||
|
||||
<script lang="uts">
|
||||
type ArticleAuthor = {
|
||||
_id: string
|
||||
nickname: string
|
||||
}
|
||||
type ArticleItem = {
|
||||
_id: string
|
||||
title: string
|
||||
publish_date: number
|
||||
thumbnail: string[]
|
||||
user_id: ArticleAuthor[]
|
||||
}
|
||||
|
||||
import {parseImageUrl} from "@/uni_modules/uni-cms-article/common/parse-image-url.uts";
|
||||
import translatePublishTime from "@/uni_modules/uni-cms-article/common/publish-time.uts";
|
||||
import type {ParseImageUrlResult} from '@/uni_modules/uni-cms-article/common/parse-image-url.uts'
|
||||
|
||||
export default {
|
||||
name: "uni-cms-article-list",
|
||||
emits: ['onRefresh', 'onLoadMore'],
|
||||
props: {
|
||||
collectionList: {
|
||||
type: Array as any[],
|
||||
default: (): any[] => []
|
||||
},
|
||||
loadTime: {
|
||||
type: String,
|
||||
default: 'auto'
|
||||
},
|
||||
refresherEnabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
articleList: [] as ArticleItem[],
|
||||
refresherTriggered: false,
|
||||
refreshState: 0,
|
||||
refreshText: [
|
||||
'继续下拉执行刷新',
|
||||
'释放立即刷新',
|
||||
'正在加载中',
|
||||
'加载成功'
|
||||
],
|
||||
networkType: ""
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.checkNetwork()
|
||||
},
|
||||
methods: {
|
||||
checkNetwork() {
|
||||
uni.getNetworkType({
|
||||
success: (res) => {
|
||||
this.networkType = res.networkType;
|
||||
}
|
||||
});
|
||||
},
|
||||
publishTime(timestamp: number): string {
|
||||
return translatePublishTime(timestamp)
|
||||
},
|
||||
async onListLoad(data: UTSJSONObject[], ended: boolean, pagination: UTSJSONObject): Promise<void> {
|
||||
const listData: ArticleItem[] = data.map((item: UTSJSONObject): ArticleItem => {
|
||||
let articleItem: ArticleItem = {
|
||||
_id: item.getString('_id')!,
|
||||
title: item.getString('title')!,
|
||||
publish_date: item.getNumber('publish_date')!,
|
||||
thumbnail: [],
|
||||
user_id: item.getArray<ArticleAuthor>('user_id')! as ArticleAuthor[]
|
||||
}
|
||||
|
||||
if (typeof item.getAny('thumbnail') === 'string') {
|
||||
articleItem.thumbnail = [item.getAny('thumbnail')! as string]
|
||||
} else {
|
||||
articleItem.thumbnail = item.getArray<string>('thumbnail')!
|
||||
}
|
||||
|
||||
return articleItem
|
||||
})
|
||||
|
||||
// 处理cloud://文件链接
|
||||
for (let i = 0; i < listData.length; i++) {
|
||||
const article = listData[i]
|
||||
const parseImages = await parseImageUrl(article.thumbnail)
|
||||
|
||||
if (parseImages != null) {
|
||||
article.thumbnail = parseImages.map((image: ParseImageUrlResult): string => image.src)
|
||||
}
|
||||
}
|
||||
|
||||
this.articleList = pagination.getNumber('current') == 1 ? listData : this.articleList.concat(listData)
|
||||
},
|
||||
refresherrefresh() {
|
||||
this.refresherTriggered = true
|
||||
this.refreshState = 2;
|
||||
|
||||
(this.$refs['udb'] as UniCloudDBElement)!.loadData({
|
||||
clear: true,
|
||||
success: (_: any) => {
|
||||
this.refresherTriggered = false
|
||||
this.refreshState = 3
|
||||
}
|
||||
})
|
||||
},
|
||||
refresherpulling(e: RefresherEvent) {
|
||||
if (e.detail.dy.toDouble() == 0.0) {
|
||||
this.refreshState = 0
|
||||
} else if (e.detail.dy > 45) {
|
||||
this.refreshState = 1
|
||||
}
|
||||
},
|
||||
scrolltolower() {
|
||||
(this.$refs['udb'] as UniCloudDBElement)!.loadMore()
|
||||
},
|
||||
reLoadList() {
|
||||
(this.$refs['udb'] as UniCloudDBElement)!.loadData({
|
||||
clear: true
|
||||
})
|
||||
},
|
||||
goToDetailPage(article: ArticleItem) {
|
||||
uni.navigateTo({
|
||||
url: `/uni_modules/uni-cms-article/pages/detail/detail?id=${article._id}&title=${article.title}`
|
||||
})
|
||||
},
|
||||
onListLoadError () {
|
||||
this.checkNetwork()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.refresh-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.text {
|
||||
padding: 30rpx 0;
|
||||
font-size: 26rpx;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
|
||||
.error-box {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 0 auto;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.disconnect-icon {
|
||||
width: 200rpx;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.tip-text {
|
||||
font-size: 26rpx;
|
||||
color: #333;
|
||||
margin-top: 40rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.load-state {
|
||||
height: 90rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.text {
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
|
||||
.list-view {
|
||||
height: 100%;
|
||||
padding: 0 20rpx;
|
||||
}
|
||||
|
||||
.list-item {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding: 20rpx 0;
|
||||
border-bottom: #f5f5f5 solid 1px;
|
||||
|
||||
&__thumbnail-1 {
|
||||
.list-item__content-title {
|
||||
height: 88rpx;
|
||||
}
|
||||
}
|
||||
|
||||
&__thumbnail-3 {
|
||||
.list-item__thumbnails {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin: 20rpx -10rpx;
|
||||
margin-left: -10rpx;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.list-item__img {
|
||||
margin: 0 10rpx;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&__thumbnails {
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
|
||||
&__img {
|
||||
width: 240rpx;
|
||||
height: 160rpx;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
|
||||
&__content {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
|
||||
&-title {
|
||||
overflow: hidden;
|
||||
|
||||
.text {
|
||||
font-size: 30rpx;
|
||||
color: #333333;
|
||||
line-height: 44rpx;
|
||||
}
|
||||
}
|
||||
|
||||
&-info {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
&__author,
|
||||
&__publish-date {
|
||||
.text {
|
||||
font-size: 24rpx;
|
||||
color: #bbbbbb;
|
||||
}
|
||||
}
|
||||
|
||||
&__author {
|
||||
margin-right: 14rpx;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</style>
|
@ -1,195 +0,0 @@
|
||||
<template>
|
||||
<view class="search-bar">
|
||||
<view :style="{ height: `${navBarHeight}px` }"></view>
|
||||
<view class="search-bar__content" @click="goToSearchPage">
|
||||
<view class="search-bar__left" v-if="!showPlaceholder">
|
||||
<view class="back-icon">
|
||||
<uni-cms-article-icons type="back" :size="26" color="#333" @click="back"></uni-cms-article-icons>
|
||||
</view>
|
||||
</view>
|
||||
<view class="search-bar__center">
|
||||
<uni-cms-article-icons type="search" :size="18" color="#c0c4cc"></uni-cms-article-icons>
|
||||
<text class="search-bar__placeholder" v-if="showPlaceholder">请输入搜索内容</text>
|
||||
<input
|
||||
v-else
|
||||
ref="search-input"
|
||||
class="search-bar__input"
|
||||
placeholder="请输入搜索内容"
|
||||
v-model="searchVal"
|
||||
confirm-type="search"
|
||||
:focus="focus"
|
||||
@confirm="confirm"
|
||||
/>
|
||||
<view class="clear-icon" v-if="hasSearchValue" @click="clear">
|
||||
<uni-cms-article-icons type="closeempty" :size="12" color="#fff"></uni-cms-article-icons>
|
||||
</view>
|
||||
</view>
|
||||
<view class="search-bar__right" v-if="!showPlaceholder">
|
||||
<!-- <uni-cms-article-icons type="scan" :size="20" color="#c0c4cc" @click="scan"></uni-cms-article-icons>-->
|
||||
<text class="search-bar__search-text" @click="confirm">搜索</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="uts">
|
||||
// import parseScanResult from "@/uni_modules/uni-cms-article/common/parse-scan-result.uts";
|
||||
|
||||
export default {
|
||||
name: 'search-bar',
|
||||
emits: ['update:modelValue', 'clear', 'confirm'],
|
||||
data() {
|
||||
return {
|
||||
navBarHeight: 44,
|
||||
searchVal: ""
|
||||
}
|
||||
},
|
||||
props: {
|
||||
showPlaceholder: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
focus: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
modelValue: {
|
||||
type: String,
|
||||
default: ""
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
searchVal(newValue) {
|
||||
this.$emit('update:modelValue', newValue)
|
||||
},
|
||||
modelValue: {
|
||||
immediate: true,
|
||||
handler(newVal) {
|
||||
this.searchVal = newVal
|
||||
}
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
hasSearchValue(): boolean {
|
||||
return this.searchVal != ""
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
back() {
|
||||
// 获取当前页面数量
|
||||
const pages = getCurrentPages()
|
||||
// 定义文章列表页的路径
|
||||
const pageUrl = '/uni_modules/uni-cms-article/pages/list/list'
|
||||
|
||||
// 如果当前页面数量大于1,返回上一页
|
||||
if (pages.length > 1) {
|
||||
uni.navigateBack({})
|
||||
} else { // 否则跳转到文章列表页
|
||||
uni.redirectTo({
|
||||
url: pageUrl,
|
||||
fail: (e: RedirectToFail) => {
|
||||
// 如果跳转失败,说明当前页面是tabbar页面,需要使用switchTab跳转
|
||||
if (e.errMsg.indexOf('tabbar') !== -1) {
|
||||
uni.switchTab({
|
||||
url: pageUrl
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
clear() {
|
||||
this.searchVal = '';
|
||||
(this.$refs['search-input'] as Element).blur()
|
||||
this.$emit('clear')
|
||||
},
|
||||
confirm() {
|
||||
(this.$refs['search-input'] as Element).blur()
|
||||
this.$emit('confirm', this.searchVal)
|
||||
},
|
||||
scan() {
|
||||
// 扫码暂不支持
|
||||
// uni.scanCode({
|
||||
// onlyFromCamera: true,
|
||||
// scanType: ["qrCode"],
|
||||
// success: (e) => parseScanResult(e.result),
|
||||
// fail: (e) => {
|
||||
// console.error(e)
|
||||
// }
|
||||
// })
|
||||
},
|
||||
goToSearchPage() {
|
||||
if (!this.showPlaceholder) return
|
||||
|
||||
uni.navigateTo({
|
||||
url: '/uni_modules/uni-cms-article/pages/search/search'
|
||||
})
|
||||
},
|
||||
hideKeyboard() {
|
||||
(this.$refs['search-input'] as Element).blur()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.search-bar {
|
||||
background: #fff;
|
||||
|
||||
&__content {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding: 10rpx 20rpx;
|
||||
}
|
||||
|
||||
&__left {
|
||||
margin-left: -20rpx;
|
||||
}
|
||||
|
||||
&__center {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #F8F8F8;
|
||||
padding: 20rpx;
|
||||
margin: 0 20rpx;
|
||||
margin-left: 0;
|
||||
border-radius: 40rpx;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
&__placeholder {
|
||||
color: #c0c4cc;
|
||||
font-size: 28rpx;
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
|
||||
&__input {
|
||||
margin-left: 10rpx;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
&__search-text {
|
||||
color: #c0402b;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.back-icon {
|
||||
padding: 10rpx;
|
||||
}
|
||||
|
||||
.clear-icon {
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
background: #c0c4cc;
|
||||
border-radius: 15rpx;
|
||||
margin-right: 0;
|
||||
margin-left: 10rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"noData": "No Data",
|
||||
"noNetwork": "Network error",
|
||||
"toSet": "Go to settings",
|
||||
"error": "error"
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
import en from './en.json'
|
||||
import zhHans from './zh-Hans.json'
|
||||
export default {
|
||||
en,
|
||||
'zh-Hans': zhHans
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"noData": "暂无数据",
|
||||
"noNetwork": "网络异常",
|
||||
"toSet": "前往设置",
|
||||
"error": "错误"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
新增uni-load-state组件,这是一个封装数据请求状态的组件。根据uniCloud-db组件提供的参数直接响应对应的效果。
|
||||
包括加载中、当前页面为空、没有更多数据、上拉加载更多;
|
||||
加载错误判断,如果是断网就引导打开系统网络设置页面。恢复联网后自动触发networkResume方法。
|
@ -1,171 +0,0 @@
|
||||
<template>
|
||||
<view @appear="appear">
|
||||
<view v-if="state.error">
|
||||
<view class="box" v-if="networkType == 'none'">
|
||||
<image class="icon-image" src="/uni_modules/uni-cms-article/static/disconnection.png" mode="widthFix"></image>
|
||||
<text class="tip-text">{{noNetwork}}</text>
|
||||
<view class="btn btn-default" @click="openSettings">
|
||||
<text class="btn-text">{{toSet}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<text class="error" v-else>{{error}}:{{JSON.stringify(state.error)}}</text>
|
||||
</view>
|
||||
<template v-else>
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
<text class="state-text">{{state.loading?'加载中...':(state.hasMore?'上拉加载更多':'没有更多数据了')}}</text>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef APP-NVUE -->
|
||||
<uni-load-more class="uni-load-more" :status="state.loading?'loading':(state.hasMore?'hasMore':'noMore')"></uni-load-more>
|
||||
<!-- #endif -->
|
||||
</template>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
initVueI18n
|
||||
} from '@dcloudio/uni-i18n'
|
||||
import messages from './i18n/index.js'
|
||||
const {
|
||||
t
|
||||
} = initVueI18n(messages)
|
||||
|
||||
export default {
|
||||
name: "uni-load-state",
|
||||
computed: {
|
||||
noData() {
|
||||
return t('noData')
|
||||
},
|
||||
noNetwork() {
|
||||
return t('noNetwork')
|
||||
},
|
||||
toSet() {
|
||||
return t('toSet')
|
||||
},
|
||||
error() {
|
||||
return t('error')
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
"networkType": ""
|
||||
};
|
||||
},
|
||||
props: {
|
||||
state: {
|
||||
type: Object,
|
||||
default () {
|
||||
return {
|
||||
"loading": true,
|
||||
"hasMore": false,
|
||||
"pagination": {
|
||||
"pages": 0
|
||||
},
|
||||
"data": [],
|
||||
"error": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
uni.onNetworkStatusChange(({
|
||||
networkType
|
||||
}) => {
|
||||
if (this.networkType == 'none' && networkType != 'none') { //之前没网现在有了
|
||||
this.$emit('networkResume')
|
||||
}
|
||||
this.networkType = networkType;
|
||||
});
|
||||
uni.getNetworkType({
|
||||
success: ({
|
||||
networkType
|
||||
}) => {
|
||||
this.networkType = networkType;
|
||||
}
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
appear() {
|
||||
if (!this.state.loading && this.state.hasMore) {
|
||||
this.$emit('loadMore')
|
||||
}
|
||||
},
|
||||
openSettings() {
|
||||
if (uni.getSystemInfoSync().platform == "ios") {
|
||||
var UIApplication = plus.ios.import("UIApplication");
|
||||
var application2 = UIApplication.sharedApplication();
|
||||
var NSURL2 = plus.ios.import("NSURL");
|
||||
var setting2 = NSURL2.URLWithString("App-prefs:root=General");
|
||||
application2.openURL(setting2);
|
||||
plus.ios.deleteObject(setting2);
|
||||
plus.ios.deleteObject(NSURL2);
|
||||
plus.ios.deleteObject(application2);
|
||||
} else {
|
||||
var Intent = plus.android.importClass("android.content.Intent");
|
||||
var Settings = plus.android.importClass("android.provider.Settings");
|
||||
var mainActivity = plus.android.runtimeMainActivity();
|
||||
var intent = new Intent(Settings.ACTION_SETTINGS);
|
||||
mainActivity.startActivity(intent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.box {
|
||||
flex: 1;
|
||||
width: 700rpx;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.uni-load-more{
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.state-text {
|
||||
text-align: center;
|
||||
font-size: 26rpx;
|
||||
width: 690rpx;
|
||||
padding: 10rpx;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.icon-image {
|
||||
width: 300rpx;
|
||||
}
|
||||
|
||||
.tip-text {
|
||||
color: #999999;
|
||||
font-size: 32rpx;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.btn {
|
||||
padding: 5px 10px;
|
||||
width: 128px;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.btn-text {
|
||||
color: #999999;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.btn-default {
|
||||
border-color: #999999;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.error {
|
||||
width: 690rpx;
|
||||
color: #DD524D;
|
||||
}
|
||||
</style>
|
@ -1,35 +0,0 @@
|
||||
# uni-cms源码使用许可协议
|
||||
|
||||
2022年10月
|
||||
|
||||
本许可协议,是数字天堂(北京)网络技术有限公司(以下简称DCloud)对其所拥有著作权的“DCloud uni-cms”(以下简称软件),提供的使用许可协议。
|
||||
|
||||
您对“软件”的复制、使用、修改及分发受本许可协议的条款的约束,如您不接受本协议,则不能使用、复制、修改本软件。
|
||||
|
||||
**授权许可范围**
|
||||
|
||||
a) 授予您永久性的、全球性的、免费的、非独占的、不可撤销的本软件的源码使用许可,您可以使用这些源码制作自己的应用。
|
||||
|
||||
b) 您只能在DCloud产品体系内使用本软件及其源码。您不能将源码修改后运行在DCloud产品体系之外的环境,比如客户端脱离uni-app,或服务端脱离uniCloud。
|
||||
|
||||
c) DCloud未向您授权商标使用许可。您在根据本软件源码制作自己的应用时,需以自己的名义发布软件,而不是以DCloud名义发布。
|
||||
|
||||
d) 本协议不构成代理关系。
|
||||
|
||||
DCloud的责任限制 “软件”在提供时不带任何明示或默示的担保。在任何情况下,DCloud不对任何人因使用“软件”而引发的任何直接或间接损失承担责任,不论因何种原因导致或者基于何种法律理论,即使其曾被建议有此种损失的可能性。
|
||||
|
||||
**您的责任限制**
|
||||
|
||||
a) 您需要在授权许可范围内使用软件。
|
||||
|
||||
b) 您在分发自己的应用时,不得侵犯DCloud商标和名誉权利。
|
||||
|
||||
c) 您不得进行破解、反编译、套壳等侵害DCloud知识产权的行为。您不得利用DCloud系统漏洞谋利或侵害DCloud利益,如您发现DCloud系统漏洞应第一时间通知DCloud。您不得进行攻击DCloud的服务器、网络等妨碍DCloud运营的行为。您不得利用DCloud的产品进行与DCloud争夺开发者的行为。
|
||||
|
||||
d) 如您违反本许可协议,需承担因此给DCloud造成的损失。
|
||||
|
||||
本协议签订地点为中华人民共和国北京市海淀区。
|
||||
|
||||
根据发展,DCloud可能会对本协议进行修改。修改时,DCloud会在产品或者网页中显著的位置发布相关信息以便及时通知到用户。如果您选择继续使用本框架,即表示您同意接受这些修改。
|
||||
|
||||
条款结束
|
@ -1,90 +0,0 @@
|
||||
{
|
||||
"id": "uni-cms-article",
|
||||
"displayName": "uni-cms-article",
|
||||
"version": "1.0.16",
|
||||
"description": "uni-cms的用户端,包括文章展示、搜索、看广告解锁等功能",
|
||||
"keywords": [
|
||||
"uni-cms-article",
|
||||
"cms",
|
||||
"uni-cms",
|
||||
"内容管理",
|
||||
"文章"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.1.0"
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "uniapp-template-page",
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "无",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": ""
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [
|
||||
"uni-search-bar",
|
||||
"uni-nav-bar",
|
||||
"uni-list"
|
||||
],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y",
|
||||
"alipay": "y"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
},
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "y"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "u",
|
||||
"Edge": "y",
|
||||
"Firefox": "y",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "u",
|
||||
"百度": "u",
|
||||
"字节跳动": "u",
|
||||
"QQ": "u",
|
||||
"钉钉": "u",
|
||||
"快手": "u",
|
||||
"飞书": "u",
|
||||
"京东": "u"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user