ソースを参照

📦 优化细节问题

快乐的梦鱼 1 週間 前
コミット
ce2806fec3
共有12 個のファイルを変更した3075 個の追加10379 個の削除を含む
  1. 2935 10357
      package-lock.json
  2. 4 1
      src/App.vue
  3. 1 1
      src/api/CommonContent.ts
  4. 6 5
      src/api/RequestModules.ts
  5. 8 0
      src/assets/scss/main.scss
  6. 79 0
      src/components/MobileNav.vue
  7. 3 0
      src/components/icons/IconBack.vue
  8. 1 1
      src/main.ts
  9. 7 2
      src/pages/details.vue
  10. 2 3
      src/pages/forms/common.vue
  11. 19 2
      src/pages/inheritor.vue
  12. 10 7
      src/stores/auth.ts

ファイルの差分が大きいため隠しています
+ 2935 - 10357
package-lock.json


+ 4 - 1
src/App.vue

@@ -9,8 +9,10 @@
     :componentSize="'large'"
   >
     <NavBar v-if="hasNav" />
+    <MobileNav v-else />
     <main :class="{
       'has-nav': hasNav,
+      'mobile-nav': !hasNav,
     }">
       <RouterView />
       <!-- <RouterView v-slot="{ Component }">
@@ -25,7 +27,7 @@
 </template>
 
 <script setup lang="ts">
-import { computed, onMounted, watch } from 'vue';
+import { computed, onMounted, provide, watch } from 'vue';
 import { RouterView, useRoute } from 'vue-router'
 import { useAuthStore } from './stores/auth';
 import NavBar from './components/NavBar.vue';
@@ -33,6 +35,7 @@ import zhCN from 'ant-design-vue/es/locale/zh_CN';
 import { useRedirectLoginPage } from './common/LoginPageRedirect';
 import FooterSmall from './components/FooterSmall.vue';
 import Colors from './assets/scss/vueexp.module.scss';
+import MobileNav from './components/MobileNav.vue';
 
 const authStore = useAuthStore();
 const route = useRoute();

+ 1 - 1
src/api/CommonContent.ts

@@ -1,7 +1,7 @@
 import { DataModel, transformArrayDataModel, type NewDataModel } from '@imengyu/js-request-transform';
 import { AppServerRequestModule } from './RequestModules';
-import type { QueryParams } from "@imengyu/imengyu-utils/dist/request";
 import { transformSomeToArray } from '@/api/Utils';
+import type { QueryParams } from "@imengyu/imengyu-utils";
 
 export class GetColumListParams extends DataModel<GetColumListParams> {
   

+ 6 - 5
src/api/RequestModules.ts

@@ -8,17 +8,18 @@
 
 import AppCofig from "@/common/config/AppCofig";
 import ApiCofig from "@/common/config/ApiCofig";
-import fetchImplementer from "@imengyu/imengyu-utils/dist/request/implementer/WebFetch";
 import { 
   RequestApiConfig,
   RequestApiError, RequestApiResult, type RequestApiErrorType, 
   RequestCoreInstance, RequestOptions, 
   defaultResponseDataGetErrorInfo, defaultResponseDataHandlerCatch, 
-  RequestResponse
-} from "@imengyu/imengyu-utils/dist/request";
+  RequestResponse,
+  WebFetchImplementer,
+  appendGetUrlParams, 
+  appendPostParams
+} from "@imengyu/imengyu-utils";
 import { logError } from "@imengyu/imengyu-web-shared";
 import type { DataModel, KeyValue, NewDataModel } from "@imengyu/js-request-transform";
-import { appendGetUrlParams, appendPostParams } from "@imengyu/imengyu-utils/dist/request/utils/Utils";
 import { useAuthStore } from "@/stores/auth";
 import { Modal } from "ant-design-vue";
 import { StringUtils } from "@imengyu/imengyu-utils";
