Browse Source

用户设置

guhongwei 1 year ago
parent
commit
a0d946090b

+ 1 - 1
.gitignore

@@ -26,4 +26,4 @@ coverage
 *.njsproj
 *.sln
 *.sw?
-*history
+*.history

+ 0 - 1
env.d.ts

@@ -1,4 +1,3 @@
-
 /// <reference types="vite/client" />
 interface ImportMetaEnv {
   VITE_BASE_URL: string;

+ 13 - 10
index.html

@@ -1,13 +1,16 @@
 <!DOCTYPE html>
 <html lang="en">
-  <head>
-    <meta charset="UTF-8">
-    <link rel="icon" href="/favicon.ico">
-    <meta name="viewport" content="width=device-width, initial-scale=1.0">
-    <title>加载中...</title>
-  </head>
-  <body>
-    <div id="app"></div>
-    <script type="module" src="/src/main.ts"></script>
-  </body>
+
+<head>
+  <meta charset="UTF-8">
+  <link rel="icon" href="/favicon.ico">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <title>加载中...</title>
+</head>
+
+<body>
+  <div id="app"></div>
+  <script type="module" src="/src/main.ts"></script>
+</body>
+
 </html>

+ 14 - 0
src/components/index.ts

@@ -0,0 +1,14 @@
+import type { Component } from 'vue';
+import cButton from '@common/src/components/frame/c-button.vue';
+import cDialog from '@common/src/components/frame/c-dialog.vue';
+import cSearch from '@common/src/components/frame/c-search.vue';
+import cForm from '@common/src/components/frame/c-form.vue';
+import cTable from '@common/src/components/frame/c-table.vue';
+import cUpload from '@common/src/components/frame/c-upload.vue';
+import cEditor from '@common/src/components/frame/wang-editor.vue';
+
+const components: {
+  [propName: string]: Component;
+} = { cButton, cDialog, cSearch, cForm, cTable, cUpload, cEditor };
+
+export default components;

+ 27 - 4
src/main.ts

@@ -1,14 +1,37 @@
 import { createApp } from 'vue'
 import { createPinia } from 'pinia'
-
 import App from './App.vue'
 import router from './router'
+// 样式
+import '@/assets/main.css'
+// 动画
+import 'animate.css'
+// element
+import ElementPlus from 'element-plus'
+import 'element-plus/dist/index.css'
+import locale from 'element-plus/lib/locale/lang/zh-cn'
+import * as ElementPlusIconsVue from '@element-plus/icons-vue'
+// 图标
+import '@common/src/assets/icon/iconfont.css'
+// moment
+import moment from 'moment'
+// lodash
+// import _ from 'lodash';
 
-import './assets/main.css'
-
+// 组件
+import frameComponents from '@/components/index'
 const app = createApp(App)
-
 app.use(createPinia())
 app.use(router)
+app.use(ElementPlus, { locale })
+for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
+  app.component(key, component)
+}
+app.config.globalProperties.$moment = moment
+
+for (const componentItme in frameComponents) {
+  app.component(componentItme, frameComponents[componentItme])
+}
+app.config.globalProperties.$limit = parseInt(import.meta.env.VITE_APP_PAGE_SIZE) || 10
 
 app.mount('#app')

+ 44 - 4
src/router/index.ts

@@ -1,14 +1,54 @@
-import { createRouter, createWebHistory } from 'vue-router'
+import { createRouter, createWebHistory } from 'vue-router';
+import store from '@/stores/counter';
+import axios from 'axios';
+// 公共
+import common from './module/common';
+// 公共
+import user from './module/user';
 
 const router = createRouter({
   history: createWebHistory(import.meta.env.BASE_URL),
   routes: [
+    // 公共
+    ...common,
     {
       path: '/',
-      name: 'home',
-      component: () => import('../views/home/index.vue')
+      redirect: '/homeIndex'
     },
+    {
+      path: '/homeIndex',
+      meta: { title: '中科在线(长春)' },
+      component: () => import('@common/src/components/user-frame/home.vue'),
+      children: [
+        {
+          path: '/homeIndex',
+          meta: { title: '中科在线(长春)' },
+          component: () => import('@/views/home/index.vue')
+        },
+        ...user
+      ]
+    }
   ]
 });
+router.beforeEach(async (to, from, next) => {
+  document.title = `${to.meta.title} `;
+  const token = localStorage.getItem('token');
+  if (token) {
+    const res = await axios.request({
+      method: 'get',
+      url: '/zkzx/v2/api/token/tokenView',
+      responseType: 'json',
+      headers: {
+        token: token
+      }
+    });
+    if (res.data.errcode == '0') {
+      store.commit('setUser', res.data.data, { root: true });
+    }
+    next();
+  } else {
+    window.alert('无登录信息,无法打开');
+  }
+});
 
