@@ -1,4 +1,5 @@ | |||||
module.exports = { | |||||
// 取消 自定义eslintrc验证 | |||||
/* module.exports = { | |||||
root: true, | root: true, | ||||
parserOptions: { | parserOptions: { | ||||
parser: 'babel-eslint', | parser: 'babel-eslint', | ||||
@@ -11,8 +12,6 @@ module.exports = { | |||||
}, | }, | ||||
extends: ['plugin:vue/recommended', 'eslint:recommended'], | extends: ['plugin:vue/recommended', 'eslint:recommended'], | ||||
// add your custom rules here | |||||
//it is base on https://github.com/vuejs/eslint-config-vue | |||||
rules: { | rules: { | ||||
"vue/max-attributes-per-line": [0, { | "vue/max-attributes-per-line": [0, { | ||||
"singleline": 10, | "singleline": 10, | ||||
@@ -199,3 +198,30 @@ module.exports = { | |||||
'array-bracket-spacing': [2, 'never'] | 'array-bracket-spacing': [2, 'never'] | ||||
} | } | ||||
} | } | ||||
*/ | |||||
module.exports = { | |||||
root: true, | |||||
env: { | |||||
node: true, | |||||
}, | |||||
extends: ["plugin:vue/essential", "eslint:recommended"], | |||||
parserOptions: { | |||||
parser: "babel-eslint", | |||||
}, | |||||
rules: { | |||||
"no-console": process.env.NODE_ENV === "production" ? "warn" : "off", | |||||
"no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off", | |||||
/* "prettier/prettier": "off" */ | |||||
}, | |||||
overrides: [ | |||||
{ | |||||
files: [ | |||||
"**/__tests__/*.{j,t}s?(x)", | |||||
"**/tests/unit/**/*.spec.{j,t}s?(x)", | |||||
], | |||||
env: { | |||||
jest: true, | |||||
}, | |||||
}, | |||||
], | |||||
}; |
@@ -0,0 +1,5 @@ | |||||
FROM nginx | |||||
RUN mkdir /app | |||||
COPY dist /app | |||||
COPY nginx/nginx.conf /etc/nginx/nginx.conf | |||||
EXPOSE 80 |
@@ -1,7 +1,7 @@ | |||||
<!-- | <!-- | ||||
* @Date: 2021-11-29 11:14:13 | * @Date: 2021-11-29 11:14:13 | ||||
* @LastEditors: JinxuChen | * @LastEditors: JinxuChen | ||||
* @LastEditTime: 2021-11-30 15:58:34 | |||||
* @LastEditTime: 2021-12-02 15:08:58 | |||||
* @FilePath: \GpsCardAdmin\README.md | * @FilePath: \GpsCardAdmin\README.md | ||||
* @description: | * @description: | ||||
--> | --> | ||||
@@ -15,3 +15,16 @@ | |||||
`2021年11月30日` | `2021年11月30日` | ||||
FEATURE | FEATURE | ||||
- 完成 基本项目开发环境搭建 | - 完成 基本项目开发环境搭建 | ||||
## v1.0.1F | |||||
`2021年12月1日` | |||||
FEATURE | |||||
- 完成 静态页面编写与交互 | |||||
## v1.0.2F | |||||
`2021年12月2日` | |||||
FEATURE | |||||
- 增加 docker部署文件 | |||||
- 修改 docker部署文件 |
@@ -0,0 +1,36 @@ | |||||
#!/bin/bash | |||||
### | |||||
# @Date: 2021-11-15 09:37:49 | |||||
# @LastEditors: JinxuChen | |||||
# @LastEditTime: 2021-12-02 15:19:14 | |||||
# @FilePath: \GpsCardAdmin\gps_card_admin_run.sh | |||||
# @description: 功能 | |||||
### | |||||
environment=$1 | |||||
version=$2 | |||||
echo "环境变量为${environment},版本为$version!" | |||||
if [[ ${environment} = 'production' ]]; then | |||||
echo "开始远程构建容器" | |||||
docker stop gps_card_admin_web || true; | |||||
docker rm gps_card_admin_web || true; | |||||
docker rmi -f $(docker images | grep registry.cn-shanghai.aliyuncs.com/gps_card/gps_card_admin_web | awk '{print $3}') | |||||
#docker login --username=telpo_linwl@1111649216405698 --password=telpo#1234 registry.cn-shanghai.aliyuncs.com; | |||||
docker login --username=rzl_wangjx@1111649216405698 --password=telpo.123 registry.cn-shanghai.aliyuncs.com | |||||
docker pull registry.cn-shanghai.aliyuncs.com/gps_card/gps_card_admin_web:$version | |||||
docker run -p 8803:80 -d --restart=always --name gps_card_admin_web registry.cn-shanghai.aliyuncs.com/gps_card/gps_card_admin_web:$version; | |||||
#删除产生的None镜像 | |||||
docker rmi -f $(docker images | grep none | awk '{print $3}') | |||||
docker ps -a | |||||
elif [[ ${environment} == 'test' ]]; then | |||||
echo "开始在测试环境远程构建容器" | |||||
docker stop gps_card_admin_web || true | |||||
docker rm gps_card_admin_web || true | |||||
docker rmi -f $(docker images | grep 139.224.254.18:5000/gps_card_admin_web | awk '{print $3}') | |||||
docker pull 139.224.254.18:5000/gps_card_admin_web:$version | |||||
docker run -p 8803:80 -d --restart=always --name gps_card_admin_web 139.224.254.18:5000/gps_card_admin_web:$version; | |||||
#删除产生的None镜像 | |||||
docker rmi -f $(docker images | grep none | awk '{print $3}') | |||||
docker ps -a | |||||
fi |
@@ -0,0 +1,57 @@ | |||||
#user nobody; | |||||
worker_processes 1; | |||||
#error_log logs/error.log; | |||||
#error_log logs/error.log notice; | |||||
error_log /var/log/nginx/error.log warn; | |||||
pid /var/run/nginx.pid; | |||||
events { | |||||
accept_mutex on; #设置网路连接序列化,防止惊群现象发生,默认为on | |||||
multi_accept on; #设置一个进程是否同时接受多个网络连接,默认为off | |||||
use epoll; #事件驱动模型,select|poll|kqueue|epoll|resig|/dev/poll|eventport | |||||
worker_connections 1024; | |||||
} | |||||
http { | |||||
include mime.types; | |||||
default_type application/octet-stream; | |||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" ' | |||||
'$status $body_bytes_sent "$http_referer" ' | |||||
'"$http_user_agent" "$http_x_forwarded_for"'; | |||||
#access_log logs/access.log main; | |||||
access_log /var/log/nginx/access.log main; | |||||
sendfile on; | |||||
#tcp_nopush on; | |||||
#keepalive_timeout 0; | |||||
keepalive_timeout 65; | |||||
server { | |||||
listen 80; | |||||
server_name localhost; | |||||
#charset koi8-r; | |||||
charset utf-8; | |||||
location / { | |||||
root /app; # 指向目录 | |||||
index index.html; | |||||
try_files $uri $uri/ /index.html; | |||||
} | |||||
error_page 500 502 503 504 /50x.html; | |||||
location = /50x.html { | |||||
root /usr/share/nginx/html; | |||||
} | |||||
} | |||||
} |
@@ -25,7 +25,8 @@ | |||||
"path-to-regexp": "2.4.0", | "path-to-regexp": "2.4.0", | ||||
"vue": "2.6.10", | "vue": "2.6.10", | ||||
"vue-router": "3.0.6", | "vue-router": "3.0.6", | ||||
"vuex": "3.1.0" | |||||
"vuex": "3.1.0", | |||||
"xlsx": "0.14.1" | |||||
}, | }, | ||||
"devDependencies": { | "devDependencies": { | ||||
"@vue/cli-plugin-babel": "4.4.4", | "@vue/cli-plugin-babel": "4.4.4", | ||||
@@ -0,0 +1,30 @@ | |||||
### | |||||
# @Author: JinxuChen | |||||
# @Date: 2021-11-15 | |||||
# @LastEditTime: 2021-12-02 15:19:22 | |||||
# @LastEditors: JinxuChen | |||||
# @Description: In User Settings Edit | |||||
# @FilePath: \GpsCardAdmin\setup_development.sh | |||||
### | |||||
#!/bin/bash | |||||
npm -v | |||||
npm config set registry https://registry.npm.taobao.org | |||||
npm config list | |||||
npm install | |||||
npm run build-test | |||||
image_version=`date +%Y%m%d%H%M`; | |||||
docker stop gps_card_admin_web || true; | |||||
# 删除gps_parent_web容器 | |||||
docker rm gps_card_admin_web || true; | |||||
# 删除镜像 | |||||
docker rmi -f $(docker images | grep telpo/gps_card_admin_web | awk '{print $3}') | |||||
# 构建telpo/gps_card_admin_web:$image_version镜像 | |||||
docker build . -t telpo/gps_card_admin_web:$image_version; | |||||
#删除产生的None镜像 | |||||
docker rmi -f $(docker images | grep none | awk '{print $3}') | |||||
# 查看镜像列表 | |||||
docker images; | |||||
# 启动容器 | |||||
docker run -p 8803:80 -d --restart=always --name gps_card_admin_web telpo/gps_card_admin_web:$image_version; | |||||
# 查看日志 | |||||
docker logs gps_card_admin_web; |
@@ -0,0 +1,28 @@ | |||||
### | |||||
# @Author: JinxuChen | |||||
# @Date: 2021-11-15 | |||||
# @LastEditTime: 2021-12-02 15:17:27 | |||||
# @LastEditors: JinxuChen | |||||
# @Description: In User Settings Edit | |||||
# @FilePath: \GpsCardAdmin\setup_production.sh | |||||
### | |||||
#!/bin/bash | |||||
npm -v | |||||
npm install | |||||
npm run build | |||||
image_version=$version; | |||||
# 删除镜像 | |||||
docker rmi -f $(docker images | grep registry.cn-shanghai.aliyuncs.com/gps_card/gps_card_admin_web | awk '{print $3}') | |||||
docker build . -t telpo/gps_card_admin_web:$image_version; | |||||
#TODO:推送镜像到阿里仓库 | |||||
echo '=================开始推送镜像=======================' | |||||
#docker login --username=telpo_linwl@1111649216405698 --password=telpo#1234 registry.cn-shanghai.aliyuncs.com; | |||||
docker login --username=rzl_wangjx@1111649216405698 --password=telpo.123 registry.cn-shanghai.aliyuncs.com | |||||
docker tag telpo/gps_card_admin_web:$image_version registry.cn-shanghai.aliyuncs.com/gps_card/gps_card_admin_web:$image_version | |||||
docker push registry.cn-shanghai.aliyuncs.com/gps_card/gps_card_admin_web:$image_version | |||||
echo '=================推送镜像完成=======================' | |||||
#删除产生的None镜像 | |||||
docker rmi -f $(docker images | grep none | awk '{print $3}') | |||||
# 查看镜像列表 | |||||
docker images; |
@@ -0,0 +1,31 @@ | |||||
### | |||||
# @Author: JinxuChen | |||||
# @Date: 2021-11-15 | |||||
# @LastEditTime: 2021-12-02 15:17:38 | |||||
# @LastEditors: JinxuChen | |||||
# @Description: In User Settings Edit | |||||
# @FilePath: \GpsCardAdmin\setup_test.sh | |||||
### | |||||
#!/usr/bin/env bash | |||||
npm -v | |||||
npm config set registry https://registry.npm.taobao.org | |||||
npm config list | |||||
npm install | |||||
npm run build-test | |||||
image_version=$version | |||||
# 删除镜像 | |||||
docker rmi -f $( | |||||
docker images | grep 139.224.254.18:5000/gps_card_admin_web | awk '{print $3}' | |||||
) | |||||
# 构建gps_card_admin:$image_version镜像 | |||||
docker build . -t telpo/gps_card_admin_web:$image_version; | |||||
#TODO:推送镜像到私有仓库 | |||||
echo '=================开始推送镜像=======================' | |||||
docker tag telpo/gps_card_admin_web:$image_version 139.224.254.18:5000/gps_card_admin_web:$image_version | |||||
docker push 139.224.254.18:5000/gps_card_admin_web:$image_version | |||||
echo '=================推送镜像完成=======================' | |||||
#删除产生的None镜像 | |||||
docker rmi -f $(docker images | grep none | awk '{print $3}') | |||||
# 查看镜像列表 | |||||
docker images |
@@ -0,0 +1,102 @@ | |||||
<template> | |||||
<div :class="{'hidden':hidden}" class="pagination-container"> | |||||
<el-pagination | |||||
:background="background" | |||||
:current-page.sync="currentPage" | |||||
:page-size.sync="pageSize" | |||||
:layout="layout" | |||||
:page-sizes="pageSizes" | |||||
:total="total" | |||||
v-bind="$attrs" | |||||
@size-change="handleSizeChange" | |||||
@current-change="handleCurrentChange" | |||||
/> | |||||
</div> | |||||
</template> | |||||
<script> | |||||
import { scrollTo } from '@/utils/scroll-to' | |||||
export default { | |||||
name: 'Pagination', | |||||
props: { | |||||
total: { | |||||
required: true, | |||||
type: Number | |||||
}, | |||||
page: { | |||||
type: Number, | |||||
default: 1 | |||||
}, | |||||
limit: { | |||||
type: Number, | |||||
default: 20 | |||||
}, | |||||
pageSizes: { | |||||
type: Array, | |||||
default() { | |||||
return [10, 20, 30, 50] | |||||
} | |||||
}, | |||||
layout: { | |||||
type: String, | |||||
default: 'total, sizes, prev, pager, next, jumper' | |||||
}, | |||||
background: { | |||||
type: Boolean, | |||||
default: true | |||||
}, | |||||
autoScroll: { | |||||
type: Boolean, | |||||
default: true | |||||
}, | |||||
hidden: { | |||||
type: Boolean, | |||||
default: false | |||||
} | |||||
}, | |||||
computed: { | |||||
currentPage: { | |||||
get() { | |||||
return this.page | |||||
}, | |||||
set(val) { | |||||
this.$emit('update:page', val) | |||||
} | |||||
}, | |||||
pageSize: { | |||||
get() { | |||||
return this.limit | |||||
}, | |||||
set(val) { | |||||
this.$emit('update:limit', val) | |||||
} | |||||
} | |||||
}, | |||||
methods: { | |||||
handleSizeChange(val) { | |||||
this.$emit('pagination', { page: this.currentPage, limit: val }) | |||||
if (this.autoScroll) { | |||||
scrollTo(0, 800) | |||||
} | |||||
}, | |||||
handleCurrentChange(val) { | |||||
this.$emit('pagination', { page: val, limit: this.pageSize }) | |||||
if (this.autoScroll) { | |||||
scrollTo(0, 800) | |||||
} | |||||
} | |||||
} | |||||
} | |||||
</script> | |||||
<style scoped> | |||||
.pagination-container { | |||||
width: 50%; | |||||
background: #fff; | |||||
padding: 32px 16px; | |||||
} | |||||
.pagination-container.hidden { | |||||
display: none; | |||||
} | |||||
</style> |
@@ -0,0 +1,97 @@ | |||||
<!-- | |||||
* @Date: 2021-11-30 17:19:51 | |||||
* @LastEditors: JinxuChen | |||||
* @LastEditTime: 2021-12-01 15:11:35 | |||||
* @FilePath: \GpsCardAdmin\src\components\TTable\TTable.vue | |||||
* @description: 封装通用的table组件 | |||||
--> | |||||
<template> | |||||
<div class="app-container"> | |||||
<!-- 表格 --> | |||||
<el-table :data="tableData" border fit highlight-current-row @sort-change="sortChange" > | |||||
<!-- <el-table-column prop="date" label="日期" width="180"></el-table-column> --> | |||||
<template v-for="column in columns"> | |||||
<!-- 标题 --> | |||||
<el-table-column | |||||
:key="column.prop" | |||||
:prop="column.prop" | |||||
:label="column.title" | |||||
v-if="!column.action" | |||||
height="460" | |||||
/> | |||||
<!-- 操作列 --> | |||||
<el-table-column :label="column.title" :key="column.prop" v-else > | |||||
<template slot-scope="scope"> | |||||
<el-button-group v-for="(fn,index) in column.actions" :key="index"> | |||||
<el-button | |||||
type="primary" | |||||
@click="handleClick(scope.row,fn.fnName)" | |||||
>{{fn.title}}</el-button> | |||||
</el-button-group> | |||||
</template> | |||||
</el-table-column> | |||||
</template> | |||||
</el-table> | |||||
<!-- 分页 --> | |||||
<!-- <pagination | |||||
v-show="total>0" | |||||
:total="total" | |||||
:page.sync="listQuery.page" | |||||
:limit.sync="listQuery.limit" | |||||
@pagination="getList" | |||||
/>--> | |||||
</div> | |||||
</template> | |||||
<script> | |||||
/* import Pagination from "@/components/Pagination"; */ | |||||
import waves from "@/directive/waves"; // waves directive | |||||
export default { | |||||
name: "", | |||||
/* components: { Pagination }, */ | |||||
directives: { waves }, | |||||
props: { | |||||
tableData: { | |||||
type: Array, | |||||
default: () => [] | |||||
}, | |||||
columns: { | |||||
type: Array, | |||||
default: () => [] | |||||
}, | |||||
btnType: { | |||||
type: String | |||||
} | |||||
}, | |||||
data() { | |||||
return { | |||||
total: 1, | |||||
tableKey: 0, | |||||
listQuery: { | |||||
page: 1, | |||||
limit: 10, | |||||
importance: "" | |||||
}, | |||||
importanceOptions: ["1", "2", "3"], | |||||
list: [ | |||||
{ | |||||
date: "2016-05-02", | |||||
name: "王小虎", | |||||
address: "上海市普陀区金沙江路 1518 弄" | |||||
} | |||||
] | |||||
}; | |||||
}, | |||||
methods: { | |||||
getList() {}, | |||||
sortChange() {}, | |||||
handleFilter() {}, | |||||
handleClick(row, fnName) { | |||||
this.$emit(`${fnName}`, row); | |||||
} | |||||
} | |||||
}; | |||||
</script> | |||||
<style scoped> | |||||
</style> |
@@ -0,0 +1,38 @@ | |||||
<!-- | |||||
* @Date: 2021-11-30 18:18:48 | |||||
* @LastEditors: JinxuChen | |||||
* @LastEditTime: 2021-11-30 18:56:32 | |||||
* @FilePath: \GpsCardAdmin\src\components\TopMenu\index.vue | |||||
* @description: 头部组件 | |||||
--> | |||||
<template> | |||||
<div> | |||||
<!-- 操作 --> | |||||
<!-- 按钮 --> | |||||
<el-button | |||||
class="filter-item" | |||||
v-for="(item,index) in buttonList" | |||||
:key="index" | |||||
:type="item.type" | |||||
@click="item.click" | |||||
>{{item.name}}</el-button> | |||||
</div> | |||||
</template> | |||||
<script> | |||||
export default { | |||||
name: "topMenu", | |||||
props: { | |||||
buttonList: { | |||||
type: Array, | |||||
default: [] | |||||
} | |||||
}, | |||||
data() { | |||||
return {}; | |||||
} | |||||
}; | |||||
</script> | |||||
<style scoped> | |||||
</style> |
@@ -0,0 +1,137 @@ | |||||
<template> | |||||
<div> | |||||
<input ref="excel-upload-input" class="excel-upload-input" type="file" accept=".xlsx, .xls" @change="handleClick"> | |||||
<div class="drop" @drop="handleDrop" @dragover="handleDragover" @dragenter="handleDragover"> | |||||
<el-button :loading="loading" style="margin-left:16px;" size="mini" type="primary" @click="handleUpload"> | |||||
上传 | |||||
</el-button> | |||||
</div> | |||||
</div> | |||||
</template> | |||||
<script> | |||||
import XLSX from 'xlsx' | |||||
export default { | |||||
props: { | |||||
beforeUpload: Function, // eslint-disable-line | |||||
onSuccess: Function// eslint-disable-line | |||||
}, | |||||
data() { | |||||
return { | |||||
loading: false, | |||||
excelData: { | |||||
header: null, | |||||
results: null | |||||
} | |||||
} | |||||
}, | |||||
methods: { | |||||
generateData({ header, results }) { | |||||
this.excelData.header = header | |||||
this.excelData.results = results | |||||
this.onSuccess && this.onSuccess(this.excelData) | |||||
}, | |||||
handleDrop(e) { | |||||
e.stopPropagation() | |||||
e.preventDefault() | |||||
if (this.loading) return | |||||
const files = e.dataTransfer.files | |||||
if (files.length !== 1) { | |||||
this.$message.error('Only support uploading one file!') | |||||
return | |||||
} | |||||
const rawFile = files[0] // only use files[0] | |||||
if (!this.isExcel(rawFile)) { | |||||
this.$message.error('Only supports upload .xlsx, .xls, .csv suffix files') | |||||
return false | |||||
} | |||||
this.upload(rawFile) | |||||
e.stopPropagation() | |||||
e.preventDefault() | |||||
}, | |||||
handleDragover(e) { | |||||
e.stopPropagation() | |||||
e.preventDefault() | |||||
e.dataTransfer.dropEffect = 'copy' | |||||
}, | |||||
handleUpload() { | |||||
this.$refs['excel-upload-input'].click() | |||||
}, | |||||
handleClick(e) { | |||||
const files = e.target.files | |||||
const rawFile = files[0] // only use files[0] | |||||
if (!rawFile) return | |||||
this.upload(rawFile) | |||||
}, | |||||
upload(rawFile) { | |||||
this.$refs['excel-upload-input'].value = null // fix can't select the same excel | |||||
if (!this.beforeUpload) { | |||||
this.readerData(rawFile) | |||||
return | |||||
} | |||||
const before = this.beforeUpload(rawFile) | |||||
if (before) { | |||||
this.readerData(rawFile) | |||||
} | |||||
}, | |||||
readerData(rawFile) { | |||||
this.loading = true | |||||
return new Promise((resolve, reject) => { | |||||
const reader = new FileReader() | |||||
reader.onload = e => { | |||||
const data = e.target.result | |||||
const workbook = XLSX.read(data, { type: 'array' }) | |||||
const firstSheetName = workbook.SheetNames[0] | |||||
const worksheet = workbook.Sheets[firstSheetName] | |||||
const header = this.getHeaderRow(worksheet) | |||||
const results = XLSX.utils.sheet_to_json(worksheet) | |||||
this.generateData({ header, results }) | |||||
this.loading = false | |||||
resolve() | |||||
} | |||||
reader.readAsArrayBuffer(rawFile) | |||||
}) | |||||
}, | |||||
getHeaderRow(sheet) { | |||||
const headers = [] | |||||
const range = XLSX.utils.decode_range(sheet['!ref']) | |||||
let C | |||||
const R = range.s.r | |||||
/* start in the first row */ | |||||
for (C = range.s.c; C <= range.e.c; ++C) { /* walk every column in the range */ | |||||
const cell = sheet[XLSX.utils.encode_cell({ c: C, r: R })] | |||||
/* find the cell in the first row */ | |||||
let hdr = 'UNKNOWN ' + C // <-- replace with your desired default | |||||
if (cell && cell.t) hdr = XLSX.utils.format_cell(cell) | |||||
headers.push(hdr) | |||||
} | |||||
return headers | |||||
}, | |||||
isExcel(file) { | |||||
return /\.(xlsx|xls|csv)$/.test(file.name) | |||||
} | |||||
} | |||||
} | |||||
</script> | |||||
<style scoped> | |||||
.excel-upload-input{ | |||||
display: none; | |||||
z-index: -9999; | |||||
} | |||||
.drop{ | |||||
border: 2px dashed #bbb; | |||||
width: 50%; | |||||
height: 160px; | |||||
line-height: 160px; | |||||
margin: 0 auto; | |||||
font-size: 24px; | |||||
border-radius: 5px; | |||||
text-align: center; | |||||
color: #bbb; | |||||
position: relative; | |||||
} | |||||
</style> |
@@ -0,0 +1,13 @@ | |||||
import waves from './waves' | |||||
const install = function(Vue) { | |||||
Vue.directive('waves', waves) | |||||
} | |||||
if (window.Vue) { | |||||
window.waves = waves | |||||
Vue.use(install); // eslint-disable-line | |||||
} | |||||
waves.install = install | |||||
export default waves |
@@ -0,0 +1,26 @@ | |||||
.waves-ripple { | |||||
position: absolute; | |||||
border-radius: 100%; | |||||
background-color: rgba(0, 0, 0, 0.15); | |||||
background-clip: padding-box; | |||||
pointer-events: none; | |||||
-webkit-user-select: none; | |||||
-moz-user-select: none; | |||||
-ms-user-select: none; | |||||
user-select: none; | |||||
-webkit-transform: scale(0); | |||||
-ms-transform: scale(0); | |||||
transform: scale(0); | |||||
opacity: 1; | |||||
} | |||||
.waves-ripple.z-active { | |||||
opacity: 0; | |||||
-webkit-transform: scale(2); | |||||
-ms-transform: scale(2); | |||||
transform: scale(2); | |||||
-webkit-transition: opacity 1.2s ease-out, -webkit-transform 0.6s ease-out; | |||||
transition: opacity 1.2s ease-out, -webkit-transform 0.6s ease-out; | |||||
transition: opacity 1.2s ease-out, transform 0.6s ease-out; | |||||
transition: opacity 1.2s ease-out, transform 0.6s ease-out, -webkit-transform 0.6s ease-out; | |||||
} |
@@ -0,0 +1,72 @@ | |||||
import './waves.css' | |||||
const context = '@@wavesContext' | |||||
function handleClick(el, binding) { | |||||
function handle(e) { | |||||
const customOpts = Object.assign({}, binding.value) | |||||
const opts = Object.assign({ | |||||
ele: el, // 波纹作用元素 | |||||
type: 'hit', // hit 点击位置扩散 center中心点扩展 | |||||
color: 'rgba(0, 0, 0, 0.15)' // 波纹颜色 | |||||
}, | |||||
customOpts | |||||
) | |||||
const target = opts.ele | |||||
if (target) { | |||||
target.style.position = 'relative' | |||||
target.style.overflow = 'hidden' | |||||
const rect = target.getBoundingClientRect() | |||||
let ripple = target.querySelector('.waves-ripple') | |||||
if (!ripple) { | |||||
ripple = document.createElement('span') | |||||
ripple.className = 'waves-ripple' | |||||
ripple.style.height = ripple.style.width = Math.max(rect.width, rect.height) + 'px' | |||||
target.appendChild(ripple) | |||||
} else { | |||||
ripple.className = 'waves-ripple' | |||||
} | |||||
switch (opts.type) { | |||||
case 'center': | |||||
ripple.style.top = rect.height / 2 - ripple.offsetHeight / 2 + 'px' | |||||
ripple.style.left = rect.width / 2 - ripple.offsetWidth / 2 + 'px' | |||||
break | |||||
default: | |||||
ripple.style.top = | |||||
(e.pageY - rect.top - ripple.offsetHeight / 2 - document.documentElement.scrollTop || | |||||
document.body.scrollTop) + 'px' | |||||
ripple.style.left = | |||||
(e.pageX - rect.left - ripple.offsetWidth / 2 - document.documentElement.scrollLeft || | |||||
document.body.scrollLeft) + 'px' | |||||
} | |||||
ripple.style.backgroundColor = opts.color | |||||
ripple.className = 'waves-ripple z-active' | |||||
return false | |||||
} | |||||
} | |||||
if (!el[context]) { | |||||
el[context] = { | |||||
removeHandle: handle | |||||
} | |||||
} else { | |||||
el[context].removeHandle = handle | |||||
} | |||||
return handle | |||||
} | |||||
export default { | |||||
bind(el, binding) { | |||||
el.addEventListener('click', handleClick(el, binding), false) | |||||
}, | |||||
update(el, binding) { | |||||
el.removeEventListener('click', el[context].removeHandle, false) | |||||
el.addEventListener('click', handleClick(el, binding), false) | |||||
}, | |||||
unbind(el) { | |||||
el.removeEventListener('click', el[context].removeHandle, false) | |||||
el[context] = null | |||||
delete el[context] | |||||
} | |||||
} |
@@ -1,136 +1,150 @@ | |||||
<template> | <template> | ||||
<div class="navbar"> | |||||
<hamburger :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" /> | |||||
<breadcrumb class="breadcrumb-container" /> | |||||
<div class="right-menu"> | |||||
<el-dropdown class="avatar-container" trigger="click"> | |||||
<div class="avatar-wrapper"> | |||||
<img :src="avatar+'?imageView2/1/w/80/h/80'" class="user-avatar"> | |||||
<i class="el-icon-caret-bottom" /> | |||||
<div class="navbar"> | |||||
<hamburger | |||||
:is-active="sidebar.opened" | |||||
class="hamburger-container" | |||||
@toggleClick="toggleSideBar" | |||||
/> | |||||
<breadcrumb class="breadcrumb-container" /> | |||||
<div class="left-menu"> | |||||
<span class="current-user">当前用户:{{currentUser}}</span> | |||||
</div> | </div> | ||||
<el-dropdown-menu slot="dropdown" class="user-dropdown"> | |||||
<router-link to="/"> | |||||
<el-dropdown-item> | |||||
首页 | |||||
</el-dropdown-item> | |||||
</router-link> | |||||
<!-- <a target="_blank" href="https://panjiachen.github.io/vue-element-admin-site/#/"> | |||||
<div class="right-menu"> | |||||
<el-dropdown class="avatar-container" trigger="click"> | |||||
<div class="avatar-wrapper"> | |||||
<img :src="avatar+'?imageView2/1/w/80/h/80'" class="user-avatar" /> | |||||
<i class="el-icon-caret-bottom" /> | |||||
</div> | |||||
<el-dropdown-menu slot="dropdown" class="user-dropdown"> | |||||
<router-link to="/"> | |||||
<el-dropdown-item>首页</el-dropdown-item> | |||||
</router-link> | |||||
<!-- <a target="_blank" href="https://panjiachen.github.io/vue-element-admin-site/#/"> | |||||
<el-dropdown-item>Docs</el-dropdown-item> | <el-dropdown-item>Docs</el-dropdown-item> | ||||
</a> --> | |||||
<el-dropdown-item divided @click.native="logout"> | |||||
<span style="display:block;">退出登录</span> | |||||
</el-dropdown-item> | |||||
</el-dropdown-menu> | |||||
</el-dropdown> | |||||
</a>--> | |||||
<el-dropdown-item divided @click.native="logout"> | |||||
<span style="display:block;">退出登录</span> | |||||
</el-dropdown-item> | |||||
</el-dropdown-menu> | |||||
</el-dropdown> | |||||
</div> | |||||
</div> | </div> | ||||
</div> | |||||
</template> | </template> | ||||
<script> | <script> | ||||
import { mapGetters } from 'vuex' | |||||
import Breadcrumb from '@/components/Breadcrumb' | |||||
import Hamburger from '@/components/Hamburger' | |||||
import { mapGetters } from "vuex"; | |||||
import Breadcrumb from "@/components/Breadcrumb"; | |||||
import Hamburger from "@/components/Hamburger"; | |||||
export default { | export default { | ||||
components: { | |||||
Breadcrumb, | |||||
Hamburger | |||||
}, | |||||
computed: { | |||||
...mapGetters([ | |||||
'sidebar', | |||||
'avatar' | |||||
]) | |||||
}, | |||||
methods: { | |||||
toggleSideBar() { | |||||
this.$store.dispatch('app/toggleSideBar') | |||||
components: { | |||||
Breadcrumb, | |||||
Hamburger | |||||
}, | |||||
computed: { | |||||
...mapGetters(["sidebar", "avatar"]) | |||||
}, | |||||
data() { | |||||
return { | |||||
currentUser: this.$store.getters.name | |||||
} | |||||
}, | }, | ||||
async logout() { | |||||
await this.$store.dispatch('user/logout') | |||||
this.$router.push(`/login?redirect=${this.$route.fullPath}`) | |||||
methods: { | |||||
toggleSideBar() { | |||||
this.$store.dispatch("app/toggleSideBar"); | |||||
}, | |||||
async logout() { | |||||
await this.$store.dispatch("user/logout"); | |||||
this.$router.push(`/login?redirect=${this.$route.fullPath}`); | |||||
} | |||||
} | } | ||||
} | |||||
} | |||||
}; | |||||
</script> | </script> | ||||
<style lang="scss" scoped> | <style lang="scss" scoped> | ||||
.navbar { | .navbar { | ||||
height: 50px; | |||||
overflow: hidden; | |||||
position: relative; | |||||
background: #fff; | |||||
box-shadow: 0 1px 4px rgba(0,21,41,.08); | |||||
.hamburger-container { | |||||
line-height: 46px; | |||||
height: 100%; | |||||
float: left; | |||||
cursor: pointer; | |||||
transition: background .3s; | |||||
-webkit-tap-highlight-color:transparent; | |||||
&:hover { | |||||
background: rgba(0, 0, 0, .025) | |||||
} | |||||
} | |||||
.breadcrumb-container { | |||||
float: left; | |||||
} | |||||
.right-menu { | |||||
float: right; | |||||
height: 100%; | |||||
line-height: 50px; | |||||
&:focus { | |||||
outline: none; | |||||
} | |||||
.right-menu-item { | |||||
display: inline-block; | |||||
padding: 0 8px; | |||||
height: 100%; | |||||
font-size: 18px; | |||||
color: #5a5e66; | |||||
vertical-align: text-bottom; | |||||
&.hover-effect { | |||||
height: 50px; | |||||
overflow: hidden; | |||||
position: relative; | |||||
background: #fff; | |||||
width: 100%; | |||||
box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08); | |||||
.hamburger-container { | |||||
float: left; | |||||
line-height: 46px; | |||||
cursor: pointer; | cursor: pointer; | ||||
transition: background .3s; | |||||
transition: background 0.3s; | |||||
-webkit-tap-highlight-color: transparent; | |||||
&:hover { | &:hover { | ||||
background: rgba(0, 0, 0, .025) | |||||
background: rgba(0, 0, 0, 0.025); | |||||
} | } | ||||
} | |||||
} | } | ||||
.avatar-container { | |||||
margin-right: 30px; | |||||
.avatar-wrapper { | |||||
margin-top: 5px; | |||||
position: relative; | |||||
.breadcrumb-container { | |||||
line-height: 50px; | |||||
float: left; | |||||
} | |||||
.left-menu { | |||||
float: left; | |||||
margin-left: 150px; | |||||
height: 100%; | |||||
line-height: 50px; | |||||
// 当前用户 | |||||
.current-user { | |||||
line-height: 50px; | |||||
} | |||||
} | |||||
.right-menu { | |||||
float: right; | |||||
height: 100%; | |||||
line-height: 50px; | |||||
.user-avatar { | |||||
cursor: pointer; | |||||
width: 40px; | |||||
height: 40px; | |||||
border-radius: 10px; | |||||
&:focus { | |||||
outline: none; | |||||
} | |||||
.right-menu-item { | |||||
display: inline-block; | |||||
padding: 0 8px; | |||||
height: 100%; | |||||
font-size: 18px; | |||||
color: #5a5e66; | |||||
vertical-align: text-bottom; | |||||
&.hover-effect { | |||||
cursor: pointer; | |||||
transition: background 0.3s; | |||||
&:hover { | |||||
background: rgba(0, 0, 0, 0.025); | |||||
} | |||||
} | |||||
} | } | ||||
.el-icon-caret-bottom { | |||||
cursor: pointer; | |||||
position: absolute; | |||||
right: -20px; | |||||
top: 25px; | |||||
font-size: 12px; | |||||
.avatar-container { | |||||
margin-right: 30px; | |||||
.avatar-wrapper { | |||||
margin-top: 5px; | |||||
position: relative; | |||||
.user-avatar { | |||||
cursor: pointer; | |||||
width: 40px; | |||||
height: 40px; | |||||
border-radius: 10px; | |||||
} | |||||
.el-icon-caret-bottom { | |||||
cursor: pointer; | |||||
position: absolute; | |||||
right: -20px; | |||||
top: 25px; | |||||
font-size: 12px; | |||||
} | |||||
} | |||||
} | } | ||||
} | |||||
} | } | ||||
} | |||||
} | } | ||||
</style> | </style> |
@@ -1,3 +1,10 @@ | |||||
/* | |||||
* @Date: 2021-11-30 15:35:16 | |||||
* @LastEditors: JinxuChen | |||||
* @LastEditTime: 2021-11-30 17:51:56 | |||||
* @FilePath: \GpsCardAdmin\src\main.js | |||||
* @description: | |||||
*/ | |||||
import Vue from 'vue' | import Vue from 'vue' | ||||
import 'normalize.css/normalize.css' // A modern alternative to CSS resets | import 'normalize.css/normalize.css' // A modern alternative to CSS resets | ||||
@@ -29,9 +36,9 @@ if (process.env.NODE_ENV === 'production') { | |||||
} | } | ||||
// set ElementUI lang to EN | // set ElementUI lang to EN | ||||
Vue.use(ElementUI, { locale }) | |||||
/* Vue.use(ElementUI, { locale }) */ | |||||
// 如果想要中文版 element-ui,按如下方式声明 | // 如果想要中文版 element-ui,按如下方式声明 | ||||
// Vue.use(ElementUI) | |||||
Vue.use(ElementUI) | |||||
Vue.config.productionTip = false | Vue.config.productionTip = false | ||||
@@ -103,7 +103,8 @@ export const constantRoutes = [{ | |||||
icon: 'el-icon-user-solid' | icon: 'el-icon-user-solid' | ||||
} | } | ||||
}, | }, | ||||
{ | |||||
// todo 一期先不做这个功能 后面原型图确认了再做 | |||||
/* { | |||||
path: 'related-setting', | path: 'related-setting', | ||||
name: 'related-setting', | name: 'related-setting', | ||||
component: () => import('@/views/off-limits-manage/related-setting/index'), | component: () => import('@/views/off-limits-manage/related-setting/index'), | ||||
@@ -111,7 +112,7 @@ export const constantRoutes = [{ | |||||
title: '相关设置', | title: '相关设置', | ||||
icon: 'el-icon-s-tools' | icon: 'el-icon-s-tools' | ||||
} | } | ||||
}, | |||||
}, */ | |||||
{ | { | ||||
path: 'alarm-query', | path: 'alarm-query', | ||||
name: 'alarm-query', | name: 'alarm-query', | ||||
@@ -61,5 +61,5 @@ div:focus { | |||||
// main-container global css | // main-container global css | ||||
.app-container { | .app-container { | ||||
padding: 20px; | |||||
padding: 20px 10px; | |||||
} | } |
@@ -1,8 +1,8 @@ | |||||
/* | /* | ||||
* @Date: 2021-11-30 15:09:25 | * @Date: 2021-11-30 15:09:25 | ||||
* @LastEditors: JinxuChen | * @LastEditors: JinxuChen | ||||
* @LastEditTime: 2021-11-30 15:09:49 | |||||
* @LastEditTime: 2021-12-02 10:20:39 | |||||
* @FilePath: \GpsCardAdmin\src\utils\model.js | * @FilePath: \GpsCardAdmin\src\utils\model.js | ||||
* @description: 版本号 | * @description: 版本号 | ||||
*/ | */ | ||||
export const VersionModel = '1.0.0'; | |||||
export const VersionModel = '1.0.2'; |
@@ -0,0 +1,58 @@ | |||||
Math.easeInOutQuad = function(t, b, c, d) { | |||||
t /= d / 2 | |||||
if (t < 1) { | |||||
return c / 2 * t * t + b | |||||
} | |||||
t-- | |||||
return -c / 2 * (t * (t - 2) - 1) + b | |||||
} | |||||
// requestAnimationFrame for Smart Animating http://goo.gl/sx5sts | |||||
var requestAnimFrame = (function() { | |||||
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function(callback) { window.setTimeout(callback, 1000 / 60) } | |||||
})() | |||||
/** | |||||
* Because it's so fucking difficult to detect the scrolling element, just move them all | |||||
* @param {number} amount | |||||
*/ | |||||
function move(amount) { | |||||
document.documentElement.scrollTop = amount | |||||
document.body.parentNode.scrollTop = amount | |||||
document.body.scrollTop = amount | |||||
} | |||||
function position() { | |||||
return document.documentElement.scrollTop || document.body.parentNode.scrollTop || document.body.scrollTop | |||||
} | |||||
/** | |||||
* @param {number} to | |||||
* @param {number} duration | |||||
* @param {Function} callback | |||||
*/ | |||||
export function scrollTo(to, duration, callback) { | |||||
const start = position() | |||||
const change = to - start | |||||
const increment = 20 | |||||
let currentTime = 0 | |||||
duration = (typeof (duration) === 'undefined') ? 500 : duration | |||||
var animateScroll = function() { | |||||
// increment the time | |||||
currentTime += increment | |||||
// find the value with the quadratic in-out easing function | |||||
var val = Math.easeInOutQuad(currentTime, start, change, duration) | |||||
// move the document.body | |||||
move(val) | |||||
// do the animation unless its over | |||||
if (currentTime < duration) { | |||||
requestAnimFrame(animateScroll) | |||||
} else { | |||||
if (callback && typeof (callback) === 'function') { | |||||
// the animation is done so lets callback | |||||
callback() | |||||
} | |||||
} | |||||
} | |||||
animateScroll() | |||||
} |
@@ -1,27 +1,115 @@ | |||||
<!-- | <!-- | ||||
* @Date: 2021-11-30 14:25:27 | |||||
* @Date: 2021-11-30 09:44:24 | |||||
* @LastEditors: JinxuChen | * @LastEditors: JinxuChen | ||||
* @LastEditTime: 2021-11-30 14:25:37 | |||||
* @LastEditTime: 2021-12-01 14:30:07 | |||||
* @FilePath: \GpsCardAdmin\src\views\off-limits-manage\alarm-query\index.vue | * @FilePath: \GpsCardAdmin\src\views\off-limits-manage\alarm-query\index.vue | ||||
* @description:告警查询 | |||||
* @description: | |||||
--> | --> | ||||
<template> | <template> | ||||
<div> | |||||
告警查询 | |||||
<div class="app-container"> | |||||
<div class="filter-container"> | |||||
<!-- 搜索 --> | |||||
<el-input | |||||
v-model="searchValue" | |||||
placeholder="请输入关键字" | |||||
style="width: 200px; margin-left: 10px;" | |||||
class="filter-item" | |||||
@keyup.enter.native="onSearch" | |||||
/> | |||||
<el-button | |||||
class="filter-item" | |||||
style="margin-left: 10px;" | |||||
type="primary" | |||||
icon="el-icon-search" | |||||
@click="onSearch" | |||||
>搜索</el-button> | |||||
</div> | |||||
<!-- 表格 --> | |||||
<!-- <el-table | |||||
:key="tableKey" | |||||
v-loading="listLoading" | |||||
:data="list" | |||||
border | |||||
fit | |||||
highlight-current-row | |||||
style="width: 100%;" | |||||
@sort-change="sortChange" | |||||
></el-table>--> | |||||
<TTable :tableData="list" :columns="columns" @update="onUpdate" @delete="onDelete"></TTable> | |||||
<!-- 分页 --> | |||||
<pagination | |||||
v-show="total>0" | |||||
:total="total" | |||||
:page.sync="page" | |||||
:limit.sync="limit" | |||||
@pagination="getList" | |||||
/> | |||||
</div> | </div> | ||||
</template> | </template> | ||||
<script> | <script> | ||||
import TopMenu from "@/components/TopMenu"; | |||||
import TTable from "../../../components/TTable/TTable"; | |||||
import Pagination from "@/components/Pagination"; | |||||
export default { | export default { | ||||
name:'', | |||||
data(){ | |||||
return { | |||||
} | |||||
} | |||||
} | |||||
name: "", | |||||
components: { TTable, TopMenu, Pagination }, | |||||
data() { | |||||
return { | |||||
model: "", | |||||
modelOptions: [ | |||||
{ | |||||
value: "1", | |||||
label: "类别1" | |||||
}, | |||||
{ | |||||
value: "2", | |||||
label: "类别1" | |||||
} | |||||
], | |||||
searchValue: "", | |||||
columns: [ | |||||
{ prop: "alarmType", title: "告警类别" }, | |||||
{ prop: "imei", title: "设备IMEI" }, | |||||
{ prop: "alarmAddress", title: "告警地址/经纬度" }, | |||||
{ prop: "createTime", title: "创建时间" }, | |||||
/* { | |||||
action: true, | |||||
title: "操作", | |||||
actions: [ | |||||
{ fnName: "delete", title: "删除", type: "error" }, | |||||
] | |||||
} */ | |||||
], | |||||
list: [ | |||||
{ | |||||
alarmType: '出走风险', | |||||
imei: "141152552521", | |||||
alarmAddress: "广东省佛山市南海区", | |||||
createTime: "2021-11-30" | |||||
} | |||||
], | |||||
total: 1, | |||||
page: 1, | |||||
limit: 10, | |||||
}; | |||||
}, | |||||
methods: { | |||||
// 搜索 | |||||
onSearch() {}, | |||||
// 修改 | |||||
onUpdate(row) { | |||||
console.log("修改", row); | |||||
}, | |||||
// 删除 | |||||
onDelete(row) { | |||||
console.log("删除", row); | |||||
}, | |||||
// 获取分页数据 | |||||
getList() {} | |||||
} | |||||
}; | |||||
</script> | </script> | ||||
<style scoped> | <style scoped> | ||||
</style> | </style> |
@@ -1,27 +1,298 @@ | |||||
<!-- | <!-- | ||||
* @Date: 2021-11-30 09:44:24 | * @Date: 2021-11-30 09:44:24 | ||||
* @LastEditors: JinxuChen | * @LastEditors: JinxuChen | ||||
* @LastEditTime: 2021-11-30 09:44:48 | |||||
* @LastEditTime: 2021-12-01 17:33:03 | |||||
* @FilePath: \GpsCardAdmin\src\views\off-limits-manage\alarm-recognition\index.vue | * @FilePath: \GpsCardAdmin\src\views\off-limits-manage\alarm-recognition\index.vue | ||||
* @description: | * @description: | ||||
--> | --> | ||||
<template> | <template> | ||||
<div> | |||||
告警识别内容 | |||||
<div class="app-container"> | |||||
<div class="filter-container"> | |||||
<el-button | |||||
class="filter-item" | |||||
style="margin-left: 10px;" | |||||
type="primary" | |||||
icon="el-icon-circle-plus" | |||||
@click="onAdd" | |||||
>添加</el-button> | |||||
<el-button | |||||
class="filter-item" | |||||
style="margin-left: 10px;" | |||||
type="primary" | |||||
icon="el-icon-folder-add" | |||||
@click="onImportBatch" | |||||
>批量导入</el-button> | |||||
<!-- 下拉 --> | |||||
<!-- 类型 --> | |||||
<el-select | |||||
v-model="type" | |||||
placeholder="类型" | |||||
style="width: 130px; margin-left: 10px;" | |||||
filterable | |||||
> | |||||
<el-option | |||||
v-for="item in typeOptions" | |||||
:key="item.value" | |||||
:label="item.label" | |||||
:value="item.value" | |||||
class="filter-item" | |||||
></el-option> | |||||
</el-select> | |||||
<!-- 类别 --> | |||||
<el-select | |||||
v-model="model" | |||||
placeholder="类别" | |||||
style="width: 130px; margin-left: 10px;" | |||||
filterable | |||||
> | |||||
<el-option | |||||
v-for="item in modelOptions" | |||||
:key="item.value" | |||||
:label="item.label" | |||||
:value="item.value" | |||||
class="filter-item" | |||||
></el-option> | |||||
</el-select> | |||||
<!-- 搜索 --> | |||||
<el-input | |||||
v-model="searchValue" | |||||
placeholder="请输入关键字" | |||||
style="width: 200px; margin-left: 10px;" | |||||
class="filter-item" | |||||
@keyup.enter.native="onSearch" | |||||
/> | |||||
<el-button | |||||
class="filter-item" | |||||
style="margin-left: 10px;" | |||||
type="primary" | |||||
icon="el-icon-search" | |||||
@click="onSearch" | |||||
>搜索</el-button> | |||||
</div> | |||||
<TTable :tableData="list" :columns="columns" @update="onUpdate" @delete="onDelete"></TTable> | |||||
<!-- 分页 --> | |||||
<pagination | |||||
v-show="total>0" | |||||
:total="total" | |||||
:page.sync="page" | |||||
:limit.sync="limit" | |||||
@pagination="getList" | |||||
/> | |||||
<el-dialog :visible.sync="dialogPvVisible" :title="dialogTitle"> | |||||
<el-form | |||||
ref="dataForm" | |||||
v-model="form" | |||||
label-position="left" | |||||
label-width="70px" | |||||
style="width: 400px; margin-left:50px;" | |||||
> | |||||
<!-- 类型 --> | |||||
<el-form-item label="类型" prop="type"> | |||||
<el-select v-model="form.type" class="filter-item" filterable> | |||||
<el-option | |||||
v-for="item in typeOptions" | |||||
:key="item.value" | |||||
:label="item.label" | |||||
:value="item.value" | |||||
/> | |||||
</el-select> | |||||
</el-form-item> | |||||
<!-- 类别 --> | |||||
<el-form-item label="类别" prop="model"> | |||||
<el-select v-model="form.model" class="filter-item" filterable> | |||||
<el-option | |||||
v-for="item in modelOptions" | |||||
:key="item.value" | |||||
:label="item.label" | |||||
:value="item.value" | |||||
/> | |||||
</el-select> | |||||
</el-form-item> | |||||
<!-- 内容名称 --> | |||||
<el-form-item label="内容名称" prop="content"> | |||||
<el-input v-model="form.content" /> | |||||
</el-form-item> | |||||
<!-- 创建时间 --> | |||||
<el-form-item label="创建时间" prop="timestamp"> | |||||
<el-date-picker v-model="form.createTime" type="datetime" /> | |||||
</el-form-item> | |||||
</el-form> | |||||
<span slot="footer" class="dialog-footer"> | |||||
<el-button type="error" @click="dialogPvVisible = false">取消</el-button> | |||||
<el-button type="primary" @click="dialogStatus === 'update' ? update() : add()">确认</el-button> | |||||
</span> | |||||
</el-dialog> | |||||
<el-dialog :visible.sync="dialogUpload"> | |||||
<upload-excel-component :on-success="handleSuccess" :before-upload="beforeUpload" /> | |||||
</el-dialog> | |||||
</div> | </div> | ||||
</template> | </template> | ||||
<script> | <script> | ||||
import TopMenu from "@/components/TopMenu"; | |||||
import TTable from "../../../components/TTable/TTable"; | |||||
import Pagination from "@/components/Pagination"; | |||||
import UploadExcelComponent from "@/components/UploadExcel/index.vue"; | |||||
export default { | export default { | ||||
name:'', | |||||
data(){ | |||||
return { | |||||
name: "", | |||||
components: { TTable, TopMenu, Pagination, UploadExcelComponent }, | |||||
data() { | |||||
return { | |||||
buttonList: [ | |||||
{ | |||||
name: "添加", | |||||
type: "success", | |||||
click: () => { | |||||
this.onAdd(); | |||||
} | |||||
}, | |||||
{ | |||||
name: "批量导入", | |||||
type: "success", | |||||
click: () => { | |||||
this.onImportBatch(); | |||||
} | |||||
} | |||||
], | |||||
type: "", | |||||
model: "", | |||||
typeOptions: [ | |||||
{ | |||||
value: "1", | |||||
label: "类别1" | |||||
}, | |||||
{ | |||||
value: "2", | |||||
label: "类别1" | |||||
}, | |||||
{ | |||||
value: "3", | |||||
label: "类别1" | |||||
}, | |||||
{ | |||||
value: "4", | |||||
label: "类别1" | |||||
} | |||||
], | |||||
modelOptions: [ | |||||
{ | |||||
value: "1", | |||||
label: "类别1" | |||||
}, | |||||
{ | |||||
value: "2", | |||||
label: "类别1" | |||||
} | |||||
], | |||||
searchValue: "", | |||||
columns: [ | |||||
{ prop: "type", title: "类型" }, | |||||
{ prop: "model", title: "类别" }, | |||||
{ prop: "content", title: "内容名称" }, | |||||
{ prop: "createTime", title: "创建时间" }, | |||||
{ | |||||
action: true, | |||||
title: "操作", | |||||
actions: [ | |||||
{ fnName: "update", title: "修改", type: "primary" }, | |||||
{ fnName: "delete", title: "删除", type: "error" } | |||||
] | |||||
} | |||||
], | |||||
list: [ | |||||
{ | |||||
type: "关键子", | |||||
model: "出走危险", | |||||
content: "港口码头", | |||||
createTime: "2021-11-30" | |||||
} | |||||
], | |||||
total: 1, | |||||
page: 1, | |||||
limit: 10, | |||||
dialogPvVisible: false, | |||||
dialogStatus: "", | |||||
dialogTitle: "修改告警识别内容", | |||||
form: { | |||||
type: "", | |||||
model: "", | |||||
content: "", | |||||
createTime: "" | |||||
}, | |||||
dialogUpload: false | |||||
}; | |||||
}, | |||||
methods: { | |||||
// 添加 | |||||
onAdd() { | |||||
console.log("add"); | |||||
this.form = ""; | |||||
this.dialogTitle = "添加告警识别内容"; | |||||
this.dialogPvVisible = true; | |||||
this.dialogStatus = "add"; | |||||
}, | |||||
add() { | |||||
console.log("add"); | |||||
}, | |||||
// 批量导入, ##注意 ,批量导入格式必须跟表格的一样 | |||||
onImportBatch() { | |||||
this.dialogUpload = true; | |||||
}, | |||||
// 搜索 | |||||
onSearch() {}, | |||||
// 修改 | |||||
onUpdate(row) { | |||||
this.dialogPvVisible = true; | |||||
this.dialogStatus = "update"; | |||||
this.dialogTitle = "修改告警识别内容"; | |||||
this.form = Object.assign({}, row); // copy obj | |||||
this.form.createTime = new Date(this.form.createTime); | |||||
console.log("修改", row); | |||||
}, | |||||
update() { | |||||
console.log("update"); | |||||
}, | |||||
// 删除 | |||||
onDelete(row) { | |||||
console.log("删除", row); | |||||
this.$confirm("是否删除?", { | |||||
confirmButtonText: "确定", | |||||
cancelButtonText: "取消", | |||||
type: "warning" | |||||
}) | |||||
.then(() => { | |||||
this.$message({ | |||||
type: "success", | |||||
message: "删除成功!" | |||||
}); | |||||
}) | |||||
.catch(() => {}); | |||||
}, | |||||
// 获取分页数据 | |||||
getList() {}, | |||||
beforeUpload(file) { | |||||
const isLt1M = file.size / 1024 / 1024 < 1; | |||||
} | |||||
} | |||||
} | |||||
if (isLt1M) { | |||||
return true; | |||||
} | |||||
this.$message({ | |||||
message: "导入的文件不能超过1m", | |||||
type: "warning" | |||||
}); | |||||
return false; | |||||
}, | |||||
handleSuccess({ results, header }) { | |||||
this.list = results; | |||||
this.columns = header.map(h => { | |||||
return { prop: h, title: h } | |||||
}); | |||||
this.dialogUpload = false; | |||||
} | |||||
} | |||||
}; | |||||
</script> | </script> | ||||
<style scoped> | <style scoped> | ||||
</style> | </style> |
@@ -1,27 +1,210 @@ | |||||
<!-- | <!-- | ||||
* @Date: 2021-11-30 14:22:25 | |||||
* @Date: 2021-11-30 09:44:24 | |||||
* @LastEditors: JinxuChen | * @LastEditors: JinxuChen | ||||
* @LastEditTime: 2021-11-30 14:22:37 | |||||
* @LastEditTime: 2021-12-01 17:32:44 | |||||
* @FilePath: \GpsCardAdmin\src\views\off-limits-manage\common-exception\index.vue | * @FilePath: \GpsCardAdmin\src\views\off-limits-manage\common-exception\index.vue | ||||
* @description:通用例外 | |||||
* @description: | |||||
--> | --> | ||||
<template> | <template> | ||||
<div> | |||||
通用例外 | |||||
<div class="app-container"> | |||||
<div class="filter-container"> | |||||
<el-button | |||||
class="filter-item" | |||||
style="margin-left: 10px;" | |||||
type="primary" | |||||
icon="el-icon-circle-plus" | |||||
@click="onAdd" | |||||
>添加</el-button> | |||||
<!-- 下拉 --> | |||||
<!-- 类别 --> | |||||
<el-select v-model="model" placeholder="类别" style="width: 130px; margin-left: 10px;" filterable> | |||||
<el-option | |||||
v-for="item in typeOptions" | |||||
:key="item.value" | |||||
:label="item.label" | |||||
:value="item.value" | |||||
class="filter-item" | |||||
></el-option> | |||||
</el-select> | |||||
<!-- 搜索 --> | |||||
<el-input | |||||
v-model="searchValue" | |||||
placeholder="请输入关键字" | |||||
style="width: 200px; margin-left: 10px;" | |||||
class="filter-item" | |||||
@keyup.enter.native="onSearch" | |||||
/> | |||||
<el-button | |||||
class="filter-item" | |||||
style="margin-left: 10px;" | |||||
type="primary" | |||||
icon="el-icon-search" | |||||
@click="onSearch" | |||||
>搜索</el-button> | |||||
</div> | |||||
<!-- 表格 --> | |||||
<!-- <el-table | |||||
:key="tableKey" | |||||
v-loading="listLoading" | |||||
:data="list" | |||||
border | |||||
fit | |||||
highlight-current-row | |||||
style="width: 100%;" | |||||
@sort-change="sortChange" | |||||
></el-table>--> | |||||
<TTable :tableData="list" :columns="columns" @update="onUpdate" @delete="onDelete"></TTable> | |||||
<!-- 分页 --> | |||||
<pagination | |||||
v-show="total>0" | |||||
:total="total" | |||||
:page.sync="page" | |||||
:limit.sync="limit" | |||||
@pagination="getList" | |||||
/> | |||||
<el-dialog :visible.sync="dialogPvVisible" :title="dialogTitle"> | |||||
<el-form | |||||
ref="dataForm" | |||||
v-model="form" | |||||
label-position="left" | |||||
label-width="70px" | |||||
style="width: 400px; margin-left:50px;" | |||||
> | |||||
<!-- 类别 --> | |||||
<el-form-item label="类别" prop="type"> | |||||
<el-select v-model="form.model" class="filter-item" filterable> | |||||
<el-option | |||||
v-for="item in typeOptions" | |||||
:key="item.value" | |||||
:label="item.label" | |||||
:value="item.value" | |||||
/> | |||||
</el-select> | |||||
</el-form-item> | |||||
<!-- 内容名称 --> | |||||
<el-form-item label="内容名称" prop="content"> | |||||
<el-input v-model="form.content" /> | |||||
</el-form-item> | |||||
<!-- 创建时间 --> | |||||
<el-form-item label="创建时间" prop="timestamp"> | |||||
<el-date-picker v-model="form.createTime" type="datetime" /> | |||||
</el-form-item> | |||||
</el-form> | |||||
<span slot="footer" class="dialog-footer"> | |||||
<el-button type="error" @click="dialogPvVisible = false">取消</el-button> | |||||
<el-button type="primary" @click="dialogStatus === 'update' ? update() : add()">确认</el-button> | |||||
</span> | |||||
</el-dialog> | |||||
</div> | </div> | ||||
</template> | </template> | ||||
<script> | <script> | ||||
import TopMenu from "@/components/TopMenu"; | |||||
import TTable from "../../../components/TTable/TTable"; | |||||
import Pagination from "@/components/Pagination"; | |||||
export default { | export default { | ||||
name:'', | |||||
data(){ | |||||
return { | |||||
} | |||||
} | |||||
} | |||||
name: "", | |||||
components: { TTable, TopMenu, Pagination }, | |||||
data() { | |||||
return { | |||||
typeOptions: [ | |||||
{ | |||||
value: "1", | |||||
label: "类别1" | |||||
}, | |||||
{ | |||||
value: "2", | |||||
label: "类别1" | |||||
}, | |||||
{ | |||||
value: "3", | |||||
label: "类别1" | |||||
}, | |||||
{ | |||||
value: "4", | |||||
label: "类别1" | |||||
} | |||||
], | |||||
model: '', | |||||
searchValue: "", | |||||
columns: [ | |||||
{ prop: "model", title: "类别" }, | |||||
{ prop: "content", title: "内容名称" }, | |||||
{ prop: "createTime", title: "创建时间" }, | |||||
{ | |||||
action: true, | |||||
title: "操作", | |||||
actions: [ | |||||
{ fnName: "update", title: "修改", type: "primary" }, | |||||
{ fnName: "delete", title: "删除", type: "error" } | |||||
] | |||||
} | |||||
], | |||||
list: [ | |||||
{ | |||||
model: "出走危险", | |||||
content: "港口码头", | |||||
createTime: "2021-11-30" | |||||
} | |||||
], | |||||
total: 1, | |||||
page: 1, | |||||
limit: 10, | |||||
type: "error", | |||||
dialogPvVisible: false, | |||||
dialogStatus: '', | |||||
dialogTitle: "修改通用例外", | |||||
form: { | |||||
model: "", | |||||
content: "", | |||||
createTime: "" | |||||
} | |||||
}; | |||||
}, | |||||
methods: { | |||||
// 添加 | |||||
onAdd() { | |||||
this.form = ''; | |||||
this.dialogTitle = '添加通用例外'; | |||||
this.dialogPvVisible = true; | |||||
this.dialogStatus = 'add'; | |||||
}, | |||||
add() { | |||||
console.log("addd"); | |||||
}, | |||||
// 搜索 | |||||
onSearch() {}, | |||||
// 修改 | |||||
onUpdate(row) { | |||||
this.dialogPvVisible = true; | |||||
this.dialogStatus = 'update'; | |||||
this.dialogTitle = '修改通用例外'; | |||||
this.form = Object.assign({}, row); // copy obj | |||||
this.form.createTime = new Date(this.form.createTime); | |||||
console.log("修改", row); | |||||
}, | |||||
update() { | |||||
console.log("update"); | |||||
}, | |||||
// 删除 | |||||
onDelete(row) { | |||||
console.log("删除", row); | |||||
this.$confirm("是否删除?", { | |||||
confirmButtonText: "确定", | |||||
cancelButtonText: "取消", | |||||
type: "warning" | |||||
}).then(() => { | |||||
this.$message({ | |||||
type: "success", | |||||
message: "删除成功!" | |||||
}); | |||||
}).catch(() => {}); | |||||
}, | |||||
// 获取分页数据 | |||||
getList() {} | |||||
} | |||||
}; | |||||
</script> | </script> | ||||
<style scoped> | <style scoped> | ||||
</style> | </style> |
@@ -1,7 +1,7 @@ | |||||
<!-- | <!-- | ||||
* @Date: 2021-11-30 09:28:55 | * @Date: 2021-11-30 09:28:55 | ||||
* @LastEditors: JinxuChen | * @LastEditors: JinxuChen | ||||
* @LastEditTime: 2021-11-30 09:29:14 | |||||
* @LastEditTime: 2021-11-30 16:47:31 | |||||
* @FilePath: \GpsCardAdmin\src\views\off-limits-manage\off-limits-main\off-limits-type\index.vue | * @FilePath: \GpsCardAdmin\src\views\off-limits-manage\off-limits-main\off-limits-type\index.vue | ||||
* @description: | * @description: | ||||
--> | --> | ||||
@@ -16,7 +16,7 @@ export default { | |||||
name:'', | name:'', | ||||
data(){ | data(){ | ||||
return { | return { | ||||
name: '' | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -1,24 +1,177 @@ | |||||
<!-- | <!-- | ||||
* @Date: 2021-11-30 14:23:11 | |||||
* @Date: 2021-11-30 09:44:24 | |||||
* @LastEditors: JinxuChen | * @LastEditors: JinxuChen | ||||
* @LastEditTime: 2021-11-30 14:31:21 | |||||
* @LastEditTime: 2021-12-01 17:35:09 | |||||
* @FilePath: \GpsCardAdmin\src\views\off-limits-manage\user-exception\index.vue | * @FilePath: \GpsCardAdmin\src\views\off-limits-manage\user-exception\index.vue | ||||
* @description:用户例外 | |||||
* @description: | |||||
--> | --> | ||||
<template> | <template> | ||||
<div>用户例外</div> | |||||
<div class="app-container"> | |||||
<div class="filter-container"> | |||||
<!-- 搜索 --> | |||||
<el-input | |||||
v-model="searchValue" | |||||
placeholder="请输入关键字" | |||||
style="width: 200px; margin-left: 10px;" | |||||
class="filter-item" | |||||
@keyup.enter.native="onSearch" | |||||
/> | |||||
<el-button | |||||
class="filter-item" | |||||
style="margin-left: 10px;" | |||||
type="primary" | |||||
icon="el-icon-search" | |||||
@click="onSearch" | |||||
>搜索</el-button> | |||||
</div> | |||||
<!-- 表格 --> | |||||
<!-- <el-table | |||||
:key="tableKey" | |||||
v-loading="listLoading" | |||||
:data="list" | |||||
border | |||||
fit | |||||
highlight-current-row | |||||
style="width: 100%;" | |||||
@sort-change="sortChange" | |||||
></el-table>--> | |||||
<TTable :tableData="list" :columns="columns" @update="onUpdate" @delete="onDelete" @transform="onTransform"></TTable> | |||||
<!-- 分页 --> | |||||
<pagination | |||||
v-show="total>0" | |||||
:total="total" | |||||
:page.sync="page" | |||||
:limit.sync="limit" | |||||
@pagination="getList" | |||||
/> | |||||
<el-dialog :visible.sync="dialogPvVisible" :title="dialogTitle"> | |||||
<el-form | |||||
ref="dataForm" | |||||
v-model="form" | |||||
label-position="left" | |||||
label-width="70px" | |||||
style="width: 400px; margin-left:50px;" | |||||
> | |||||
<!-- 内容名称 --> | |||||
<el-form-item label="IMEI" prop="imei"> | |||||
<el-input v-model="form.imei" /> | |||||
</el-form-item> | |||||
<!-- 内容名称 --> | |||||
<el-form-item label="内容名称" prop="title"> | |||||
<el-input v-model="form.content" /> | |||||
</el-form-item> | |||||
<!-- 创建时间 --> | |||||
<el-form-item label="创建时间" prop="timestamp"> | |||||
<el-date-picker v-model="form.createTime" type="datetime" /> | |||||
</el-form-item> | |||||
</el-form> | |||||
<span slot="footer" class="dialog-footer"> | |||||
<el-button type="error" @click="dialogPvVisible = false">取消</el-button> | |||||
<el-button type="primary" @click="dialogStatus === 'update' ? update() : add()">确认</el-button> | |||||
</span> | |||||
</el-dialog> | |||||
</div> | |||||
</template> | </template> | ||||
<script> | <script> | ||||
import TopMenu from "@/components/TopMenu"; | |||||
import TTable from "../../../components/TTable/TTable"; | |||||
import Pagination from "@/components/Pagination"; | |||||
export default { | export default { | ||||
name: "", | name: "", | ||||
components: { TTable, TopMenu, Pagination }, | |||||
data() { | data() { | ||||
return { | return { | ||||
model: "", | |||||
modelOptions: [ | |||||
{ | |||||
value: "1", | |||||
label: "类别1" | |||||
}, | |||||
{ | |||||
value: "2", | |||||
label: "类别1" | |||||
} | |||||
], | |||||
searchValue: "", | |||||
columns: [ | |||||
{ prop: "imei", title: "IMEI" }, | |||||
{ prop: "content", title: "内容名称" }, | |||||
{ prop: "createTime", title: "创建时间" }, | |||||
{ | |||||
action: true, | |||||
title: "操作", | |||||
actions: [ | |||||
{ fnName: "update", title: "修改", type: "primary" }, | |||||
{ fnName: "delete", title: "删除", type: "error" }, | |||||
{ fnName: "transform", title: "转通用", type: "primary" } | |||||
] | |||||
} | |||||
], | |||||
list: [ | |||||
{ | |||||
imei: "141152552521", | |||||
model: "出走危险", | |||||
content: "港口码头", | |||||
createTime: "2021-11-30" | |||||
} | |||||
], | |||||
total: 1, | |||||
page: 1, | |||||
limit: 10, | |||||
dialogPvVisible: false, | |||||
dialogStatus: "", | |||||
dialogTitle: "修改用户例外", | |||||
form: { | |||||
imei: "", | |||||
content: "", | |||||
createTime: "" | |||||
}, | |||||
}; | }; | ||||
}, | |||||
methods: { | |||||
// 搜索 | |||||
onSearch() {}, | |||||
// 修改 | |||||
onUpdate(row) { | |||||
this.dialogPvVisible = true; | |||||
this.dialogStatus = 'update'; | |||||
this.dialogTitle = '修改用户例外'; | |||||
this.form = Object.assign({}, row); // copy obj | |||||
this.form.createTime = new Date(this.form.createTime); | |||||
console.log("修改", row); | |||||
}, | |||||
// 删除 | |||||
onDelete(row) { | |||||
this.$confirm("是否删除?", { | |||||
confirmButtonText: "确定", | |||||
cancelButtonText: "取消", | |||||
type: "warning" | |||||
}).then(() => { | |||||
this.$message({ | |||||
type: "success", | |||||
message: "删除成功!" | |||||
}); | |||||
}).catch(() => {}); | |||||
}, | |||||
// 转通用例外 | |||||
onTransform(row) { | |||||
this.$confirm("是否转到通用列外?", { | |||||
confirmButtonText: "确定", | |||||
cancelButtonText: "取消", | |||||
type: "warning" | |||||
}).then(() => { | |||||
this.$message({ | |||||
type: "success", | |||||
message: "转移成功!" | |||||
}); | |||||
}).catch(() => {}); | |||||
}, | |||||
// 获取分页数据 | |||||
getList() {} | |||||
} | } | ||||
}; | }; | ||||
</script> | </script> | ||||
<style scoped> | <style scoped> | ||||
</style> | |||||
</style> |