简单封装 基于 quasar组件的 日期选择器

引入 moment
引入高德地图
引入axios
This commit is contained in:
Shikong 2023-03-16 15:59:01 +08:00
parent 4051173743
commit a27006572a
15 changed files with 475 additions and 45 deletions

View File

@ -5,6 +5,13 @@
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + Vue + TS</title>
<script type="text/javascript">
window._AMapSecurityConfig = {
// serviceHost:'您的代理服务器域名或地址/_AMapService',
// 例如 serviceHost:'http://1.1.1.1:80/_AMapService',
securityJsCode: "5d02234aa9de86567268e33be3c22aef"
}
</script>
</head>
<body>
<div id="app"></div>

View File

@ -11,7 +11,10 @@
"build-storybook": "storybook build"
},
"dependencies": {
"@amap/amap-jsapi-loader": "^1.0.1",
"@quasar/extras": "^1.15.11",
"axios": "^1.3.4",
"moment": "^2.29.4",
"pinia": "^2.0.30",
"quasar": "^2.11.5",
"vue": "^3.2.45",

View File

@ -1,30 +1,5 @@
<script setup lang="ts">
import HelloWorld from './components/HelloWorld.vue'
</script>
<template>
<div>
<a href="https://vitejs.dev" target="_blank">
<img src="/vite.svg" class="logo" alt="Vite logo" />
</a>
<a href="https://vuejs.org/" target="_blank">
<img src="./assets/vue.svg" class="logo vue" alt="Vue logo" />
</a>
</div>
<HelloWorld msg="Vite + Vue" />
<router-view></router-view>
</template>
<style scoped lang="scss">
.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.vue:hover {
filter: drop-shadow(0 0 2em #42b883aa);
}
</style>

View File

@ -0,0 +1,8 @@
import {getAxiosInstance} from "matrix-middle-service-web/src/api/utils";
export const http = getAxiosInstance({
baseURL: "/api",
timeout: 30 * 1000
})
export default http;

View File

@ -0,0 +1,3 @@
export const record = {
getLocationRecord: "/record/location/get"
}

View File

@ -0,0 +1,65 @@
import axios, {AxiosInstance, AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig} from "axios";
import {useQuasar} from "quasar";
export function getAxiosInstance(axiosRequestConfig: AxiosRequestConfig): AxiosInstance {
let instance = axios.create(axiosRequestConfig);
// 全局 请求拦截器
instance.interceptors.request.use(async (config: InternalAxiosRequestConfig) => {
let headers = config.headers || {}
return config;
})
// 全局 响应拦截器
instance.interceptors.response.use(successCB, rejectCB);
return instance;
}
// 请求成功回调
export function successCB(response: AxiosResponse | Promise<AxiosResponse>): AxiosResponse | Promise<AxiosResponse> {
function processResponse(response: AxiosResponse) {
if (response.status === 200) { // 响应成功
if (response.data.code === 401) {
const $q = useQuasar()
$q.notify({
position: "top",
color: 'negative',
message: "登录状态失效, 请重新登录",
icon: 'report_problem'
})
console.log(response,response.data.msg)
} else if (response.data.code === 403) {
setTimeout(() => {
console.log(response,response.data.msg)
}, 0)
}
return response;
} else {
return Promise.reject(response);
}
}
if (response instanceof Promise) {
let resp: AxiosResponse
return new Promise((resolve)=>{
response.then((r: AxiosResponse) => {
resp = r;
resolve(processResponse(resp))
});
})
} else {
return processResponse(response);
}
}
// 请求失败回调
export function rejectCB(error: any): any {
let response = error.response
if(response.status === 401){
return response;
} else if(response.status === 403){
setTimeout(() => {
console.log(response.data.msg)
}, 0)
return response;
}
return Promise.reject(error);
}

View File

@ -0,0 +1,251 @@
<template>
<div class="q-pa-md">
<q-input filled v-model="model" dense @click="show = true" :style="{width: range?'350px':'280px'}">
<template v-slot:prepend>
<q-icon name="event" class="cursor-pointer">
<q-popup-proxy transition-show="scale" transition-hide="scale" v-model="show" dense>
<div class="q-gutter-xs row items-stretch">
<q-scroll-area
class="pt-0.5 pl-2 pr-2"
:thumb-style="scrollArea.thumbStyle"
:bar-style="scrollArea.barStyle"
style="width: 150px;max-height: 380px">
<q-btn
v-for="item in (range?rangeShortcut:shortcut)"
class="full-width m-0.5"
color="primary"
size="sm"
@click="setValue(item.value)"
:label="item.label"
/>
</q-scroll-area>
<div class="flex" v-if="!range">
<div class="flex flex-col">
<q-btn color="primary" class="full-width m-1 h-1/3" push>
<div class="row items-center no-wrap">
<q-icon left name="access_time"></q-icon>
<span>{{ date }}</span>
</div>
<q-popup-proxy cover transition-show="scale" transition-hide="scale">
<q-time v-model="date" mask="YYYY-MM-DD HH:mm:ss" format24h with-seconds>
<div class="row items-center justify-end q-gutter-sm">
<q-btn label="确定" color="primary" flat v-close-popup/>
</div>
</q-time>
</q-popup-proxy>
</q-btn>
<q-date v-model="date" mask="YYYY-MM-DD HH:mm:ss" class="flex-2"></q-date>
</div>
</div>
<div v-else class="flex">
<div class="flex flex-col">
<q-btn color="primary" class="m-1 h-1/3" push>
<div class="row items-center no-wrap">
<q-icon left name="access_time"></q-icon>
<span>{{ date.from }}</span>
</div>
<q-popup-proxy cover transition-show="scale" transition-hide="scale">
<q-time v-model="date.from" mask="YYYY-MM-DD HH:mm:ss" format24h
with-seconds>
<div class="row items-center justify-end q-gutter-sm">
<q-btn label="确定" color="primary" flat v-close-popup/>
</div>
</q-time>
</q-popup-proxy>
</q-btn>
<q-date v-model="date.from" mask="YYYY-MM-DD HH:mm:ss" class="flex-2"></q-date>
</div>
<div class="flex flex-col">
<q-btn color="primary" class="full-width m-1 h-1/3" push>
<div class="row items-center no-wrap">
<q-icon left name="access_time"></q-icon>
<span>{{ date.to }}</span>
</div>
<q-popup-proxy cover transition-show="scale" transition-hide="scale">
<q-time v-model="date.to" mask="YYYY-MM-DD HH:mm:ss" format24h with-seconds>
<div class="row items-center justify-end q-gutter-sm">
<q-btn label="确定" color="primary" flat v-close-popup/>
</div>
</q-time>
</q-popup-proxy>
</q-btn>
<q-date v-model="date.to" mask="YYYY-MM-DD HH:mm:ss" class="flex-2" :options="rangeToOptions"></q-date>
</div>
</div>
</div>
</q-popup-proxy>
</q-icon>
</template>
</q-input>
</div>
</template>
<script setup>
import {computed, reactive, ref} from "vue";
import moment from 'moment';
const props = defineProps({
modelValue: String || Object,
range: Boolean
})
const range = computed(() => props.range)
const date = computed({
get() {
return props.modelValue
},
set(value) {
console.log(value)
emit('update:modelValue', value)
}
})
const emit = defineEmits(['update:modelValue'])
const model = computed(() => {
if (range.value) {
return date.value ? `${date.value.from || ""} - ${date.value.to || ""}` : ""
} else {
return date.value;
}
})
const datePicker = ref()
const show = ref(false)
const scrollArea = reactive({
thumbStyle: {
right: '4px',
borderRadius: '5px',
backgroundColor: '#027be3',
width: '5px',
opacity: "0.75"
},
barStyle: {
right: '2px',
borderRadius: '9px',
backgroundColor: '#027be3',
width: '9px',
opacity: "0.2"
}
})
function setValue(value) {
date.value = value();
}
const shortcut = reactive([
{
label: "今天",
value: ()=>moment().startOf('d').format("YYYY-MM-DD HH:mm:ss")
},
])
function rangeToOptions(dateData){
if(!date.value.from){
return true;
}
let result = moment(date.value.from).isSameOrBefore(dateData)
if(!result){
date.value.to = date.value.from
}
return result;
}
const rangeShortcut = reactive([
{
label: "今天至当前时间",
value:()=>({
from: moment().startOf('d').format("YYYY-MM-DD HH:mm:ss"),
to: moment().format("YYYY-MM-DD HH:mm:ss"),
})
},
{
label: "最近5分钟",
value:()=>({
from: moment().subtract(5, 'm').format("YYYY-MM-DD HH:mm:ss"),
to: moment().format("YYYY-MM-DD HH:mm:ss"),
})
},
{
label: "最近30分钟",
value:()=>({
from: moment().subtract(30, 'm').format("YYYY-MM-DD HH:mm:ss"),
to: moment().format("YYYY-MM-DD HH:mm:ss"),
})
},
{
label: "最近1小时",
value:()=>({
from: moment().subtract(1, 'h').format("YYYY-MM-DD HH:mm:ss"),
to: moment().format("YYYY-MM-DD HH:mm:ss"),
})
},
{
label: "最近2小时",
value:()=>({
from: moment().subtract(2, 'h').format("YYYY-MM-DD HH:mm:ss"),
to: moment().format("YYYY-MM-DD HH:mm:ss"),
})
},
{
label: "最近4小时",
value:()=>({
from: moment().subtract(4, 'h').format("YYYY-MM-DD HH:mm:ss"),
to: moment().format("YYYY-MM-DD HH:mm:ss"),
})
},
{
label: "最近6小时",
value:()=>({
from: moment().subtract(6, 'h').format("YYYY-MM-DD HH:mm:ss"),
to: moment().format("YYYY-MM-DD HH:mm:ss"),
})
},
{
label: "最近12小时",
value:()=>({
from: moment().subtract(12, 'h').format("YYYY-MM-DD HH:mm:ss"),
to: moment().format("YYYY-MM-DD HH:mm:ss"),
})
},
{
label: "最近24小时",
value:()=>({
from: moment().subtract(24, 'h').format("YYYY-MM-DD HH:mm:ss"),
to: moment().format("YYYY-MM-DD HH:mm:ss"),
})
},
{
label: "最近2天",
value:()=>({
from: moment().subtract(2, 'd').format("YYYY-MM-DD HH:mm:ss"),
to: moment().format("YYYY-MM-DD HH:mm:ss"),
})
},
{
label: "最近3天",
value:()=>({
from: moment().subtract(3, 'd').format("YYYY-MM-DD HH:mm:ss"),
to: moment().format("YYYY-MM-DD HH:mm:ss"),
})
},
{
label: "最近7天",
value:()=>({
from: moment().subtract(7, 'd').format("YYYY-MM-DD HH:mm:ss"),
to: moment().format("YYYY-MM-DD HH:mm:ss"),
})
},
])
</script>
<style scoped>
</style>

View File

@ -1,9 +1,16 @@
<script setup lang="ts">
import { ref } from 'vue'
import http from "matrix-middle-service-web/src/api";
import {record} from "matrix-middle-service-web/src/api/record";
defineProps<{ msg: string }>()
const count = ref(0)
http.post(record.getLocationRecord,{}).then(resp=>{
let res = resp.data || {}
console.log(res)
})
</script>
<template>

View File

@ -21,6 +21,8 @@ import Store from "matrix-middle-service-web/src/stores";
import Router from "matrix-middle-service-web/src/router";
let app = createApp(App);
app.use(Store())
app.use(Router())
app.use(Quasar, {
plugins: {}, // import Quasar plugins and add here
lang: quasarLang,
@ -37,8 +39,4 @@ app.use(Quasar, {
}
*/
})
app.use(Store)
app.use(Router)
app.mount('#app')

View File

@ -1,9 +1,6 @@
import {
createRouter,
createWebHashHistory,
} from 'vue-router';
import {createRouter, createWebHistory,} from 'vue-router';
import routes from './routes';
import routes from 'matrix-middle-service-web/src/router/routes';
/*
* If not building with SSR mode, you can
@ -15,17 +12,15 @@ import routes from './routes';
*/
export default function Router(/* { store, ssrContext } */) {
const createHistory = createWebHashHistory;
const createHistory = createWebHistory;
const Router = createRouter({
return createRouter({
scrollBehavior: () => ({left: 0, top: 0}),
routes,
// Leave this as is and make changes in quasar.conf.js instead!
// quasar.conf.js -> build -> vueRouterMode
// quasar.conf.js -> build -> publicPath
history: createHistory("/"),
history: createHistory("./"),
});
return Router;
};

View File

@ -3,7 +3,7 @@ import { RouteRecordRaw } from 'vue-router';
const routes: RouteRecordRaw[] = [
{
path: '/',
component: () => import('matrix-middle-service-web/src/components/HelloWorld.vue'),
component: () => import('matrix-middle-service-web/src/views/record/AMapLocation.vue'),
},
];

View File

@ -60,9 +60,7 @@ button:focus-visible {
}
#app {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
text-align: center;
}

View File

@ -0,0 +1,65 @@
<template>
<div class="flex justify-start flex-wrap items-center">
<DateTimeSelector v-model="date" range></DateTimeSelector>
</div>
<div class="flex justify-end flex-wrap items-center p-1">
<q-toggle
label="卫星地图"
v-model="layers.satellite.show"
color="primary"
keep-color
/>
<q-toggle
label="路网"
v-model="layers.roadNet.show"
color="primary"
keep-color
/>
<q-toggle
label="实时交通"
v-model="layers.traffic.show"
color="primary"
keep-color
/>
</div>
<div id="container"></div>
</template>
<script setup>
import AMapLoader from '@amap/amap-jsapi-loader';
import {reactive, ref} from "vue";
import DateTimeSelector from "matrix-middle-service-web/src/components/DateTimeSelector.vue";
const date = ref({})
let map = {}
const layers = reactive({
satellite: {
inst: {},
show: true,
},
roadNet: {
inst: {},
show: false,
},
traffic: {
inst: {},
show: false,
}
})
AMapLoader.load({
"key": "e01d7df3a4c3a1b8f06fa4544ddbbe9c", // WebKey load
"version": "2.0", // JSAPI 1.4.15
"plugins": [], // 使'AMap.Scale'
}).then((AMap) => {
map = new AMap.Map('container');
}).catch(e => {
console.log(e);
})
</script>
<style scoped lang="scss">
#container {
width: 100vw;
height: 80vh;
}
</style>

View File

@ -8,7 +8,13 @@ export default defineConfig({
base: "./",
server: {
strictPort: true,
port: 7868
port: 7868,
proxy:{
"^/api/.*":{
target: "http://10.10.10.100:6573/",
rewrite: (path) => path.replace(/^\/api\//, ''),
},
}
},
resolve: {
alias: {

View File

@ -5,6 +5,13 @@ __metadata:
version: 6
cacheKey: 8
"@amap/amap-jsapi-loader@npm:^1.0.1":
version: 1.0.1
resolution: "@amap/amap-jsapi-loader@npm:1.0.1"
checksum: 9fedc17818b5ab07527340a2e6a50546069a3ec27589a0a504b3c524dc33c26757a34486e65fc3d2a926537b2699912ff9f6e0c336685bb8f7e599995c1002f8
languageName: node
linkType: hard
"@ampproject/remapping@npm:^2.2.0":
version: 2.2.0
resolution: "@ampproject/remapping@npm:2.2.0"
@ -3695,6 +3702,17 @@ __metadata:
languageName: node
linkType: hard
"axios@npm:^1.3.4":
version: 1.3.4
resolution: "axios@npm:1.3.4"
dependencies:
follow-redirects: ^1.15.0
form-data: ^4.0.0
proxy-from-env: ^1.1.0
checksum: 7440edefcf8498bc3cdf39de00443e8101f249972c83b739c6e880d9d669fea9486372dbe8739e88b3bf8bb1ad15f6106693f206f078f4516fe8fd47b1c3093c
languageName: node
linkType: hard
"babel-core@npm:^7.0.0-bridge.0":
version: 7.0.0-bridge.0
resolution: "babel-core@npm:7.0.0-bridge.0"
@ -5276,6 +5294,16 @@ __metadata:
languageName: node
linkType: hard
"follow-redirects@npm:^1.15.0":
version: 1.15.2
resolution: "follow-redirects@npm:1.15.2"
peerDependenciesMeta:
debug:
optional: true
checksum: faa66059b66358ba65c234c2f2a37fcec029dc22775f35d9ad6abac56003268baf41e55f9ee645957b32c7d9f62baf1f0b906e68267276f54ec4b4c597c2b190
languageName: node
linkType: hard
"for-each@npm:^0.3.3":
version: 0.3.3
resolution: "for-each@npm:0.3.3"
@ -5296,6 +5324,17 @@ __metadata:
languageName: node
linkType: hard
"form-data@npm:^4.0.0":
version: 4.0.0
resolution: "form-data@npm:4.0.0"
dependencies:
asynckit: ^0.4.0
combined-stream: ^1.0.8
mime-types: ^2.1.12
checksum: 01135bf8675f9d5c61ff18e2e2932f719ca4de964e3be90ef4c36aacfc7b9cb2fceb5eca0b7e0190e3383fe51c5b37f4cb80b62ca06a99aaabfcfd6ac7c9328c
languageName: node
linkType: hard
"forwarded@npm:0.2.0":
version: 0.2.0
resolution: "forwarded@npm:0.2.0"
@ -6862,6 +6901,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "matrix-middle-service-web@workspace:."
dependencies:
"@amap/amap-jsapi-loader": ^1.0.1
"@babel/core": ^7.21.0
"@quasar/extras": ^1.15.11
"@quasar/vite-plugin": ^1.3.0
@ -6876,7 +6916,9 @@ __metadata:
"@storybook/vue3-vite": ^7.0.0-beta.54
"@vitejs/plugin-vue": ^4.0.0
autoprefixer: latest
axios: ^1.3.4
babel-loader: ^8.3.0
moment: ^2.29.4
pinia: ^2.0.30
postcss: latest
quasar: ^2.11.5
@ -7611,6 +7653,13 @@ __metadata:
languageName: node
linkType: hard
"moment@npm:^2.29.4":
version: 2.29.4
resolution: "moment@npm:2.29.4"
checksum: 0ec3f9c2bcba38dc2451b1daed5daded747f17610b92427bebe1d08d48d8b7bdd8d9197500b072d14e326dd0ccf3e326b9e3d07c5895d3d49e39b6803b76e80e
languageName: node
linkType: hard
"mri@npm:^1.1.0, mri@npm:^1.2.0":
version: 1.2.0
resolution: "mri@npm:1.2.0"
@ -8414,7 +8463,7 @@ __metadata:
languageName: node
linkType: hard
"proxy-from-env@npm:^1.0.0":
"proxy-from-env@npm:^1.0.0, proxy-from-env@npm:^1.1.0":
version: 1.1.0
resolution: "proxy-from-env@npm:1.1.0"
checksum: ed7fcc2ba0a33404958e34d95d18638249a68c430e30fcb6c478497d72739ba64ce9810a24f53a7d921d0c065e5b78e3822759800698167256b04659366ca4d4