-export default router
+export default router;

+ 1 - 0
src/router/module/common.ts

@@ -0,0 +1 @@
+export default [];

+ 38 - 0
src/router/module/user.ts

@@ -0,0 +1,38 @@
+export default [
+  {
+    path: '/basic',
+    meta: { title: '基本信息' },
+    component: () => import('@/views/basic/index.vue')
+  },
+  {
+    path: '/message',
+    meta: { title: '基本信息' },
+    component: () => import('@/views/message/index.vue')
+  }, 
+  {
+    path: '/product',
+    meta: { title: '信息发布' },
+    component: () => import('@/views/product/index.vue')
+  },
+  {
+    path: '/dock/next',
+    meta: { title: '下期直播' },
+    component: () => import('@/views/dock/next/index.vue')
+  },
+  {
+    path: '/dock/pass',
+    meta: { title: '已往直播' },
+    component: () => import('@/views/dock/pass/index.vue')
+  }, 
+  {
+    path: '/matter',
+    meta: { title: '事项管理' },
+    component: () => import('@/views/matter/index.vue')
+  }, 
+  {
+    path: '/passupdate',
+    meta: { title: '修改密码' },
+    component: () => import('@/views/passupdate/index.vue')
+  },
+  
+];

+ 10 - 11
src/stores/counter.ts

@@ -1,12 +1,11 @@
-import { ref, computed } from 'vue'
-import { defineStore } from 'pinia'
+import * as ustate from '@common/src/stores/user/state';
+import * as umutations from '@common/src/stores/user/mutations';
 
-export const useCounterStore = defineStore('counter', () => {
-  const count = ref(0)
-  const doubleCount = computed(() => count.value * 2)
-  function increment() {
-    count.value++
-  }
-
-  return { count, doubleCount, increment }
-})
+import { createStore } from 'vuex';
+const store = createStore({
+  state: { ...ustate },
+  mutations: { ...umutations },
+  actions: {},
+  modules: {}
+});
+export default store;

+ 150 - 0
src/util/axios-wrapper.ts

