Commit df430779 by 李乾广

千喜鹤h5项目

1 parent 9e26f6e8
node_modules
.DS_Store
dist
dist-ssr
*.local
\ No newline at end of file
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
# project
# vion-player
> A Vue.js project
## Build Setup
``` bash
# install dependencies
npm install
## Project setup
```
yarn install
```
# serve with hot reload at localhost:8080
npm run dev
### Compiles and hot-reloads for development
```
yarn serve
```
# build for production with minification
npm run build
### Compiles and minifies for production
```
yarn build
```
# build for production and view the bundle analyzer report
npm run build --report
### Lints and fixes files
```
yarn lint
```
For a detailed explanation on how things work, check out the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader).
#萤石播放视频截图功能需要找到源码,把下载动作拦截掉,方法是JS_CapturePicture(),重排代码后位置大概在48405行,z.oTool.downloadFile()方法注释掉
#如果萤石视频流切换路由时,视频流没有停掉,是因为js中代码一个判断报错,将代码21403行,方法hide中代码换成最简单的获取dom方法 document.getElementById(this.jSPlugin.id, "-ez-ptz-item").style = "display: none";
#h5端萤石视频截图报错,需要将预计59500多行的this.getPic方法中的var a中的 rect:this.stYUVRect 改为 rect: {...this.stYUVRect}
\ No newline at end of file
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,viewport-fit=cover,initial-scale=1.0,maximum-scale=1.0, user-scalable=no">
<title>视频巡店</title>
</head>
<body>
<div id="app" class="fullPage"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
{
"name": "vite",
"version": "0.0.0",
"name": "vion-player",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "vite",
"build": "vite build"
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"@vitejs/plugin-vue-jsx": "^1.3.9",
"axios": "^0.26.1",
"blueimp-md5": "^2.16.0",
"echarts": "^5.3.2",
"ezuikit-js": "^7.7.0",
"jquery": "^3.7.1",
"moment": "^2.29.4",
"postcss-px-to-viewport": "^1.1.1",
"rollup-plugin-copy": "^3.4.0",
"uglifyjs-webpack-plugin": "^1.1.1",
"url-param-parser": "^0.0.2",
"vant": "^3.6.12",
"vconsole": "^3.14.6",
"vue": "^3.0.6",
"weixin-js-sdk": "^1.6.0"
"core-js": "^3.8.3",
"element-ui": "^2.15.14",
"vue": "^2.6.14",
"vue-router": "^3.5.1"
},
"devDependencies": {
"@vitejs/plugin-vue": "^1.2.2",
"@vue/compiler-sfc": "^3.0.11",
"less": "^4.1.1",
"vite": "^2.2.4",
"vite-plugin-style-import": "^0.10.0"
"@babel/core": "^7.12.16",
"@babel/eslint-parser": "^7.12.16",
"@vue/cli-plugin-babel": "~5.0.0",
"@vue/cli-plugin-eslint": "~5.0.0",
"@vue/cli-plugin-router": "~5.0.0",
"@vue/cli-service": "~5.0.0",
"@vue/eslint-config-standard": "^6.1.0",
"eslint": "^7.32.0",
"eslint-plugin-import": "^2.25.3",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^5.1.0",
"eslint-plugin-vue": "^8.0.3",
"sass": "^1.32.7",
"sass-loader": "^12.0.0",
"vue-template-compiler": "^2.6.14"
}
}
No preview for this file type
This diff could not be displayed because it is too large.
No preview for this file type
This diff could not be displayed because it is too large.
No preview for this file type
import axios from 'axios'
import md5 from 'blueimp-md5'
import { param2 } from '@/utils'
import { Toast } from 'vant';
//const baseURL = 'https://store.keliuyun.com/report';
//const baseURL = 'https://mall.keliuyun.com';
const baseURL = 'https://store.keliuyun.com';
const Axios = axios.create({
baseURL: baseURL, // 因为我本地做了反向代理
timeout: 0,
// responseType: "json",
// changeOrigin: true,//允许跨域
withCredentials: true, // 是否允许带cookie这些
headers: {
"Content-Type": "application/json;charset=UTF-8"
// 'Content-Type': 'application/x-www-form-urlencoded'
}
})
let store = {
source: {
token: null,
cancel: null
}
}
// 请求拦截器
Axios.interceptors.request.use(
config => {
const suffix = '4c413628731691abc99eb2fca5f69aab'
const { method, params, data, url } = config
let language = localStorage.getItem('lang'),
aToken = localStorage.getItem('atoken');
if (language) {
let languageObj = {
'mall_CN': 'zh-CN,zh;q=0.9',
'zh_CN': 'zh-CN,zh;q=0.9',
'en_US': 'en-US,en;q=0.5',
'zh_TW': 'zh-TW,zh;q=0.3',
// 'zh_ar': 'zh-AR,zh;q=0.9'
}
languageObj[language] && (config.headers['Accept-Language'] = languageObj[language]);
}
aToken && (config.headers.Authorization = aToken);
config.cancelToken = store.source.token
const signalStr = method.toUpperCase() +
(params ? param2(params) : '') +
(data ? JSON.stringify(data) : '') +
suffix + (config.headers.Authorization ? config.headers.Authorization : '');
const hashSignature = md5(signalStr)
config.headers['signature'] = hashSignature
return config;
}, error => {
console.error(error);
return Promise.reject(error.data.msg)
}
)
Axios.interceptors.response.use(
res => {
if (res.data && !res.data.success) {
if (res.data.ecode && res.data.ecode != 200) {
Toast.fail(res.data.enote)
console.error(res.data.enote)
return ;
} else {
// 非标准返回体
if (res.status == 200) {
return res;
}
}
if (res.data.code == 500) {
console.error(res.data.msg)
}
return Promise.reject(res.data.msg);
} else if (!res.data && res.status == 200) {
return res;
} else if (res.data.success && res.config.method != 'get') {
//
}
return res;
}
)
export default function(method, url, data = null, config = null, bodyDelete) {
method = method.toLowerCase()
if (method == 'post') {
return Axios.post(url, data, config)
} else if (method == 'get') {
let defaultParam = {
_t: Date.parse(new Date()) / 1000
}
return Axios.get(url, { params: {...defaultParam, ...data }, config })
} else if (bodyDelete) {
return Axios.delete(url, { data: data }, config)
} else if (method == 'delete') {
return Axios.delete(url, { params: data }, config)
} else if (method == 'put') {
return Axios.put(url, data, config)
} else {
console.error('unknown method' + method)
return false
}
}
\ No newline at end of file
import req from '@/api/http.js'
const tourApi = {
getLiveAddress(params,config) {
return req('get', `/patrol/patrolDeviceChannel/getLiveAddress/${params.id}`, params, config)
},
getLiveInfo(params,config){
return req('get', `/patrol/patrolDeviceChannel/getLiveInfo/${params.id}`, params, config)
},
// 截图
getCapture(params,config) {
return req('get', `/patrol/patrolDeviceChannel/capture/${params.id}`, params, config)
},
// 提交巡店记录
submitPatrolRecord(params,config) {
return req('post', `/patrol/patrolRecord`, params, config)
},
setBookmark(params,config) {
return req('post', `/patrol/patrolGate/bookmark`, params, config)
},
delBookmark(params,config) {
return req('post', `/patrol/patrolGate/unbookmark`, params, config)
},
// 获取监控点
getPatrolGateList(params,config) {
return req('get', `/patrol/patrolGate/list`, params, config)
},
uploadScreenshot(params,config){
return req('post', `/patrol/b-patrol-screenshot`, params, config)
},
// 获取抓拍图
getScreenshotList(params,config){
return req('GET', `/b-patrol-screenshot/list`, params, config)
},
// 巡店模板
getPatrolTemplateListFun(params,config){
return req('get', `/patrol/b-patrol-template/list`, params, config)
},
// 查询单个模板
getPatrolTemplateOne(params,config){
return req('get', `/patrol/b-patrol-template/${params.id}`, params, config)
},
getPatrolSopTypeTree(params,config) {
return req('get', `/patrol/patrolSopType/tree`, params, config)
},
getUsers(params,config) {
return req('get', `/patrol/s-user/mall/${params.mallId}`)
},
//提交巡店记录
confirmPatrolRecord(params,config) {
return req('post', `/patrol/patrolRecord`, params, config)
},
// 云控制
ptzStart(params,config) {
return req('PUT', `/patrol/patrolDeviceChannel/ptzStart`, params, config)
},
ptzStop(params,config) {
return req('PUT', `/patrol/patrolDeviceChannel/ptzStop`, params, config)
},
}
export default tourApi;
\ No newline at end of file
<template>
<div class="tour-btns1">
<div class="box">
<span @click="navBack">{{decodeURIComponent(paramObj.name)}}<van-icon class="icon" name="play" /></span>
</div>
<div class="box box1">
<span v-if="bookmark" @click="delCollectGate">
<van-icon class="iconMargin" color="#F7B500" name="star" />收藏
</span>
<span v-else @click="collectGate">
<van-icon class="iconMargin" name="star-o" />收藏
</span>
<span @click="pictureBtn">
<van-icon class="iconMargin" name="photograph" />开始巡检
</span>
</div>
</div>
</template>
<script setup>
import { reactive, ref, onMounted, getCurrentInstance } from 'vue';
import { Toast } from 'vant';
import tourApi from '@/api';
const navBack = () => {
wx.miniProgram.redirectTo({
url: `/pages/tour/gate/index?type=${paramObj.type}&atoken=${paramObj.atoken}&userId=${paramObj.userId}&id=${paramObj.id}&channelid=${paramObj.channelid}&platform=${paramObj.platform}&mallId=${paramObj.mallId}&name=${paramObj.name}`
});
};
const bookmark = ref(paramObj.bookmark)
const collectGate= ()=>{
tourApi.setBookmark({
userId:paramObj.userId,
patrolGateIds:[paramObj.id]
}).then(res=>{
if(res.data.code==200){
bookmark.value = true;
return Toast.success('收藏成功');
}
})
}
const delCollectGate= ()=>{
tourApi.delBookmark({
userId:paramObj.userId,
patrolGateIds:[paramObj.id]
}).then(res=>{
if(res.data.code==200){
bookmark.value = false;
return Toast.success('取消收藏成功');
}
})
}
const pictureBtn = () => {
Toast.loading({
duration: 0,
message: '视频截图中···',
forbidClick: true,
});
// tourApi.getCapture({id:paramObj.channelid}).then(res=>{
// if(res.status!=200){
// return Toast.fail(res.data.msg);
// }
// let picUrl = res.data.data;
// Toast.clear();
// if(paramObj.type!='titem'){
// wx.miniProgram.redirectTo({
// url: `/pages/tour/index/index?action=capture&picUrl=${picUrl}&id=${paramObj.id}&channelid=${paramObj.channelid}&mallId=${paramObj.mallId}&title=${paramObj.name}&atoken=${paramObj.atoken}&userId=${paramObj.userId}`
// });
// }else{
// /***********巡店详情截图****************/
// wx.miniProgram.navigateTo({
// url: `/pages/tour/titemDetail/index?action=capture&picUrl=${picUrl}&id=${paramObj.tid}`
// });
// }
// })
};
</script>
<style scoped lang="less">
.tour-btns1{
display: flex;
background: #E6EDFF;
height: 15vw;
line-height: 15vw;
padding: 0 20px;
.box{
display: inline-block;
flex: 1;
}
.box1{
text-align: right;
span{
margin-left: 20px;
}
}
.icon{
transform: rotate(90deg);
}
}
</style>
\ No newline at end of file
import { createApp } from 'vue';
import wx from 'weixin-js-sdk';
window.wx = wx;
import App from './App.vue';
import Vant from 'vant';
import '@s/css/index.css';
import 'vant/lib/index.css';
const app = createApp(App);
app.use(Vant);
app.mount('#app')
import Vue from 'vue'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App)
}).$mount('#app')
@charset "utf-8";
/*=====================================
reset
=====================================*/
html,
body,
h1,
h2,
h3,
h4,
h5,
h6,
table,
thead,
tfoot,
tbody,
form,
fieldset,
legend,
div,
p,
span,
dl,
dt,
dd,
ul,
ol,
li,
blockquote,
pre,
q,
cite,
code,
input,
select,
textarea{margin:0;padding:0;/* font-family:"fang"; */}
h1,
h2,
h3,
h4,
h5,
h6,
strong,
em,
cite,
address,
sup,
sub,
th{font-weight:normal;font-style:normal;vertical-align:auto;font-size:1em;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-tap-highlight-color:transparent;}
i{font-style:normal;}
/* @font-face{
font-family: fang;
src: url('http://h5.wufae.com/Chevrolet/upload/static/css/fang.ttf') format('truetype');
} */
*{/* font-family:"fang"; */box-sizing:border-box;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-tap-highlight-color:transparent;}
input,
textarea,
input:focus,
select:focus,
textarea:focus{/* font-family:"fang"; */border-width:0px;border-color:transparent;-webkit-tap-highlight-color:transparent;outline:transparent;}
ul,
ol{list-style-type:none;}
a:link,
a:visited{text-decoration:none;outline:0 none;}
a:hover,
a:active{text-decoration:underline;outline:0 none;}
fieldset,
a img{border:none;}
img{vertical-align:top;display:block;}
input,
textarea,
button{font-size:100%;}
button{cursor:pointer;}
textarea{resize:none;overflow:auto;}
table{border-collapse:collapse;border-spacing:0;}
select optgroup{font-style:normal;}
legend{display:none;}
input[type="radio"],
input[type="checkbox"],
textarea{vertical-align:middle;}
input,
select{background:transparent;border:0;outline:none;}
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button{-webkit-appearance:none!important;margin:0;}
.iswin input[type="radio"],
.iswin input[type="checkbox"],
.iswin textarea{vertical-align:-3px;}
input[type="radio"],
input[type="checkbox"]{margin-right:3px;}
input[type="text"],
input[type="password"],
textarea{border:none;}
input[type="text"]:focus,
input[type="password"]:focus,
a,
img{tap-highlight-color:rgba(0,0,0,0);focus-ring-color:rgba(0,0,0,0);-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-focus-ring-color:rgba(0,0,0,0);-moz-tap-highlight-color:rgba(0,0,0,0);-moz-focus-ring-color:rgba(0,0,0,0);}
.application{position:absolute;left:0;top:0;bottom:0;right:0;}
/*=====================================
ȫ?? =====================================*/
html{height:100%;overflow:hidden;}
body{transition:opacity 0.25s;position:relative;margin:0 auto;width:100%;height:100%;}
body.succ{opacity:1;}
.root_gap{position:relative; /* width:96%; */margin:0 30px;}
.clearfix{zoom:1;}
.clearfix:after{content:"";display:block;height:0;font-size:0;clear:both;overflow:hidden;visibility:hidden;}
.fullPage{position:absolute;left:0;top:0;width: 100%;height: 100%;background-color: #f3f9ff;}
.touchmove{overflow:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch;overflow-scrolling:touch;}
\ No newline at end of file
This diff could not be displayed because it is too large.
No preview for this file type
This diff could not be displayed because it is too large.
No preview for this file type
/**
* @param {array} actual
* @returns {array}
*/
export function cleanArray(actual) {
const newArray = []
for (let i = 0; i < actual.length; i++) {
if (actual[i]) {
newArray.push(actual[i])
}
}
return newArray
}
/**
* @param {object} json
* @returns {string}
*/
export function param2(json) {
if (!json) return ''
return cleanArray(
Object.keys(json).map(key => {
if (json[key] === undefined ||
json[key] === null
) return ''
return encodeURIComponent(key) + '=' + json[key]
})
).join('&')
}
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import pxtovw from 'postcss-px-to-viewport'
import styleImport, { VantResolve } from 'vite-plugin-style-import';
const loder_pxtovw=pxtovw({
unitToConvert: "px", // 需要转换的单位,默认为"px"
viewportWidth: 750, // 设计稿的视口宽度
unitPrecision: 2, // 单位转换后保留的精度
propList: ["*"], // 能转化为vw的属性列表
viewportUnit: "vw", // 希望使用的视口单位
fontViewportUnit: "vw", // 字体使用的视口单位
selectorBlackList: ['ignore'], // 需要忽略的CSS选择器
exclude:[/node_module/],
})
import path from 'path';
import copy from 'rollup-plugin-copy'
export default defineConfig({
base:'./',
publicDir:'public',
plugins: [
vue(),
vueJsx(),
styleImport({
libs: [
{
libraryName: "vant",
esModule: true,
resolveStyle: (name) => `vant/es/${name}/style`,
},
],
}),
],
css: {
postcss:{
plugins: [loder_pxtovw]
}
},
resolve:{
alias:{
"@": path.resolve(__dirname, "./src"),
"@s": path.resolve(__dirname, "./src/static")
}
},
build:{
assetsDir:'static',
// rollupOptions:{
// plugins:[copy({
// targets: [
// { src: 'public/*', dest: 'dist/static' }
// ]
// })]
// }
}
})
This diff could not be displayed because it is too large.
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!