董国庆
2025-03-04 17ccc0c9baeaa76772fe328f5871c6c25497a6e5
Merge branch 'master' of http://120.76.84.145:10101/gitblit/r/H5/shehong-vehicle-supervision
1个文件已删除
13个文件已添加
8个文件已修改
529 ■■■■ 已修改文件
src/assets/header/more.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/header/photo.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/routerIcon/alarm.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/routerIcon/car.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/routerIcon/company.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/routerIcon/complaint.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/routerIcon/home.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/routerIcon/sys.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/storeLogo.png 补丁 | 查看 | 原始文档 | blame | 历史
src/layouts/index.vue 104 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main.js 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/index.js 21 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/router.js 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/index.js 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/app.css 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/baseurl.js 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/request.js 88 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/view/complaint/index.vue 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/view/early-warning/index.vue 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/view/login/index.vue 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/view/login/service.js 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
vue.config.js 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/header/more.png
src/assets/header/photo.png
src/assets/routerIcon/alarm.png
src/assets/routerIcon/car.png
src/assets/routerIcon/company.png
src/assets/routerIcon/complaint.png
src/assets/routerIcon/home.png
src/assets/routerIcon/sys.png
src/assets/storeLogo.png
Binary files differ
src/layouts/index.vue
@@ -1,33 +1,62 @@
<template>
    <div>
        <div class="header">
    <div class="sticky top0">
        <div class="header relative">
            <div class="title">
                <img src="@/assets/logo.png" alt="">
                射洪“两客一危”监管平台
            </div>
            <div></div>
            <div class="flex a-center pr--40">
                <div class="flex a-center mr--72">
                    <img src="@/assets/header/photo.png" class="w--32 h--32 shrink0 mr--10" />
                    <div class="fs-- 18 lh--25 color2">admin</div>
                </div>
                <div class="dropdown" @mouseenter="toggleDropdown(true)" @mouseleave="toggleDropdown(false)">
                    <img src="@/assets/header/more.png" class="w--16 h--16" />
                    <div v-if="isOpen" class="dropdown-menu">
                        <div class="dropdown-item" v-for="item in menuItems" :key="item.text">
                            <i :class="item.icon"></i> {{ item.text }}
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="menu w100 bgColor1">
            <div v-for="(item, index) in routesList" :key="index" class="flex a-center h100">
                <div v-for="(item2, index2) in item.children" :key="index2" class="h100">
                    <div v-if="!item2.hide" class="flex a-center h100 px--40 menuItemHover pointer"
                        :class="item2.path == $route.path && 'bgColor2'">
                        <img :src="require(`@/assets/routerIcon/${item2.icon}.png`)"
                            class="w--15 h--15 mr--12 shrink0" />
                        <div class="color1">
                            {{ item2.title }}
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <router-view :key="key"></router-view>
    </div>