@@ -234,7 +235,7 @@ function responseErrorHandler<T extends DataModel>(err: Error, instance: Request
  */
 export class AppServerRequestModule<T extends DataModel> extends RequestCoreInstance<T> {
   constructor() {
-    super(fetchImplementer);
+    super(WebFetchImplementer);
     this.config.baseUrl = ApiCofig.serverProd;
     this.config.errCodes = []; //
     this.config.requestInceptor = requestInceptor;

+ 8 - 0
src/assets/scss/main.scss

@@ -16,6 +16,8 @@ html {
 }
 main {
   position: relative;
+  min-height: 100vh;
+  background-color: #fffffb;
 }
 
 //Header
@@ -280,6 +282,12 @@ $small-banner-height: 445px;
   }
 }
 
+.main-top-banner {
+  width: 100%;
+  height: auto;
+  object-fit: cover;
+}
+
 .form-container {
   max-width: 600px;
   margin: 0 auto;

+ 79 - 0
src/components/MobileNav.vue

@@ -0,0 +1,79 @@
+<template>
+  <nav class="main mobile">
+    <button v-if="canGoBack" @click="router.back()">
+      <IconBack />
+    </button>
+    <span>{{ title }}</span>
+    <span class="button-placeholder"></span>
+  </nav>
+</template>
+
+<script setup lang="ts">
+import { computed } from 'vue';
+import { useRouter } from 'vue-router'
+import IconBack from './icons/IconBack.vue';
+const router = useRouter();
+const canGoBack = computed(() => router.currentRoute.value.name !== 'Home');
+
+defineProps({
+  title: {
+    type: String,
+    default: '',
+  },
+})
+</script>
+
+<style lang="scss">
+@use '@/assets/scss/colors.scss' as *;
+
+$nav-height: 44px;
+
+nav.main.mobile {
+  position: fixed;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  z-index: 100;
+  width: 100%;
+  height: $nav-height;
+  padding: 0;
+  background-color: $primary-color;
+  border-bottom: 1px solid rgba(#fff, 0.2);
+  color: #fff;
+  transition: all ease-in-out 0.3s;
+
+  button {
+    width: $nav-height;
+    height: $nav-height;
+    cursor: pointer;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    color: #fff;
+    background-color: transparent;
+    outline: none;
+    border: none;
+
+    &:hover {
+      background-color: rgba(#fff, 0.2);
+    }
+
+    svg {
+      width: 25px;
+      height: 25px;
+      fill: currentColor;
+    }
+  }
+  .button-placeholder {
+    width: $nav-height;
+  }
+}
+
+main.mobile-nav {
+  .nav-placeholder {
+    height: $nav-height; 
+    background-color: $primary-color;
+  }
+}
+
+</style>

+ 3 - 0
src/components/icons/IconBack.vue

@@ -0,0 +1,3 @@
+<template>
+  <svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M688.8 907c-9.2 0-18.4-3.5-25.5-10.5l-359-359c-14.1-14.1-14.1-36.9 0-50.9l359-359c14.1-14.1 36.9-14.1 50.9 0 14.1 14.1 14.1 36.9 0 50.9L380.7 512l333.6 333.6c14.1 14.1 14.1 36.9 0 50.9-7 7-16.3 10.5-25.5 10.5z"></path></svg>
+</template>

+ 1 - 1
src/main.ts

@@ -1,6 +1,6 @@
 import 'vue3-carousel/carousel.css'
 import '@imengyu/imengyu-web-shared/lib/imengyu-web-shared.css'
-import '@imengyu/vue-dynamic-form/dist/vue-dynamic-form.css'
+import '@imengyu/vue-dynamic-form/dist/style.css'
 import '@vueup/vue-quill/dist/vue-quill.snow.css';
 import 'tinymce/tinymce';
 import 'tinymce/themes/silver/theme';

+ 7 - 2
src/pages/details.vue

@@ -5,11 +5,14 @@
     <!-- 表单 -->
     <section class="main-section">
       <div class="content">
-        <div class="title left-right">
+        <div v-if="hasNav" class="title left-right">
           <a-button :icon="h(ArrowLeftOutlined)" class="mb-3" @click="router.back()">返回</a-button>
           <h2>{{ querys.name }}</h2>
           <span style="width:50px;"></span>
         </div>
+        <div v-else class="title">
+          <h2>{{ querys.name }}</h2>
+        </div>
         <img class="head-img w-100 radius-base" src="https://mn.wenlvti.net/app_static/xiangan/banner_dig_1.jpg"/>
  
         <div class="mt-2 p-2 bg-primary radius-s rounded-3 d-flex flex-row align-center">
@@ -52,7 +55,7 @@
               <div class="desc">维护文化多样性</div>
             </div>
             <a-button type="primary" @click="goForm('ich', 0)">
-              填写
+              填写
             </a-button>
           </div>
           <div v-if="canCollect('environment')" class="item">
@@ -148,6 +151,7 @@ import { useCollectStore } from '@/stores/collect';
 import { useTaskEntryForm } from './composeable/TaskEntryForm';
 import { useAuthStore } from '@/stores/auth';
 
+const authStore = useAuthStore();
 const router = useRouter();
 const { querys } = useLoadQuerys({ 
   id: 0,  
@@ -160,6 +164,7 @@ const nextPageData = computed(() => ({
   villageId: querys.value.id,  
   villageVolunteerId: querys.value.villageVolunteerId,
 }));
+const hasNav = computed(() => authStore.loginFromEmbed === false);
 const { isAdmin } = useAuthStore();
 const { canCollect, isEmpty } = useCollectStore();
 const { goForm } = useTaskEntryForm();

+ 2 - 3
src/pages/forms/common.vue

@@ -39,15 +39,14 @@
 <script setup lang="ts">
 import { ref, h, reactive } from 'vue';
 import { getVillageInfoForm } from './forms';
-import { RequestApiError } from '@imengyu/imengyu-utils/dist/request';
+import { RequestApiError, waitTimeOut } from '@imengyu/imengyu-utils';
 import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
 import { logError, useLoadQuerys, usePageAction } from '@imengyu/imengyu-web-shared';
 import { message, Modal } from 'ant-design-vue';
 import { DynamicForm, type IDynamicFormOptions, type IDynamicFormRef } from '@imengyu/vue-dynamic-form';
-import VillageInfoApi from '@/api/inhert/VillageInfoApi';
 import type { FormInstance } from 'ant-design-vue/es/form/Form';
-import { waitTimeOut } from '@imengyu/imengyu-utils';
 import { ArrowLeftOutlined } from '@ant-design/icons-vue';
+import VillageInfoApi from '@/api/inhert/VillageInfoApi';
 
 const loading = ref(false);
 const formRef = ref<IDynamicFormRef>();

+ 19 - 2
src/pages/inheritor.vue

@@ -3,10 +3,11 @@
   <div class="about main-background main-background-type0">
     <div class="nav-placeholder">
     </div>
+    <img class="main-top-banner" src="https://mn.wenlvti.net/app_static/xiangan/banner_submit.jpg" />
     <!-- 表单 -->
     <section class="main-section large">
       <div class="content">
-        <div class="title left-right">
+        <div v-if="hasNav" class="title left-right">
           <span style="width:160px;"></span>
           <h2>乡源·乡村文化资源挖掘平台</h2>
           <small class="text-secondary">技术支持:18649931391</small>
@@ -45,6 +46,19 @@
           </div>
         </SimplePageContentLoader>
 
+        <h3 class="text-center p-3 mt-3">我的贡献</h3>
+        <div class="d-flex flex-row justify-between bg-white radius-s p-3">
+          <div class="d-flex flex-column align-center flex-one">
+            <text class="size-ll iconfont icon-total-points"></text>
+            <div class="size-l text-bold color-primary">{{ volunteerInfoLoader.content.value?.points || 0 }}</div>
+            <div>文化积分</div>
+          </div>
+          <div class="d-flex flex-column align-center flex-one">
+            <text class="size-ll iconfont icon-level"></text>
+            <div class="size-l text-bold color-primary">Lv.{{ volunteerInfoLoader.content.value?.level || 1 }}</div>
+            <div>等级</div>
+          </div>
+        </div>
       </div>
     </section>
   </div>
@@ -54,11 +68,13 @@
 import { useRouter } from 'vue-router';
 import { useSimpleDataLoader, SimplePageContentLoader } from '@imengyu/imengyu-web-shared';
 import { useCollectStore } from '@/stores/collect';
-import VillageApi, { VillageListItem } from '@/api/inhert/VillageApi';
 import { useAuthStore } from '@/stores/auth';
+import { computed } from 'vue';
+import VillageApi, { VillageListItem } from '@/api/inhert/VillageApi';
 
 const router = useRouter();
 const authStore = useAuthStore();
+const hasNav = computed(() => authStore.loginFromEmbed === false);
 
 const collectStore = useCollectStore();
 const villageListLoader = useSimpleDataLoader(async () => await VillageApi.getClaimedVallageList(), true);
@@ -75,6 +91,7 @@ function goSubmitDigPage(item: VillageListItem) {
     query: {
       id: item.villageId,
       name: item.villageName,
+      villageId: item.villageId,
       villageVolunteerId: item.villageVolunteerId,
       points: volunteerInfoLoader.content.value?.points,
       level: volunteerInfoLoader.content.value?.level,

+ 10 - 7
src/stores/auth.ts

@@ -1,10 +1,10 @@
 import UserApi, { LoginResult, UserInfo } from "@/api/auth/UserApi";
-import { HtmlUtils, SettingsUtils } from "@imengyu/imengyu-utils";
+import { HtmlUtils, LogUtils, SettingsUtils } from "@imengyu/imengyu-utils";
 import { defineStore } from "pinia"
 import { useRoute, type RouteLocationNormalizedLoadedGeneric } from "vue-router";
 
 const STORAGE_KEY = 'authInfo';
-const canRefresh = false;
+const TAG = 'AuthStore';
 
 export const useAuthStore = defineStore('auth', {
   state: () => ({
@@ -18,13 +18,14 @@ export const useAuthStore = defineStore('auth', {
   actions: {
     async loadLoginState(route: RouteLocationNormalizedLoadedGeneric) {
       try {
-        const query = route.query.internalAuth as string|undefined;
-        let res = localStorage.getItem(STORAGE_KEY);
+        let res : string|null = null;
         let saveLoginData = false;
-        if (!res && query) {
+        const query = route.query.internalAuth as string|undefined;
+        if (query) {
           res = decodeURIComponent(query);
-          this.loginFromEmbed = true;
           saveLoginData = true;
+        } else {
+          res = localStorage.getItem(STORAGE_KEY);
         }
         if (!res)
           throw 'no storage';
@@ -36,8 +37,10 @@ export const useAuthStore = defineStore('auth', {
         this.loginType = authInfo.loginType;
         this.loginFromEmbed = authInfo.loginFromEmbed;
 
-        if (saveLoginData)
+        if (saveLoginData) {
+          this.loginFromEmbed = true;
           this.saveLoginData();
+        }
 
         // 检查token是否过期,如果快要过期,则刷新token
         /*if (canRefresh && Date.now() > this.expireAt + 1000 * 3600 * 5) {