@@ -0,0 +1,150 @@
+/* eslint-disable no-console */
+/* eslint-disable no-param-reassign */
+
+import _ from 'lodash';
+import Axios from 'axios';
+import { Util, Error } from 'naf-core';
+// import { Indicator } from 'mint-ui';
+import type { IOptionsType, IQueryType, IRequestResult } from './types.util';
+
+const { trimData, isNullOrUndefined } = Util;
+const { ErrorCode } = Error;
+
+let currentRequests = 0;
+
+// // 参数类型设置
+// type valueType = string | number | object | boolean | Array<any>;
+// type queryType = string | number | boolean;
+
+// export interface IQueryType {
+//   [props: string]: queryType;
+// }
+// export interface IOptionsType {
+//   [props: string]: valueType;
+// }
+
+// export interface IRequestResult {
+//   errcode: string | number;
+//   errmsg: string | number;
+//   details?: string;
+//   [props: string]: any;
+// }
+
+export class AxiosWrapper {
+  constructor({ baseUrl = import.meta.env.VITE_REQUEST_BASE, unwrap = true } = {}) {
+    this.baseUrl = baseUrl;
+    this.unwrap = unwrap;
+  }
+  baseUrl: string;
+  unwrap: boolean;
+
+  // 替换uri中的参数变量
+  static merge(uri: string, query: IQueryType) {
+    if (!uri.includes(':')) {
+      return uri;
+    }
+    const keys = [];
+    const regexp = /\/:([a-z0-9_]+)/gi;
+    let res;
+    // eslint-disable-next-line no-cond-assign
+    while ((res = regexp.exec(uri)) != null) {
+      keys.push(res[1]);
+    }
+    keys.forEach((key) => {
+      const val = _.get(query, key);
+      if (!isNullOrUndefined(val)) {
+        uri = uri.replace(`:${key}`, `${val}`);
+      }
+    });
+    return uri;
+  }
+
+  $get(uri: string, query?: IQueryType, options?: IOptionsType) {
+    return this.$request(uri, undefined, query, options);
+  }
+
+  $post(uri: string, data: object = {}, query?: IQueryType, options?: IOptionsType) {
+    return this.$request(uri, data, query, options);
+  }
+  $delete(uri: string, data: object = {}, query?: IQueryType, options: IOptionsType = {}) {
+    options = { ...options, method: 'delete' };
+    return this.$request(uri, data, query, options);
+  }
+  async $request(uri: string, data?: object, query?: IQueryType, options?: IOptionsType) {
+    if (query && _.isObject(query)) {
+      const keys = Object.keys(query);
+      for (const key of keys) {
+        const val = _.get(query, key);
+        if (val === '') {
+          delete query[key];
+        }
+      }
+    }
+    if (_.isObject(query) && _.isObject(options)) {
+      options = { ...options, params: query, method: 'get' };
+    } else if (_.isObject(query) && !query.params) {
+      options = { params: query };
+    } else if (_.isObject(query) && query.params) {
+      options = query;
+    }
+    if (!options) options = {};
+    if (options.params) options.params = trimData(options.params, null, null);
+    const params = _.get(options, 'params');
+    const url = AxiosWrapper.merge(uri, params as IQueryType);
+    currentRequests += 1;
+    // Indicator.open({
+    //   spinnerType: 'fading-circle',
+    // });
+    try {
+      let returnData: any;
+      const axios = Axios.create({
+        baseURL: this.baseUrl,
+      });
+      // if (util.token && util.token !== null) axios.defaults.headers.common.Authorization = util.token;
+      const token = localStorage.getItem('token');
+      const apiToken = sessionStorage.getItem('apiToken');
+      if (token) axios.defaults.headers.common['token'] = token;
+      if (apiToken) axios.defaults.headers.common['api-token'] = apiToken;
+      const res = await axios.request({
+        method: isNullOrUndefined(data) ? 'get' : 'post',
+        url,
+        data,
+        responseType: 'json',
+        ...options,
+      });
+      const returnRes: IRequestResult = res.data;
+      const { errcode, errmsg, details } = returnRes;
+      if (errcode) {
+        console.warn(`[${uri}] fail: ${errcode}-${errmsg} ${details}`);
+        return returnRes;
+      }
+      // unwrap data
+      if (this.unwrap) {
+        returnData = returnRes;
+      }
+      // 处理apiToken
+      const { apiToken: at, ...others } = returnData;
+      if (at) sessionStorage.setItem('apiToken', at);
+      return others;
+    } catch (err: any) {
+      let errmsg = '接口请求失败,请稍后重试';
+      if (err.response) {
+        const { status } = err.response;
+        if (status === 401) errmsg = '用户认证失败,请重新登录';
+        if (status === 403) errmsg = '当前用户不允许执行该操作';
+      }
+      console.error(
+        `[AxiosWrapper] 接口请求失败: ${err.config && err.config.url} - 
+        ${err.message}`
+      );
+      return { errcode: ErrorCode.SERVICE_FAULT, errmsg, details: err.message };
+    } finally {
+      /* eslint-disable */
+      currentRequests -= 1;
+      if (currentRequests <= 0) {
+        currentRequests = 0;
+        // Indicator.close();
+      }
+    }
+  }
+}

+ 29 - 0
src/util/types.util.ts

@@ -0,0 +1,29 @@
+// 参数类型设置
+type valueType = string | number | Object | boolean | Array<any>;
+type queryType = string | number | boolean;
+
+export interface IQueryType {
+  [props: string]: queryType;
+}
+export interface IOptionsType {
+  [props: string]: valueType;
+}
+
+export interface IRequestResult {
+  errcode: string | number;
+  errmsg: string | number;
+  details?: string;
+  [props: string]: any;
+}
+export interface IQueryResult {
+  errcode?: string | number;
+  errmsg?: string | number;
+  data: valueType;
+  total: number;
+}
+
+export interface IQueryParams {
+  skip?: number;
+  limit?: number;
+  [props: string]: any;
+}

+ 38 - 0
src/views/basic/index.vue

@@ -0,0 +1,38 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
+        <el-col :span="24" class="one">系统首页</el-col>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup lang="ts">
+// 基础
+import type { Ref } from 'vue';
+// reactive,
+import { onMounted, ref, getCurrentInstance } from 'vue';
+// 接口
+//import { TestStore } from '@common/src/stores/test';
+//import type { IQueryResult } from '@/util/types.util';
+//const testAxios = TestStore();
+const { proxy } = getCurrentInstance() as any;
+// 加载中
+const loading: Ref<any> = ref(false);
+// 分页数据
+//  const skip = 0;
+//  const limit = proxy.limit;;
+// 请求
+onMounted(async () => {
+  loading.value = true;
+  //  await search({ skip, limit });
+  loading.value = false;
+});
+//const search = async (e: { skip: number; limit: number }) => {
+//  const info = { skip: e.skip, limit: e.limit, ...searchInfo.value  };
+//  const res: IQueryResult = await testAxios.query(info);
+//  console.log(res);
+//};
+</script>
+<style scoped lang="scss"></style>