</template>
<script>
import routes from '@/router/router'
export default {
    data() {
        return {
            activeIndex2: '1'
            routesList: routes,
            isOpen: false,
            menuItems: [
                { text: '密码设置' },
                { text: '退出登录' },
            ]
        };
    },
    computed: {
        key() {
            return this.$route.path
        },
    created() {
    },
    methods: {
        handleSelect(key, keyPath) {
            console.log(key, keyPath);
        toggleDropdown(state) {
            this.isOpen = state;
        }
    }
}
@@ -38,12 +67,24 @@
    background-color: #0E6EFD;
}
.bgColor2 {
    background: #0D55B9;
}
.color1 {
    color: #fff;
}
.color2 {
    color: rgba(0, 0, 0, .6);
}
.header {
    height: 80px;
    background: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    justify-content: space-between;
    .title {
        display: flex;
@@ -51,6 +92,11 @@
        font-weight: 600;
        font-size: 24px;
        align-items: center;
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        color: rgba(0, 0, 0, .8);
        img {
            width: 40px;
@@ -62,5 +108,41 @@
.menu {
    height: 60px;
    display: flex;
    align-items: center;
    justify-content: center;
}
.menuItemHover:hover {
    background: #0D55B9;
}
.dropdown {
    position: relative;
    display: inline-block;
    cursor: pointer;
}
.dropdown-menu {
    position: absolute;
    top: 100%;
    left: 0;
    transform: translateX(-50%);
    background: white;
    border: 1px solid #ccc;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
    z-index: 1000;
    border-radius: 8px;
}
.dropdown-item {
    padding: 8px 16px;
    white-space: nowrap;
    /* 防止文本换行 */
}
.dropdown-item:hover {
    background-color: #f0f0f0;
    /* 添加 hover 效果 */
}
</style>
src/main.js
@@ -1,30 +1,16 @@
import Vue from 'vue'
import App from './App.vue'
import './assets/tailwind.css'
import router from './router'
import store from './store'
import cookies from 'vue-cookies'
Vue.prototype.$cookies = cookies;
import ElementUI from 'element-ui';
import cookies from 'vue-cookies'
import apiConfig from './utils/baseurl'
Vue.use(ElementUI)
Vue.prototype.$cookies = cookies;
Vue.prototype.$baseURL = apiConfig.baseURL
Vue.config.productionTip = false
Vue.filter('formatNumber', (num) => {
  if (num != 0 && num < 1000 && num.toString().split('.').length == 1) {
    return num + '.0'
  }
  if (num && num >= 1000) {
    if (num.toString().split('.').length == 1) {
      return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + ".0"
    }
    return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
  }
  return num || 0
})
new Vue({
src/router/index.js
@@ -1,6 +1,7 @@
import Vue from 'vue'
import Router from 'vue-router'
import routes from './router'
import store from '@/store' // 导入 Vuex store
const changePush = Router.prototype.push;
Router.prototype.push = function push(location) {
@@ -17,9 +18,21 @@
})
const router = createRouter()
export function resetRouter() {
  const newRouter = createRouter()
  router.matcher = newRouter.matcher // reset router
}
// 路由守卫
// router.beforeEach((to, from, next) => {
//   const token = store.state.token
//   if (!token && to.path != '/') {
//     // 如果没有 token 并且不是去登录页,重定向到登录页
//     next('/')
//   } else if (token && to.path === '/') {
//     // 如果有 token 并且要去登录页,重定向到首页
//     next('/home')
//   } else {
//     // 清理 localStorage
//     localStorage.removeItem('registerForm')
//     next()
//   }
// })
export default router
src/router/router.js
@@ -1,17 +1,49 @@
import Layout from '@/layouts'
/**
 * icon
 * home: 首页
 * alarm: 报警
 * car: 车辆
 * company: 公司
 * complaint: 投诉
 * sys: 系统
 * order: 订单
 *
 * hide: true, // 是否隐藏
 *
 */
export default [
    {
        path: '/',
        component: () => import('@/view/login'),
    },
    {
        path: '/home',
        component: Layout,
        children: [
            {
                path: '/',
                path: '/home',
                component: () => import('@/view/home'),
                title: '首页',
                icon: 'home'
            },
            {
                path: '/early-warning',
                component: () => import('@/view/early-warning'),
                meta: {
                    title: '首页'
                    title: '报警记录',
                    icon: 'home'
                }
            },
            {
                path: '/complaint',
                component: () => import('@/view/complaint/index'),
                meta: {
                    title: '投诉记录'
                }
            } 
        ]
    },
]
]
src/store/index.js
@@ -1,49 +1,26 @@
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
import Vue from 'vue';
import Vuex from 'vuex';
const store = new Vuex.Store({
Vue.use(Vuex);
export default new Vuex.Store({
  state: {
    loginOrIndex: 'Login',
    subjectUI: 'darkBlue', // darkBlue  BlueIndex  Green  Purple
    selectGoodsList: [],
    date: '',
    changeRouterClass: 'statistics'
    token: localStorage.getItem('token') || sessionStorage.getItem('token') || '',
    userInfo: {}
  },
  mutations: {
    SET_LOGIN_OR_INDEX(state, data) {
      state.loginOrIndex = data;
    setToken(state, token) {
      state.token = token;
      localStorage.setItem('token', token);
    },
    SET_SUBJECT_UI(state, data) {
      state.subjectUI = data;
    clearToken(state) {
      state.token = '';
      localStorage.clear();
    },
    SET_SELECT_GOODS_LIST(state, data) {
      state.selectGoodsList = data;
    },
    SET_DATE(state, data) {
      state.date = data;
    },
    SET_CHANGE_ROUTER_CLASS(state, data) {
      state.changeRouterClass = data;
    setUserInfo(state, userInfo) {
      state.userInfo = userInfo;
    }
  },
  actions: {
    setLoginOrIndex({ commit }, data) {
      commit('SET_LOGIN_OR_INDEX', data);
    },
    setSubjectUI({ commit }, data) {
      commit('SET_SUBJECT_UI', data);
    },
    setSelectGoodsList({ commit }, data) {
      commit('SET_SELECT_GOODS_LIST', data);
    },
    setDate({ commit }, data) {
      commit('SET_DATE', data);
    },
    setChangeRouterClass({ commit }, data) {
      commit('SET_CHANGE_ROUTER_CLASS', data);
    }
  }
})
export default store
  actions: {},
  modules: {}
});
src/utils/app.css
@@ -13,9 +13,11 @@
.flex-w {
    flex-wrap: wrap;
}
.flex-start{
.flex-start {
    align-items: flex-start;
}
.j-between {
    justify-content: space-between;
}
@@ -280,6 +282,15 @@
    position: absolute;
}
.sticky {
    position: -webkit-sticky;
    position: sticky;
}
.top0 {
    top: 0;
}
.h100 {
    height: 100%;
}
src/utils/baseurl.js
New file
@@ -0,0 +1,10 @@
const apiConfig = {
    // 开发环境
    development: {
        baseURL: "",
    },
    // 生产环境
    production: {
    },
};
export default apiConfig[process.env.NODE_ENV];
src/utils/request.js
@@ -1,15 +1,13 @@
import axios from 'axios'
import store from '@/store'
import apiConfig from './baseurl'
import store from '@/store' // 导入 Vuex store
import {
  Message
} from 'element-ui'
const service = axios.create({
  // baseURL: `http://vwpmxwbhv59i.guyubao.com`,
  baseURL: `http://192.168.110.34:8081`,
  // baseURL: 'http://112.44.213.180:8081',
  baseURL: apiConfig.baseURL,
  withCredentials: false, // 当跨域请求时发送cookie
  timeout: 30000, // request timeout
})
@@ -17,27 +15,7 @@
// 请求拦截
service.interceptors.request.use(
  config => {
    let token = ''
    let shopType = localStorage.getItem('shopStyle')
    switch (shopType) {
      case '1':
        token = localStorage.getItem('tokenBlue')
        break;
      case '2':
        token = localStorage.getItem('tokenGreen')
        break;
      case '3':
        token = localStorage.getItem('tokenDarkBlue')
        break;
      case '4':
        token = localStorage.getItem('tokenPurple')
        break;
      default:
        break;
    }
    // console.log(shopType,'shopType shopType shopType',token,'token token token');
    config['headers']['Authorization'] = `${token}`
    config.headers['Authorization'] = 'Bearer ' + store.state.token
    if (config.method == 'get') {
      if (!config.params) config.params = {};
      config.params = {
@@ -65,10 +43,10 @@
    }
    const res = response;
    if (res.data.code == 200) {
      if (!res.data) {
      if (!res.data.data) {
        return Promise.resolve({})
      }
      return Promise.resolve(res.data)
      return Promise.resolve(res.data.data)
    } else {
      if (res.data.code == 103 || res.data.code == 401) {
        Message({
@@ -76,58 +54,26 @@
          type: 'warning',
          duration: 2000
        })
        setTimeout(() => {
          let subjectUI = store.state.subjectUI
          switch (subjectUI) {
            case 'BlueIndex':
              localStorage.removeItem('shopStyle')
              localStorage.removeItem('tokenBlue')
              window.location.replace('/shop1/#/');
              break;
            case 'Green':
              localStorage.removeItem('shopStyle')
              localStorage.removeItem('tokenGreen')
              window.location.replace('/shop2/#/');
              break;
            case 'darkBlue':
              let obj = JSON.parse(localStorage.getItem('acountObj'))
              localStorage.setItem('acountObj', JSON.stringify(obj))
              localStorage.removeItem('shopStyle')
              localStorage.removeItem('tokenDarkBlue')
              window.location.replace('/shop3/#/');
              break;
            case 'Purple':
              localStorage.removeItem('shopStyle')
              localStorage.removeItem('tokenPurple')
              window.location.replace('/shop4/#/');
              break;
            default:
              break;
          }
          // if (store.state.subjectUI == 'BlueIndex' || store.state.subjectUI == 'Green' || store.state.subjectUI == 'Purple') {
          //   localStorage.clear();
          //   window.location.replace('/');
          // }
          // if (store.state.subjectUI == 'darkBlue') {
          //   let obj = JSON.parse(localStorage.getItem('acountObj'))
          //   localStorage.clear();
          //   localStorage.setItem('acountObj', JSON.stringify(obj))
          //   window.location.replace('/');
          // }
        }, 2000)
        return Promise.reject(res.data)
        store.commit('clearToken')
        window.location.replace(`/`);
        return Promise.reject(res.data.data)
      }
      Message({
        message: res.data.msg || '服务器错误',
        type: 'error',
        duration: 2000
      })
      return Promise.reject(res.data)
      return Promise.reject(res.data.data)
    }
  },
  error => {
    return Promise.reject(error.message)
    Message({
      message: error.message,
      type: 'error',
      duration: 5000
    })
    return Promise.reject(error)
  }
)
export default service
src/view/complaint/index.vue
New file
@@ -0,0 +1,113 @@
<template>
    <div>
        <div class="form flex a-center j-between mt--23">
            <div class="form-left ml--30">
                <el-form :inline="true" :model="searchForm" class="demo-form-inline">
                    <el-form-item label="预警类型:" prop="type" class="unset_m" style="margin-right: 15px;">
                        <el-select :popper-append-to-body="false" v-model="searchForm.type" placeholder="请选择">
                            <el-option label="全部" value=""></el-option>
                            <el-option label="预警" value="1"></el-option>
                            <el-option label="报警" value="2"></el-option>
                        </el-select>
                    </el-form-item>
                    <el-form-item label="车辆号牌:" prop="level" class="unset_m" style="margin-right: 15px;">
                        <el-input v-model="searchForm.level" placeholder="请输入"></el-input>
                    </el-form-item>
                    <el-form-item label="驾驶员姓名:" prop="name" class="unset_m" style="margin-right: 15px;">
                        <el-input v-model="searchForm.name" placeholder="请输入"></el-input>
                    </el-form-item>
                    <el-form-item label="公司名称:" prop="name" class="unset_m" style="margin-right: 15px;">
                        <el-input v-model="searchForm.name" placeholder="请输入"></el-input>
                    </el-form-item>
                    <el-form-item label="预警时间:" prop="date" class="unset_m" style="margin-right: 15px;">
                        <el-date-picker :append-to-body="false" v-model="searchForm.date" type="daterange"
                            range-separator=" " start-placeholder="开始日期" end-placeholder="结束日期">
                        </el-date-picker>
                    </el-form-item>
                </el-form>
            </div>
            <div class="form-right mr--24 mb--22">
                <el-button class="search-button h--40 w--90 fs--14" icon="el-icon-search" type="primary" size="small"
                    @click="search">查询</el-button>
                <el-button @click="reset" icon="el-icon-refresh-right" class="reset-button h--40 w--90 fs--14"
                    size="small">重置</el-button>
            </div>
        </div>
        <div class="table-box-btn mt--23 ml--30">
            <el-button class="search-button h--40 w--90 fs--14" icon="el-icon-top" type="primary" size="small"
                @click="exportExcell">导出</el-button>
        </div>
        <div class="table-box ml--30 mt--23 mr--30">
            <el-table :data="tableData" border stripe style="width: 100%">
                <el-table-column prop="date" label="序号"></el-table-column>
                <el-table-column prop="name" label="车辆名称"></el-table-column>
                <el-table-column prop="name" label="车牌号码"></el-table-column>
                <el-table-column prop="name" label="投诉内容"></el-table-column>
                <el-table-column prop="name" label="投诉人电话"></el-table-column>
                <el-table-column prop="name" label="被投诉所属公司"></el-table-column>
                <el-table-column prop="name" label="被投诉驾驶员"></el-table-column>
                <el-table-column prop="name" label="投诉时间"></el-table-column>
                <el-table-column prop="name" label="操作">
                    <template slot-scope="scope">
                        <el-button type="text" @click="handle(scope.$index, scope.row)">处理</el-button>
                    </template>
                </el-table-column>
            </el-table>
            <div class="pagination-box relative mt--23 flex j-end">
                <el-pagination :popper-append-to-body="false" @size-change="handleSizeChange"  @current-change="handleCurrentChange"
                    :current-page="searchForm.page" background layout="total,sizes,prev, pager, next,jumper"
                    :total="searchForm.total"  >
                </el-pagination>
            </div>
        </div>
    </div>
</template>
<script>
import { search } from 'core-js/fn/symbol';
export default {
    data() {
        return {
            searchForm: {
                date: '',
                type: '',
                level: '',
                name: '',
                total: 40,
                page: 1,
                pageSize: 10
            },
            tableData: [],
        };
    },
    methods: {
        reset() {
        },
        search() {
        },
        exportExcell() {
        },
        handleSizeChange(e) {
            this.searchForm.pageSize = e
        },
        handleCurrentChange(e) {
            this.searchForm.page = e
        },
    }
}
</script>
<style scoped lang="less">
.search-button {
    height: 40px !important;
}
</style>
src/view/early-warning/index.vue
New file
@@ -0,0 +1,23 @@
<template>
    <div>
        <p>当前路径:{{ $route.path }}</p>
    </div>
</template>
<script>
export default {
    data() {
        return {
            activeIndex: '1',
            activeIndex2: '1'
        };
    },
    methods: {
        handleSelect(key, keyPath) {
            console.log(key, keyPath);
        }
    }
}
</script>
<style></style>
src/view/login/index.vue
New file
@@ -0,0 +1,22 @@
<template>
  <div class="flex a-center">
    <div>射洪“两客一危”监管平台</div>
    <div></div>
  </div>
</template>
<script>
export default {
  components: {},
  props: {},
  data() {
    return {};
  },
  computed: {},
  watch: {},
  created() { },
  mounted() { },
  methods: {},
};
</script>
<style scoped lang="less"></style>
src/view/login/service.js
New file
@@ -0,0 +1,6 @@
import axios from '@/utils/request';
// 密码登录
export const loginPwd = (data) => {
    return axios.post('/auth/companyLogin', data)
}
vue.config.js
@@ -8,8 +8,7 @@
  devServer: {
    proxy: { //跨域配置
      "/api": { //是自定义的本地请求时的名字
        // target: "http://192.168.110.64:8000",
        target: "http://vwpmxwbhv59i.guyubao.com",
        target: "",
        changeOrigin: true, //在本地会创建一个虚拟服务端,然后发送请求的数据,并同时接收请求的数据,这样服务端和服务端进行数据的交互就不会有跨域问题
        pathRewrite: { //路径重写
          "^/api": "/" // '^/api'是一个正则表达式,表示要匹配请求的url中,全部 '/api' 转接为 '/'
@@ -25,4 +24,11 @@
      }
    }
  },
  configureWebpack: {
    resolve: {
      alias: {
        '@': resolve('src'),
      }
    }
  }
}