Commit 3c47ab2b authored by 朱松文's avatar 朱松文

天网犬只识别系统架构初始搭建

parent f216b03f
Pipeline #758 canceled with stages
> 1%
last 2 versions
not dead
VUE_APP_PRE_CSS = najiu
\ No newline at end of file
vue.config.js
\ No newline at end of file
module.exports = {
root: true,
env: {
node: true,
},
extends: [
"plugin:vue/essential",
"eslint:recommended",
"@vue/typescript/recommended",
"@vue/prettier",
"@vue/prettier/@typescript-eslint",
],
parserOptions: {
ecmaVersion: 2020,
},
rules: {
"no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
"no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off",
"@typescript-eslint/ban-ts-comment": "off",
"prettier/prettier": "off",
"@typescript-eslint/no-this-alias": ["off"],
"@typescript-eslint/no-explicit-any": ["off"],
"@typescript-eslint/explicit-module-boundary-types":["off"]
},
};
.DS_Store
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?
{
"endOfLine": "auto"
}
# skynet
# najiu-skynet-amin
天网犬只识别系统
\ No newline at end of file
天网犬只识别系统-UI
module.exports = {
presets: ["@vue/cli-plugin-babel/preset"],
plugins: [
[
"component",
{
"libraryName": "element-ui",
"styleLibraryName": "theme-chalk"
}
]
]
};
This diff is collapsed.
{
"name": "skynet",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"core-js": "^3.6.5",
"element-ui": "^2.15.6",
"postcss-px2rem": "^0.3.0",
"px2rem-loader": "^0.1.9",
"vue": "^2.6.11",
"vue-class-component": "^7.2.3",
"vue-property-decorator": "^9.1.2",
"vue-router": "^3.2.0",
"vuex": "^3.4.0"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^4.18.0",
"@typescript-eslint/parser": "^4.18.0",
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-plugin-router": "~4.5.0",
"@vue/cli-plugin-typescript": "~4.5.0",
"@vue/cli-plugin-vuex": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"@vue/eslint-config-prettier": "^6.0.0",
"@vue/eslint-config-typescript": "^7.0.0",
"babel-plugin-component": "^1.1.1",
"eslint": "^6.7.2",
"eslint-plugin-prettier": "^3.3.1",
"eslint-plugin-vue": "^6.2.2",
"node-sass": "^4.12.0",
"prettier": "^2.2.1",
"sass-loader": "^8.0.2",
"typescript": "~4.1.5",
"vue-template-compiler": "^2.6.11"
}
}
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
<template>
<div id="app">
<Layout />
</div>
</template>
<script lang="ts">
import "@/assets/scss/index.scss";
import { Component, Vue } from "vue-property-decorator";
import Layout from "@/layout/index.vue";
@Component({
components: { Layout },
})
export default class App extends Vue {}
</script>
@font-face {
font-family: "iconfont"; /* Project id 2811303 */
src: url('iconfont.woff2?t=1631592389352') format('woff2'),
url('iconfont.woff?t=1631592389352') format('woff'),
url('iconfont.ttf?t=1631592389352') format('truetype');
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-diannaoliushui:before {
content: "\e604";
}
.icon-shexiangtou:before {
content: "\e621";
}
.icon-xitongshezhi:before {
content: "\e600";
}
.icon-camera:before {
content: "\e62f";
}
.icon-jiantou:before {
content: "\e619";
}
.icon-bofang:before {
content: "\e635";
}
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="240px" height="60px" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient gradientUnits="userSpaceOnUse" x1="240" y1="30" x2="0" y2="30" id="LinearGradient52">
<stop id="Stop53" stop-color="#0079fe" offset="0" />
<stop id="Stop54" stop-color="#3500cb" offset="1" />
</linearGradient>
</defs>
<g>
<path d="M 0 0 L 240 0 L 240 60 L 0 60 L 0 0 Z " fill-rule="nonzero" fill="url(#LinearGradient52)" stroke="none" />
</g>
</svg>
\ No newline at end of file
body {
font-family: Avenir, Helvetica, Arial, sans-serif;
font-size: 14px;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
background-color: $theme-background-color;
color: #D7D7D7;
}
.display-none {
display: none;
}
\ No newline at end of file
@import url('./variable.scss');
@import url('./resest.scss');
@import url('./base.scss');
@import url('../iconfont/iconfont.css');
\ No newline at end of file
body,
h1,
h2,
h3,
h4,
h5,
h6,
hr,
p,
blockquote,
dl,
dt,
dd,
ul,
ol,
li,
pre,
form,
fieldset,
legend,
button,
input,
textarea,
th,
td {
margin: 0;
padding: 0;
}
body,
button,
input,
select,
textarea {
font: 12px/1.5 tahoma, arial, \5b8b\4f53;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-size: 100%;
}
address,
cite,
dfn,
em,
var {
font-style: normal;
}
code,
kbd,
pre,
samp {
font-family: courier new, courier, monospace;
}
small {
font-size: 12px;
}
ul,
ol {
list-style: none;
}
a {
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
sup {
vertical-align: text-top;
}
sub {
vertical-align: text-bottom;
}
legend {
color: #000;
}
et,
img {
border: 0;
}
button,
input,
select,
textarea {
font-size: 100%;
}
\ No newline at end of file
$prefixCls:'najiu';
$item-background-color:#1A2332;
$theme-background-color:rgba(51, 51, 51, 1);
\ No newline at end of file
export interface CameraItem {
provinceCode?: string;
provinceName?: string;
cityCode?: string;
cityName?: string;
areaCode?: string;
areaName: string;
list: Detail[];
}
export interface Detail {
id: number;
name: string;
total: number;
}
<template>
<div class="area-camera">
<div class="area">
<a v-on:click="hideCameras">
<Icon name="jiantou" :iconClass="`icon-jiantou-${showCarmera ? 'down' : 'left'}`" />
<span>{{ cameraItem.areaName }}</span>
</a>
</div>
<div v-show="showCarmera" class="item" v-for="item in cameraItem.list" :key="item.id">
<div class="item-name">
<Icon name="camera" iconClass="icon-camera" />
<span>{{ item.name }}</span>
</div>
<div class="item-total">
<span>{{ item.total }}</span>
</div>
</div>
</div>
</template>
<script lang="ts">
import { Component, Vue, Prop } from "vue-property-decorator";
import { CameraItem } from "./data";
import Icon from "@/components/Icon/index.vue";
@Component({ components: { Icon } })
export default class Camera extends Vue {
@Prop() private cameraItem!: CameraItem;
showCarmera = true;
hideCameras(): void {
this.showCarmera = !this.showCarmera;
}
}
</script>
<style lang="scss">
.area-camera {
margin-top: 15px;
// border: 1px solid red;
.area {
height: 35px;
line-height: 35px;
padding-left: 20px;
border-bottom: 1px solid #444d56;
a {
text-decoration: none;
cursor: pointer;
}
.icon-jiantou-down {
display: inline-block;
transform: rotate(90deg);
padding-right: 5px;
font-size: 14px;
}
.icon-jiantou-left {
padding-right: 5px;
font-size: 14px;
}
}
.item {
display: flex;
justify-content: space-between;
border-bottom: 1px solid #444d56;
padding-left: 40px;
padding-right: 10px;
.item-name {
height: 35px;
line-height: 35px;
}
.item-total {
display: flex;
height: 35px;
min-width: 35px;
justify-content: center;
align-items: center;
span {
display: inline-block;
min-width: 35px;
text-align: center;
padding: 2px 5px;
font-size: 11px;
border-radius: 13px;
background-color: rgba(249, 94, 90, 1);
}
}
.icon-camera {
font-size: 14px;
padding-right: 10px;
}
}
}
</style>
<template>
<div class="search">
<div class="left">
<div class="search-date"></div>
<div class="search-name"></div>
</div>
<div class="right">
<a>搜索</a>
</div>
</div>
</template>
<style lang="scss">
.search {
display: flex;
.left {
flex: 1;
margin-right: 10px;
.search-date {
border: 1px solid #d7d7d7;
height: 30px;
}
.search-name {
border: 1px solid #d7d7d7;
height: 30px;
margin-top: 5px;
}
}
.right {
background-color: rgba(0, 121, 254, 1);
border-radius: 5px;
text-align: center;
a {
display: inline-block;
cursor: pointer;
width: 65px;
height: 65px;
font-weight: 700;
font-size: 16px;
line-height: 65px;
}
}
}
</style>
export interface DogData {
id: number;
picture: string;
beginTime: string;
endTime: string;
totalTime: string;
isHand: boolean;
dogType: string;
hairColor: string;
}
<template>
<div class="dog">
<div class="dog-info">
<div class="dog-img">
<img :src="dog.picture" alt />
</div>
<div class="dog-data">
<div class="row">
<div class="col-left">识别开始时间</div>
<div class="col">{{ dog.beginTime }}</div>
</div>
<div class="row">
<div class="col-left">识别结束时间</div>
<div class="col">{{ dog.endTime }}</div>
</div>
<div class="row">
<div class="col-left">识别时长</div>
<div class="col">{{ dog.totalTime }}</div>
</div>
<div class="row">
<div class="col-left">是否牵狗绳</div>
<div class="col">{{ dog.isHand ? "" : "" }}</div>
</div>
<div class="row">
<div class="col-left">品种</div>
<div class="col">{{ dog.dogType }}</div>
</div>
<div class="row none-border-bottom">
<div class="col-left">毛色</div>
<div class="col">{{ dog.hairColor }}</div>
</div>
</div>
</div>
<div class="dog-footer">
<a v-on:click="play">
<Icon name="bofang" iconClass="icon-player" />
<span>播放</span>
</a>
</div>
</div>
</template>
<script lang="ts">
import { Component, Vue, Prop } from "vue-property-decorator";
import { DogData } from "./data";
import Icon from "@/components/Icon/index.vue";
@Component({ components: { Icon } })
export default class DogInfo extends Vue {
@Prop() private dog: DogData;
play(): void {
console.log("play");
}
}
</script>
<style lang="scss">
.dog {
border: 1px solid #444d56;
margin-bottom: 10px;
background-color: black;
font-size: 12px;
font-weight: 700;
.none-border-bottom {
border-bottom: 0 !important;
}
.dog-info {
display: flex;
.dog-img {
width: 100px;
height: 100px;
padding: 10px;
border-right: 1px solid #444d56;
img {
width: 100%;
}
}
.dog-data {
flex: 1;
.row {
display: flex;
border-bottom: 1px solid #444d56;
.col-left {
width: 120px;
text-align: center;
border-right: 1px solid #444d56;
height: 19px;
line-height: 20px;
}
.col {
flex: 1;
padding-left: 8px;
}
}
}
}
.dog-footer {
height: 30px;
line-height: 30px;
text-align: center;
color: #0079fe;
border-top: 1px solid #444d56;
a {
cursor: pointer;
text-decoration: none;
}
.icon-player {
font-size: 12px;
padding-right: 5px;
}
}
}
</style>
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>
For a guide and recipes on how to configure / customize this project,<br />
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener"
>vue-cli documentation</a
>.
</p>
<h3>Installed CLI Plugins</h3>
<ul>
<li>
<a
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel"
target="_blank"
rel="noopener"
>babel</a
>
</li>
<li>
<a
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-router"
target="_blank"
rel="noopener"
>router</a
>
</li>
<li>
<a
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-vuex"
target="_blank"
rel="noopener"
>vuex</a
>
</li>
<li>
<a
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint"
target="_blank"
rel="noopener"
>eslint</a
>
</li>
<li>
<a
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-typescript"
target="_blank"
rel="noopener"
>typescript</a
>
</li>
</ul>
<h3>Essential Links</h3>
<ul>
<li>
<a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a>
</li>
<li>
<a href="https://forum.vuejs.org" target="_blank" rel="noopener"
>Forum</a
>
</li>
<li>
<a href="https://chat.vuejs.org" target="_blank" rel="noopener"
>Community Chat</a
>
</li>
<li>
<a href="https://twitter.com/vuejs" target="_blank" rel="noopener"
>Twitter</a
>
</li>
<li>
<a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a>
</li>
</ul>
<h3>Ecosystem</h3>
<ul>
<li>
<a href="https://router.vuejs.org" target="_blank" rel="noopener"
>vue-router</a
>
</li>
<li>
<a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a>
</li>
<li>
<a
href="https://github.com/vuejs/vue-devtools#vue-devtools"
target="_blank"
rel="noopener"
>vue-devtools</a
>
</li>
<li>
<a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener"
>vue-loader</a
>
</li>
<li>
<a
href="https://github.com/vuejs/awesome-vue"
target="_blank"
rel="noopener"
>awesome-vue</a
>
</li>
</ul>
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator";
@Component
export default class HelloWorld extends Vue {
@Prop() private msg!: string;
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
<template>
<span v-if="name" :class="`icon iconfont icon-${name} ${iconClass}`"></span>
</template>
<script lang="ts">
import { Component, Vue, Prop } from "vue-property-decorator";
@Component({})
export default class Icon extends Vue {
@Prop() private name!: string;
@Prop() private iconClass!: string;
}
</script>
const API = {
'development': {
skyNet: 'http://10.2.60.59:9110/'
},
'production': {
skyNet: 'http://10.2.60.59:9110/'
}
}
console.log('env', process.env)
export default API[process.env.NODE_ENV]
\ No newline at end of file
<template>
<div :class="`${prefixCls}-menu`">
<div
v-for="(item, index) in getMenus"
:key="index"
:class="{ 'menu-item': true, active: currentPath === item.path }"
>
<router-link :to="item.path" class="title" @click.native="selectMenu(item.path)">
<Icon :name="item.icon" iconClass="icon-menu" />
{{ item.name }}
</router-link>
</div>
</div>
</template>
<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
import { MenuItem } from "../data";
import Icon from "@/components/Icon/index.vue";
import { MENU_CURRENT_PATH_KEY, CLICK_HOME_PAGE_EVENT } from "@/utils/constant";
import eventBus from "@/utils/eventBus";
@Component({ components: { Icon } })
export default class Menu extends Vue {
currentPath = "/";
created(): void {
const _this = this;
//刷新页面时,定位当前菜单
const pathValue = sessionStorage.getItem(MENU_CURRENT_PATH_KEY);
this.currentPath = pathValue ? pathValue : this.currentPath;
//
eventBus.$on(CLICK_HOME_PAGE_EVENT, () => {
_this.currentPath = "/";
});
}
get prefixCls(): string {
return process.env.VUE_APP_PRE_CSS;
}
get getMenus(): MenuItem[] {
const { routes } = this.$router.options;
if (!routes) return [];
return (
routes
// @ts-ignore
.filter((r) => r.show)
.map((r) => ({ name: r.meta?.title, path: r.path, icon: r.meta?.icon }))
);
}
selectMenu(path: string): void {
this.currentPath = path;
sessionStorage.setItem(MENU_CURRENT_PATH_KEY, this.currentPath);
}
}
</script>
<style lang="scss">
.#{$prefixCls}-menu {
display: flex;
background-color: $item-background-color;
flex: 1;
.active {
background-color: #2c3b52;
}
.menu-item {
display: flex;
justify-content: center;
min-width: 140px;
height: 60px;
a {
font-weight: 700;
font-style: normal;
font-size: 16px;
line-height: 60px;
text-decoration: none;
color: white;
}
}
.icon-menu {
font-size: 20px;
padding-right: 5px;
line-height: 60px;
}
}
</style>
export interface MenuItem {
name: string;
path: string;
}
<template>
<div>
<Nav />
<Main />
</div>
</template>
<script lang="ts">
import { Vue, Component } from "vue-property-decorator";
import Nav from "./nav.vue";
import Main from "./main.vue";
@Component({ components: { Nav, Main } })
export default class Index extends Vue {}
</script>
<template>
<div :class="`${prefixCls}-main`">
<router-view />
</div>
</template>
<script lang="ts">
import { Vue, Component } from "vue-property-decorator";
@Component({})
export default class Main extends Vue {
get prefixCls(): string {
return process.env.VUE_APP_PRE_CSS;
}
}
</script>
<template>
<div :class="`${prefixCls}-nav`">
<a v-on:click="handleClick" href="#/">
<div class="logo">
<img src="@/assets/images/logo_background.svg" />
<div class="title">
<span>天网犬只识别系统</span>
</div>
</div>
</a>
<Menu />
</div>
</template>
<script lang="ts">
import { Vue, Component } from "vue-property-decorator";
import Menu from "./compoments/menu.vue";
import { MENU_CURRENT_PATH_KEY, CLICK_HOME_PAGE_EVENT } from "@/utils/constant";
import eventBus from "@/utils/eventBus";
@Component({ components: { Menu } })
export default class Nav extends Vue {
get prefixCls(): string {
return process.env.VUE_APP_PRE_CSS;
}
handleClick(): void {
sessionStorage.setItem(MENU_CURRENT_PATH_KEY, "/");
eventBus.$emit(CLICK_HOME_PAGE_EVENT);
}
}
</script>
<style lang="scss">
.#{$prefixCls}-nav {
height: 60px;
display: flex;
a {
color: #d7d7d7;
text-decoration: none;
}
.logo {
position: relative;
display: flex;
justify-content: center;
width: 240px;
img {
border-width: 0px;
position: absolute;
left: 0px;
top: 0px;
width: 100%;
z-index: -1;
}
.title {
font-weight: 700;
font-style: normal;
font-size: 20px;
line-height: 60px;
}
}
.main-container {
font-size: 14px;
}
// a {
// font-weight: bold;
// color: #2c3e50;
// // &.router-link-exact-active {
// // color: #42b983;
// // }
// }
}
</style>
import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
import "@/utils/rem";
import { Message } from 'element-ui';
Vue.config.productionTip = false;
Vue.prototype.$message = Message;
new Vue({
router,
store,
render: (h) => h(App),
}).$mount("#app");
import Vue from "vue";
import VueRouter from "vue-router";
import Dashboard from "@/views/dashboard/index.vue";
import { MyRouteConfig } from "./myRouteConfig";
Vue.use(VueRouter);
const routes: Array<MyRouteConfig> = [
{
path: "/",
name: "Dashboard",
component: Dashboard,
meta: {
title: "视频识别",
icon: "shexiangtou",
},
show: true,
},
{
path: "/dogHot",
name: "DogHot",
show: true,
meta: {
title: "犬只热力",
icon: "diannaoliushui",
},
component: () => import("../views/dogHot/index.vue"),
},
{
path: "/sysSetting",
name: "SysSetting",
show: true,
meta: {
title: "系统设置",
icon: "xitongshezhi",
},
component: () => import("../views/sysSetting/index.vue"),
},
{
path: "/about",
name: "About",
show: false,
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () =>
import(/* webpackChunkName: "about" */ "../views/About.vue"),
},
];
const router = new VueRouter({
routes,
});
export default router;
import { RouteConfig } from "vue-router";
export type MyRouteConfig = RouteConfig & _ExtendConfig;
interface _ExtendConfig {
show?: boolean;
}
import { responseData } from "@/types/response"
import NetUtil from '@/utils/http'
export function getCamera(pageData: any): Promise<responseData> {
return NetUtil.fetch_request('camera/paging', 'POST', pageData)
}
\ No newline at end of file
import Vue, { VNode } from "vue";
declare global {
namespace JSX {
// tslint:disable no-empty-interface
interface Element extends VNode {}
// tslint:disable no-empty-interface
interface ElementClass extends Vue {}
interface IntrinsicElements {
[elem: string]: any;
}
}
}
declare module "*.vue" {
import Vue from "vue";
export default Vue;
}
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
state: {},
mutations: {},
actions: {},
modules: {},
});
export interface responseData {
code: string,
msg: string,
data:any
}
\ No newline at end of file
export const MENU_CURRENT_PATH_KEY = "current-path-key";
//event
export const CLICK_HOME_PAGE_EVENT='clickHomePageEvent'
\ No newline at end of file
import {Vue} from 'vue-property-decorator'
export default new Vue()
\ No newline at end of file
import { responseData } from '@/types/response'
import { Message } from 'element-ui'
import api from '@/configs/apiConfig'
/**
* 使用Promise封装Fetch,具有网络超时、请求终止的功能
*/
class NetUtil {
static baseUrl = "http://10.2.60.59:9110/";
static token = '';
/**
* post请求
* url : 请求地址
* data : 参数(Json对象)
* callback : 回调函数
* */
static fetch_request(url: string, method: 'POST' | 'GET', params = ''): Promise<responseData> {
const header = {
'Accept': 'application/json',
'Content-Type': 'application/json;charset=UTF-8',
'accesstoken': NetUtil.token,
}
let promise = null;
if (params == '') {
promise = new Promise((resolve, reject) => {
fetch(api.skyNet + url, { method: method, headers: header })
.then(response => response.json())
.then(responseData => resolve(responseData))
.then(err => reject(err))
})
} else {
promise = new Promise((resolve, reject) => {
fetch(api.skyNet + url, { method: method, headers: header, body: JSON.stringify(params) })
.then(response => response.json())
.then(responseData => resolve(responseData))
.then(err => reject(err))
})
}
return NetUtil.warp_fetch(promise).catch(err => {
Message.error(err)
throw err
});
}
/**
* 创建两个promise对象,一个负责网络请求,另一个负责计时,如果超过指定时间,就会先回调计时的promise,代表网络超时。
* @param {Promise} fetch_promise fetch请求返回的Promise
* @param {number} [timeout=10000] 单位:毫秒,这里设置默认超时时间为10秒
* @return 返回Promise
*/
static warp_fetch(fetch_promise: Promise<responseData>, timeout = 5000): Promise<responseData> {
let timeout_fn = null;
let abort = null;
//创建一个超时promise
const timeout_promise: Promise<responseData> = new Promise(function (resolve, reject) {
timeout_fn = function () {
reject('网络请求超时');
};
});
//创建一个终止promise
const abort_promise: Promise<responseData> = new Promise(function (resolve, reject) {
abort = function () {
reject('请求终止');
};
});
//竞赛
const abortable_promise = Promise.race([
fetch_promise,
timeout_promise,
abort_promise,
]);
//计时
setTimeout(timeout_fn, timeout);
//终止
//@ts-ignore
abortable_promise.abort = abort;
return abortable_promise;
}
}
export default NetUtil;
\ No newline at end of file
// rem等比适配配置文件
// 基准大小
const baseSize = 16;
// 设置 rem 函数
function setRem() {
// 当前页面宽度相对于 1920宽的缩放比例,可根据自己需要修改。
const scale = document.documentElement.clientWidth / 1920;
// 设置页面根节点字体大小(“Math.min(scale, 2)” 指最高放大比例为2,可根据实际业务需求调整)
document.documentElement.style.fontSize =
baseSize * Math.min(scale, 2) + "px";
}
// 初始化
setRem();
// 改变窗口大小时重新设置 rem
window.onresize = function () {
setRem();
};
<template>
<div class="about">
<h1>This is an about page</h1>
</div>
</template>
<template>
<div class="home">
<img alt="Vue logo" src="../assets/logo.png" />
<HelloWorld msg="Welcome to Your Vue.js + TypeScript App" />
</div>
</template>
<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
import HelloWorld from "@/components/HelloWorld.vue"; // @ is an alias to /src
@Component({
components: {
HelloWorld,
},
})
export default class Home extends Vue {}
</script>
import { CameraItem } from "@/components/Camera/data";
import { DogData } from "@/components/DogInfo/data";
export interface DashBoardData {
cameras: CameraItem[];
dogData: DogData[];
}
<template>
<div :class="`${prefixCls}-dashboard`">
<div class="camera-list">
<div>
<div class="title">摄像头选择</div>
<Search />
</div>
<div class="cameras">
<Camera v-for="(camera, i) in cameras" :key="i" :cameraItem="camera" />
</div>
</div>
<div class="player">player</div>
<div class="video-list">
<div class="title">犬只记录</div>
<div class="detail">
<DogInfo v-for="(dog, i) in dogData" :key="i" :dog="dog" />
</div>
</div>
</div>
</template>
<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
import Camera from "@/components/Camera/index.vue";
import { DashBoardData } from "./data";
import DogInfo from "@/components/DogInfo/index.vue";
import Search from "@/components/Camera/search.vue";
import { getCamera } from "@/service/CameraService";
@Component({ components: { Camera, DogInfo, Search } })
export default class Dashboard extends Vue {
get prefixCls(): string {
return process.env.VUE_APP_PRE_CSS;
}
created(): void {
getCamera({
current: 1,
groupName: "",
name: "",
size: 20,
}).then((data) => {
console.log("api***", data);
});
}
//#region data
data(): DashBoardData {
return {
cameras: [
{
areaName: "开福区",
list: [
{ id: 1, name: "捞刀河街道楚家湖路爱民公园", total: 6588 },
{ id: 2, name: "开福大道与横四路交叉路口", total: 188 },
],
},
{
areaName: " 芙蓉区",
list: [
{ id: 3, name: "芙蓉路与雀园路交叉路口", total: 757 },
{ id: 4, name: "合平路与泉坝路交叉路口东北角", total: 0 },
{ id: 5, name: "八一路韶山路口", total: 2 },
],
},
{
areaName: " 芙蓉区",
list: [
{ id: 3, name: "芙蓉路与雀园路交叉路口", total: 757 },
{ id: 4, name: "合平路与泉坝路交叉路口东北角", total: 0 },
{ id: 5, name: "八一路韶山路口", total: 2 },
],
},
],
dogData: [
{
id: 1,
beginTime: "2021-09-13 09:51:47",
endTime: "2021-09-13 10:05:26",
totalTime: "13:39",
isHand: false,
dogType: "威尔士柯基犬",
hairColor: "黑白相间",
picture:
"http://10.2.100.131/tianwang/images/%E8%A7%86%E9%A2%91%E7%BB%93%E6%9E%84%E5%8C%96/u283.png",
},
{
id: 2,
beginTime: "2021-09-13 09:51:47",
endTime: "2021-09-13 10:05:26",
totalTime: "19:25",
isHand: true,
dogType: "卡斯罗犬",
hairColor: "黑色",
picture:
"http://10.2.100.131/tianwang/images/%E8%A7%86%E9%A2%91%E7%BB%93%E6%9E%84%E5%8C%96/u301.png",
},
{
id: 3,
beginTime: "2021-09-13 09:51:47",
endTime: "2021-09-13 10:05:26",
totalTime: "19:25",
isHand: true,
dogType: "卡斯罗犬",
hairColor: "黑色",
picture:
"http://10.2.100.131/tianwang/images/%E8%A7%86%E9%A2%91%E7%BB%93%E6%9E%84%E5%8C%96/u319.png",
},
{
id: 4,
beginTime: "2021-09-13 09:51:47",
endTime: "2021-09-13 10:05:26",
totalTime: "19:25",
isHand: true,
dogType: "卡斯罗犬",
hairColor: "黑色",
picture:
"http://10.2.100.131/tianwang/images/%E8%A7%86%E9%A2%91%E7%BB%93%E6%9E%84%E5%8C%96/u337.png",
},
{
id: 5,
beginTime: "2021-09-13 09:51:47",
endTime: "2021-09-13 10:05:26",
totalTime: "19:25",
isHand: true,
dogType: "卡斯罗犬",
hairColor: "黑色",
picture:
"http://10.2.100.131/tianwang/images/%E8%A7%86%E9%A2%91%E7%BB%93%E6%9E%84%E5%8C%96/u355.png",
},
],
};
}
//#endregion
}
</script>
<style lang="scss">
.#{$prefixCls}-dashboard {
display: flex;
max-width: 1905px;
min-width: 1650px;
margin: 5px auto;
.title {
height: 40px;
line-height: 40px;
font-size: 15px;
font-weight: 400;
border-bottom: 1px solid #444d56;
margin-bottom: 10px;
}
.camera-list {
width: 335px;
border: 1px solid #444d56;
background-color: $item-background-color;
padding: 0 10px;
padding-bottom: 15px;
.cameras {
margin-top: 10px;
max-height: 669px;
min-height: 600px;
overflow: auto;
}
}
.player {
flex: 1;
background-color: $item-background-color;
margin-left: 5px;
margin-right: 5px;
border: 1px solid #444d56;
}
.video-list {
width: 440px;
background-color: $item-background-color;
border: 1px solid #444d56;
padding: 0 10px;
padding-bottom: 15px;
.detail {
max-height: 758px;
min-height: 600px;
overflow: auto;
}
}
}
</style>
<template>
<div>
<div class="demo">
<div class="item"></div>
</div>
</div>
</template>
<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
@Component({})
export default class Demo extends Vue {}
</script>
<style lang="scss">
.demo {
width: 200px;
height: 500px;
border: 1px solid red;
position: relative;
}
.item {
position: absolute;
width: 20px;
height: 30px;
background-color: white;
left: 30px;
top: 60px;
}
</style>
<template>
<div>dog hot</div>
</template>
<template>
<div>sys setting</div>
</template>
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"strict": false,
"jsx": "preserve",
"importHelpers": true,
"moduleResolution": "node",
"experimentalDecorators": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"baseUrl": ".",
"types": [
"webpack-env"
],
"paths": {
"@/*": [
"src/*"
]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
},
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue",
"tests/**/*.ts",
"tests/**/*.tsx"
],
"exclude": [
"node_modules"
]
}
// 引入等比适配插件
const px2rem = require("postcss-px2rem");
// 配置基本大小
const postcss = px2rem({
// 基准大小 baseSize,需要和rem.js中相同
remUnit: 16,
});
module.exports = {
chainWebpack: (config) => {
config.devtool(
process.env.NODE_ENV === "production" ? "none" : "inline-source-map"
);
config.plugin("html").tap((args) => {
args[0].title = "skynet";
return args;
});
},
css: {
loaderOptions: {
postcss: {
plugins: [postcss],
},
sass: {
prependData: `@import
"@/assets/scss/variable.scss";`,
},
},
},
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment