wangyue
2 years ago
88 changed files with 2054 additions and 901 deletions
@ -0,0 +1,140 @@ |
|||
#!/usr/bin/env bash |
|||
|
|||
Help() |
|||
{ |
|||
echo "你也可以使用自定义参数进行指定查询" |
|||
echo |
|||
echo "格式: bash $0 [2021-01-01] [2022-04-04] [author]" |
|||
echo "示例: bash code996.sh 2021-01-01 2022-12-31 digua" |
|||
echo "参数:" |
|||
echo "1st 分析的起始时间." |
|||
echo "2nd 分析的结束时间." |
|||
echo "3rd 指定提交用户,可以是 name 或 email." |
|||
echo |
|||
} |
|||
|
|||
OS_DETECT() |
|||
{ |
|||
# Detect OS |
|||
case "$(uname -s)" in |
|||
|
|||
Linux) |
|||
# echo 'Linux' |
|||
open_url="xdg-open" |
|||
;; |
|||
|
|||
Darwin) |
|||
# echo 'macOS' |
|||
open_url="open" |
|||
;; |
|||
|
|||
CYGWIN*|MINGW32*|MSYS*|MINGW*) |
|||
# echo 'Windows' |
|||
open_url="start" |
|||
;; |
|||
|
|||
*) |
|||
echo 'Other OS' |
|||
echo "trying to use xdg-open to open the url" |
|||
open_url="xdg-open" |
|||
;; |
|||
esac |
|||
|
|||
} |
|||
OS_DETECT |
|||
|
|||
|
|||
time_start=$1 |
|||
|
|||
|
|||
if [ "$1" == "--help" ] |
|||
then |
|||
Help |
|||
exit 0 |
|||
elif [ "$1" == "-h" ] |
|||
then |
|||
Help |
|||
exit 0 |
|||
fi |
|||
|
|||
if [ -z $1 ] |
|||
then |
|||
time_start="2021-01-01" |
|||
fi |
|||
|
|||
time_end=$2 |
|||
if [ -z $2 ] |
|||
then |
|||
time_end=$(date "+%Y-%m-%d") |
|||
fi |
|||
|
|||
author=$3 |
|||
if [ -z $3 ] |
|||
then |
|||
author="" |
|||
fi |
|||
|
|||
|
|||
by_day_output=`git -C $PWD log --author=$author --date=format:%u --after="$time_start" --before="$time_end" |grep "Date:"|awk '{print $2}'|sort|uniq -c` |
|||
|
|||
by_hour_output=`git -C $PWD log --author=$author --date=format:%H --after="$time_start" --before="$time_end" |grep "Date:"|awk '{print $2}'|sort|uniq -c` |
|||
|
|||
for i in "${by_day_output[@]}" |
|||
do |
|||
by_day_result=`echo "$i"|sed -E 's/^ +//g'|sed 's/ /_/g'|tr '\n' ','` |
|||
|
|||
done |
|||
|
|||
|
|||
# should modify by day format %a or %A |
|||
# day_sorted=('Monday' 'Tuesday' 'Wednesday' 'Thursday' 'Friday' 'Saturday' 'Sunday') |
|||
# day_sorted=('Mon' 'Tue' 'Wed' 'Thu' 'Fri' 'Sat' 'Sun') |
|||
|
|||
RED='\033[1;91m' |
|||
NC='\033[0m' # No Color |
|||
|
|||
echo -e "${RED}统计时间范围:$time_start 至 $time_end" |
|||
|
|||
for i in "${by_day_output[@]}" |
|||
do |
|||
echo |
|||
echo -e "${NC}一周七天 commit 分布${RED}" |
|||
echo -e " 总提交次数 星期\n$i"|column -t |
|||
by_day_result=`echo "$i"|sed -E 's/^ +//g'|sed "s/ /_/g"|tr '\n' ','` |
|||
done |
|||
|
|||
|
|||
for i in "${by_hour_output[@]}" |
|||
do |
|||
echo |
|||
echo -e "${NC}24小时 commit 分布${RED}" |
|||
echo -e " 总提交次数 小时\n$i"|column -t |
|||
by_hour_result=`echo "$i"|sed -E 's/^ +//g'|sed "s/ /_/g"|tr '\n' ','` |
|||
done |
|||
|
|||
|
|||
by_day_result=`echo "$by_day_result"|sed -E 's/,$//g'` |
|||
|
|||
by_hour_result=`echo "$by_hour_result"|sed -E 's/,$//g'` |
|||
|
|||
|
|||
result=$time_start"_"$time_end"&week="$by_day_result"&hour="$by_hour_result |
|||
|
|||
# url |
|||
github_url="https://hellodigua.github.io/code996/#/result?time=$result" |
|||
vercel_url="https://code996.vercel.app/#/result?time=$result" |
|||
gitee_url="https://hellodigua.gitee.io/code996/#/result?time=$result" |
|||
|
|||
echo |
|||
echo -e "${NC}复制以下url以查看可视化分析结果:" |
|||
echo -e "${RED}$github_url" |
|||
echo -e "${NC}" |
|||
echo -e "${NC}若 GitHub 访问过慢,也可以访问以下镜像链接:" |
|||
echo -e "${NC}Vercel节点:" |
|||
echo -e "${RED}$vercel_url" |
|||
echo -e "${NC}" |
|||
echo -e "${NC}Gitee节点:" |
|||
echo -e "${RED}$gitee_url" |
|||
echo -e "${NC}" |
|||
|
|||
$open_url "$github_url" |
@ -0,0 +1,19 @@ |
|||
pipeline { |
|||
agent { |
|||
node{ |
|||
label 'jnlp-slave' |
|||
} |
|||
} |
|||
|
|||
stages { |
|||
stage('Highways4Good Api ......') { |
|||
steps { |
|||
sh 'switch-auth.sh anxinyun' |
|||
buildName "#${BUILD_NUMBER} ~/fs-cloud/${JOB_NAME}:${IMAGE_VERSION}" |
|||
buildDescription "registry.cn-hangzhou.aliyuncs.com/${CLOUD}/${JOB_NAME}:${IMAGE_VERSION}" |
|||
sh 'docker build -t registry.cn-hangzhou.aliyuncs.com/${CLOUD}/${JOB_NAME}:${IMAGE_VERSION} ./scripts/0.0.1/data/3_init_report_pic_data' |
|||
sh 'docker push registry.cn-hangzhou.aliyuncs.com/${CLOUD}/${JOB_NAME}:${IMAGE_VERSION}' |
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,11 @@ |
|||
FROM repository.anxinyun.cn/base-images/nodejs12:20.10.12.2 |
|||
|
|||
COPY . /var/app |
|||
|
|||
WORKDIR /var/app |
|||
|
|||
RUN npm cache clean -f |
|||
RUN rm -rf package-lock.json |
|||
RUN npm install --registry http://10.8.30.22:7000 |
|||
|
|||
CMD ["node", "index.js"] |
@ -0,0 +1,10 @@ |
|||
-- ---------------------------- |
|||
-- Records of file_type |
|||
-- ---------------------------- |
|||
BEGIN; |
|||
INSERT INTO "public"."file_type" VALUES (1, '前期资料', NULL); |
|||
INSERT INTO "public"."file_type" VALUES (3, '竣工资料', NULL); |
|||
INSERT INTO "public"."file_type" VALUES (4, '维修资料', NULL); |
|||
INSERT INTO "public"."file_type" VALUES (5, '道路图片', NULL); |
|||
INSERT INTO "public"."file_type" VALUES (2, '施工资料', NULL); |
|||
COMMIT; |
@ -0,0 +1,3 @@ |
|||
export default { |
|||
navigationBarTitleText: '视频监控' |
|||
} |
@ -0,0 +1,85 @@ |
|||
import React, { useState, useEffect } from 'react' |
|||
import Taro from '@tarojs/taro' |
|||
import { View, Image, Input, Picker, LivePlayer } from '@tarojs/components' |
|||
import request from '@/services/request' |
|||
import './index.scss' |
|||
import '../patrolView/index.scss' |
|||
import patrolIcon from '../../static/img/patrolView/patrol.svg' |
|||
import patrolActiveIcon from '../../static/img/patrolView/patrol-active.svg' |
|||
import conserveIcon from '../../static/img/patrolView/conserve.svg' |
|||
import conserveActiveIcon from '../../static/img/patrolView/conserve-active.svg' |
|||
import chevronDown from '../../static/img/patrolView/chevron-down.png' |
|||
import searchIcon from '../../static/img/patrolView/search.png' |
|||
|
|||
function Index() { |
|||
const [isBus, setIsBus] = useState(true) |
|||
const [filterText, setFilterText] = useState('') |
|||
const [videoList, setVideoList] = useState([]) |
|||
|
|||
useEffect(() => { |
|||
getVideoList() |
|||
}, []) |
|||
|
|||
const getVideoList = () => { |
|||
let nextVideoList = [] |
|||
for (let i = 0; i < 10; i++) { |
|||
nextVideoList.push({ title: '视频' + i, url: '链接' + i }) |
|||
} |
|||
setVideoList(nextVideoList) |
|||
} |
|||
|
|||
const onTypeChange = bool => { |
|||
setIsBus(bool) |
|||
} |
|||
|
|||
const handleConfirm = e => { |
|||
|
|||
} |
|||
|
|||
const handleInput = e => { |
|||
|
|||
} |
|||
|
|||
return ( |
|||
<View> |
|||
<View className='type-box'> |
|||
<View className='item' onClick={() => onTypeChange(true)}> |
|||
<Image className='type-img' src={isBus ? patrolActiveIcon : patrolIcon} /> |
|||
<View style={{ color: isBus ? '#346FC2' : '#999999' }}>公交</View> |
|||
</View> |
|||
<View className='line'></View> |
|||
<View className='item' onClick={() => onTypeChange(false)}> |
|||
<Image className='type-img' src={isBus ? conserveIcon : conserveActiveIcon} /> |
|||
<View style={{ color: isBus ? '#999999' : '#346FC2' }}>道路</View> |
|||
</View> |
|||
</View> |
|||
<View className='filter-box'> |
|||
<View className='filter-item'> |
|||
<View style={{ float: 'left', marginLeft: '20rpx', color: '#333' }}>路段:</View> |
|||
<Picker> |
|||
<View className='filter-name'>{'请选择'}</View> |
|||
<Image className='filter-img' src={chevronDown} /> |
|||
</Picker> |
|||
</View> |
|||
<View class='head-search'> |
|||
<Image className='search-img' src={searchIcon} /> |
|||
<Input class='heard-search-input' value={filterText} placeholder='请输入道路名称' onConfirm={handleConfirm} onInput={handleInput} /> |
|||
</View> |
|||
</View> |
|||
<View className='video-box'> |
|||
{ |
|||
videoList && videoList.map(v => { |
|||
return ( |
|||
<View className='video-card'> |
|||
<View className='title'>{v.title}</View> |
|||
<LivePlayer className='video' src={v.url} mode='live' /> |
|||
</View> |
|||
) |
|||
}) |
|||
} |
|||
</View> |
|||
</View> |
|||
) |
|||
} |
|||
|
|||
export default Index |
@ -0,0 +1,28 @@ |
|||
page { |
|||
background-color: #f6f6f6; |
|||
|
|||
.video-box { |
|||
padding-top: 180px; |
|||
|
|||
.video-card { |
|||
background-color: #fff; |
|||
height: 488px; |
|||
margin-bottom: 20px; |
|||
display: flex; |
|||
flex-direction: column; |
|||
align-items: left; |
|||
|
|||
.title { |
|||
height: 88px; |
|||
margin-left: 30px; |
|||
display: flex; |
|||
align-items: center; |
|||
} |
|||
|
|||
.video { |
|||
height: 400px; |
|||
width: 100%; |
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,212 @@ |
|||
'use strict'; |
|||
|
|||
export function sort(arr, sortProperty) { |
|||
if (!Array.isArray(arr)) { |
|||
throw new Error('参数必须是数组'); |
|||
} |
|||
|
|||
const map = arr.reduce((p, n) => { |
|||
let sortProperty_ = sortProperty || 'name' |
|||
if (n[sortProperty_]) { |
|||
const sortKey = getOrderableString(n[sortProperty_]).join(''); |
|||
|
|||
if (p[sortKey]) { |
|||
if (Array.isArray(p[sortKey])) { |
|||
p[sortKey].push(n); |
|||
} else { |
|||
p[sortKey] = [p[sortKey], n]; |
|||
} |
|||
} else { |
|||
p[sortKey] = n; |
|||
} |
|||
return p; |
|||
} else { |
|||
throw new Error('排序对象不包含指定属性或name属性'); |
|||
} |
|||
}, {}); |
|||
|
|||
const keys = Object.keys(map); |
|||
|
|||
keys.sort(); |
|||
|
|||
let result = []; |
|||
keys.forEach(key => { |
|||
if (Array.isArray(map[key])) { |
|||
result = result.concat(map[key]); |
|||
} else { |
|||
result.push(map[key]); |
|||
} |
|||
}); |
|||
|
|||
return result; |
|||
} |
|||
|
|||
export function getOrderableString(source) { |
|||
// let result = source.includes('-') ? source.split('-') : source.includes('_') ? source.split('_') : source.split(''); //区分批量添加测点的-
|
|||
|
|||
// result = replaceNumber(result);
|
|||
|
|||
let result; |
|||
if (source.includes('-') || source.includes('_')) { |
|||
result = source.includes('-') ? source.split('-') : source; |
|||
result = Array.isArray(result) ? result.reduce((p, n) => { |
|||
if (!n.includes('_')) return p.concat(n); |
|||
|
|||
return p.concat(n.split('_')) |
|||
}, []) : result.includes('_') ? result.split('_') : result; |
|||
result = result.reduce((p, n) => { |
|||
p = p.concat(replaceNumber(n.split(''))) |
|||
|
|||
return p; |
|||
}, []); |
|||
} else { |
|||
result = replaceNumber(source.split('')) |
|||
} |
|||
|
|||
result = replaceChineseNumber(result); |
|||
|
|||
result = replaceSpecialWord(result); |
|||
|
|||
return result; |
|||
} |
|||
|
|||
function replaceNumber(source) { |
|||
let result = source.concat([]); |
|||
let numFound = false; |
|||
let numStart = 0; |
|||
let baseLine = 0; |
|||
for (let i = 0; i < source.length; i++) { |
|||
let calc = false; |
|||
let len = 0; |
|||
let num = parseInt(source[i]); |
|||
if (!Number.isNaN(num)) { |
|||
if (!numFound) { |
|||
numFound = true; |
|||
numStart = i; |
|||
} |
|||
if (i == source.length - 1) { |
|||
calc = true; |
|||
len = source.length - numStart; |
|||
} |
|||
} |
|||
else { |
|||
if (numFound) { |
|||
numFound = false; |
|||
calc = true; |
|||
len = i - numStart; |
|||
} |
|||
} |
|||
if (calc) { |
|||
if (len < 5) { |
|||
let zeroes = ''; |
|||
for (let j = 0; j < 5 - len; j++) { |
|||
zeroes += "0"; |
|||
} |
|||
|
|||
if (baseLine > 0 && Number(num) < 10) { |
|||
//为解决[3d-12,3d-2]排序结果为[3d-12,3d-2]的问题,添加此处
|
|||
baseLine--; |
|||
} |
|||
result.splice(baseLine + numStart, 0, zeroes); |
|||
baseLine += zeroes.length; |
|||
} |
|||
} |
|||
} |
|||
|
|||
return result.join('').split(''); |
|||
} |
|||
|
|||
function replaceSpecialWord(source) { |
|||
const map = { "上": "1001", "中": "1002", "下": "1003", "左": "1001", "右": "1003" }; |
|||
|
|||
let result = source.join(''); |
|||
Object.keys(map).forEach(key => { |
|||
result = result.replace(key, map[key]); |
|||
}); |
|||
|
|||
return result.split(''); |
|||
} |
|||
|
|||
function replaceChineseNumber(source) { |
|||
var map = |
|||
{ |
|||
"零": 0, |
|||
"一": 1, |
|||
"二": 2, |
|||
"三": 3, |
|||
"四": 4, |
|||
"五": 5, |
|||
"六": 6, |
|||
"七": 7, |
|||
"八": 8, |
|||
"九": 9, |
|||
"十": 10 |
|||
}; |
|||
|
|||
var result = source; |
|||
var numFound = false; |
|||
var numStart = 0; |
|||
var baseLine = 0; |
|||
for (let i = 0; i < source.length; i++) { |
|||
var calc = false; |
|||
var len = 0; |
|||
if (map[source[i]]) {//零不作处理
|
|||
if (!numFound) { |
|||
numFound = true; |
|||
numStart = i; |
|||
} |
|||
if (i == source.length - 1) { |
|||
calc = true; |
|||
len = source.length - numStart; |
|||
} |
|||
} |
|||
else { |
|||
if (numFound) { |
|||
numFound = false; |
|||
calc = true; |
|||
len = i - numStart; |
|||
} |
|||
} |
|||
|
|||
if (calc) { |
|||
var cp = ''; |
|||
var num = -1; |
|||
if (len == 1) { |
|||
num = map[source[numStart]]; |
|||
} |
|||
else if (len == 2) { |
|||
if (source[numStart] == '十') { |
|||
num = 10 + map[source[numStart + 1]]; |
|||
} |
|||
else if (source[numStart + 1] == '十') { |
|||
num = map[source[numStart]] * 10; |
|||
} |
|||
else { |
|||
num = map[source[numStart]] * 10 + map[source[numStart + 1]]; |
|||
} |
|||
} |
|||
else if (len == 3) { |
|||
if (source[numStart + 1] == '十') { |
|||
num = map[source[numStart]] * 10 + map[source[numStart + 2]]; |
|||
} |
|||
else { |
|||
num = map[source[numStart]] * 100 + map[source[numStart + 1]] * 10 + map[source[numStart + 2]]; |
|||
} |
|||
} |
|||
|
|||
if (num != -1) { |
|||
var l = 3 - num.toString().length; |
|||
var zeroes = ''; |
|||
for (let j = 0; j < l; j++) { |
|||
zeroes += "0"; |
|||
} |
|||
cp = zeroes + num; |
|||
|
|||
result.splice(baseLine + numStart, len, cp); |
|||
baseLine += cp.length - len; |
|||
} |
|||
} |
|||
} |
|||
|
|||
return result.join('').split(''); |
|||
} |
Loading…
Reference in new issue