+ 38 - 0
src/views/dock/next/index.vue

@@ -0,0 +1,38 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
+        <el-col :span="24" class="one">系统首页</el-col>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup lang="ts">
+// 基础
+import type { Ref } from 'vue';
+// reactive,
+import { onMounted, ref, getCurrentInstance } from 'vue';
+// 接口
+//import { TestStore } from '@common/src/stores/test';
+//import type { IQueryResult } from '@/util/types.util';
+//const testAxios = TestStore();
+const { proxy } = getCurrentInstance() as any;
+// 加载中
+const loading: Ref<any> = ref(false);
+// 分页数据
+//  const skip = 0;
+//  const limit = proxy.limit;;
+// 请求
+onMounted(async () => {
+  loading.value = true;
+  //  await search({ skip, limit });
+  loading.value = false;
+});
+//const search = async (e: { skip: number; limit: number }) => {
+//  const info = { skip: e.skip, limit: e.limit, ...searchInfo.value  };
+//  const res: IQueryResult = await testAxios.query(info);
+//  console.log(res);
+//};
+</script>
+<style scoped lang="scss"></style>

+ 38 - 0
src/views/dock/pass/index.vue

@@ -0,0 +1,38 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
+        <el-col :span="24" class="one">系统首页</el-col>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup lang="ts">
+// 基础
+import type { Ref } from 'vue';
+// reactive,
+import { onMounted, ref, getCurrentInstance } from 'vue';
+// 接口
+//import { TestStore } from '@common/src/stores/test';
+//import type { IQueryResult } from '@/util/types.util';
+//const testAxios = TestStore();
+const { proxy } = getCurrentInstance() as any;
+// 加载中
+const loading: Ref<any> = ref(false);
+// 分页数据
+//  const skip = 0;
+//  const limit = proxy.limit;;
+// 请求
+onMounted(async () => {
+  loading.value = true;
+  //  await search({ skip, limit });
+  loading.value = false;
+});
+//const search = async (e: { skip: number; limit: number }) => {
+//  const info = { skip: e.skip, limit: e.limit, ...searchInfo.value  };
+//  const res: IQueryResult = await testAxios.query(info);
+//  console.log(res);
+//};
+</script>
+<style scoped lang="scss"></style>

+ 38 - 0
src/views/matter/index.vue

@@ -0,0 +1,38 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
+        <el-col :span="24" class="one">系统首页</el-col>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup lang="ts">
+// 基础
+import type { Ref } from 'vue';
+// reactive,
+import { onMounted, ref, getCurrentInstance } from 'vue';
+// 接口
+//import { TestStore } from '@common/src/stores/test';
+//import type { IQueryResult } from '@/util/types.util';
+//const testAxios = TestStore();
+const { proxy } = getCurrentInstance() as any;
+// 加载中
+const loading: Ref<any> = ref(false);
+// 分页数据
+//  const skip = 0;
+//  const limit = proxy.limit;;
+// 请求
+onMounted(async () => {
+  loading.value = true;
+  //  await search({ skip, limit });
+  loading.value = false;
+});
+//const search = async (e: { skip: number; limit: number }) => {
+//  const info = { skip: e.skip, limit: e.limit, ...searchInfo.value  };
+//  const res: IQueryResult = await testAxios.query(info);
+//  console.log(res);
+//};
+</script>
+<style scoped lang="scss"></style>

+ 38 - 0
src/views/message/index.vue

@@ -0,0 +1,38 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
+        <el-col :span="24" class="one">系统首页</el-col>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup lang="ts">
+// 基础
+import type { Ref } from 'vue';
+// reactive,
+import { onMounted, ref, getCurrentInstance } from 'vue';
+// 接口
+//import { TestStore } from '@common/src/stores/test';
+//import type { IQueryResult } from '@/util/types.util';
+//const testAxios = TestStore();
+const { proxy } = getCurrentInstance() as any;
+// 加载中
+const loading: Ref<any> = ref(false);
+// 分页数据
+//  const skip = 0;
+//  const limit = proxy.limit;;
+// 请求
+onMounted(async () => {
+  loading.value = true;
+  //  await search({ skip, limit });
+  loading.value = false;
+});
+//const search = async (e: { skip: number; limit: number }) => {
+//  const info = { skip: e.skip, limit: e.limit, ...searchInfo.value  };
+//  const res: IQueryResult = await testAxios.query(info);
+//  console.log(res);
+//};
+</script>
+<style scoped lang="scss"></style>

