'初始化框架'
This commit is contained in:
commit
4c8780569f
3
.env.development
Normal file
3
.env.development
Normal file
@ -0,0 +1,3 @@
|
||||
NODE_ENV='development'
|
||||
VITE_APP_TITLE='开发环境'
|
||||
VITE_APP_BASE_API='http://114.132.197.85:8099'
|
3
.env.production
Normal file
3
.env.production
Normal file
@ -0,0 +1,3 @@
|
||||
NODE_ENV='production'
|
||||
VITE_APP_TITLE='生产环境'
|
||||
VITE_APP_BASE_API=''
|
3
.env.test
Normal file
3
.env.test
Normal file
@ -0,0 +1,3 @@
|
||||
NODE_ENV='test'
|
||||
VITE_APP_TITLE='测试环境'
|
||||
VITE_APP_BASE_API=''
|
21
.gitignore
vendored
Normal file
21
.gitignore
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
.DS_Store
|
||||
dist
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
24
README.md
Normal file
24
README.md
Normal file
@ -0,0 +1,24 @@
|
||||
## 介绍
|
||||
- - DCloud / uni-preset-vue 基于这个框架再次进行修改
|
||||
- - 基于vue3、pinia、uni-ui、luch-request、sass、uniapp强大的移动端框架。
|
||||
- - 开箱即用省去部分的开发时间;支持微信小程序和h5的框架
|
||||
- - 本框架已实现请求数据库的封装,pinia的基本使用,跨域请求数据、以及全局的自定义样式弹窗(个人感觉比uniapp里面的好看和实用)
|
||||
|
||||
## 安装依赖
|
||||
建议node版本在18版本
|
||||
pnpm install
|
||||
|
||||
# 开发注意
|
||||
1. 处理富文本必须使用rich-text标签,用html-parser.js来转换数据
|
||||
2. 简单的弹窗提醒用公共组件ConfirmPopup
|
||||
3. 消息提醒必须用uni.$showTost
|
||||
|
||||
# h5打包发布
|
||||
配置相对应的env文件
|
||||
测试环境 pnpm run build:h5:test
|
||||
正式环境 pnpm run build:h5
|
||||
|
||||
# 如果使用pnpm install报错 (应该是报的版本问题:Error: Expected "0.17.19" but got "0.16.17")
|
||||
1. pnpm store prune
|
||||
2. 删除node_modules
|
||||
3. 手动安装esbuild@0.17.19
|
20
index.html
Normal file
20
index.html
Normal file
@ -0,0 +1,20 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<script>
|
||||
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
|
||||
CSS.supports('top: constant(a)'))
|
||||
document.write(
|
||||
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
|
||||
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
|
||||
</script>
|
||||
<title></title>
|
||||
<!--preload-links-->
|
||||
<!--app-context-->
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"><!--app-html--></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</body>
|
||||
</html>
|
76
package.json
Normal file
76
package.json
Normal file
@ -0,0 +1,76 @@
|
||||
{
|
||||
"name": "uni-preset-vue",
|
||||
"version": "0.0.0",
|
||||
"scripts": {
|
||||
"dev:app": "uni -p app",
|
||||
"dev:app-android": "uni -p app-android",
|
||||
"dev:app-ios": "uni -p app-ios",
|
||||
"dev:custom": "uni -p",
|
||||
"dev:h5": "cross-env vite --mode development",
|
||||
"dev:h5:ssr": "uni --ssr",
|
||||
"dev:mp-alipay": "uni -p mp-alipay",
|
||||
"dev:mp-baidu": "uni -p mp-baidu",
|
||||
"dev:mp-jd": "uni -p mp-jd",
|
||||
"dev:mp-kuaishou": "uni -p mp-kuaishou",
|
||||
"dev:mp-lark": "uni -p mp-lark",
|
||||
"dev:mp-qq": "uni -p mp-qq",
|
||||
"dev:mp-toutiao": "uni -p mp-toutiao",
|
||||
"dev:mp-weixin": "uni -p mp-weixin",
|
||||
"dev:mp-xhs": "uni -p mp-xhs",
|
||||
"dev:quickapp-webview": "uni -p quickapp-webview",
|
||||
"dev:quickapp-webview-huawei": "uni -p quickapp-webview-huawei",
|
||||
"dev:quickapp-webview-union": "uni -p quickapp-webview-union",
|
||||
"build:app": "uni build -p app",
|
||||
"build:app-android": "uni build -p app-android",
|
||||
"build:app-ios": "uni build -p app-ios",
|
||||
"build:custom": "uni build -p",
|
||||
"build:h5:test": "cross-env NODE_ENV=test vite build --mode test",
|
||||
"build:h5": "cross-env NODE_ENV=production vite build --mode production",
|
||||
"build:h5:ssr": "uni build --ssr",
|
||||
"build:mp-alipay": "uni build -p mp-alipay",
|
||||
"build:mp-baidu": "uni build -p mp-baidu",
|
||||
"build:mp-jd": "uni build -p mp-jd",
|
||||
"build:mp-kuaishou": "uni build -p mp-kuaishou",
|
||||
"build:mp-lark": "uni build -p mp-lark",
|
||||
"build:mp-qq": "uni build -p mp-qq",
|
||||
"build:mp-toutiao": "uni build -p mp-toutiao",
|
||||
"build:mp-weixin": "uni build -p mp-weixin",
|
||||
"build:mp-xhs": "uni build -p mp-xhs",
|
||||
"build:quickapp-webview": "uni build -p quickapp-webview",
|
||||
"build:quickapp-webview-huawei": "uni build -p quickapp-webview-huawei",
|
||||
"build:quickapp-webview-union": "uni build -p quickapp-webview-union"
|
||||
},
|
||||
"dependencies": {
|
||||
"@dcloudio/uni-app": "3.0.0-3090420231025001",
|
||||
"@dcloudio/uni-app-plus": "3.0.0-3090420231025001",
|
||||
"@dcloudio/uni-components": "3.0.0-3090420231025001",
|
||||
"@dcloudio/uni-h5": "3.0.0-3090420231025001",
|
||||
"@dcloudio/uni-mp-alipay": "3.0.0-3090420231025001",
|
||||
"@dcloudio/uni-mp-baidu": "3.0.0-3090420231025001",
|
||||
"@dcloudio/uni-mp-jd": "3.0.0-3090420231025001",
|
||||
"@dcloudio/uni-mp-kuaishou": "3.0.0-3090420231025001",
|
||||
"@dcloudio/uni-mp-lark": "3.0.0-3090420231025001",
|
||||
"@dcloudio/uni-mp-qq": "3.0.0-3090420231025001",
|
||||
"@dcloudio/uni-mp-toutiao": "3.0.0-3090420231025001",
|
||||
"@dcloudio/uni-mp-weixin": "3.0.0-3090420231025001",
|
||||
"@dcloudio/uni-mp-xhs": "3.0.0-3090420231025001",
|
||||
"@dcloudio/uni-quickapp-webview": "3.0.0-3090420231025001",
|
||||
"@dcloudio/uni-ui": "^1.5.6",
|
||||
"cross-env": "^7.0.3",
|
||||
"esbuild": "0.17.19",
|
||||
"lodash": "^4.17.21",
|
||||
"pinia": "2.0.3",
|
||||
"sass": "1.63.4",
|
||||
"vue": "^3.2.45",
|
||||
"vue-i18n": "9.1.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@dcloudio/types": "^3.3.2",
|
||||
"@dcloudio/uni-automator": "3.0.0-3090420231025001",
|
||||
"@dcloudio/uni-cli-shared": "3.0.0-3090420231025001",
|
||||
"@dcloudio/uni-stacktracey": "3.0.0-3090420231025001",
|
||||
"@dcloudio/vite-plugin-uni": "3.0.0-3090420231025001",
|
||||
"@vue/runtime-core": "^3.2.45",
|
||||
"vite": "4.0.3"
|
||||
}
|
||||
}
|
7514
pnpm-lock.yaml
Normal file
7514
pnpm-lock.yaml
Normal file
File diff suppressed because it is too large
Load Diff
19
src/App.vue
Normal file
19
src/App.vue
Normal file
@ -0,0 +1,19 @@
|
||||
<script>
|
||||
export default {
|
||||
globalData: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<script setup>
|
||||
import { onLaunch } from "@dcloudio/uni-app";
|
||||
import { ref } from "vue";
|
||||
|
||||
onLaunch( async(e) => {
|
||||
|
||||
})
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@import 'assets/css/common.scss';
|
||||
</style>
|
10
src/api/index.js
Normal file
10
src/api/index.js
Normal file
@ -0,0 +1,10 @@
|
||||
import request from '@/utils/request';
|
||||
|
||||
/**
|
||||
* @function
|
||||
* @return
|
||||
**/
|
||||
export const getFriendLink = (params) => {
|
||||
return request.get('',{params})
|
||||
}
|
||||
|
12
src/assets/css/common.scss
Normal file
12
src/assets/css/common.scss
Normal file
@ -0,0 +1,12 @@
|
||||
view{
|
||||
box-sizing: border-box;
|
||||
}
|
||||
button {
|
||||
margin: 0 !important;
|
||||
border: none !important;
|
||||
border-radius: 16rpx;
|
||||
}
|
||||
.pages {
|
||||
height: 100vh;
|
||||
font-size: 26rpx;
|
||||
}
|
137
src/components/comfirm-popup.vue
Normal file
137
src/components/comfirm-popup.vue
Normal file
@ -0,0 +1,137 @@
|
||||
<template>
|
||||
<view>
|
||||
<uni-popup ref="popup" background-color="#fff" :is-mask-click="processLoad.isMaskClick" :mask-click="processLoad.isMaskClick">
|
||||
<view class="popup-content">
|
||||
<view class="header">{{params.title}}</view>
|
||||
<view class="main">
|
||||
<slot name="main">
|
||||
<view class="content-box" v-if="!processLoad.isHtml" :style="processLoad.contentStyle">
|
||||
{{params.content}}
|
||||
</view>
|
||||
<rich-text v-else class="content-box" :style="processLoad.contentStyle" :nodes="params.content"></rich-text>
|
||||
</slot>
|
||||
</view>
|
||||
<slot name="footer">
|
||||
<view class="footer">
|
||||
<view v-if="processLoad.showCancel" class="confirm-btn1 cancel" @click="close" type="primary">取消</view>
|
||||
<button :loading="confirmLoading" class="confirm-btn1" @click="confirm" type="primary">{{processLoad.confirmMsg}}</button>
|
||||
</view>
|
||||
</slot>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref,computed } from 'vue';
|
||||
|
||||
const popup = ref()
|
||||
const confirmLoading = ref(false)
|
||||
const params = ref({})
|
||||
|
||||
const processLoad = computed(() => {
|
||||
const {
|
||||
isHtml=false, // 是否为html
|
||||
showCancel=true, // 是否显示取消按钮
|
||||
isMaskClick=false, //点击遮罩层是否关闭弹窗
|
||||
isLoading=false, // 确认按钮是否加loading
|
||||
confirmMsg='确定', // 确认按钮的文字
|
||||
close=()=>{}, // 弹窗关闭回调
|
||||
confirm=()=>{}, // 弹窗确认回调
|
||||
contentStyle // content样式
|
||||
} = params.value.load || {}
|
||||
|
||||
return {
|
||||
isHtml,
|
||||
showCancel,
|
||||
isMaskClick,
|
||||
isLoading,
|
||||
confirmMsg,
|
||||
close,
|
||||
confirm,
|
||||
contentStyle
|
||||
}
|
||||
})
|
||||
|
||||
const setParams = (row) => {
|
||||
params.value = row
|
||||
}
|
||||
|
||||
const close = () => {
|
||||
processLoad.value.close()
|
||||
popup.value.close()
|
||||
}
|
||||
|
||||
const confirm = async () => {
|
||||
if (processLoad.value.isLoading) {
|
||||
confirmLoading.value = true
|
||||
try {
|
||||
await processLoad.value.confirm()
|
||||
confirmLoading.value = false
|
||||
popup.value.close()
|
||||
} catch(err) {
|
||||
confirmLoading.value = false
|
||||
popup.value.close()
|
||||
}
|
||||
} else {
|
||||
popup.value.close()
|
||||
processLoad.value.confirm()
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
popup,
|
||||
setParams
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep(.uni-popup__wrapper) {
|
||||
border-radius: 16rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
.popup-content {
|
||||
width: 668rpx;
|
||||
.header {
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
line-height: 90rpx;
|
||||
text-align: center;
|
||||
color: #4679f0;
|
||||
font-size: 35rpx;
|
||||
background-color: #eff3ff;
|
||||
}
|
||||
.main {
|
||||
width: 100%;
|
||||
max-height: 800rpx;
|
||||
margin-bottom: 20rpx;
|
||||
padding: 22rpx;
|
||||
overflow-y: auto;
|
||||
.content-box {
|
||||
margin-top: 40rpx;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
.footer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
padding-bottom: 20rpx;
|
||||
.confirm-btn1 {
|
||||
width: 260rpx;
|
||||
height: 80rpx;
|
||||
background: #4679F0;
|
||||
border-radius: 16rpx;
|
||||
font-size: 30rpx;
|
||||
color: #FFFFFF;
|
||||
text-align: center;
|
||||
line-height: 80rpx;
|
||||
}
|
||||
.cancel {
|
||||
border: 1px solid #e8e8e8;
|
||||
background: none !important;
|
||||
color:#333333;
|
||||
}
|
||||
}
|
||||
</style>
|
25
src/hooks/utils.js
Normal file
25
src/hooks/utils.js
Normal file
@ -0,0 +1,25 @@
|
||||
import { ref, nextTick } from 'vue';
|
||||
|
||||
// 公共弹窗hooks
|
||||
export const useComfirmPopup = () => {
|
||||
const popupShow = ref(false)
|
||||
const comfirmPopupRef = ref()
|
||||
|
||||
const openPopup = (row = {}) => {
|
||||
popupShow.value = true
|
||||
nextTick(() => {
|
||||
comfirmPopupRef.value.setParams({
|
||||
title: row.title || '温馨提示',
|
||||
content: row.content || '',
|
||||
load: row.load || {}
|
||||
})
|
||||
comfirmPopupRef.value.popup.open()
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
popupShow,
|
||||
comfirmPopupRef,
|
||||
openPopup
|
||||
}
|
||||
}
|
132
src/js_sdk/luch-request/luch-request/adapters/index.js
Normal file
132
src/js_sdk/luch-request/luch-request/adapters/index.js
Normal file
@ -0,0 +1,132 @@
|
||||
import buildURL from '../helpers/buildURL'
|
||||
import buildFullPath from '../core/buildFullPath'
|
||||
import settle from '../core/settle'
|
||||
import {isUndefined} from "../utils"
|
||||
|
||||
/**
|
||||
* 返回可选值存在的配置
|
||||
* @param {Array} keys - 可选值数组
|
||||
* @param {Object} config2 - 配置
|
||||
* @return {{}} - 存在的配置项
|
||||
*/
|
||||
const mergeKeys = (keys, config2) => {
|
||||
let config = {}
|
||||
keys.forEach(prop => {
|
||||
if (!isUndefined(config2[prop])) {
|
||||
config[prop] = config2[prop]
|
||||
}
|
||||
})
|
||||
return config
|
||||
}
|
||||
export default (config) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
let fullPath = buildURL(buildFullPath(config.baseURL, config.url), config.params, config.paramsSerializer)
|
||||
const _config = {
|
||||
url: fullPath,
|
||||
header: config.header,
|
||||
complete: (response) => {
|
||||
config.fullPath = fullPath
|
||||
response.config = config
|
||||
response.rawData = response.data
|
||||
try {
|
||||
let jsonParseHandle = false
|
||||
const forcedJSONParsingType = typeof config.forcedJSONParsing
|
||||
if (forcedJSONParsingType === 'boolean') {
|
||||
jsonParseHandle = config.forcedJSONParsing
|
||||
} else if (forcedJSONParsingType === 'object') {
|
||||
const includesMethod = config.forcedJSONParsing.include || []
|
||||
jsonParseHandle = includesMethod.includes(config.method)
|
||||
}
|
||||
|
||||
// 对可能字符串不是json 的情况容错
|
||||
if (jsonParseHandle && typeof response.data === 'string') {
|
||||
response.data = JSON.parse(response.data)
|
||||
}
|
||||
// eslint-disable-next-line no-empty
|
||||
} catch (e) {
|
||||
}
|
||||
settle(resolve, reject, response)
|
||||
}
|
||||
}
|
||||
let requestTask
|
||||
if (config.method === 'UPLOAD') {
|
||||
delete _config.header['content-type']
|
||||
delete _config.header['Content-Type']
|
||||
let otherConfig = {
|
||||
// #ifdef MP-ALIPAY
|
||||
fileType: config.fileType,
|
||||
// #endif
|
||||
filePath: config.filePath,
|
||||
name: config.name
|
||||
}
|
||||
const optionalKeys = [
|
||||
// #ifdef APP-PLUS || H5
|
||||
'files',
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
'file',
|
||||
// #endif
|
||||
// #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
|
||||
'timeout',
|
||||
// #endif
|
||||
'formData'
|
||||
]
|
||||
requestTask = uni.uploadFile({..._config, ...otherConfig, ...mergeKeys(optionalKeys, config)})
|
||||
} else if (config.method === 'DOWNLOAD') {
|
||||
const optionalKeys = [
|
||||
// #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
|
||||
'timeout',
|
||||
// #endif
|
||||
// #ifdef MP
|
||||
'filePath',
|
||||
// #endif
|
||||
]
|
||||
requestTask = uni.downloadFile({..._config, ...mergeKeys(optionalKeys, config)})
|
||||
} else {
|
||||
const optionalKeys = [
|
||||
'data',
|
||||
'method',
|
||||
// #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN
|
||||
'timeout',
|
||||
// #endif
|
||||
'dataType',
|
||||
// #ifndef MP-ALIPAY
|
||||
'responseType',
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
'sslVerify',
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
'withCredentials',
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
'firstIpv4',
|
||||
// #endif
|
||||
// #ifdef MP-WEIXIN
|
||||
'enableHttp2',
|
||||
'enableQuic',
|
||||
// #endif
|
||||
// #ifdef MP-TOUTIAO || MP-WEIXIN
|
||||
'enableCache',
|
||||
// #endif
|
||||
// #ifdef MP-WEIXIN
|
||||
'enableHttpDNS',
|
||||
'httpDNSServiceId',
|
||||
'enableChunked',
|
||||
'forceCellularNetwork',
|
||||
// #endif
|
||||
// #ifdef MP-ALIPAY
|
||||
'enableCookie',
|
||||
// #endif
|
||||
// #ifdef MP-BAIDU
|
||||
'cloudCache',
|
||||
'defer'
|
||||
// #endif
|
||||
]
|
||||
requestTask = uni.request({..._config, ...mergeKeys(optionalKeys, config)})
|
||||
}
|
||||
if (config.getTask) {
|
||||
config.getTask(requestTask, config)
|
||||
}
|
||||
})
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
'use strict'
|
||||
|
||||
|
||||
function InterceptorManager() {
|
||||
this.handlers = []
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new interceptor to the stack
|
||||
*
|
||||
* @param {Function} fulfilled The function to handle `then` for a `Promise`
|
||||
* @param {Function} rejected The function to handle `reject` for a `Promise`
|
||||
*
|
||||
* @return {Number} An ID used to remove interceptor later
|
||||
*/
|
||||
InterceptorManager.prototype.use = function use(fulfilled, rejected) {
|
||||
this.handlers.push({
|
||||
fulfilled: fulfilled,
|
||||
rejected: rejected
|
||||
})
|
||||
return this.handlers.length - 1
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an interceptor from the stack
|
||||
*
|
||||
* @param {Number} id The ID that was returned by `use`
|
||||
*/
|
||||
InterceptorManager.prototype.eject = function eject(id) {
|
||||
if (this.handlers[id]) {
|
||||
this.handlers[id] = null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate over all the registered interceptors
|
||||
*
|
||||
* This method is particularly useful for skipping over any
|
||||
* interceptors that may have become `null` calling `eject`.
|
||||
*
|
||||
* @param {Function} fn The function to call for each interceptor
|
||||
*/
|
||||
InterceptorManager.prototype.forEach = function forEach(fn) {
|
||||
this.handlers.forEach(h => {
|
||||
if (h !== null) {
|
||||
fn(h)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export default InterceptorManager
|
201
src/js_sdk/luch-request/luch-request/core/Request.js
Normal file
201
src/js_sdk/luch-request/luch-request/core/Request.js
Normal file
@ -0,0 +1,201 @@
|
||||
/**
|
||||
* @Class Request
|
||||
* @description luch-request http请求插件
|
||||
* @Author lu-ch
|
||||
* @Email webwork.s@qq.com
|
||||
* 文档: https://www.quanzhan.co/luch-request/
|
||||
* github: https://github.com/lei-mu/luch-request
|
||||
* DCloud: http://ext.dcloud.net.cn/plugin?id=392
|
||||
*/
|
||||
|
||||
|
||||
import dispatchRequest from './dispatchRequest'
|
||||
import InterceptorManager from './InterceptorManager'
|
||||
import mergeConfig from './mergeConfig'
|
||||
import defaults from './defaults'
|
||||
import { isPlainObject } from '../utils'
|
||||
import clone from '../utils/clone'
|
||||
|
||||
export default class Request {
|
||||
/**
|
||||
* @param {Object} arg - 全局配置
|
||||
* @param {String} arg.baseURL - 全局根路径
|
||||
* @param {Object} arg.header - 全局header
|
||||
* @param {String} arg.method = [GET|POST|PUT|DELETE|CONNECT|HEAD|OPTIONS|TRACE] - 全局默认请求方式
|
||||
* @param {String} arg.dataType = [json] - 全局默认的dataType
|
||||
* @param {String} arg.responseType = [text|arraybuffer] - 全局默认的responseType。支付宝小程序不支持
|
||||
* @param {Object} arg.custom - 全局默认的自定义参数
|
||||
* @param {Number} arg.timeout - 全局默认的超时时间,单位 ms。默认60000。H5(HBuilderX 2.9.9+)、APP(HBuilderX 2.9.9+)、微信小程序(2.10.0)、支付宝小程序
|
||||
* @param {Boolean} arg.sslVerify - 全局默认的是否验证 ssl 证书。默认true.仅App安卓端支持(HBuilderX 2.3.3+)
|
||||
* @param {Boolean} arg.withCredentials - 全局默认的跨域请求时是否携带凭证(cookies)。默认false。仅H5支持(HBuilderX 2.6.15+)
|
||||
* @param {Boolean} arg.firstIpv4 - 全DNS解析时优先使用ipv4。默认false。仅 App-Android 支持 (HBuilderX 2.8.0+)
|
||||
* @param {Function(statusCode):Boolean} arg.validateStatus - 全局默认的自定义验证器。默认statusCode >= 200 && statusCode < 300
|
||||
*/
|
||||
constructor(arg = {}) {
|
||||
if (!isPlainObject(arg)) {
|
||||
arg = {}
|
||||
console.warn('设置全局参数必须接收一个Object')
|
||||
}
|
||||
this.config = clone({...defaults, ...arg})
|
||||
this.interceptors = {
|
||||
request: new InterceptorManager(),
|
||||
response: new InterceptorManager()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Function
|
||||
* @param {Request~setConfigCallback} f - 设置全局默认配置
|
||||
*/
|
||||
setConfig(f) {
|
||||
this.config = f(this.config)
|
||||
}
|
||||
|
||||
middleware(config) {
|
||||
config = mergeConfig(this.config, config)
|
||||
let chain = [dispatchRequest, undefined]
|
||||
let promise = Promise.resolve(config)
|
||||
|
||||
this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
|
||||
chain.unshift(interceptor.fulfilled, interceptor.rejected)
|
||||
})
|
||||
|
||||
this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
|
||||
chain.push(interceptor.fulfilled, interceptor.rejected)
|
||||
})
|
||||
|
||||
while (chain.length) {
|
||||
promise = promise.then(chain.shift(), chain.shift())
|
||||
}
|
||||
|
||||
return promise
|
||||
}
|
||||
|
||||
/**
|
||||
* @Function
|
||||
* @param {Object} config - 请求配置项
|
||||
* @prop {String} options.url - 请求路径
|
||||
* @prop {Object} options.data - 请求参数
|
||||
* @prop {Object} [options.responseType = config.responseType] [text|arraybuffer] - 响应的数据类型
|
||||
* @prop {Object} [options.dataType = config.dataType] - 如果设为 json,会尝试对返回的数据做一次 JSON.parse
|
||||
* @prop {Object} [options.header = config.header] - 请求header
|
||||
* @prop {Object} [options.method = config.method] - 请求方法
|
||||
* @returns {Promise<unknown>}
|
||||
*/
|
||||
request(config = {}) {
|
||||
return this.middleware(config)
|
||||
}
|
||||
|
||||
get(url, options = {}) {
|
||||
return this.middleware({
|
||||
url,
|
||||
method: 'GET',
|
||||
...options
|
||||
})
|
||||
}
|
||||
|
||||
post(url, data, options = {}) {
|
||||
return this.middleware({
|
||||
url,
|
||||
data,
|
||||
method: 'POST',
|
||||
...options
|
||||
})
|
||||
}
|
||||
|
||||
// #ifndef MP-ALIPAY || MP-KUAISHOU || MP-JD
|
||||
put(url, data, options = {}) {
|
||||
return this.middleware({
|
||||
url,
|
||||
data,
|
||||
method: 'PUT',
|
||||
...options
|
||||
})
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
// #ifdef APP-PLUS || H5 || MP-WEIXIN || MP-BAIDU
|
||||
delete(url, data, options = {}) {
|
||||
return this.middleware({
|
||||
url,
|
||||
data,
|
||||
method: 'DELETE',
|
||||
...options
|
||||
})
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
// #ifdef H5 || MP-WEIXIN
|
||||
connect(url, data, options = {}) {
|
||||
return this.middleware({
|
||||
url,
|
||||
data,
|
||||
method: 'CONNECT',
|
||||
...options
|
||||
})
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
// #ifdef H5 || MP-WEIXIN || MP-BAIDU
|
||||
head(url, data, options = {}) {
|
||||
return this.middleware({
|
||||
url,
|
||||
data,
|
||||
method: 'HEAD',
|
||||
...options
|
||||
})
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
// #ifdef APP-PLUS || H5 || MP-WEIXIN || MP-BAIDU
|
||||
options(url, data, options = {}) {
|
||||
return this.middleware({
|
||||
url,
|
||||
data,
|
||||
method: 'OPTIONS',
|
||||
...options
|
||||
})
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
// #ifdef H5 || MP-WEIXIN
|
||||
trace(url, data, options = {}) {
|
||||
return this.middleware({
|
||||
url,
|
||||
data,
|
||||
method: 'TRACE',
|
||||
...options
|
||||
})
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
upload(url, config = {}) {
|
||||
config.url = url
|
||||
config.method = 'UPLOAD'
|
||||
return this.middleware(config)
|
||||
}
|
||||
|
||||
download(url, config = {}) {
|
||||
config.url = url
|
||||
config.method = 'DOWNLOAD'
|
||||
return this.middleware(config)
|
||||
}
|
||||
|
||||
get version () {
|
||||
return '3.1.0'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* setConfig回调
|
||||
* @return {Object} - 返回操作后的config
|
||||
* @callback Request~setConfigCallback
|
||||
* @param {Object} config - 全局默认config
|
||||
*/
|
20
src/js_sdk/luch-request/luch-request/core/buildFullPath.js
Normal file
20
src/js_sdk/luch-request/luch-request/core/buildFullPath.js
Normal file
@ -0,0 +1,20 @@
|
||||
'use strict'
|
||||
|
||||
import isAbsoluteURL from '../helpers/isAbsoluteURL'
|
||||
import combineURLs from '../helpers/combineURLs'
|
||||
|
||||
/**
|
||||
* Creates a new URL by combining the baseURL with the requestedURL,
|
||||
* only when the requestedURL is not already an absolute URL.
|
||||
* If the requestURL is absolute, this function returns the requestedURL untouched.
|
||||
*
|
||||
* @param {string} baseURL The base URL
|
||||
* @param {string} requestedURL Absolute or relative URL to combine
|
||||
* @returns {string} The combined full path
|
||||
*/
|
||||
export default function buildFullPath(baseURL, requestedURL) {
|
||||
if (baseURL && !isAbsoluteURL(requestedURL)) {
|
||||
return combineURLs(baseURL, requestedURL)
|
||||
}
|
||||
return requestedURL
|
||||
}
|
33
src/js_sdk/luch-request/luch-request/core/defaults.js
Normal file
33
src/js_sdk/luch-request/luch-request/core/defaults.js
Normal file
@ -0,0 +1,33 @@
|
||||
/**
|
||||
* 默认的全局配置
|
||||
*/
|
||||
|
||||
|
||||
export default {
|
||||
baseURL: '',
|
||||
header: {},
|
||||
method: 'GET',
|
||||
dataType: 'json',
|
||||
paramsSerializer: null,
|
||||
// #ifndef MP-ALIPAY
|
||||
responseType: 'text',
|
||||
// #endif
|
||||
custom: {},
|
||||
// #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
|
||||
timeout: 60000,
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
sslVerify: true,
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
withCredentials: false,
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
firstIpv4: false,
|
||||
// #endif
|
||||
validateStatus: function validateStatus(status) {
|
||||
return status >= 200 && status < 300
|
||||
},
|
||||
// 是否尝试将响应数据json化
|
||||
forcedJSONParsing: true
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
import adapter from '../adapters/index'
|
||||
|
||||
|
||||
export default (config) => {
|
||||
return adapter(config)
|
||||
}
|
126
src/js_sdk/luch-request/luch-request/core/mergeConfig.js
Normal file
126
src/js_sdk/luch-request/luch-request/core/mergeConfig.js
Normal file
@ -0,0 +1,126 @@
|
||||
import {deepMerge, isUndefined} from '../utils'
|
||||
|
||||
/**
|
||||
* 合并局部配置优先的配置,如果局部有该配置项则用局部,如果全局有该配置项则用全局
|
||||
* @param {Array} keys - 配置项
|
||||
* @param {Object} globalsConfig - 当前的全局配置
|
||||
* @param {Object} config2 - 局部配置
|
||||
* @return {{}}
|
||||
*/
|
||||
const mergeKeys = (keys, globalsConfig, config2) => {
|
||||
let config = {}
|
||||
keys.forEach(prop => {
|
||||
if (!isUndefined(config2[prop])) {
|
||||
config[prop] = config2[prop]
|
||||
} else if (!isUndefined(globalsConfig[prop])) {
|
||||
config[prop] = globalsConfig[prop]
|
||||
}
|
||||
})
|
||||
return config
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param globalsConfig - 当前实例的全局配置
|
||||
* @param config2 - 当前的局部配置
|
||||
* @return - 合并后的配置
|
||||
*/
|
||||
export default (globalsConfig, config2 = {}) => {
|
||||
const method = config2.method || globalsConfig.method || 'GET'
|
||||
let config = {
|
||||
baseURL: config2.baseURL || globalsConfig.baseURL || '',
|
||||
method: method,
|
||||
url: config2.url || '',
|
||||
params: config2.params || {},
|
||||
custom: {...(globalsConfig.custom || {}), ...(config2.custom || {})},
|
||||
header: deepMerge(globalsConfig.header || {}, config2.header || {})
|
||||
}
|
||||
const defaultToConfig2Keys = ['getTask', 'validateStatus', 'paramsSerializer', 'forcedJSONParsing']
|
||||
config = {...config, ...mergeKeys(defaultToConfig2Keys, globalsConfig, config2)}
|
||||
|
||||
// eslint-disable-next-line no-empty
|
||||
if (method === 'DOWNLOAD') {
|
||||
const downloadKeys = [
|
||||
// #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
|
||||
'timeout',
|
||||
// #endif
|
||||
// #ifdef MP
|
||||
'filePath',
|
||||
// #endif
|
||||
]
|
||||
config = {...config, ...mergeKeys(downloadKeys, globalsConfig, config2)}
|
||||
} else if (method === 'UPLOAD') {
|
||||
delete config.header['content-type']
|
||||
delete config.header['Content-Type']
|
||||
const uploadKeys = [
|
||||
// #ifdef APP-PLUS || H5
|
||||
'files',
|
||||
// #endif
|
||||
// #ifdef MP-ALIPAY
|
||||
'fileType',
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
'file',
|
||||
// #endif
|
||||
'filePath',
|
||||
'name',
|
||||
// #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
|
||||
'timeout',
|
||||
// #endif
|
||||
'formData',
|
||||
]
|
||||
uploadKeys.forEach(prop => {
|
||||
if (!isUndefined(config2[prop])) {
|
||||
config[prop] = config2[prop]
|
||||
}
|
||||
})
|
||||
// #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
|
||||
if (isUndefined(config.timeout) && !isUndefined(globalsConfig.timeout)) {
|
||||
config['timeout'] = globalsConfig['timeout']
|
||||
}
|
||||
// #endif
|
||||
} else {
|
||||
const defaultsKeys = [
|
||||
'data',
|
||||
// #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN
|
||||
'timeout',
|
||||
// #endif
|
||||
'dataType',
|
||||
// #ifndef MP-ALIPAY
|
||||
'responseType',
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
'sslVerify',
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
'withCredentials',
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
'firstIpv4',
|
||||
// #endif
|
||||
// #ifdef MP-WEIXIN
|
||||
'enableHttp2',
|
||||
'enableQuic',
|
||||
// #endif
|
||||
// #ifdef MP-TOUTIAO || MP-WEIXIN
|
||||
'enableCache',
|
||||
// #endif
|
||||
// #ifdef MP-WEIXIN
|
||||
'enableHttpDNS',
|
||||
'httpDNSServiceId',
|
||||
'enableChunked',
|
||||
'forceCellularNetwork',
|
||||
// #endif
|
||||
// #ifdef MP-ALIPAY
|
||||
'enableCookie',
|
||||
// #endif
|
||||
// #ifdef MP-BAIDU
|
||||
'cloudCache',
|
||||
'defer'
|
||||
// #endif
|
||||
|
||||
]
|
||||
config = {...config, ...mergeKeys(defaultsKeys, globalsConfig, config2)}
|
||||
}
|
||||
|
||||
return config
|
||||
}
|
16
src/js_sdk/luch-request/luch-request/core/settle.js
Normal file
16
src/js_sdk/luch-request/luch-request/core/settle.js
Normal file
@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Resolve or reject a Promise based on response status.
|
||||
*
|
||||
* @param {Function} resolve A function that resolves the promise.
|
||||
* @param {Function} reject A function that rejects the promise.
|
||||
* @param {object} response The response.
|
||||
*/
|
||||
export default function settle(resolve, reject, response) {
|
||||
const validateStatus = response.config.validateStatus
|
||||
const status = response.statusCode
|
||||
if (status && (!validateStatus || validateStatus(status))) {
|
||||
resolve(response)
|
||||
} else {
|
||||
reject(response)
|
||||
}
|
||||
}
|
64
src/js_sdk/luch-request/luch-request/helpers/buildURL.js
Normal file
64
src/js_sdk/luch-request/luch-request/helpers/buildURL.js
Normal file
@ -0,0 +1,64 @@
|
||||
'use strict'
|
||||
|
||||
import * as utils from './../utils'
|
||||
|
||||
function encode(val) {
|
||||
return encodeURIComponent(val).replace(/%40/gi, '@').replace(/%3A/gi, ':').replace(/%24/g, '$').replace(/%2C/gi, ',').replace(/%20/g, '+').replace(/%5B/gi, '[').replace(/%5D/gi, ']')
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a URL by appending params to the end
|
||||
*
|
||||
* @param {string} url The base of the url (e.g., http://www.google.com)
|
||||
* @param {object} [params] The params to be appended
|
||||
* @returns {string} The formatted url
|
||||
*/
|
||||
export default function buildURL(url, params, paramsSerializer) {
|
||||
/*eslint no-param-reassign:0*/
|
||||
if (!params) {
|
||||
return url
|
||||
}
|
||||
|
||||
var serializedParams
|
||||
if (paramsSerializer) {
|
||||
serializedParams = paramsSerializer(params)
|
||||
} else if (utils.isURLSearchParams(params)) {
|
||||
serializedParams = params.toString()
|
||||
} else {
|
||||
var parts = []
|
||||
|
||||
utils.forEach(params, function serialize(val, key) {
|
||||
if (val === null || typeof val === 'undefined') {
|
||||
return
|
||||
}
|
||||
|
||||
if (utils.isArray(val)) {
|
||||
key = key + '[]'
|
||||
} else {
|
||||
val = [val]
|
||||
}
|
||||
|
||||
utils.forEach(val, function parseValue(v) {
|
||||
if (utils.isDate(v)) {
|
||||
v = v.toISOString()
|
||||
} else if (utils.isObject(v)) {
|
||||
v = JSON.stringify(v)
|
||||
}
|
||||
parts.push(encode(key) + '=' + encode(v))
|
||||
})
|
||||
})
|
||||
|
||||
serializedParams = parts.join('&')
|
||||
}
|
||||
|
||||
if (serializedParams) {
|
||||
var hashmarkIndex = url.indexOf('#')
|
||||
if (hashmarkIndex !== -1) {
|
||||
url = url.slice(0, hashmarkIndex)
|
||||
}
|
||||
|
||||
url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams
|
||||
}
|
||||
|
||||
return url
|
||||
}
|
14
src/js_sdk/luch-request/luch-request/helpers/combineURLs.js
Normal file
14
src/js_sdk/luch-request/luch-request/helpers/combineURLs.js
Normal file
@ -0,0 +1,14 @@
|
||||
'use strict'
|
||||
|
||||
/**
|
||||
* Creates a new URL by combining the specified URLs
|
||||
*
|
||||
* @param {string} baseURL The base URL
|
||||
* @param {string} relativeURL The relative URL
|
||||
* @returns {string} The combined URL
|
||||
*/
|
||||
export default function combineURLs(baseURL, relativeURL) {
|
||||
return relativeURL
|
||||
? baseURL.replace(/\/+$/, '') + '/' + relativeURL.replace(/^\/+/, '')
|
||||
: baseURL
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
'use strict'
|
||||
|
||||
/**
|
||||
* Determines whether the specified URL is absolute
|
||||
*
|
||||
* @param {string} url The URL to test
|
||||
* @returns {boolean} True if the specified URL is absolute, otherwise false
|
||||
*/
|
||||
export default function isAbsoluteURL(url) {
|
||||
// A URL is considered absolute if it begins with "<scheme>://" or "//" (protocol-relative URL).
|
||||
// RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed
|
||||
// by any combination of letters, digits, plus, period, or hyphen.
|
||||
return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url)
|
||||
}
|
197
src/js_sdk/luch-request/luch-request/index.d.ts
vendored
Normal file
197
src/js_sdk/luch-request/luch-request/index.d.ts
vendored
Normal file
@ -0,0 +1,197 @@
|
||||
export type HttpTask = UniApp.RequestTask | UniApp.UploadTask | UniApp.DownloadTask;
|
||||
|
||||
export type HttpRequestTask = UniApp.RequestTask;
|
||||
|
||||
export type HttpUploadTask = UniApp.UploadTask;
|
||||
|
||||
export type HttpDownloadTask = UniApp.DownloadTask;
|
||||
|
||||
export type HttpMethod =
|
||||
"GET"
|
||||
| "POST"
|
||||
| "PUT"
|
||||
| "DELETE"
|
||||
| "CONNECT"
|
||||
| "HEAD"
|
||||
| "OPTIONS"
|
||||
| "TRACE"
|
||||
| "UPLOAD"
|
||||
| "DOWNLOAD";
|
||||
|
||||
export type HttpRequestHeader = Record<string, string>;
|
||||
|
||||
export type HttpParams = Record<string, any>;
|
||||
|
||||
export type HttpData = Record<string, any>;
|
||||
|
||||
export type HttpResponseType = 'arraybuffer' | 'text';
|
||||
|
||||
export type HttpCustom = Record<string, any>;
|
||||
|
||||
export type HttpFileType = 'image' | 'video' | 'audio';
|
||||
|
||||
export type HttpFormData = Record<string, any>;
|
||||
|
||||
export type HttpResponseHeader = Record<string, string> & {
|
||||
"set-cookie"?: string[]
|
||||
};
|
||||
|
||||
export interface HttpRequestConfig<T = HttpTask> {
|
||||
/** @desc 请求服务器接口地址 */
|
||||
url?: string;
|
||||
/** @desc 请求方式,默认为 GET */
|
||||
method?: HttpMethod;
|
||||
/** @desc 请求基地址 */
|
||||
baseURL?: string;
|
||||
/** @desc 请求头信息,不能设置 Referer,App、H5 端会自动带上 cookie,且 H5 端不可手动修改 */
|
||||
header?: HttpRequestHeader;
|
||||
/** @desc 请求查询参数,自动拼接为查询字符串 */
|
||||
params?: HttpParams;
|
||||
/** @desc 请求体参数 */
|
||||
data?: HttpData;
|
||||
/** @desc 超时时间,单位 ms,默认为 60000,仅 H5 (HBuilderX 2.9.9+)、APP (HBuilderX 2.9.9+)、微信小程序 (2.10.0)、支付宝小程序支持 */
|
||||
timeout?: number;
|
||||
/** @desc 跨域请求时是否携带凭证 (cookies),默认为 false,仅 H5 (HBuilderX 2.6.15+) 支持 */
|
||||
withCredentials?: boolean;
|
||||
/** @desc 设置响应的数据类型,支付宝小程序不支持 */
|
||||
responseType?: HttpResponseType;
|
||||
/** @desc 全局自定义验证器 */
|
||||
validateStatus?: ((statusCode: number) => boolean) | null;
|
||||
|
||||
|
||||
/** params 参数自定义处理 */
|
||||
paramsSerializer?: (params: AnyObject) => string | void;
|
||||
|
||||
/** @desc 默认为 json,如果设为 json,会尝试对返回的数据做一次 JSON.parse */
|
||||
dataType?: string;
|
||||
/** @desc DNS 解析时是否优先使用 ipv4,默认为 false,仅 App-Android (HBuilderX 2.8.0+) 支持 */
|
||||
firstIpv4?: boolean;
|
||||
/** @desc 是否验证 SSL 证书,默认为 true,仅 App-Android (HBuilderX 2.3.3+) 支持 */
|
||||
sslVerify?: boolean;
|
||||
|
||||
/** @desc 开启 http2;微信小程序 */
|
||||
enableHttp2?: boolean;
|
||||
|
||||
/** @desc 开启 quic;微信小程序 */
|
||||
enableQuic?: boolean;
|
||||
/** @desc 开启 cache;微信小程序、字节跳动小程序 2.31.0+ */
|
||||
enableCache?: boolean;
|
||||
/** @desc 开启 httpDNS;微信小程序 */
|
||||
enableHttpDNS?: boolean;
|
||||
/** @desc httpDNS 服务商;微信小程序 */
|
||||
httpDNSServiceId?: string;
|
||||
/** @desc 开启 transfer-encoding chunked;微信小程序 */
|
||||
enableChunked?: boolean;
|
||||
/** @desc wifi下使用移动网络发送请求;微信小程序 */
|
||||
forceCellularNetwork?: boolean;
|
||||
/** @desc 开启后可在headers中编辑cookie;支付宝小程序 10.2.33+ */
|
||||
enableCookie?: boolean;
|
||||
/** @desc 是否开启云加速;百度小程序 3.310.11+ */
|
||||
cloudCache?: boolean | object;
|
||||
/** @desc 控制当前请求是否延时至首屏内容渲染后发送;百度小程序 3.310.11+ */
|
||||
defer?: boolean;
|
||||
|
||||
/** @desc 自定义参数 */
|
||||
custom?: HttpCustom;
|
||||
|
||||
/** @desc 返回当前请求的 task 和 options,不要在这里修改 options */
|
||||
getTask?: (task: T, options: HttpRequestConfig<T>) => void;
|
||||
|
||||
/** @desc 需要上传的文件列表,使用 files 时,filePath 和 name 不生效,仅支持 App、H5 (2.6.15+) */
|
||||
files?: { name?: string; file?: File; uri: string; }[];
|
||||
/** @desc 文件类型,仅支付宝小程序支持且为必填项 */
|
||||
fileType?: HttpFileType;
|
||||
/** @desc 要上传的文件对象,仅 H5 (2.6.15+) 支持 */
|
||||
file?: File;
|
||||
/** @desc 要上传文件资源的路径,使用 files 时,filePath 和 name 不生效 */
|
||||
filePath?: string;
|
||||
/** @desc 文件对应的 key,开发者在服务器端通过这个 key 可以获取到文件二进制内容,使用 files 时,filePath 和 name 不生效 */
|
||||
name?: string;
|
||||
/** @desc 请求中其他额外的 form data */
|
||||
formData?: HttpFormData;
|
||||
}
|
||||
|
||||
export interface HttpResponse<T = any, D = HttpTask> {
|
||||
data: T;
|
||||
statusCode: number;
|
||||
header: HttpResponseHeader;
|
||||
config: HttpRequestConfig<D>;
|
||||
cookies: string[];
|
||||
errMsg: string;
|
||||
rawData: any;
|
||||
}
|
||||
|
||||
export interface HttpUploadResponse<T = any, D = HttpTask> {
|
||||
data: T;
|
||||
statusCode: number;
|
||||
config: HttpRequestConfig<D>;
|
||||
errMsg: string;
|
||||
rawData: any;
|
||||
}
|
||||
|
||||
export interface HttpDownloadResponse extends HttpResponse {
|
||||
tempFilePath: string;
|
||||
apFilePath?: string;
|
||||
filePath?: string;
|
||||
fileContent?: string;
|
||||
}
|
||||
|
||||
export interface HttpError<T = any, D = HttpTask> {
|
||||
data?: T;
|
||||
statusCode?: number;
|
||||
header?: HttpResponseHeader;
|
||||
config: HttpRequestConfig<D>;
|
||||
cookies?: string[];
|
||||
errMsg: string;
|
||||
}
|
||||
|
||||
export interface HttpPromise<T = any> extends Promise<HttpResponse<T>> {
|
||||
}
|
||||
|
||||
export interface HttpInterceptorManager<V, E = V> {
|
||||
use(onFulfilled?: (value: V) => V | Promise<V>, onRejected?: (error: E) => T | Promise<E>): void;
|
||||
|
||||
eject(id: number): void;
|
||||
}
|
||||
|
||||
export abstract class HttpRequestAbstract {
|
||||
constructor(config?: HttpRequestConfig);
|
||||
|
||||
interceptors: {
|
||||
request: HttpInterceptorManager<HttpRequestConfig>;
|
||||
response: HttpInterceptorManager<HttpResponse, HttpError>;
|
||||
}
|
||||
|
||||
request<T = any, R = HttpResponse<T>, D = HttpRequestTask>(config: HttpRequestConfig<D>): Promise<R>;
|
||||
|
||||
get<T = any, R = HttpResponse<T>, D = HttpRequestTask>(url: string, config?: HttpRequestConfig<D>): Promise<R>;
|
||||
|
||||
delete<T = any, R = HttpResponse<T>, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig<D>): Promise<R>;
|
||||
|
||||
head<T = any, R = HttpResponse<T>, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig<D>): Promise<R>;
|
||||
|
||||
options<T = any, R = HttpResponse<T>, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig<D>): Promise<R>;
|
||||
|
||||
post<T = any, R = HttpResponse<T>, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig<D>): Promise<R>;
|
||||
|
||||
put<T = any, R = HttpResponse<T>, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig<D>): Promise<R>;
|
||||
|
||||
config: HttpRequestConfig;
|
||||
|
||||
setConfig<D = HttpTask>(onSend: (config: HttpRequestConfig<D>) => HttpRequestConfig<D>): void;
|
||||
|
||||
connect<T = any, R = HttpResponse<T>, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig<D>): Promise<R>;
|
||||
|
||||
trace<T = any, R = HttpResponse<T>, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig<D>): Promise<R>;
|
||||
|
||||
upload<T = any, R = HttpUploadResponse<T>, D = HttpUploadTask>(url: string, config?: HttpRequestConfig<D>): Promise<R>;
|
||||
|
||||
download<T = any, R = HttpDownloadResponse<T>, D = HttpDownloadTask>(url: string, config?: HttpRequestConfig<D>): Promise<R>;
|
||||
|
||||
middleware<T = any, R = HttpResponse<T>, D = HttpTask>(config: HttpRequestConfig<D>): Promise<R>;
|
||||
}
|
||||
|
||||
declare class HttpRequest extends HttpRequestAbstract {
|
||||
}
|
||||
|
||||
export default HttpRequest;
|
2
src/js_sdk/luch-request/luch-request/index.js
Normal file
2
src/js_sdk/luch-request/luch-request/index.js
Normal file
@ -0,0 +1,2 @@
|
||||
import Request from './core/Request'
|
||||
export default Request
|
135
src/js_sdk/luch-request/luch-request/utils.js
Normal file
135
src/js_sdk/luch-request/luch-request/utils.js
Normal file
@ -0,0 +1,135 @@
|
||||
'use strict'
|
||||
|
||||
// utils is a library of generic helper functions non-specific to axios
|
||||
|
||||
var toString = Object.prototype.toString
|
||||
|
||||
/**
|
||||
* Determine if a value is an Array
|
||||
*
|
||||
* @param {Object} val The value to test
|
||||
* @returns {boolean} True if value is an Array, otherwise false
|
||||
*/
|
||||
export function isArray (val) {
|
||||
return toString.call(val) === '[object Array]'
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine if a value is an Object
|
||||
*
|
||||
* @param {Object} val The value to test
|
||||
* @returns {boolean} True if value is an Object, otherwise false
|
||||
*/
|
||||
export function isObject (val) {
|
||||
return val !== null && typeof val === 'object'
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a value is a Date
|
||||
*
|
||||
* @param {Object} val The value to test
|
||||
* @returns {boolean} True if value is a Date, otherwise false
|
||||
*/
|
||||
export function isDate (val) {
|
||||
return toString.call(val) === '[object Date]'
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a value is a URLSearchParams object
|
||||
*
|
||||
* @param {Object} val The value to test
|
||||
* @returns {boolean} True if value is a URLSearchParams object, otherwise false
|
||||
*/
|
||||
export function isURLSearchParams (val) {
|
||||
return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Iterate over an Array or an Object invoking a function for each item.
|
||||
*
|
||||
* If `obj` is an Array callback will be called passing
|
||||
* the value, index, and complete array for each item.
|
||||
*
|
||||
* If 'obj' is an Object callback will be called passing
|
||||
* the value, key, and complete object for each property.
|
||||
*
|
||||
* @param {Object|Array} obj The object to iterate
|
||||
* @param {Function} fn The callback to invoke for each item
|
||||
*/
|
||||
export function forEach (obj, fn) {
|
||||
// Don't bother if no value provided
|
||||
if (obj === null || typeof obj === 'undefined') {
|
||||
return
|
||||
}
|
||||
|
||||
// Force an array if not already something iterable
|
||||
if (typeof obj !== 'object') {
|
||||
/*eslint no-param-reassign:0*/
|
||||
obj = [obj]
|
||||
}
|
||||
|
||||
if (isArray(obj)) {
|
||||
// Iterate over array values
|
||||
for (var i = 0, l = obj.length; i < l; i++) {
|
||||
fn.call(null, obj[i], i, obj)
|
||||
}
|
||||
} else {
|
||||
// Iterate over object keys
|
||||
for (var key in obj) {
|
||||
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
||||
fn.call(null, obj[key], key, obj)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为boolean 值
|
||||
* @param val
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isBoolean(val) {
|
||||
return typeof val === 'boolean'
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为真正的对象{} new Object
|
||||
* @param {any} obj - 检测的对象
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isPlainObject(obj) {
|
||||
return Object.prototype.toString.call(obj) === '[object Object]'
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Function equal to merge with the difference being that no reference
|
||||
* to original objects is kept.
|
||||
*
|
||||
* @see merge
|
||||
* @param {Object} obj1 Object to merge
|
||||
* @returns {Object} Result of all merge properties
|
||||
*/
|
||||
export function deepMerge(/* obj1, obj2, obj3, ... */) {
|
||||
let result = {}
|
||||
function assignValue(val, key) {
|
||||
if (typeof result[key] === 'object' && typeof val === 'object') {
|
||||
result[key] = deepMerge(result[key], val)
|
||||
} else if (typeof val === 'object') {
|
||||
result[key] = deepMerge({}, val)
|
||||
} else {
|
||||
result[key] = val
|
||||
}
|
||||
}
|
||||
for (let i = 0, l = arguments.length; i < l; i++) {
|
||||
forEach(arguments[i], assignValue)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
export function isUndefined (val) {
|
||||
return typeof val === 'undefined'
|
||||
}
|
264
src/js_sdk/luch-request/luch-request/utils/clone.js
Normal file
264
src/js_sdk/luch-request/luch-request/utils/clone.js
Normal file
@ -0,0 +1,264 @@
|
||||
/* eslint-disable */
|
||||
var clone = (function() {
|
||||
'use strict';
|
||||
|
||||
function _instanceof(obj, type) {
|
||||
return type != null && obj instanceof type;
|
||||
}
|
||||
|
||||
var nativeMap;
|
||||
try {
|
||||
nativeMap = Map;
|
||||
} catch(_) {
|
||||
// maybe a reference error because no `Map`. Give it a dummy value that no
|
||||
// value will ever be an instanceof.
|
||||
nativeMap = function() {};
|
||||
}
|
||||
|
||||
var nativeSet;
|
||||
try {
|
||||
nativeSet = Set;
|
||||
} catch(_) {
|
||||
nativeSet = function() {};
|
||||
}
|
||||
|
||||
var nativePromise;
|
||||
try {
|
||||
nativePromise = Promise;
|
||||
} catch(_) {
|
||||
nativePromise = function() {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones (copies) an Object using deep copying.
|
||||
*
|
||||
* This function supports circular references by default, but if you are certain
|
||||
* there are no circular references in your object, you can save some CPU time
|
||||
* by calling clone(obj, false).
|
||||
*
|
||||
* Caution: if `circular` is false and `parent` contains circular references,
|
||||
* your program may enter an infinite loop and crash.
|
||||
*
|
||||
* @param `parent` - the object to be cloned
|
||||
* @param `circular` - set to true if the object to be cloned may contain
|
||||
* circular references. (optional - true by default)
|
||||
* @param `depth` - set to a number if the object is only to be cloned to
|
||||
* a particular depth. (optional - defaults to Infinity)
|
||||
* @param `prototype` - sets the prototype to be used when cloning an object.
|
||||
* (optional - defaults to parent prototype).
|
||||
* @param `includeNonEnumerable` - set to true if the non-enumerable properties
|
||||
* should be cloned as well. Non-enumerable properties on the prototype
|
||||
* chain will be ignored. (optional - false by default)
|
||||
*/
|
||||
function clone(parent, circular, depth, prototype, includeNonEnumerable) {
|
||||
if (typeof circular === 'object') {
|
||||
depth = circular.depth;
|
||||
prototype = circular.prototype;
|
||||
includeNonEnumerable = circular.includeNonEnumerable;
|
||||
circular = circular.circular;
|
||||
}
|
||||
// maintain two arrays for circular references, where corresponding parents
|
||||
// and children have the same index
|
||||
var allParents = [];
|
||||
var allChildren = [];
|
||||
|
||||
var useBuffer = typeof Buffer != 'undefined';
|
||||
|
||||
if (typeof circular == 'undefined')
|
||||
circular = true;
|
||||
|
||||
if (typeof depth == 'undefined')
|
||||
depth = Infinity;
|
||||
|
||||
// recurse this function so we don't reset allParents and allChildren
|
||||
function _clone(parent, depth) {
|
||||
// cloning null always returns null
|
||||
if (parent === null)
|
||||
return null;
|
||||
|
||||
if (depth === 0)
|
||||
return parent;
|
||||
|
||||
var child;
|
||||
var proto;
|
||||
if (typeof parent != 'object') {
|
||||
return parent;
|
||||
}
|
||||
|
||||
if (_instanceof(parent, nativeMap)) {
|
||||
child = new nativeMap();
|
||||
} else if (_instanceof(parent, nativeSet)) {
|
||||
child = new nativeSet();
|
||||
} else if (_instanceof(parent, nativePromise)) {
|
||||
child = new nativePromise(function (resolve, reject) {
|
||||
parent.then(function(value) {
|
||||
resolve(_clone(value, depth - 1));
|
||||
}, function(err) {
|
||||
reject(_clone(err, depth - 1));
|
||||
});
|
||||
});
|
||||
} else if (clone.__isArray(parent)) {
|
||||
child = [];
|
||||
} else if (clone.__isRegExp(parent)) {
|
||||
child = new RegExp(parent.source, __getRegExpFlags(parent));
|
||||
if (parent.lastIndex) child.lastIndex = parent.lastIndex;
|
||||
} else if (clone.__isDate(parent)) {
|
||||
child = new Date(parent.getTime());
|
||||
} else if (useBuffer && Buffer.isBuffer(parent)) {
|
||||
if (Buffer.from) {
|
||||
// Node.js >= 5.10.0
|
||||
child = Buffer.from(parent);
|
||||
} else {
|
||||
// Older Node.js versions
|
||||
child = new Buffer(parent.length);
|
||||
parent.copy(child);
|
||||
}
|
||||
return child;
|
||||
} else if (_instanceof(parent, Error)) {
|
||||
child = Object.create(parent);
|
||||
} else {
|
||||
if (typeof prototype == 'undefined') {
|
||||
proto = Object.getPrototypeOf(parent);
|
||||
child = Object.create(proto);
|
||||
}
|
||||
else {
|
||||
child = Object.create(prototype);
|
||||
proto = prototype;
|
||||
}
|
||||
}
|
||||
|
||||
if (circular) {
|
||||
var index = allParents.indexOf(parent);
|
||||
|
||||
if (index != -1) {
|
||||
return allChildren[index];
|
||||
}
|
||||
allParents.push(parent);
|
||||
allChildren.push(child);
|
||||
}
|
||||
|
||||
if (_instanceof(parent, nativeMap)) {
|
||||
parent.forEach(function(value, key) {
|
||||
var keyChild = _clone(key, depth - 1);
|
||||
var valueChild = _clone(value, depth - 1);
|
||||
child.set(keyChild, valueChild);
|
||||
});
|
||||
}
|
||||
if (_instanceof(parent, nativeSet)) {
|
||||
parent.forEach(function(value) {
|
||||
var entryChild = _clone(value, depth - 1);
|
||||
child.add(entryChild);
|
||||
});
|
||||
}
|
||||
|
||||
for (var i in parent) {
|
||||
var attrs = Object.getOwnPropertyDescriptor(parent, i);
|
||||
if (attrs) {
|
||||
child[i] = _clone(parent[i], depth - 1);
|
||||
}
|
||||
|
||||
try {
|
||||
var objProperty = Object.getOwnPropertyDescriptor(parent, i);
|
||||
if (objProperty.set === 'undefined') {
|
||||
// no setter defined. Skip cloning this property
|
||||
continue;
|
||||
}
|
||||
child[i] = _clone(parent[i], depth - 1);
|
||||
} catch(e){
|
||||
if (e instanceof TypeError) {
|
||||
// when in strict mode, TypeError will be thrown if child[i] property only has a getter
|
||||
// we can't do anything about this, other than inform the user that this property cannot be set.
|
||||
continue
|
||||
} else if (e instanceof ReferenceError) {
|
||||
//this may happen in non strict mode
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (Object.getOwnPropertySymbols) {
|
||||
var symbols = Object.getOwnPropertySymbols(parent);
|
||||
for (var i = 0; i < symbols.length; i++) {
|
||||
// Don't need to worry about cloning a symbol because it is a primitive,
|
||||
// like a number or string.
|
||||
var symbol = symbols[i];
|
||||
var descriptor = Object.getOwnPropertyDescriptor(parent, symbol);
|
||||
if (descriptor && !descriptor.enumerable && !includeNonEnumerable) {
|
||||
continue;
|
||||
}
|
||||
child[symbol] = _clone(parent[symbol], depth - 1);
|
||||
Object.defineProperty(child, symbol, descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
if (includeNonEnumerable) {
|
||||
var allPropertyNames = Object.getOwnPropertyNames(parent);
|
||||
for (var i = 0; i < allPropertyNames.length; i++) {
|
||||
var propertyName = allPropertyNames[i];
|
||||
var descriptor = Object.getOwnPropertyDescriptor(parent, propertyName);
|
||||
if (descriptor && descriptor.enumerable) {
|
||||
continue;
|
||||
}
|
||||
child[propertyName] = _clone(parent[propertyName], depth - 1);
|
||||
Object.defineProperty(child, propertyName, descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
return _clone(parent, depth);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple flat clone using prototype, accepts only objects, usefull for property
|
||||
* override on FLAT configuration object (no nested props).
|
||||
*
|
||||
* USE WITH CAUTION! This may not behave as you wish if you do not know how this
|
||||
* works.
|
||||
*/
|
||||
clone.clonePrototype = function clonePrototype(parent) {
|
||||
if (parent === null)
|
||||
return null;
|
||||
|
||||
var c = function () {};
|
||||
c.prototype = parent;
|
||||
return new c();
|
||||
};
|
||||
|
||||
// private utility functions
|
||||
|
||||
function __objToStr(o) {
|
||||
return Object.prototype.toString.call(o);
|
||||
}
|
||||
clone.__objToStr = __objToStr;
|
||||
|
||||
function __isDate(o) {
|
||||
return typeof o === 'object' && __objToStr(o) === '[object Date]';
|
||||
}
|
||||
clone.__isDate = __isDate;
|
||||
|
||||
function __isArray(o) {
|
||||
return typeof o === 'object' && __objToStr(o) === '[object Array]';
|
||||
}
|
||||
clone.__isArray = __isArray;
|
||||
|
||||
function __isRegExp(o) {
|
||||
return typeof o === 'object' && __objToStr(o) === '[object RegExp]';
|
||||
}
|
||||
clone.__isRegExp = __isRegExp;
|
||||
|
||||
function __getRegExpFlags(re) {
|
||||
var flags = '';
|
||||
if (re.global) flags += 'g';
|
||||
if (re.ignoreCase) flags += 'i';
|
||||
if (re.multiline) flags += 'm';
|
||||
return flags;
|
||||
}
|
||||
clone.__getRegExpFlags = __getRegExpFlags;
|
||||
|
||||
return clone;
|
||||
})();
|
||||
|
||||
export default clone
|
20
src/js_sdk/luch-request/package.json
Normal file
20
src/js_sdk/luch-request/package.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"id": "luch-request",
|
||||
"name": "luch-request",
|
||||
"displayName": "luch-request",
|
||||
"version": "3.1.0",
|
||||
"description": "基于Promise开发的跨平台、项目级别的请求库,它有更小的体积,易用的api,方便简单的自定义能力",
|
||||
"keywords": [
|
||||
"request",
|
||||
"axios",
|
||||
"网络请求",
|
||||
"拦截器",
|
||||
"promise"
|
||||
],
|
||||
"dcloudext": {
|
||||
"category": [
|
||||
"JS SDK",
|
||||
"通用 SDK"
|
||||
]
|
||||
}
|
||||
}
|
124
src/locale/en.json
Normal file
124
src/locale/en.json
Normal file
@ -0,0 +1,124 @@
|
||||
{
|
||||
"common": {
|
||||
"readMore": "READ MORE",
|
||||
"viewDetails": "view details",
|
||||
"truckModel": "Truck Model",
|
||||
"dimension": "Dimension (LxWxH)(mm)",
|
||||
"overhang": "Overhang (front/rear)(mm)",
|
||||
"wheelBase": "Wheelbase (mm)",
|
||||
"maxSpeed": "Max speed (km/h)",
|
||||
"curbWeight": "Curb weight (kg)",
|
||||
"loadingWeight": "Loading weight (kg)",
|
||||
"approachingAngle/Departure": "Approaching angle/Departure angle (º)",
|
||||
"products": "PRODUCTS",
|
||||
"companyProducts": "COMPANY PRODUCTS",
|
||||
"brand": "Brand",
|
||||
"driveWheel": "Drive Wheel",
|
||||
"drivingStyle": "Driving Style",
|
||||
"placeofOrigin": "Place of Origin",
|
||||
"tel": "Tel",
|
||||
"Mob/Whatsapp/Wechat": "Mob/Whatsapp/Wechat",
|
||||
"E-mail": "E-mail",
|
||||
"send": "SEND",
|
||||
"enterEail": "Enter your email here",
|
||||
"addressLabel": "Address",
|
||||
"fax": "Fax",
|
||||
"submit": "SUBMIT",
|
||||
"sendInquiry": "Send Inquiry",
|
||||
"chatNow": "Chat Now",
|
||||
"menu": "Menu",
|
||||
"search": "Search",
|
||||
"next": "Next",
|
||||
"prev": "Prev",
|
||||
"submitSuccess": "Submit success",
|
||||
"fulltextsearch": "Full text search",
|
||||
"language": "Language",
|
||||
"Categories": "Categories",
|
||||
"empty": "No data available at the moment",
|
||||
"Contact": "Contact",
|
||||
"Online": "Online",
|
||||
"Whats": "Whats",
|
||||
"TOP": "TOP"
|
||||
},
|
||||
"menu": {
|
||||
"Home": "Home",
|
||||
"AboutUs": "AboutUs",
|
||||
"Products": "Products",
|
||||
"News": "News",
|
||||
"Exhibition": "Exhibition",
|
||||
"ContactUs": "ContactUs",
|
||||
"Feedback": "Feedback"
|
||||
},
|
||||
"news": {
|
||||
"news": "News",
|
||||
"newsCenter": "NEWS CENTER",
|
||||
"allNews": "ALL NEWS",
|
||||
"relatedNews": "Related News",
|
||||
"relatedProducts": "Related Products"
|
||||
},
|
||||
"exhibition": {
|
||||
"exhibition": "Exhibition",
|
||||
"exhibitionCenter": "EXHIBITION CENTER",
|
||||
"allExhibition": "ALL EXHIBITION",
|
||||
"relatedExhibition": "Related Exhibition",
|
||||
"relatedProducts": "Related Products"
|
||||
},
|
||||
"products": {
|
||||
"products": "PRODUCTS",
|
||||
"allProducts": "ALL PRODUCTS",
|
||||
"productDetails": "Product Details",
|
||||
"inquiry": "Inquiry"
|
||||
},
|
||||
"index": {
|
||||
"companyProfile": "COMPANY PROFILE",
|
||||
"corporateName": "SINOTRUCK HOWO SALES CO.,LTD.",
|
||||
"companyProfileContent": "SINOTRUCK HOWO SALES CO.,LTD.is located in Jinan city, Shandong Province, P.R. China. It is the cradle and leading production base of the heavy-duty truck industry in China. It is famous for developing and manufacturing SINOTRUK HOWO tractor trucks, dump trucks, fuel tanker trucks and concrete mixer truck, water spraying trucks etc.",
|
||||
"highQuality": "HIGH QUALITY",
|
||||
"LEadingbBraNd": "LEADING BRAND",
|
||||
"experiencedStaff": "EXPERIENCED STAFF",
|
||||
"advancedEquipment": "ADVANCED EQUIPMENT",
|
||||
"popularProduct": "POPULAR PRODUCT",
|
||||
"productDesc": "The company's popular products are on display. Welcome to purchase",
|
||||
"pressCenter": "PRESS CENTER",
|
||||
"realTimeNewsReadingOnline": "Real-time news reading online",
|
||||
"joinOurNewsletter": "JOIN OUR NEWSLETTER",
|
||||
"signUpOurNewsletter": "Sign up our newsletter and get more events & promotions!"
|
||||
},
|
||||
"aboutUs": {
|
||||
"AboutUs": "About Us",
|
||||
"company": "Sinotruck Howo Sales Co.,Ltd",
|
||||
"address": "Room 2403, No.1 Yinzuo Jingdu Mansion, Shunhe East Street No.66, District Shizhong, Jinan city, shandong province, China"
|
||||
},
|
||||
"contactUs": {
|
||||
"contactUs": "Contact Us",
|
||||
"contacts": "Alice",
|
||||
"way": "Find us through some contact information",
|
||||
"contact": "Contact",
|
||||
"name": "Your name",
|
||||
"title": "Title",
|
||||
"company": "Company",
|
||||
"mail": "Mail",
|
||||
"contactWay": "Phone/WhatsApp",
|
||||
"desc": "Please fill in the form with details so we can send you a quotation correctly",
|
||||
"address": "Shangang xintiandi No8, 19 floor, Lixia district, jinan, Shandong, China"
|
||||
},
|
||||
"feedback": {
|
||||
"feedback": "Feedback",
|
||||
"way": "Find us through some contact information"
|
||||
},
|
||||
"footer": {
|
||||
"contactUs": "Contact us"
|
||||
},
|
||||
"seo": {
|
||||
"news": {
|
||||
"title": "China National Heavy Duty Truck Group Co., Ltd. - News List",
|
||||
"keywords": "China National Heavy Duty Truck Group (CNHTC) HOWO, HOWO Trucks, Heavy Truck Sales, Commercial Vehicles, Heavy duty Trucks, HOWO News, CNHTC News, Truck Trading, HOWO After sales Service, Large Trucks",
|
||||
"description": "China National Heavy Duty Truck Group Co., Ltd. provides the latest news, product information, and industry trends on HOWO trucks, focusing on heavy-duty truck sales and services. Understand the information of HOWO models, grasp the trends of the heavy-duty truck industry, and help you make wise purchasing decisions."
|
||||
},
|
||||
"product": {
|
||||
"title": "China National Heavy Duty Truck Group HOWO Product Display - HOWO Truck Series",
|
||||
"keywords": "China National Heavy Duty Truck Group (CNHTC) HOWO, HOWO Trucks, Heavy Truck Products, Heavy duty Trucks, Commercial Vehicles, HOWO Models, CNHTC Products, HOWO Truck Series, Large Trucks, Commercial Vehicle Products",
|
||||
"description": "China National Heavy Duty Truck Group Co., Ltd. provides a rich range of HOWO truck products, including various models and configurations. Understand the performance, technical specifications, and industry advantages of our heavy-duty trucks to meet your procurement needs."
|
||||
}
|
||||
}
|
||||
}
|
124
src/locale/zh.json
Normal file
124
src/locale/zh.json
Normal file
@ -0,0 +1,124 @@
|
||||
{
|
||||
"common": {
|
||||
"readMore": "阅读更多",
|
||||
"viewDetails": "查看详情",
|
||||
"truckModel": "卡车型号",
|
||||
"dimension": "尺寸(长x宽x高)(毫米)",
|
||||
"overhang": "悬垂(前/后)(mm)",
|
||||
"wheelBase": "轴距(mm)",
|
||||
"maxSpeed": "最高速度(公里/小时)",
|
||||
"curbWeight": "整备质量(kg)",
|
||||
"loadingWeight": "装载重量(kg)",
|
||||
"approachingAngle/Departure": "接近角/离开角(º)",
|
||||
"products": "产品",
|
||||
"companyProducts": "公司产品",
|
||||
"brand": "品牌",
|
||||
"driveWheel": "驱动轮",
|
||||
"drivingStyle": "驾驶方式",
|
||||
"placeofOrigin": "产地",
|
||||
"tel": "电话",
|
||||
"Mob/Whatsapp/Wechat": "手机/Whatsapp/微信",
|
||||
"E-mail": "电子邮件",
|
||||
"send": "发送",
|
||||
"enterEail": "在此处输入您的电子邮件",
|
||||
"addressLabel": "地址",
|
||||
"fax": "传真",
|
||||
"submit": "提交",
|
||||
"sendInquiry": "发送咨询",
|
||||
"chatNow": "立即聊天",
|
||||
"menu": "菜单",
|
||||
"search": "搜索",
|
||||
"next": "下一个",
|
||||
"prev": "上一个",
|
||||
"submitSuccess": "提交成功",
|
||||
"fulltextsearch": "全站搜索",
|
||||
"language": "语言",
|
||||
"Categories": "分类",
|
||||
"empty": "暂无数据",
|
||||
"Contact": "联系我们",
|
||||
"Online": "在线",
|
||||
"Whats": "Whatsapp",
|
||||
"TOP": "顶部"
|
||||
},
|
||||
"menu": {
|
||||
"Home": "首页",
|
||||
"AboutUs": "关于我们",
|
||||
"Products": "产品",
|
||||
"News": "新闻",
|
||||
"Exhibition": "展览",
|
||||
"ContactUs": "联系我们",
|
||||
"Feedback": "反馈"
|
||||
},
|
||||
"index": {
|
||||
"companyProfile": "公司简介",
|
||||
"corporateName": "中国重汽豪沃销售有限公司",
|
||||
"companyProfileContent": "中国重汽豪沃销售有限公司位于中国山东省济南市。它是中国重型卡车行业的摇篮和领先的生产基地。以开发和制造中国重汽豪沃牵引车、自卸卡车、油罐车和混凝土搅拌车、洒水车等而闻名。",
|
||||
"highQuality": "高品质",
|
||||
"LEadingbBraNd": "领先品牌",
|
||||
"experiencedStaff": "经验丰富的员工",
|
||||
"advancedEquipment": "先进设备",
|
||||
"popularProduct": "热门产品",
|
||||
"productDesc": "该公司的热门产品正在展出。欢迎购买",
|
||||
"pressCenter": "新闻中心",
|
||||
"realTimeNewsReadingOnline": "实时新闻在线阅读",
|
||||
"joinOurNewsletter": "加入我们的实时通讯",
|
||||
"signUpOurNewsletter": "注册我们的实时通讯,获取更多活动和促销!"
|
||||
},
|
||||
"news": {
|
||||
"news": "新闻",
|
||||
"newsCenter": "新闻中心",
|
||||
"allNews": "所有新闻",
|
||||
"relatedNews": "相关新闻",
|
||||
"relatedProducts": "相关产品"
|
||||
},
|
||||
"exhibition": {
|
||||
"exhibition": "展览",
|
||||
"exhibitionCenter": "展览中心",
|
||||
"allExhibition": "所有展览",
|
||||
"relatedExhibition": "相关展览",
|
||||
"relatedProducts": "相关产品"
|
||||
},
|
||||
"products": {
|
||||
"products": "产品",
|
||||
"allProducts": "所有产品",
|
||||
"productDetails": "产品详情",
|
||||
"inquiry": "询价"
|
||||
},
|
||||
"aboutUs": {
|
||||
"AboutUs": "关于我们",
|
||||
"company": "中车豪沃销售有限公司",
|
||||
"address": "中国山东省济南市市中区顺河东街66号银座京都大厦1号2403室"
|
||||
},
|
||||
"contactUs": {
|
||||
"contactUs": "联系我们",
|
||||
"contacts": "艾丽斯",
|
||||
"way": "通过一些联系方式找到我们",
|
||||
"contact": "联系",
|
||||
"name": "你的名字",
|
||||
"title": "你的职位",
|
||||
"company": "你的公司",
|
||||
"mail": "邮件",
|
||||
"contactWay": "电话/WhatsApp",
|
||||
"desc": "请详细填写表格,以便我们正确地向您发送报价",
|
||||
"address": "山东省济南市历下区19楼善港新天地8号"
|
||||
},
|
||||
"feedback": {
|
||||
"feedback": "反馈",
|
||||
"way": "通过一些联系方式找到我们"
|
||||
},
|
||||
"footer": {
|
||||
"contactUs": "联系我们"
|
||||
},
|
||||
"seo": {
|
||||
"news": {
|
||||
"title": "中国重汽豪沃销售有限公司 - 新闻列表",
|
||||
"keywords": "中国重汽豪沃, 豪沃卡车, 重卡销售, 商用车, 重型卡车, 豪沃新闻, 重汽新闻, 卡车交易, 豪沃售后服务, 大型卡车",
|
||||
"description": "中国重汽豪沃销售有限公司提供最新的豪沃卡车新闻、产品信息及行业动态,专注于重卡销售与服务。了解豪沃车型资讯,掌握重型卡车行业趋势,助您做出明智的采购决策。"
|
||||
},
|
||||
"product": {
|
||||
"title": "中国重汽豪沃产品展示 - 豪沃卡车系列",
|
||||
"keywords": "中国重汽豪沃, 豪沃卡车, 重卡产品, 重型卡车, 商用车, 豪沃车型, 重汽产品, 豪沃卡车系列, 大型卡车, 商用车产品",
|
||||
"description": "中国重汽豪沃销售有限公司提供丰富的豪沃卡车产品系列,包括各种车型和配置。了解我们的重型卡车性能、技术参数及行业优势,满足您的采购需求。"
|
||||
}
|
||||
}
|
||||
}
|
43
src/main.js
Normal file
43
src/main.js
Normal file
@ -0,0 +1,43 @@
|
||||
import { createSSRApp,provide,h } from "vue";
|
||||
import App from "./App.vue";
|
||||
import { createPinia } from 'pinia';
|
||||
import { createI18n } from 'vue-i18n';
|
||||
import zh from './locale/zh.json';
|
||||
import en from './locale/en.json';
|
||||
import ConfirmPopup from '@/components/comfirm-popup.vue'; // 全局统一的操作弹窗
|
||||
|
||||
uni.$showTost = function (title='加载失败!',duration=1500,mask=false) {
|
||||
// 变成异步代码,处理一些特殊页面 必须等待消息提示结束后在做操作
|
||||
return new Promise((res,rej) => {
|
||||
uni.showToast({
|
||||
title,
|
||||
mask,
|
||||
icon:'none',
|
||||
duration
|
||||
})
|
||||
setTimeout(() => {
|
||||
res(true)
|
||||
},duration)
|
||||
})
|
||||
}
|
||||
|
||||
const messages = {
|
||||
en,
|
||||
zh,
|
||||
}
|
||||
let i18nConfig = {
|
||||
locale: uni.getLocale(),// 获取已设置的语言
|
||||
messages
|
||||
}
|
||||
|
||||
const i18n = createI18n(i18nConfig)
|
||||
|
||||
export function createApp() {
|
||||
const app = createSSRApp(App);
|
||||
app.use(i18n)
|
||||
app.use(createPinia());
|
||||
app.component('ConfirmPopup', ConfirmPopup)
|
||||
return {
|
||||
app,
|
||||
};
|
||||
}
|
85
src/manifest.json
Normal file
85
src/manifest.json
Normal file
@ -0,0 +1,85 @@
|
||||
{
|
||||
"name" : "HOWO",
|
||||
"appid" : "__UNI__DADC1D2",
|
||||
"description" : "Sinotruck Howo Sales Co.,Ltd is one of the most professional trailer, truck, trailer parts, truck parts manufacturers in China. Our factory brings here a great selection of truck for sale. Welcome to consult price with us.",
|
||||
"versionName" : "1.0.0",
|
||||
"versionCode" : "100",
|
||||
"transformPx" : false,
|
||||
/* 5+App特有相关 */
|
||||
"app-plus" : {
|
||||
"usingComponents" : true,
|
||||
"nvueStyleCompiler" : "uni-app",
|
||||
"compilerVersion" : 3,
|
||||
"splashscreen" : {
|
||||
"alwaysShowBeforeRender" : true,
|
||||
"waiting" : true,
|
||||
"autoclose" : true,
|
||||
"delay" : 0
|
||||
},
|
||||
/* 模块配置 */
|
||||
"modules" : {},
|
||||
/* 应用发布信息 */
|
||||
"distribute" : {
|
||||
/* android打包配置 */
|
||||
"android" : {
|
||||
"permissions" : [
|
||||
"<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\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
|
||||
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
|
||||
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
|
||||
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
|
||||
"<uses-feature android:name=\"android.hardware.camera\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
|
||||
]
|
||||
},
|
||||
/* ios打包配置 */
|
||||
"ios" : {},
|
||||
/* SDK配置 */
|
||||
"sdkConfigs" : {}
|
||||
}
|
||||
},
|
||||
/* 快应用特有相关 */
|
||||
"quickapp" : {},
|
||||
/* 小程序特有相关 */
|
||||
"mp-weixin" : {
|
||||
"appid" : "wx4cb7d04123386d0e",
|
||||
"setting" : {
|
||||
"urlCheck" : false,
|
||||
"postcss" : true,
|
||||
"es6" : true,
|
||||
"minified" : true
|
||||
},
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-alipay" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-baidu" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-toutiao" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"uniStatistics" : {
|
||||
"enable" : false
|
||||
},
|
||||
"vueVersion" : "3",
|
||||
"h5" : {
|
||||
"router" : {
|
||||
"mode" : "history"
|
||||
},
|
||||
"devServer" : {
|
||||
"port" : 5173
|
||||
},
|
||||
"title" : "China Trailer, Truck, Trailer Parts, Truck Parts Manufacturers and Factory - Price - SINOTRUCK"
|
||||
},
|
||||
"locale" : "en"
|
||||
}
|
24
src/pages.json
Normal file
24
src/pages.json
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"easycom": {
|
||||
"autoscan": true,
|
||||
"custom": {
|
||||
// uni-ui 规则如下配置
|
||||
"^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue"
|
||||
}
|
||||
},
|
||||
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
|
||||
{
|
||||
"path": "pages/index/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "China Trailer, Truck, Trailer Parts, Truck Parts Manufacturers and Factory - Price - SINOTRUCK"
|
||||
}
|
||||
}
|
||||
],
|
||||
"globalStyle": {
|
||||
"navigationStyle": "custom",
|
||||
"navigationBarTextStyle": "black",
|
||||
"navigationBarTitleText": "China Trailer, Truck, Trailer Parts, Truck Parts Manufacturers and Factory - Price - SINOTRUCK",
|
||||
"navigationBarBackgroundColor": "#F8F8F8",
|
||||
"backgroundColor": "#F8F8F8"
|
||||
}
|
||||
}
|
25
src/pages/index/index.vue
Normal file
25
src/pages/index/index.vue
Normal file
@ -0,0 +1,25 @@
|
||||
<template>
|
||||
<view class="content">
|
||||
{{$t('index.companyProfile')}}
|
||||
<ConfirmPopup ref="comfirmPopupRef" v-if="popupShow" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { index } from '@/stores/index.js';
|
||||
import { useComfirmPopup } from '@/hooks/utils.js';
|
||||
import { getFriendLink } from '@/api/index.js';
|
||||
|
||||
const { popupShow,comfirmPopupRef,openPopup } = useComfirmPopup()
|
||||
|
||||
const piniaIndex = index()
|
||||
onLoad(() => {
|
||||
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
BIN
src/static/logo.png
Normal file
BIN
src/static/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.9 KiB |
14
src/stores/index.js
Normal file
14
src/stores/index.js
Normal file
@ -0,0 +1,14 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import { reactive, ref } from 'vue';
|
||||
|
||||
export const index = defineStore('index',()=>{
|
||||
let num = ref(0);
|
||||
|
||||
const countHanderl = () => {
|
||||
num.value += 1
|
||||
}
|
||||
return {
|
||||
num,
|
||||
countHanderl
|
||||
}
|
||||
})
|
76
src/uni.scss
Normal file
76
src/uni.scss
Normal file
@ -0,0 +1,76 @@
|
||||
/**
|
||||
* 这里是uni-app内置的常用样式变量
|
||||
*
|
||||
* uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
|
||||
* 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
|
||||
*
|
||||
* 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
|
||||
*/
|
||||
|
||||
/* 颜色变量 */
|
||||
|
||||
/* 行为相关颜色 */
|
||||
$uni-color-primary: #007aff;
|
||||
$uni-color-success: #4cd964;
|
||||
$uni-color-warning: #f0ad4e;
|
||||
$uni-color-error: #dd524d;
|
||||
|
||||
/* 文字基本颜色 */
|
||||
$uni-text-color: #333; // 基本色
|
||||
$uni-text-color-inverse: #fff; // 反色
|
||||
$uni-text-color-grey: #999; // 辅助灰色,如加载更多的提示信息
|
||||
$uni-text-color-placeholder: #808080;
|
||||
$uni-text-color-disable: #c0c0c0;
|
||||
|
||||
/* 背景颜色 */
|
||||
$uni-bg-color: #fff;
|
||||
$uni-bg-color-grey: #f8f8f8;
|
||||
$uni-bg-color-hover: #f1f1f1; // 点击状态颜色
|
||||
$uni-bg-color-mask: rgba(0, 0, 0, 0.4); // 遮罩颜色
|
||||
|
||||
/* 边框颜色 */
|
||||
$uni-border-color: #c8c7cc;
|
||||
|
||||
/* 尺寸变量 */
|
||||
|
||||
/* 文字尺寸 */
|
||||
$uni-font-size-sm: 12px;
|
||||
$uni-font-size-base: 14px;
|
||||
$uni-font-size-lg: 16;
|
||||
|
||||
/* 图片尺寸 */
|
||||
$uni-img-size-sm: 20px;
|
||||
$uni-img-size-base: 26px;
|
||||
$uni-img-size-lg: 40px;
|
||||
|
||||
/* Border Radius */
|
||||
$uni-border-radius-sm: 2px;
|
||||
$uni-border-radius-base: 3px;
|
||||
$uni-border-radius-lg: 6px;
|
||||
$uni-border-radius-circle: 50%;
|
||||
|
||||
/* 水平间距 */
|
||||
$uni-spacing-row-sm: 5px;
|
||||
$uni-spacing-row-base: 10px;
|
||||
$uni-spacing-row-lg: 15px;
|
||||
|
||||
/* 垂直间距 */
|
||||
$uni-spacing-col-sm: 4px;
|
||||
$uni-spacing-col-base: 8px;
|
||||
$uni-spacing-col-lg: 12px;
|
||||
|
||||
/* 透明度 */
|
||||
$uni-opacity-disabled: 0.3; // 组件禁用态的透明度
|
||||
|
||||
/* 文章场景相关 */
|
||||
$uni-color-title: #2c405a; // 文章标题颜色
|
||||
$uni-font-size-title: 20px;
|
||||
$uni-color-subtitle: #555; // 二级标题颜色
|
||||
$uni-font-size-subtitle: 18px;
|
||||
$uni-color-paragraph: #3f536e; // 文章段落颜色
|
||||
$uni-font-size-paragraph: 15px;
|
352
src/utils/html-parser.js
Normal file
352
src/utils/html-parser.js
Normal file
@ -0,0 +1,352 @@
|
||||
/*
|
||||
* HTML5 Parser By Sam Blowes
|
||||
*
|
||||
* Designed for HTML5 documents
|
||||
*
|
||||
* Original code by John Resig (ejohn.org)
|
||||
* http://ejohn.org/blog/pure-javascript-html-parser/
|
||||
* Original code by Erik Arvidsson, Mozilla Public License
|
||||
* http://erik.eae.net/simplehtmlparser/simplehtmlparser.js
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* License
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* This code is triple licensed using Apache Software License 2.0,
|
||||
* Mozilla Public License or GNU Public License
|
||||
*
|
||||
* ////////////////////////////////////////////////////////////////////////////
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* ////////////////////////////////////////////////////////////////////////////
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing rights and limitations
|
||||
* under the License.
|
||||
*
|
||||
* The Original Code is Simple HTML Parser.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Erik Arvidsson.
|
||||
* Portions created by Erik Arvidssson are Copyright (C) 2004. All Rights
|
||||
* Reserved.
|
||||
*
|
||||
* ////////////////////////////////////////////////////////////////////////////
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* Usage
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* // Use like so:
|
||||
* HTMLParser(htmlString, {
|
||||
* start: function(tag, attrs, unary) {},
|
||||
* end: function(tag) {},
|
||||
* chars: function(text) {},
|
||||
* comment: function(text) {}
|
||||
* });
|
||||
*
|
||||
* // or to get an XML string:
|
||||
* HTMLtoXML(htmlString);
|
||||
*
|
||||
* // or to get an XML DOM Document
|
||||
* HTMLtoDOM(htmlString);
|
||||
*
|
||||
* // or to inject into an existing document/DOM node
|
||||
* HTMLtoDOM(htmlString, document);
|
||||
* HTMLtoDOM(htmlString, document.body);
|
||||
*
|
||||
*/
|
||||
// Regular Expressions for parsing tags and attributes
|
||||
var startTag = /^<([-A-Za-z0-9_]+)((?:\s+[a-zA-Z_:][-a-zA-Z0-9_:.]*(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/;
|
||||
var endTag = /^<\/([-A-Za-z0-9_]+)[^>]*>/;
|
||||
var attr = /([a-zA-Z_:][-a-zA-Z0-9_:.]*)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|([^>\s]+)))?/g; // Empty Elements - HTML 5
|
||||
|
||||
var empty = makeMap('area,base,basefont,br,col,frame,hr,img,input,link,meta,param,embed,command,keygen,source,track,wbr'); // Block Elements - HTML 5
|
||||
// fixed by xxx 将 ins 标签从块级名单中移除
|
||||
|
||||
var block = makeMap('a,address,article,applet,aside,audio,blockquote,button,canvas,center,dd,del,dir,div,dl,dt,fieldset,figcaption,figure,footer,form,frameset,h1,h2,h3,h4,h5,h6,header,hgroup,hr,iframe,isindex,li,map,menu,noframes,noscript,object,ol,output,p,pre,section,script,table,tbody,td,tfoot,th,thead,tr,ul,video'); // Inline Elements - HTML 5
|
||||
|
||||
var inline = makeMap('abbr,acronym,applet,b,basefont,bdo,big,br,button,cite,code,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,object,q,s,samp,script,select,small,span,strike,strong,sub,sup,textarea,tt,u,var'); // Elements that you can, intentionally, leave open
|
||||
// (and which close themselves)
|
||||
|
||||
var closeSelf = makeMap('colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr'); // Attributes that have their values filled in disabled="disabled"
|
||||
|
||||
var fillAttrs = makeMap('checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected'); // Special Elements (can contain anything)
|
||||
|
||||
var special = makeMap('script,style');
|
||||
function HTMLParser(html, handler) {
|
||||
var index;
|
||||
var chars;
|
||||
var match;
|
||||
var stack = [];
|
||||
var last = html;
|
||||
|
||||
stack.last = function () {
|
||||
return this[this.length - 1];
|
||||
};
|
||||
|
||||
while (html) {
|
||||
chars = true; // Make sure we're not in a script or style element
|
||||
|
||||
if (!stack.last() || !special[stack.last()]) {
|
||||
// Comment
|
||||
if (html.indexOf('<!--') == 0) {
|
||||
index = html.indexOf('-->');
|
||||
|
||||
if (index >= 0) {
|
||||
if (handler.comment) {
|
||||
handler.comment(html.substring(4, index));
|
||||
}
|
||||
|
||||
html = html.substring(index + 3);
|
||||
chars = false;
|
||||
} // end tag
|
||||
|
||||
} else if (html.indexOf('</') == 0) {
|
||||
match = html.match(endTag);
|
||||
|
||||
if (match) {
|
||||
html = html.substring(match[0].length);
|
||||
match[0].replace(endTag, parseEndTag);
|
||||
chars = false;
|
||||
} // start tag
|
||||
|
||||
} else if (html.indexOf('<') == 0) {
|
||||
match = html.match(startTag);
|
||||
|
||||
if (match) {
|
||||
html = html.substring(match[0].length);
|
||||
match[0].replace(startTag, parseStartTag);
|
||||
chars = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (chars) {
|
||||
index = html.indexOf('<');
|
||||
var text = index < 0 ? html : html.substring(0, index);
|
||||
html = index < 0 ? '' : html.substring(index);
|
||||
|
||||
if (handler.chars) {
|
||||
handler.chars(text);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
html = html.replace(new RegExp('([\\s\\S]*?)<\/' + stack.last() + '[^>]*>'), function (all, text) {
|
||||
text = text.replace(/<!--([\s\S]*?)-->|<!\[CDATA\[([\s\S]*?)]]>/g, '$1$2');
|
||||
|
||||
if (handler.chars) {
|
||||
handler.chars(text);
|
||||
}
|
||||
|
||||
return '';
|
||||
});
|
||||
parseEndTag('', stack.last());
|
||||
}
|
||||
|
||||
if (html == last) {
|
||||
throw 'Parse Error: ' + html;
|
||||
}
|
||||
|
||||
last = html;
|
||||
} // Clean up any remaining tags
|
||||
|
||||
|
||||
parseEndTag();
|
||||
|
||||
function parseStartTag(tag, tagName, rest, unary) {
|
||||
tagName = tagName.toLowerCase();
|
||||
|
||||
if (block[tagName]) {
|
||||
while (stack.last() && inline[stack.last()]) {
|
||||
parseEndTag('', stack.last());
|
||||
}
|
||||
}
|
||||
|
||||
if (closeSelf[tagName] && stack.last() == tagName) {
|
||||
parseEndTag('', tagName);
|
||||
}
|
||||
|
||||
unary = empty[tagName] || !!unary;
|
||||
|
||||
if (!unary) {
|
||||
stack.push(tagName);
|
||||
}
|
||||
|
||||
if (handler.start) {
|
||||
var attrs = [];
|
||||
rest.replace(attr, function (match, name) {
|
||||
var value = arguments[2] ? arguments[2] : arguments[3] ? arguments[3] : arguments[4] ? arguments[4] : fillAttrs[name] ? name : '';
|
||||
attrs.push({
|
||||
name: name,
|
||||
value: value,
|
||||
escaped: value.replace(/(^|[^\\])"/g, '$1\\\"') // "
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
if (handler.start) {
|
||||
handler.start(tagName, attrs, unary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function parseEndTag(tag, tagName) {
|
||||
// If no tag name is provided, clean shop
|
||||
if (!tagName) {
|
||||
var pos = 0;
|
||||
} // Find the closest opened tag of the same type
|
||||
else {
|
||||
for (var pos = stack.length - 1; pos >= 0; pos--) {
|
||||
if (stack[pos] == tagName) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pos >= 0) {
|
||||
// Close all the open elements, up the stack
|
||||
for (var i = stack.length - 1; i >= pos; i--) {
|
||||
if (handler.end) {
|
||||
handler.end(stack[i]);
|
||||
}
|
||||
} // Remove the open elements from the stack
|
||||
|
||||
|
||||
stack.length = pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function makeMap(str) {
|
||||
var obj = {};
|
||||
var items = str.split(',');
|
||||
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
obj[items[i]] = true;
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
function removeDOCTYPE(html) {
|
||||
return html.replace(/<\?xml.*\?>\n/, '').replace(/<!doctype.*>\n/, '').replace(/<!DOCTYPE.*>\n/, '');
|
||||
}
|
||||
|
||||
function parseAttrs(attrs) {
|
||||
return attrs.reduce(function (pre, attr) {
|
||||
var value = attr.value;
|
||||
var name = attr.name;
|
||||
|
||||
if (pre[name]) {
|
||||
pre[name] = pre[name] + " " + value;
|
||||
} else {
|
||||
pre[name] = value;
|
||||
}
|
||||
|
||||
return pre;
|
||||
}, {});
|
||||
}
|
||||
|
||||
function parseHtml(html) {
|
||||
html = removeDOCTYPE(html);
|
||||
var stacks = [];
|
||||
var results = {
|
||||
node: 'root',
|
||||
children: []
|
||||
};
|
||||
HTMLParser(html, {
|
||||
start: function start(tag, attrs, unary) {
|
||||
var node = {
|
||||
name: tag
|
||||
};
|
||||
|
||||
if (attrs.length !== 0) {
|
||||
node.attrs = parseAttrs(attrs);
|
||||
}
|
||||
|
||||
if (unary) {
|
||||
var parent = stacks[0] || results;
|
||||
|
||||
if (!parent.children) {
|
||||
parent.children = [];
|
||||
}
|
||||
|
||||
parent.children.push(node);
|
||||
} else {
|
||||
stacks.unshift(node);
|
||||
}
|
||||
},
|
||||
end: function end(tag) {
|
||||
var node = stacks.shift();
|
||||
if (node.name !== tag) console.error('invalid state: mismatch end tag');
|
||||
|
||||
if (stacks.length === 0) {
|
||||
results.children.push(node);
|
||||
} else {
|
||||
var parent = stacks[0];
|
||||
|
||||
if (!parent.children) {
|
||||
parent.children = [];
|
||||
}
|
||||
|
||||
parent.children.push(node);
|
||||
}
|
||||
},
|
||||
chars: function chars(text) {
|
||||
var node = {
|
||||
type: 'text',
|
||||
text: text
|
||||
};
|
||||
|
||||
if (stacks.length === 0) {
|
||||
results.children.push(node);
|
||||
} else {
|
||||
var parent = stacks[0];
|
||||
|
||||
if (!parent.children) {
|
||||
parent.children = [];
|
||||
}
|
||||
|
||||
parent.children.push(node);
|
||||
}
|
||||
},
|
||||
comment: function comment(text) {
|
||||
var node = {
|
||||
node: 'comment',
|
||||
text: text
|
||||
};
|
||||
var parent = stacks[0];
|
||||
|
||||
if (!parent.children) {
|
||||
parent.children = [];
|
||||
}
|
||||
|
||||
parent.children.push(node);
|
||||
}
|
||||
});
|
||||
return results.children;
|
||||
}
|
||||
|
||||
export default parseHtml;
|
49
src/utils/request.js
Normal file
49
src/utils/request.js
Normal file
@ -0,0 +1,49 @@
|
||||
import Request from '@/js_sdk/luch-request/luch-request/index.js';
|
||||
|
||||
let $http = new Request()
|
||||
|
||||
$http.config = {
|
||||
baseURL: import.meta.env.VITE_APP_BASE_API
|
||||
}
|
||||
|
||||
// 请求拦截器
|
||||
// web运行端口默认5173;可在manifest进行修改默认端口号
|
||||
$http.interceptors.request.use(async (config) => { // 可使用async await 做异步操作
|
||||
config.header = {
|
||||
...config.header,
|
||||
'Token': uni.getStorageSync('annualTicketToken'),
|
||||
}
|
||||
uni.showLoading({
|
||||
title: '加载中...',
|
||||
mask: true
|
||||
})
|
||||
return config
|
||||
|
||||
}, config => { // 可使用async await 做异步操作
|
||||
return Promise.reject(config)
|
||||
})
|
||||
|
||||
// 响应拦截器
|
||||
$http.interceptors.response.use((response) => {
|
||||
uni.hideLoading()
|
||||
switch(response.data.code) {
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
// 加入到messageBoxUrl的请求url可触发弹窗形式的提示
|
||||
let messageBoxUrl = []
|
||||
if (messageBoxUrl.indexOf(response.config.url) !== -1) {
|
||||
uni.$showModal('提示',response.data.msg)
|
||||
} else {
|
||||
if (response.data.msg) {
|
||||
uni.$showTost(response.data.msg)
|
||||
}
|
||||
}
|
||||
return Promise.reject(response)
|
||||
}
|
||||
return response
|
||||
}, (response) => {
|
||||
return Promise.reject(response)
|
||||
})
|
||||
|
||||
export default $http
|
87
src/utils/tool.js
Normal file
87
src/utils/tool.js
Normal file
@ -0,0 +1,87 @@
|
||||
/**
|
||||
* @function 获取uuid
|
||||
* @return {string} 返回uuid
|
||||
**/
|
||||
export const getUuid = () => {
|
||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
|
||||
return (c === 'x' ? (Math.random() * 16 | 0) : ('r&0x3' | '0x8')).toString(16)
|
||||
})
|
||||
}
|
||||
|
||||
// 实现rich-text富文本中图片宽度最大100%
|
||||
export function formatContent(html) {
|
||||
// 去掉img标签里的style、width、height属性
|
||||
let content_data = html.replace(/<img[^>]*>/gi, function(match, capture) {
|
||||
match = match.replace(/style="[^"]+"/gi, '').replace(/style='[^']+'/gi, '');
|
||||
match = match.replace(/width="[^"]+"/gi, '').replace(/width='[^']+'/gi, '');
|
||||
match = match.replace(/height="[^"]+"/gi, '').replace(/height='[^']+'/gi, '');
|
||||
return match;
|
||||
});
|
||||
// 修改所有style里的width属性为max-width:100%
|
||||
content_data = content_data.replace(/style="[^"]+"/gi, function(match, capture) {
|
||||
match = match.replace(/width:[^;]+;/gi, 'max-width:100%;').replace(/width:[^;]+;/gi, 'max-width:100%;');
|
||||
return match;
|
||||
});
|
||||
// 去掉<br/>标签
|
||||
content_data = content_data.replace(/<br[^>]*\/>/gi, '');
|
||||
// img标签添加style属性:max-width:100%;height:auto
|
||||
content_data = content_data.replace(/\<img/gi,
|
||||
'<img style="max-width:100%;height:auto;display:block;margin:0px auto;"');
|
||||
return content_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @function 保存图片
|
||||
* @param {string} url 下载地址
|
||||
**/
|
||||
export const downloadFile = (url, type='img') => {
|
||||
if (!url) {
|
||||
return uni.$showTost('请传入下载地址!')
|
||||
}
|
||||
url = url.replace(/http:\/\//g, 'https://')
|
||||
uni.showLoading({
|
||||
title: '保存中...',
|
||||
mask: true
|
||||
})
|
||||
uni.downloadFile({
|
||||
url: url,
|
||||
success: async (res) => {
|
||||
if (type==='img') {
|
||||
uni.saveImageToPhotosAlbum({
|
||||
filePath: res.tempFilePath,
|
||||
success: () => {
|
||||
uni.$showTost('保存成功!')
|
||||
},
|
||||
fail: (err) => {
|
||||
uni.$showTost('保存失败,请手动截屏保存!')
|
||||
},
|
||||
complete: () => {
|
||||
uni.hideLoading()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
await uni.$showTost('即将打开文件,点击文件预览下拉保存文件!', 2000)
|
||||
uni.openDocument({
|
||||
filePath: res.tempFilePath,
|
||||
fileType: 'pdf',
|
||||
complete: () => {
|
||||
uni.hideLoading()
|
||||
},
|
||||
fail:() => {
|
||||
uni.setClipboardData({
|
||||
data: url,
|
||||
success: () => {
|
||||
uni.$showTost('已复制到系统剪切板,请前往浏览器进行下载')
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
},
|
||||
fail: err => {
|
||||
uni.hideLoading()
|
||||
uni.$showTost('保存失败')
|
||||
}
|
||||
})
|
||||
}
|
29
vite.config.js
Normal file
29
vite.config.js
Normal file
@ -0,0 +1,29 @@
|
||||
import uni from "@dcloudio/vite-plugin-uni";
|
||||
import { defineConfig, loadEnv } from 'vite';
|
||||
|
||||
export default defineConfig(({ command, mode }) => {
|
||||
// 根据当前工作目录中的 `mode` 加载 .env 文件
|
||||
// 设置第三个参数为 '' 来加载所有环境变量,而不管是否有 `VITE_` 前缀。
|
||||
const env = loadEnv(mode, process.cwd(), '')
|
||||
return {
|
||||
// vite 配置
|
||||
plugins: [uni()],
|
||||
base: './',
|
||||
define: {
|
||||
__APP_ENV__: env.APP_ENV,
|
||||
MY_APP_CONFIG: {
|
||||
|
||||
},
|
||||
},
|
||||
// 产生跨域请求打开
|
||||
// server: {
|
||||
// proxy: {
|
||||
// '/dev': {
|
||||
// target: '', // 代理地址
|
||||
// changeOrigin: true, //支持跨域
|
||||
// rewrite: (path) => path.replace(/^\/dev/, ""),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
})
|
Loading…
Reference in New Issue
Block a user