+ 74 - 0
src/views/passupdate/index.vue

@@ -0,0 +1,74 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
+        <el-col :span="24" class="one">
+          <cForm :span="24" :fields="fields" :form="form" :rules="rules" @save="toSave"> </cForm>
+        </el-col>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup lang="ts">
+// 基础
+import store from '@/stores/counter';
+import type { Ref } from 'vue';
+import { onMounted, ref } from 'vue';
+import { ElMessage } from 'element-plus';
+
+// 接口
+import { PersonalStore } from '@common/src/stores/admins/personal'; // 个人
+import { CompanyStore } from '@common/src/stores/admins/company'; // 企业
+import { ExpertStore } from '@common/src/stores/admins/expert'; // 专家
+import type { IQueryResult } from '@/util/types.util';
+const personalAxios = PersonalStore();
+const companyAxios = CompanyStore();
+const expertAxiso = ExpertStore();
+// 加载中
+const loading: Ref<any> = ref(false);
+
+// 表单
+const form: Ref<any> = ref({});
+const fields: Ref<any> = ref([
+  { label: '新密码', model: 'password', type: 'password' },
+  { label: '确认新密码', model: 'ispassword', type: 'password' }
+]);
+const rules: Ref<any> = ref({
+  password: [{ required: true, message: '请输入新密码' }],
+  ispassword: [
+    { required: true, message: '请输入确认新密码' },
+    {
+      trigger: 'blur',
+      validator: (rule, value, callback) => {
+        if (form.value.password !== value) {
+          callback(new Error('两次输入的密码不一致'));
+        } else {
+          callback();
+        }
+      }
+    }
+  ]
+});
+
+// 请求
+onMounted(async () => {
+  loading.value = true;
+  loading.value = false;
+});
+// 提交保存
+const toSave = async (data) => {
+  let user = store.state.user;
+  let res: IQueryResult;
+  if (user.type == '4') res = await personalAxios.rp({ password: data.password });
+  else if (user.type == '5') res = await companyAxios.rp({ password: data.password });
+  else if (user.type == '6') res = await expertAxiso.rp({ password: data.password });
+  if (res.errcode == '0') {
+    ElMessage({ type: 'success', message: '修改密码成功' });
+    // 退出登录--待做
+  } else {
+    ElMessage({ type: 'error', message: `${res.errmsg}` });
+  }
+};
+</script>
+<style scoped lang="scss"></style>

+ 38 - 0
src/views/product/index.vue

@@ -0,0 +1,38 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
+        <el-col :span="24" class="one">系统首页</el-col>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup lang="ts">
+// 基础
+import type { Ref } from 'vue';
+// reactive,
+import { onMounted, ref, getCurrentInstance } from 'vue';
+// 接口
+//import { TestStore } from '@common/src/stores/test';
+//import type { IQueryResult } from '@/util/types.util';
+//const testAxios = TestStore();
+const { proxy } = getCurrentInstance() as any;
+// 加载中
+const loading: Ref<any> = ref(false);
+// 分页数据
+//  const skip = 0;
+//  const limit = proxy.limit;;
+// 请求
+onMounted(async () => {
+  loading.value = true;
+  //  await search({ skip, limit });
+  loading.value = false;
+});
+//const search = async (e: { skip: number; limit: number }) => {
+//  const info = { skip: e.skip, limit: e.limit, ...searchInfo.value  };
+//  const res: IQueryResult = await testAxios.query(info);
+//  console.log(res);
+//};
+</script>
+<style scoped lang="scss"></style>

+ 0 - 4
tsconfig.json

@@ -27,11 +27,7 @@
         "../common/*"
       ]
     },
-    "types": [
-      "vite/client"
-    ],
     "isolatedModules": false,
-    "suppressImplicitAnyIndexErrors": true,
     "sourceMap": true,
     "resolveJsonModule": true,
     "esModuleInterop": true,

+ 6 - 2
vite.config.ts

@@ -17,9 +17,13 @@ export default defineConfig(({ mode }) => {
       port: 8002,
       proxy: {
         '/files': {
-          target: 'http://basic.waityou24.cn'
+          target: 'http://broadcast.waityou24.cn'
         },
-        
+        '/zkzx/v2/api': {
+          target: 'http://192.168.1.113:12001',
+          changeOrigin: true,
+          ws: false
+        }
       },
       fs: { strict: false }
     },