mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-10-31 10:18:42 +08:00 
			
		
		
		
	style: 切换页面布局
This commit is contained in:
		| @@ -1,3 +1,6 @@ | |||||||
|  | <template> | ||||||
|  |   <Error type="403" @error-click="errorClick" /> | ||||||
|  | </template> | ||||||
| <script setup lang="ts"> | <script setup lang="ts"> | ||||||
| import { Error } from '@/components/Error' | import { Error } from '@/components/Error' | ||||||
| import { useRouter } from 'vue-router' | import { useRouter } from 'vue-router' | ||||||
| @@ -8,7 +11,3 @@ const errorClick = () => { | |||||||
|   push('/') |   push('/') | ||||||
| } | } | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <template> |  | ||||||
|   <Error type="403" @error-click="errorClick" /> |  | ||||||
| </template> |  | ||||||
|   | |||||||
| @@ -1,3 +1,7 @@ | |||||||
|  | <template> | ||||||
|  |   <Error @error-click="errorClick" /> | ||||||
|  | </template> | ||||||
|  |  | ||||||
| <script setup lang="ts"> | <script setup lang="ts"> | ||||||
| import { Error } from '@/components/Error' | import { Error } from '@/components/Error' | ||||||
| import { useRouter } from 'vue-router' | import { useRouter } from 'vue-router' | ||||||
| @@ -8,7 +12,3 @@ const errorClick = () => { | |||||||
|   push('/') |   push('/') | ||||||
| } | } | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <template> |  | ||||||
|   <Error @error-click="errorClick" /> |  | ||||||
| </template> |  | ||||||
|   | |||||||
| @@ -1,3 +1,7 @@ | |||||||
|  | <template> | ||||||
|  |   <Error type="500" @error-click="errorClick" /> | ||||||
|  | </template> | ||||||
|  |  | ||||||
| <script setup lang="ts"> | <script setup lang="ts"> | ||||||
| import { Error } from '@/components/Error' | import { Error } from '@/components/Error' | ||||||
| import { useRouter } from 'vue-router' | import { useRouter } from 'vue-router' | ||||||
| @@ -8,7 +12,3 @@ const errorClick = () => { | |||||||
|   push('/') |   push('/') | ||||||
| } | } | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <template> |  | ||||||
|   <Error type="500" @error-click="errorClick" /> |  | ||||||
| </template> |  | ||||||
|   | |||||||
| @@ -1,3 +1,165 @@ | |||||||
|  | <template> | ||||||
|  |   <div> | ||||||
|  |     <el-card shadow="never"> | ||||||
|  |       <el-skeleton :loading="loading" animated> | ||||||
|  |         <el-row :gutter="20" justify="space-between"> | ||||||
|  |           <el-col :xl="12" :lg="12" :md="12" :sm="24" :xs="24"> | ||||||
|  |             <div class="flex items-center"> | ||||||
|  |               <img :src="avatar" alt="" class="w-70px h-70px rounded-[50%] mr-20px" /> | ||||||
|  |               <div> | ||||||
|  |                 <div class="text-20px text-700"> | ||||||
|  |                   {{ t('workplace.welcome') }} {{ username }} {{ t('workplace.happyDay') }} | ||||||
|  |                 </div> | ||||||
|  |                 <div class="mt-10px text-14px text-gray-500"> | ||||||
|  |                   {{ t('workplace.toady') }},20℃ - 32℃! | ||||||
|  |                 </div> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |           </el-col> | ||||||
|  |           <el-col :xl="12" :lg="12" :md="12" :sm="24" :xs="24"> | ||||||
|  |             <div class="flex h-70px items-center justify-end <sm:mt-10px"> | ||||||
|  |               <div class="px-8px text-right"> | ||||||
|  |                 <div class="text-14px text-gray-400 mb-20px">{{ t('workplace.project') }}</div> | ||||||
|  |                 <CountTo | ||||||
|  |                   class="text-20px" | ||||||
|  |                   :start-val="0" | ||||||
|  |                   :end-val="totalSate.project" | ||||||
|  |                   :duration="2600" | ||||||
|  |                 /> | ||||||
|  |               </div> | ||||||
|  |               <el-divider direction="vertical" /> | ||||||
|  |               <div class="px-8px text-right"> | ||||||
|  |                 <div class="text-14px text-gray-400 mb-20px">{{ t('workplace.toDo') }}</div> | ||||||
|  |                 <CountTo | ||||||
|  |                   class="text-20px" | ||||||
|  |                   :start-val="0" | ||||||
|  |                   :end-val="totalSate.todo" | ||||||
|  |                   :duration="2600" | ||||||
|  |                 /> | ||||||
|  |               </div> | ||||||
|  |               <el-divider direction="vertical" border-style="dashed" /> | ||||||
|  |               <div class="px-8px text-right"> | ||||||
|  |                 <div class="text-14px text-gray-400 mb-20px">{{ t('workplace.access') }}</div> | ||||||
|  |                 <CountTo | ||||||
|  |                   class="text-20px" | ||||||
|  |                   :start-val="0" | ||||||
|  |                   :end-val="totalSate.access" | ||||||
|  |                   :duration="2600" | ||||||
|  |                 /> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |           </el-col> | ||||||
|  |         </el-row> | ||||||
|  |       </el-skeleton> | ||||||
|  |     </el-card> | ||||||
|  |   </div> | ||||||
|  |  | ||||||
|  |   <el-row class="mt-5px" :gutter="20" justify="space-between"> | ||||||
|  |     <el-col :xl="16" :lg="16" :md="24" :sm="24" :xs="24" class="mb-10px"> | ||||||
|  |       <el-card shadow="never"> | ||||||
|  |         <template #header> | ||||||
|  |           <div class="flex justify-between h-3"> | ||||||
|  |             <span>{{ t('workplace.project') }}</span> | ||||||
|  |             <el-link type="primary" :underline="false">{{ t('workplace.more') }}</el-link> | ||||||
|  |           </div> | ||||||
|  |         </template> | ||||||
|  |         <el-skeleton :loading="loading" animated> | ||||||
|  |           <el-row> | ||||||
|  |             <el-col | ||||||
|  |               v-for="(item, index) in projects" | ||||||
|  |               :key="`card-${index}`" | ||||||
|  |               :xl="8" | ||||||
|  |               :lg="8" | ||||||
|  |               :md="8" | ||||||
|  |               :sm="24" | ||||||
|  |               :xs="24" | ||||||
|  |             > | ||||||
|  |               <el-card shadow="hover"> | ||||||
|  |                 <div class="flex items-center"> | ||||||
|  |                   <Icon :icon="item.icon" :size="25" class="mr-10px" /> | ||||||
|  |                   <span class="text-16px">{{ item.name }}</span> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="mt-15px text-14px text-gray-400">{{ t(item.message) }}</div> | ||||||
|  |                 <div class="mt-20px text-12px text-gray-400 flex justify-between"> | ||||||
|  |                   <span>{{ item.personal }}</span> | ||||||
|  |                   <span>{{ formatTime(item.time, 'yyyy-MM-dd') }}</span> | ||||||
|  |                 </div> | ||||||
|  |               </el-card> | ||||||
|  |             </el-col> | ||||||
|  |           </el-row> | ||||||
|  |         </el-skeleton> | ||||||
|  |       </el-card> | ||||||
|  |  | ||||||
|  |       <el-card shadow="never" class="mt-5px"> | ||||||
|  |         <el-skeleton :loading="loading" animated> | ||||||
|  |           <el-row :gutter="20" justify="space-between"> | ||||||
|  |             <el-col :xl="10" :lg="10" :md="24" :sm="24" :xs="24"> | ||||||
|  |               <el-card shadow="hover" class="mb-10px"> | ||||||
|  |                 <el-skeleton :loading="loading" animated> | ||||||
|  |                   <Echart :options="pieOptionsData" :height="280" /> | ||||||
|  |                 </el-skeleton> | ||||||
|  |               </el-card> | ||||||
|  |             </el-col> | ||||||
|  |             <el-col :xl="14" :lg="14" :md="24" :sm="24" :xs="24"> | ||||||
|  |               <el-card shadow="hover" class="mb-10px"> | ||||||
|  |                 <el-skeleton :loading="loading" animated> | ||||||
|  |                   <Echart :options="barOptionsData" :height="280" /> | ||||||
|  |                 </el-skeleton> | ||||||
|  |               </el-card> | ||||||
|  |             </el-col> | ||||||
|  |           </el-row> | ||||||
|  |         </el-skeleton> | ||||||
|  |       </el-card> | ||||||
|  |     </el-col> | ||||||
|  |     <el-col :xl="8" :lg="8" :md="24" :sm="24" :xs="24" class="mb-10px"> | ||||||
|  |       <el-card shadow="never"> | ||||||
|  |         <template #header> | ||||||
|  |           <div class="flex justify-between h-3"> | ||||||
|  |             <span>{{ t('workplace.shortcutOperation') }}</span> | ||||||
|  |           </div> | ||||||
|  |         </template> | ||||||
|  |         <el-skeleton :loading="loading" animated> | ||||||
|  |           <el-row> | ||||||
|  |             <el-col v-for="item in shortcut" :key="`team-${item.name}`" :span="8" class="mb-10px"> | ||||||
|  |               <div class="flex items-center"> | ||||||
|  |                 <Icon :icon="item.icon" class="mr-10px" /> | ||||||
|  |                 <el-link type="default" :underline="false" :href="item.url"> | ||||||
|  |                   {{ item.name }} | ||||||
|  |                 </el-link> | ||||||
|  |               </div> | ||||||
|  |             </el-col> | ||||||
|  |           </el-row> | ||||||
|  |         </el-skeleton> | ||||||
|  |       </el-card> | ||||||
|  |       <el-card shadow="never" class="mt-10px"> | ||||||
|  |         <template #header> | ||||||
|  |           <div class="flex justify-between h-3"> | ||||||
|  |             <span>{{ t('workplace.notice') }}</span> | ||||||
|  |             <el-link type="primary" :underline="false">{{ t('workplace.more') }}</el-link> | ||||||
|  |           </div> | ||||||
|  |         </template> | ||||||
|  |         <el-skeleton :loading="loading" animated> | ||||||
|  |           <div v-for="(item, index) in notice" :key="`dynamics-${index}`"> | ||||||
|  |             <div class="flex items-center"> | ||||||
|  |               <img :src="avatar" alt="" class="w-35px h-35px rounded-[50%] mr-20px" /> | ||||||
|  |               <div> | ||||||
|  |                 <div class="text-14px"> | ||||||
|  |                   <Highlight :keys="item.keys.map((v) => t(v))"> | ||||||
|  |                     {{ item.type }} : {{ item.title }} | ||||||
|  |                   </Highlight> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="mt-15px text-12px text-gray-400"> | ||||||
|  |                   {{ formatTime(item.date, 'yyyy-MM-dd') }} | ||||||
|  |                 </div> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |             <el-divider /> | ||||||
|  |           </div> | ||||||
|  |         </el-skeleton> | ||||||
|  |       </el-card> | ||||||
|  |     </el-col> | ||||||
|  |   </el-row> | ||||||
|  | </template> | ||||||
| <script setup lang="ts"> | <script setup lang="ts"> | ||||||
| import { ElRow, ElCol, ElSkeleton, ElCard, ElDivider, ElLink } from 'element-plus' | import { ElRow, ElCol, ElSkeleton, ElCard, ElDivider, ElLink } from 'element-plus' | ||||||
| import { useI18n } from '@/hooks/web/useI18n' | import { useI18n } from '@/hooks/web/useI18n' | ||||||
| @@ -217,166 +379,3 @@ const getAllApi = async () => { | |||||||
|  |  | ||||||
| getAllApi() | getAllApi() | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <template> |  | ||||||
|   <div> |  | ||||||
|     <el-card shadow="never"> |  | ||||||
|       <el-skeleton :loading="loading" animated> |  | ||||||
|         <el-row :gutter="20" justify="space-between"> |  | ||||||
|           <el-col :xl="12" :lg="12" :md="12" :sm="24" :xs="24"> |  | ||||||
|             <div class="flex items-center"> |  | ||||||
|               <img :src="avatar" alt="" class="w-70px h-70px rounded-[50%] mr-20px" /> |  | ||||||
|               <div> |  | ||||||
|                 <div class="text-20px text-700"> |  | ||||||
|                   {{ t('workplace.welcome') }} {{ username }} {{ t('workplace.happyDay') }} |  | ||||||
|                 </div> |  | ||||||
|                 <div class="mt-10px text-14px text-gray-500"> |  | ||||||
|                   {{ t('workplace.toady') }},20℃ - 32℃! |  | ||||||
|                 </div> |  | ||||||
|               </div> |  | ||||||
|             </div> |  | ||||||
|           </el-col> |  | ||||||
|           <el-col :xl="12" :lg="12" :md="12" :sm="24" :xs="24"> |  | ||||||
|             <div class="flex h-70px items-center justify-end <sm:mt-10px"> |  | ||||||
|               <div class="px-8px text-right"> |  | ||||||
|                 <div class="text-14px text-gray-400 mb-20px">{{ t('workplace.project') }}</div> |  | ||||||
|                 <CountTo |  | ||||||
|                   class="text-20px" |  | ||||||
|                   :start-val="0" |  | ||||||
|                   :end-val="totalSate.project" |  | ||||||
|                   :duration="2600" |  | ||||||
|                 /> |  | ||||||
|               </div> |  | ||||||
|               <el-divider direction="vertical" /> |  | ||||||
|               <div class="px-8px text-right"> |  | ||||||
|                 <div class="text-14px text-gray-400 mb-20px">{{ t('workplace.toDo') }}</div> |  | ||||||
|                 <CountTo |  | ||||||
|                   class="text-20px" |  | ||||||
|                   :start-val="0" |  | ||||||
|                   :end-val="totalSate.todo" |  | ||||||
|                   :duration="2600" |  | ||||||
|                 /> |  | ||||||
|               </div> |  | ||||||
|               <el-divider direction="vertical" border-style="dashed" /> |  | ||||||
|               <div class="px-8px text-right"> |  | ||||||
|                 <div class="text-14px text-gray-400 mb-20px">{{ t('workplace.access') }}</div> |  | ||||||
|                 <CountTo |  | ||||||
|                   class="text-20px" |  | ||||||
|                   :start-val="0" |  | ||||||
|                   :end-val="totalSate.access" |  | ||||||
|                   :duration="2600" |  | ||||||
|                 /> |  | ||||||
|               </div> |  | ||||||
|             </div> |  | ||||||
|           </el-col> |  | ||||||
|         </el-row> |  | ||||||
|       </el-skeleton> |  | ||||||
|     </el-card> |  | ||||||
|   </div> |  | ||||||
|  |  | ||||||
|   <el-row class="mt-5px" :gutter="20" justify="space-between"> |  | ||||||
|     <el-col :xl="16" :lg="16" :md="24" :sm="24" :xs="24" class="mb-10px"> |  | ||||||
|       <el-card shadow="never"> |  | ||||||
|         <template #header> |  | ||||||
|           <div class="flex justify-between h-3"> |  | ||||||
|             <span>{{ t('workplace.project') }}</span> |  | ||||||
|             <el-link type="primary" :underline="false">{{ t('workplace.more') }}</el-link> |  | ||||||
|           </div> |  | ||||||
|         </template> |  | ||||||
|         <el-skeleton :loading="loading" animated> |  | ||||||
|           <el-row> |  | ||||||
|             <el-col |  | ||||||
|               v-for="(item, index) in projects" |  | ||||||
|               :key="`card-${index}`" |  | ||||||
|               :xl="8" |  | ||||||
|               :lg="8" |  | ||||||
|               :md="8" |  | ||||||
|               :sm="24" |  | ||||||
|               :xs="24" |  | ||||||
|             > |  | ||||||
|               <el-card shadow="hover"> |  | ||||||
|                 <div class="flex items-center"> |  | ||||||
|                   <Icon :icon="item.icon" :size="25" class="mr-10px" /> |  | ||||||
|                   <span class="text-16px">{{ item.name }}</span> |  | ||||||
|                 </div> |  | ||||||
|                 <div class="mt-15px text-14px text-gray-400">{{ t(item.message) }}</div> |  | ||||||
|                 <div class="mt-20px text-12px text-gray-400 flex justify-between"> |  | ||||||
|                   <span>{{ item.personal }}</span> |  | ||||||
|                   <span>{{ formatTime(item.time, 'yyyy-MM-dd') }}</span> |  | ||||||
|                 </div> |  | ||||||
|               </el-card> |  | ||||||
|             </el-col> |  | ||||||
|           </el-row> |  | ||||||
|         </el-skeleton> |  | ||||||
|       </el-card> |  | ||||||
|  |  | ||||||
|       <el-card shadow="never" class="mt-5px"> |  | ||||||
|         <el-skeleton :loading="loading" animated> |  | ||||||
|           <el-row :gutter="20" justify="space-between"> |  | ||||||
|             <el-col :xl="10" :lg="10" :md="24" :sm="24" :xs="24"> |  | ||||||
|               <el-card shadow="hover" class="mb-10px"> |  | ||||||
|                 <el-skeleton :loading="loading" animated> |  | ||||||
|                   <Echart :options="pieOptionsData" :height="280" /> |  | ||||||
|                 </el-skeleton> |  | ||||||
|               </el-card> |  | ||||||
|             </el-col> |  | ||||||
|             <el-col :xl="14" :lg="14" :md="24" :sm="24" :xs="24"> |  | ||||||
|               <el-card shadow="hover" class="mb-10px"> |  | ||||||
|                 <el-skeleton :loading="loading" animated> |  | ||||||
|                   <Echart :options="barOptionsData" :height="280" /> |  | ||||||
|                 </el-skeleton> |  | ||||||
|               </el-card> |  | ||||||
|             </el-col> |  | ||||||
|           </el-row> |  | ||||||
|         </el-skeleton> |  | ||||||
|       </el-card> |  | ||||||
|     </el-col> |  | ||||||
|     <el-col :xl="8" :lg="8" :md="24" :sm="24" :xs="24" class="mb-10px"> |  | ||||||
|       <el-card shadow="never"> |  | ||||||
|         <template #header> |  | ||||||
|           <div class="flex justify-between h-3"> |  | ||||||
|             <span>{{ t('workplace.shortcutOperation') }}</span> |  | ||||||
|           </div> |  | ||||||
|         </template> |  | ||||||
|         <el-skeleton :loading="loading" animated> |  | ||||||
|           <el-row> |  | ||||||
|             <el-col v-for="item in shortcut" :key="`team-${item.name}`" :span="8" class="mb-10px"> |  | ||||||
|               <div class="flex items-center"> |  | ||||||
|                 <Icon :icon="item.icon" class="mr-10px" /> |  | ||||||
|                 <el-link type="default" :underline="false" :href="item.url"> |  | ||||||
|                   {{ item.name }} |  | ||||||
|                 </el-link> |  | ||||||
|               </div> |  | ||||||
|             </el-col> |  | ||||||
|           </el-row> |  | ||||||
|         </el-skeleton> |  | ||||||
|       </el-card> |  | ||||||
|       <el-card shadow="never" class="mt-10px"> |  | ||||||
|         <template #header> |  | ||||||
|           <div class="flex justify-between h-3"> |  | ||||||
|             <span>{{ t('workplace.notice') }}</span> |  | ||||||
|             <el-link type="primary" :underline="false">{{ t('workplace.more') }}</el-link> |  | ||||||
|           </div> |  | ||||||
|         </template> |  | ||||||
|         <el-skeleton :loading="loading" animated> |  | ||||||
|           <div v-for="(item, index) in notice" :key="`dynamics-${index}`"> |  | ||||||
|             <div class="flex items-center"> |  | ||||||
|               <img :src="avatar" alt="" class="w-35px h-35px rounded-[50%] mr-20px" /> |  | ||||||
|               <div> |  | ||||||
|                 <div class="text-14px"> |  | ||||||
|                   <Highlight :keys="item.keys.map((v) => t(v))"> |  | ||||||
|                     {{ item.type }} : {{ item.title }} |  | ||||||
|                   </Highlight> |  | ||||||
|                 </div> |  | ||||||
|                 <div class="mt-15px text-12px text-gray-400"> |  | ||||||
|                   {{ formatTime(item.date, 'yyyy-MM-dd') }} |  | ||||||
|                 </div> |  | ||||||
|               </div> |  | ||||||
|             </div> |  | ||||||
|             <el-divider /> |  | ||||||
|           </div> |  | ||||||
|         </el-skeleton> |  | ||||||
|       </el-card> |  | ||||||
|     </el-col> |  | ||||||
|   </el-row> |  | ||||||
| </template> |  | ||||||
|   | |||||||
| @@ -1,133 +1,3 @@ | |||||||
| <script setup lang="ts"> |  | ||||||
| import { ref, reactive } from 'vue' |  | ||||||
| import { set } from 'lodash-es' |  | ||||||
| import { EChartsOption } from 'echarts' |  | ||||||
| import { Echart } from '@/components/Echart' |  | ||||||
| import { useI18n } from '@/hooks/web/useI18n' |  | ||||||
| import { CountTo } from '@/components/CountTo' |  | ||||||
| import type { AnalysisTotalTypes } from './types' |  | ||||||
| import { useDesign } from '@/hooks/web/useDesign' |  | ||||||
| import { ElRow, ElCol, ElCard, ElSkeleton } from 'element-plus' |  | ||||||
| import { pieOptions, barOptions, lineOptions } from './echarts-data' |  | ||||||
|  |  | ||||||
| const { t } = useI18n() |  | ||||||
| const loading = ref(true) |  | ||||||
| const { getPrefixCls } = useDesign() |  | ||||||
| const prefixCls = getPrefixCls('panel') |  | ||||||
| const pieOptionsData = reactive<EChartsOption>(pieOptions) as EChartsOption |  | ||||||
|  |  | ||||||
| let totalState = reactive<AnalysisTotalTypes>({ |  | ||||||
|   users: 0, |  | ||||||
|   messages: 0, |  | ||||||
|   moneys: 0, |  | ||||||
|   shoppings: 0 |  | ||||||
| }) |  | ||||||
|  |  | ||||||
| const getCount = async () => { |  | ||||||
|   const data = { |  | ||||||
|     users: 102400, |  | ||||||
|     messages: 81212, |  | ||||||
|     moneys: 9280, |  | ||||||
|     shoppings: 13600 |  | ||||||
|   } |  | ||||||
|   totalState = Object.assign(totalState, data) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // 用户来源 |  | ||||||
| const getUserAccessSource = async () => { |  | ||||||
|   const data = [ |  | ||||||
|     { value: 335, name: 'analysis.directAccess' }, |  | ||||||
|     { value: 310, name: 'analysis.mailMarketing' }, |  | ||||||
|     { value: 234, name: 'analysis.allianceAdvertising' }, |  | ||||||
|     { value: 135, name: 'analysis.videoAdvertising' }, |  | ||||||
|     { value: 1548, name: 'analysis.searchEngines' } |  | ||||||
|   ] |  | ||||||
|   set( |  | ||||||
|     pieOptionsData, |  | ||||||
|     'legend.data', |  | ||||||
|     data.map((v) => t(v.name)) |  | ||||||
|   ) |  | ||||||
|   set(pieOptionsData, 'series.data', data) |  | ||||||
| } |  | ||||||
| const barOptionsData = reactive<EChartsOption>(barOptions) as EChartsOption |  | ||||||
|  |  | ||||||
| // 周活跃量 |  | ||||||
| const getWeeklyUserActivity = async () => { |  | ||||||
|   const data = [ |  | ||||||
|     { value: 13253, name: 'analysis.monday' }, |  | ||||||
|     { value: 34235, name: 'analysis.tuesday' }, |  | ||||||
|     { value: 26321, name: 'analysis.wednesday' }, |  | ||||||
|     { value: 12340, name: 'analysis.thursday' }, |  | ||||||
|     { value: 24643, name: 'analysis.friday' }, |  | ||||||
|     { value: 1322, name: 'analysis.saturday' }, |  | ||||||
|     { value: 1324, name: 'analysis.sunday' } |  | ||||||
|   ] |  | ||||||
|   set( |  | ||||||
|     barOptionsData, |  | ||||||
|     'xAxis.data', |  | ||||||
|     data.map((v) => t(v.name)) |  | ||||||
|   ) |  | ||||||
|   set(barOptionsData, 'series', [ |  | ||||||
|     { |  | ||||||
|       name: t('analysis.activeQuantity'), |  | ||||||
|       data: data.map((v) => v.value), |  | ||||||
|       type: 'bar' |  | ||||||
|     } |  | ||||||
|   ]) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| const lineOptionsData = reactive<EChartsOption>(lineOptions) as EChartsOption |  | ||||||
|  |  | ||||||
| // 每月销售总额 |  | ||||||
| const getMonthlySales = async () => { |  | ||||||
|   const data = [ |  | ||||||
|     { estimate: 100, actual: 120, name: 'analysis.january' }, |  | ||||||
|     { estimate: 120, actual: 82, name: 'analysis.february' }, |  | ||||||
|     { estimate: 161, actual: 91, name: 'analysis.march' }, |  | ||||||
|     { estimate: 134, actual: 154, name: 'analysis.april' }, |  | ||||||
|     { estimate: 105, actual: 162, name: 'analysis.may' }, |  | ||||||
|     { estimate: 160, actual: 140, name: 'analysis.june' }, |  | ||||||
|     { estimate: 165, actual: 145, name: 'analysis.july' }, |  | ||||||
|     { estimate: 114, actual: 250, name: 'analysis.august' }, |  | ||||||
|     { estimate: 163, actual: 134, name: 'analysis.september' }, |  | ||||||
|     { estimate: 185, actual: 56, name: 'analysis.october' }, |  | ||||||
|     { estimate: 118, actual: 99, name: 'analysis.november' }, |  | ||||||
|     { estimate: 123, actual: 123, name: 'analysis.december' } |  | ||||||
|   ] |  | ||||||
|   set( |  | ||||||
|     lineOptionsData, |  | ||||||
|     'xAxis.data', |  | ||||||
|     data.map((v) => t(v.name)) |  | ||||||
|   ) |  | ||||||
|   set(lineOptionsData, 'series', [ |  | ||||||
|     { |  | ||||||
|       name: t('analysis.estimate'), |  | ||||||
|       smooth: true, |  | ||||||
|       type: 'line', |  | ||||||
|       data: data.map((v) => v.estimate), |  | ||||||
|       animationDuration: 2800, |  | ||||||
|       animationEasing: 'cubicInOut' |  | ||||||
|     }, |  | ||||||
|     { |  | ||||||
|       name: t('analysis.actual'), |  | ||||||
|       smooth: true, |  | ||||||
|       type: 'line', |  | ||||||
|       itemStyle: {}, |  | ||||||
|       data: data.map((v) => v.actual), |  | ||||||
|       animationDuration: 2800, |  | ||||||
|       animationEasing: 'quadraticOut' |  | ||||||
|     } |  | ||||||
|   ]) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| const getAllApi = async () => { |  | ||||||
|   await Promise.all([getCount(), getUserAccessSource(), getWeeklyUserActivity(), getMonthlySales()]) |  | ||||||
|   loading.value = false |  | ||||||
| } |  | ||||||
|  |  | ||||||
| getAllApi() |  | ||||||
| </script> |  | ||||||
|  |  | ||||||
| <template> | <template> | ||||||
|   <el-row :gutter="20" justify="space-between" :class="prefixCls"> |   <el-row :gutter="20" justify="space-between" :class="prefixCls"> | ||||||
|     <el-col :xl="6" :lg="6" :md="12" :sm="12" :xs="24"> |     <el-col :xl="6" :lg="6" :md="12" :sm="12" :xs="24"> | ||||||
| @@ -270,6 +140,136 @@ getAllApi() | |||||||
|     </el-col> |     </el-col> | ||||||
|   </el-row> |   </el-row> | ||||||
| </template> | </template> | ||||||
|  | <script setup lang="ts"> | ||||||
|  | import { ref, reactive } from 'vue' | ||||||
|  | import { set } from 'lodash-es' | ||||||
|  | import { EChartsOption } from 'echarts' | ||||||
|  | import { Echart } from '@/components/Echart' | ||||||
|  | import { useI18n } from '@/hooks/web/useI18n' | ||||||
|  | import { CountTo } from '@/components/CountTo' | ||||||
|  | import type { AnalysisTotalTypes } from './types' | ||||||
|  | import { useDesign } from '@/hooks/web/useDesign' | ||||||
|  | import { ElRow, ElCol, ElCard, ElSkeleton } from 'element-plus' | ||||||
|  | import { pieOptions, barOptions, lineOptions } from './echarts-data' | ||||||
|  |  | ||||||
|  | const { t } = useI18n() | ||||||
|  | const loading = ref(true) | ||||||
|  | const { getPrefixCls } = useDesign() | ||||||
|  | const prefixCls = getPrefixCls('panel') | ||||||
|  | const pieOptionsData = reactive<EChartsOption>(pieOptions) as EChartsOption | ||||||
|  |  | ||||||
|  | let totalState = reactive<AnalysisTotalTypes>({ | ||||||
|  |   users: 0, | ||||||
|  |   messages: 0, | ||||||
|  |   moneys: 0, | ||||||
|  |   shoppings: 0 | ||||||
|  | }) | ||||||
|  |  | ||||||
|  | const getCount = async () => { | ||||||
|  |   const data = { | ||||||
|  |     users: 102400, | ||||||
|  |     messages: 81212, | ||||||
|  |     moneys: 9280, | ||||||
|  |     shoppings: 13600 | ||||||
|  |   } | ||||||
|  |   totalState = Object.assign(totalState, data) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // 用户来源 | ||||||
|  | const getUserAccessSource = async () => { | ||||||
|  |   const data = [ | ||||||
|  |     { value: 335, name: 'analysis.directAccess' }, | ||||||
|  |     { value: 310, name: 'analysis.mailMarketing' }, | ||||||
|  |     { value: 234, name: 'analysis.allianceAdvertising' }, | ||||||
|  |     { value: 135, name: 'analysis.videoAdvertising' }, | ||||||
|  |     { value: 1548, name: 'analysis.searchEngines' } | ||||||
|  |   ] | ||||||
|  |   set( | ||||||
|  |     pieOptionsData, | ||||||
|  |     'legend.data', | ||||||
|  |     data.map((v) => t(v.name)) | ||||||
|  |   ) | ||||||
|  |   set(pieOptionsData, 'series.data', data) | ||||||
|  | } | ||||||
|  | const barOptionsData = reactive<EChartsOption>(barOptions) as EChartsOption | ||||||
|  |  | ||||||
|  | // 周活跃量 | ||||||
|  | const getWeeklyUserActivity = async () => { | ||||||
|  |   const data = [ | ||||||
|  |     { value: 13253, name: 'analysis.monday' }, | ||||||
|  |     { value: 34235, name: 'analysis.tuesday' }, | ||||||
|  |     { value: 26321, name: 'analysis.wednesday' }, | ||||||
|  |     { value: 12340, name: 'analysis.thursday' }, | ||||||
|  |     { value: 24643, name: 'analysis.friday' }, | ||||||
|  |     { value: 1322, name: 'analysis.saturday' }, | ||||||
|  |     { value: 1324, name: 'analysis.sunday' } | ||||||
|  |   ] | ||||||
|  |   set( | ||||||
|  |     barOptionsData, | ||||||
|  |     'xAxis.data', | ||||||
|  |     data.map((v) => t(v.name)) | ||||||
|  |   ) | ||||||
|  |   set(barOptionsData, 'series', [ | ||||||
|  |     { | ||||||
|  |       name: t('analysis.activeQuantity'), | ||||||
|  |       data: data.map((v) => v.value), | ||||||
|  |       type: 'bar' | ||||||
|  |     } | ||||||
|  |   ]) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const lineOptionsData = reactive<EChartsOption>(lineOptions) as EChartsOption | ||||||
|  |  | ||||||
|  | // 每月销售总额 | ||||||
|  | const getMonthlySales = async () => { | ||||||
|  |   const data = [ | ||||||
|  |     { estimate: 100, actual: 120, name: 'analysis.january' }, | ||||||
|  |     { estimate: 120, actual: 82, name: 'analysis.february' }, | ||||||
|  |     { estimate: 161, actual: 91, name: 'analysis.march' }, | ||||||
|  |     { estimate: 134, actual: 154, name: 'analysis.april' }, | ||||||
|  |     { estimate: 105, actual: 162, name: 'analysis.may' }, | ||||||
|  |     { estimate: 160, actual: 140, name: 'analysis.june' }, | ||||||
|  |     { estimate: 165, actual: 145, name: 'analysis.july' }, | ||||||
|  |     { estimate: 114, actual: 250, name: 'analysis.august' }, | ||||||
|  |     { estimate: 163, actual: 134, name: 'analysis.september' }, | ||||||
|  |     { estimate: 185, actual: 56, name: 'analysis.october' }, | ||||||
|  |     { estimate: 118, actual: 99, name: 'analysis.november' }, | ||||||
|  |     { estimate: 123, actual: 123, name: 'analysis.december' } | ||||||
|  |   ] | ||||||
|  |   set( | ||||||
|  |     lineOptionsData, | ||||||
|  |     'xAxis.data', | ||||||
|  |     data.map((v) => t(v.name)) | ||||||
|  |   ) | ||||||
|  |   set(lineOptionsData, 'series', [ | ||||||
|  |     { | ||||||
|  |       name: t('analysis.estimate'), | ||||||
|  |       smooth: true, | ||||||
|  |       type: 'line', | ||||||
|  |       data: data.map((v) => v.estimate), | ||||||
|  |       animationDuration: 2800, | ||||||
|  |       animationEasing: 'cubicInOut' | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       name: t('analysis.actual'), | ||||||
|  |       smooth: true, | ||||||
|  |       type: 'line', | ||||||
|  |       itemStyle: {}, | ||||||
|  |       data: data.map((v) => v.actual), | ||||||
|  |       animationDuration: 2800, | ||||||
|  |       animationEasing: 'quadraticOut' | ||||||
|  |     } | ||||||
|  |   ]) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const getAllApi = async () => { | ||||||
|  |   await Promise.all([getCount(), getUserAccessSource(), getWeeklyUserActivity(), getMonthlySales()]) | ||||||
|  |   loading.value = false | ||||||
|  | } | ||||||
|  |  | ||||||
|  | getAllApi() | ||||||
|  | </script> | ||||||
|  |  | ||||||
| <style lang="less" scoped> | <style lang="less" scoped> | ||||||
| @prefix-cls: ~'@{namespace}-panel'; | @prefix-cls: ~'@{namespace}-panel'; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,21 +1,3 @@ | |||||||
| <script setup lang="ts"> |  | ||||||
| import { LoginForm, MobileForm, RegisterForm, QrCodeForm } from './components' |  | ||||||
| import { ThemeSwitch } from '@/components/ThemeSwitch' |  | ||||||
| import { LocaleDropdown } from '@/components/LocaleDropdown' |  | ||||||
| import { useI18n } from '@/hooks/web/useI18n' |  | ||||||
| import { underlineToHump } from '@/utils' |  | ||||||
| import { useAppStore } from '@/store/modules/app' |  | ||||||
| import { useDesign } from '@/hooks/web/useDesign' |  | ||||||
|  |  | ||||||
| const { t } = useI18n() |  | ||||||
|  |  | ||||||
| const { getPrefixCls } = useDesign() |  | ||||||
|  |  | ||||||
| const prefixCls = getPrefixCls('login') |  | ||||||
|  |  | ||||||
| const appStore = useAppStore() |  | ||||||
| </script> |  | ||||||
|  |  | ||||||
| <template> | <template> | ||||||
|   <div |   <div | ||||||
|     :class="prefixCls" |     :class="prefixCls" | ||||||
| @@ -76,6 +58,23 @@ const appStore = useAppStore() | |||||||
|     </div> |     </div> | ||||||
|   </div> |   </div> | ||||||
| </template> | </template> | ||||||
|  | <script setup lang="ts"> | ||||||
|  | import { LoginForm, MobileForm, RegisterForm, QrCodeForm } from './components' | ||||||
|  | import { ThemeSwitch } from '@/components/ThemeSwitch' | ||||||
|  | import { LocaleDropdown } from '@/components/LocaleDropdown' | ||||||
|  | import { useI18n } from '@/hooks/web/useI18n' | ||||||
|  | import { underlineToHump } from '@/utils' | ||||||
|  | import { useAppStore } from '@/store/modules/app' | ||||||
|  | import { useDesign } from '@/hooks/web/useDesign' | ||||||
|  |  | ||||||
|  | const { t } = useI18n() | ||||||
|  |  | ||||||
|  | const { getPrefixCls } = useDesign() | ||||||
|  |  | ||||||
|  | const prefixCls = getPrefixCls('login') | ||||||
|  |  | ||||||
|  | const appStore = useAppStore() | ||||||
|  | </script> | ||||||
|  |  | ||||||
| <style lang="less" scoped> | <style lang="less" scoped> | ||||||
| @prefix-cls: ~'@{namespace}-login'; | @prefix-cls: ~'@{namespace}-login'; | ||||||
|   | |||||||
| @@ -1,3 +1,141 @@ | |||||||
|  | <template> | ||||||
|  |   <el-form | ||||||
|  |     :model="loginData.loginForm" | ||||||
|  |     :rules="LoginRules" | ||||||
|  |     label-position="top" | ||||||
|  |     class="login-form" | ||||||
|  |     label-width="120px" | ||||||
|  |     size="large" | ||||||
|  |     v-show="getShow" | ||||||
|  |     ref="formLogin" | ||||||
|  |   > | ||||||
|  |     <el-row style="maring-left: -10px; maring-right: -10px"> | ||||||
|  |       <el-col :span="24" style="padding-left: 10px; padding-right: 10px"> | ||||||
|  |         <el-form-item> | ||||||
|  |           <LoginFormTitle style="width: 100%" /> | ||||||
|  |         </el-form-item> | ||||||
|  |       </el-col> | ||||||
|  |       <el-col :span="24" style="padding-left: 10px; padding-right: 10px"> | ||||||
|  |         <el-form-item prop="tenantName"> | ||||||
|  |           <el-input | ||||||
|  |             type="text" | ||||||
|  |             v-model="loginData.loginForm.tenantName" | ||||||
|  |             :placeholder="t('login.tenantNamePlaceholder')" | ||||||
|  |             :prefix-icon="iconHouse" | ||||||
|  |           /> | ||||||
|  |         </el-form-item> | ||||||
|  |       </el-col> | ||||||
|  |       <el-col :span="24" style="padding-left: 10px; padding-right: 10px"> | ||||||
|  |         <el-form-item prop="username"> | ||||||
|  |           <el-input | ||||||
|  |             v-model="loginData.loginForm.username" | ||||||
|  |             :placeholder="t('login.usernamePlaceholder')" | ||||||
|  |             :prefix-icon="iconAvatar" | ||||||
|  |           /> | ||||||
|  |         </el-form-item> | ||||||
|  |       </el-col> | ||||||
|  |       <el-col :span="24" style="padding-left: 10px; padding-right: 10px"> | ||||||
|  |         <el-form-item prop="password"> | ||||||
|  |           <el-input | ||||||
|  |             v-model="loginData.loginForm.password" | ||||||
|  |             type="password" | ||||||
|  |             :placeholder="t('login.passwordPlaceholder')" | ||||||
|  |             show-password | ||||||
|  |             @keyup.enter="getCode()" | ||||||
|  |             :prefix-icon="iconLock" | ||||||
|  |           /> | ||||||
|  |         </el-form-item> | ||||||
|  |       </el-col> | ||||||
|  |       <el-col | ||||||
|  |         :span="24" | ||||||
|  |         style="padding-left: 10px; padding-right: 10px; margin-top: -20px; margin-bottom: -20px" | ||||||
|  |       > | ||||||
|  |         <el-form-item> | ||||||
|  |           <el-row justify="space-between" style="width: 100%"> | ||||||
|  |             <el-col :span="6"> | ||||||
|  |               <el-checkbox v-model="loginData.loginForm.rememberMe"> | ||||||
|  |                 {{ t('login.remember') }} | ||||||
|  |               </el-checkbox> | ||||||
|  |             </el-col> | ||||||
|  |             <el-col :span="12" :offset="6"> | ||||||
|  |               <el-link type="primary" style="float: right">{{ t('login.forgetPassword') }}</el-link> | ||||||
|  |             </el-col> | ||||||
|  |           </el-row> | ||||||
|  |         </el-form-item> | ||||||
|  |       </el-col> | ||||||
|  |       <el-col :span="24" style="padding-left: 10px; padding-right: 10px"> | ||||||
|  |         <el-form-item> | ||||||
|  |           <el-button :loading="loginLoading" type="primary" class="w-[100%]" @click="getCode()"> | ||||||
|  |             {{ t('login.login') }} | ||||||
|  |           </el-button> | ||||||
|  |         </el-form-item> | ||||||
|  |       </el-col> | ||||||
|  |       <Verify | ||||||
|  |         ref="verify" | ||||||
|  |         mode="pop" | ||||||
|  |         :captchaType="captchaType" | ||||||
|  |         :imgSize="{ width: '400px', height: '200px' }" | ||||||
|  |         @success="handleLogin" | ||||||
|  |       /> | ||||||
|  |       <el-col :span="24" style="padding-left: 10px; padding-right: 10px"> | ||||||
|  |         <el-form-item> | ||||||
|  |           <el-row justify="space-between" style="width: 100%" :gutter="5"> | ||||||
|  |             <el-col :span="8"> | ||||||
|  |               <el-button class="w-[100%]" @click="setLoginState(LoginStateEnum.MOBILE)"> | ||||||
|  |                 {{ t('login.btnMobile') }} | ||||||
|  |               </el-button> | ||||||
|  |             </el-col> | ||||||
|  |             <el-col :span="8"> | ||||||
|  |               <el-button class="w-[100%]" @click="setLoginState(LoginStateEnum.QR_CODE)"> | ||||||
|  |                 {{ t('login.btnQRCode') }} | ||||||
|  |               </el-button> | ||||||
|  |             </el-col> | ||||||
|  |             <el-col :span="8"> | ||||||
|  |               <el-button class="w-[100%]" @click="setLoginState(LoginStateEnum.REGISTER)"> | ||||||
|  |                 {{ t('login.btnRegister') }} | ||||||
|  |               </el-button> | ||||||
|  |             </el-col> | ||||||
|  |           </el-row> | ||||||
|  |         </el-form-item> | ||||||
|  |       </el-col> | ||||||
|  |       <el-divider content-position="center">{{ t('login.otherLogin') }}</el-divider> | ||||||
|  |       <el-col :span="24" style="padding-left: 10px; padding-right: 10px"> | ||||||
|  |         <el-form-item> | ||||||
|  |           <div class="flex justify-between w-[100%]"> | ||||||
|  |             <Icon | ||||||
|  |               icon="ant-design:github-filled" | ||||||
|  |               :size="iconSize" | ||||||
|  |               class="cursor-pointer anticon" | ||||||
|  |               :color="iconColor" | ||||||
|  |               @click="doSocialLogin('github')" | ||||||
|  |             /> | ||||||
|  |             <Icon | ||||||
|  |               icon="ant-design:wechat-filled" | ||||||
|  |               :size="iconSize" | ||||||
|  |               class="cursor-pointer anticon" | ||||||
|  |               :color="iconColor" | ||||||
|  |               @click="doSocialLogin('wechat')" | ||||||
|  |             /> | ||||||
|  |             <Icon | ||||||
|  |               icon="ant-design:alipay-circle-filled" | ||||||
|  |               :size="iconSize" | ||||||
|  |               :color="iconColor" | ||||||
|  |               class="cursor-pointer anticon" | ||||||
|  |               @click="doSocialLogin('alipay')" | ||||||
|  |             /> | ||||||
|  |             <Icon | ||||||
|  |               icon="ant-design:dingtalk-circle-filled" | ||||||
|  |               :size="iconSize" | ||||||
|  |               :color="iconColor" | ||||||
|  |               class="cursor-pointer anticon" | ||||||
|  |               @click="doSocialLogin('dingtalk')" | ||||||
|  |             /> | ||||||
|  |           </div> | ||||||
|  |         </el-form-item> | ||||||
|  |       </el-col> | ||||||
|  |     </el-row> | ||||||
|  |   </el-form> | ||||||
|  | </template> | ||||||
| <script setup lang="ts"> | <script setup lang="ts"> | ||||||
| import { useIcon } from '@/hooks/web/useIcon' | import { useIcon } from '@/hooks/web/useIcon' | ||||||
| import LoginFormTitle from './LoginFormTitle.vue' | import LoginFormTitle from './LoginFormTitle.vue' | ||||||
| @@ -153,144 +291,7 @@ onMounted(() => { | |||||||
|   getCookie() |   getCookie() | ||||||
| }) | }) | ||||||
| </script> | </script> | ||||||
| <template> |  | ||||||
|   <el-form |  | ||||||
|     :model="loginData.loginForm" |  | ||||||
|     :rules="LoginRules" |  | ||||||
|     label-position="top" |  | ||||||
|     class="login-form" |  | ||||||
|     label-width="120px" |  | ||||||
|     size="large" |  | ||||||
|     v-show="getShow" |  | ||||||
|     ref="formLogin" |  | ||||||
|   > |  | ||||||
|     <el-row style="maring-left: -10px; maring-right: -10px"> |  | ||||||
|       <el-col :span="24" style="padding-left: 10px; padding-right: 10px"> |  | ||||||
|         <el-form-item> |  | ||||||
|           <LoginFormTitle style="width: 100%" /> |  | ||||||
|         </el-form-item> |  | ||||||
|       </el-col> |  | ||||||
|       <el-col :span="24" style="padding-left: 10px; padding-right: 10px"> |  | ||||||
|         <el-form-item prop="tenantName"> |  | ||||||
|           <el-input |  | ||||||
|             type="text" |  | ||||||
|             v-model="loginData.loginForm.tenantName" |  | ||||||
|             :placeholder="t('login.tenantNamePlaceholder')" |  | ||||||
|             :prefix-icon="iconHouse" |  | ||||||
|           /> |  | ||||||
|         </el-form-item> |  | ||||||
|       </el-col> |  | ||||||
|       <el-col :span="24" style="padding-left: 10px; padding-right: 10px"> |  | ||||||
|         <el-form-item prop="username"> |  | ||||||
|           <el-input |  | ||||||
|             v-model="loginData.loginForm.username" |  | ||||||
|             :placeholder="t('login.usernamePlaceholder')" |  | ||||||
|             :prefix-icon="iconAvatar" |  | ||||||
|           /> |  | ||||||
|         </el-form-item> |  | ||||||
|       </el-col> |  | ||||||
|       <el-col :span="24" style="padding-left: 10px; padding-right: 10px"> |  | ||||||
|         <el-form-item prop="password"> |  | ||||||
|           <el-input |  | ||||||
|             v-model="loginData.loginForm.password" |  | ||||||
|             type="password" |  | ||||||
|             :placeholder="t('login.passwordPlaceholder')" |  | ||||||
|             show-password |  | ||||||
|             @keyup.enter="getCode()" |  | ||||||
|             :prefix-icon="iconLock" |  | ||||||
|           /> |  | ||||||
|         </el-form-item> |  | ||||||
|       </el-col> |  | ||||||
|       <el-col |  | ||||||
|         :span="24" |  | ||||||
|         style="padding-left: 10px; padding-right: 10px; margin-top: -20px; margin-bottom: -20px" |  | ||||||
|       > |  | ||||||
|         <el-form-item> |  | ||||||
|           <el-row justify="space-between" style="width: 100%"> |  | ||||||
|             <el-col :span="6"> |  | ||||||
|               <el-checkbox v-model="loginData.loginForm.rememberMe"> |  | ||||||
|                 {{ t('login.remember') }} |  | ||||||
|               </el-checkbox> |  | ||||||
|             </el-col> |  | ||||||
|             <el-col :span="12" :offset="6"> |  | ||||||
|               <el-link type="primary" style="float: right">{{ t('login.forgetPassword') }}</el-link> |  | ||||||
|             </el-col> |  | ||||||
|           </el-row> |  | ||||||
|         </el-form-item> |  | ||||||
|       </el-col> |  | ||||||
|       <el-col :span="24" style="padding-left: 10px; padding-right: 10px"> |  | ||||||
|         <el-form-item> |  | ||||||
|           <el-button :loading="loginLoading" type="primary" class="w-[100%]" @click="getCode()"> |  | ||||||
|             {{ t('login.login') }} |  | ||||||
|           </el-button> |  | ||||||
|         </el-form-item> |  | ||||||
|       </el-col> |  | ||||||
|       <Verify |  | ||||||
|         ref="verify" |  | ||||||
|         mode="pop" |  | ||||||
|         :captchaType="captchaType" |  | ||||||
|         :imgSize="{ width: '400px', height: '200px' }" |  | ||||||
|         @success="handleLogin" |  | ||||||
|       /> |  | ||||||
|       <el-col :span="24" style="padding-left: 10px; padding-right: 10px"> |  | ||||||
|         <el-form-item> |  | ||||||
|           <el-row justify="space-between" style="width: 100%" :gutter="5"> |  | ||||||
|             <el-col :span="8"> |  | ||||||
|               <el-button class="w-[100%]" @click="setLoginState(LoginStateEnum.MOBILE)"> |  | ||||||
|                 {{ t('login.btnMobile') }} |  | ||||||
|               </el-button> |  | ||||||
|             </el-col> |  | ||||||
|             <el-col :span="8"> |  | ||||||
|               <el-button class="w-[100%]" @click="setLoginState(LoginStateEnum.QR_CODE)"> |  | ||||||
|                 {{ t('login.btnQRCode') }} |  | ||||||
|               </el-button> |  | ||||||
|             </el-col> |  | ||||||
|             <el-col :span="8"> |  | ||||||
|               <el-button class="w-[100%]" @click="setLoginState(LoginStateEnum.REGISTER)"> |  | ||||||
|                 {{ t('login.btnRegister') }} |  | ||||||
|               </el-button> |  | ||||||
|             </el-col> |  | ||||||
|           </el-row> |  | ||||||
|         </el-form-item> |  | ||||||
|       </el-col> |  | ||||||
|       <el-divider content-position="center">{{ t('login.otherLogin') }}</el-divider> |  | ||||||
|       <el-col :span="24" style="padding-left: 10px; padding-right: 10px"> |  | ||||||
|         <el-form-item> |  | ||||||
|           <div class="flex justify-between w-[100%]"> |  | ||||||
|             <Icon |  | ||||||
|               icon="ant-design:github-filled" |  | ||||||
|               :size="iconSize" |  | ||||||
|               class="cursor-pointer anticon" |  | ||||||
|               :color="iconColor" |  | ||||||
|               @click="doSocialLogin('github')" |  | ||||||
|             /> |  | ||||||
|             <Icon |  | ||||||
|               icon="ant-design:wechat-filled" |  | ||||||
|               :size="iconSize" |  | ||||||
|               class="cursor-pointer anticon" |  | ||||||
|               :color="iconColor" |  | ||||||
|               @click="doSocialLogin('wechat')" |  | ||||||
|             /> |  | ||||||
|             <Icon |  | ||||||
|               icon="ant-design:alipay-circle-filled" |  | ||||||
|               :size="iconSize" |  | ||||||
|               :color="iconColor" |  | ||||||
|               class="cursor-pointer anticon" |  | ||||||
|               @click="doSocialLogin('alipay')" |  | ||||||
|             /> |  | ||||||
|             <Icon |  | ||||||
|               icon="ant-design:dingtalk-circle-filled" |  | ||||||
|               :size="iconSize" |  | ||||||
|               :color="iconColor" |  | ||||||
|               class="cursor-pointer anticon" |  | ||||||
|               @click="doSocialLogin('dingtalk')" |  | ||||||
|             /> |  | ||||||
|           </div> |  | ||||||
|         </el-form-item> |  | ||||||
|       </el-col> |  | ||||||
|     </el-row> |  | ||||||
|   </el-form> |  | ||||||
| </template> |  | ||||||
| <style lang="less" scoped> | <style lang="less" scoped> | ||||||
| :deep(.anticon) { | :deep(.anticon) { | ||||||
|   &:hover { |   &:hover { | ||||||
|   | |||||||
| @@ -1,3 +1,8 @@ | |||||||
|  | <template> | ||||||
|  |   <h2 class="mb-3 text-2xl font-bold text-center xl:text-3xl enter-x xl:text-center"> | ||||||
|  |     {{ getFormTitle }} | ||||||
|  |   </h2> | ||||||
|  | </template> | ||||||
| <script setup lang="ts"> | <script setup lang="ts"> | ||||||
| import { computed, unref } from 'vue' | import { computed, unref } from 'vue' | ||||||
| import { useI18n } from '@/hooks/web/useI18n' | import { useI18n } from '@/hooks/web/useI18n' | ||||||
| @@ -18,8 +23,3 @@ const getFormTitle = computed(() => { | |||||||
|   return titleObj[unref(getLoginState)] |   return titleObj[unref(getLoginState)] | ||||||
| }) | }) | ||||||
| </script> | </script> | ||||||
| <template> |  | ||||||
|   <h2 class="mb-3 text-2xl font-bold text-center xl:text-3xl enter-x xl:text-center"> |  | ||||||
|     {{ getFormTitle }} |  | ||||||
|   </h2> |  | ||||||
| </template> |  | ||||||
|   | |||||||
| @@ -1,3 +1,89 @@ | |||||||
|  | <template> | ||||||
|  |   <el-form | ||||||
|  |     :model="loginData.loginForm" | ||||||
|  |     :rules="rules" | ||||||
|  |     label-position="top" | ||||||
|  |     class="login-form" | ||||||
|  |     label-width="120px" | ||||||
|  |     size="large" | ||||||
|  |     v-show="getShow" | ||||||
|  |     ref="formSmsLogin" | ||||||
|  |   > | ||||||
|  |     <el-row style="margin-left: -10px; margin-right: -10px"> | ||||||
|  |       <!-- 租户名 --> | ||||||
|  |       <el-col :span="24" style="padding-left: 10px; padding-right: 10px"> | ||||||
|  |         <el-form-item> | ||||||
|  |           <LoginFormTitle style="width: 100%" /> | ||||||
|  |         </el-form-item> | ||||||
|  |       </el-col> | ||||||
|  |       <el-col :span="24" style="padding-left: 10px; padding-right: 10px"> | ||||||
|  |         <el-form-item prop="tenantName"> | ||||||
|  |           <el-input | ||||||
|  |             type="text" | ||||||
|  |             v-model="loginData.loginForm.tenantName" | ||||||
|  |             :placeholder="t('login.tenantNamePlaceholder')" | ||||||
|  |             :prefix-icon="iconHouse" | ||||||
|  |           /> | ||||||
|  |         </el-form-item> | ||||||
|  |       </el-col> | ||||||
|  |       <!-- 手机号 --> | ||||||
|  |       <el-col :span="24" style="padding-left: 10px; padding-right: 10px"> | ||||||
|  |         <el-form-item prop="mobileNumber"> | ||||||
|  |           <el-input | ||||||
|  |             v-model="loginData.loginForm.mobileNumber" | ||||||
|  |             :placeholder="t('login.mobileNumberPlaceholder')" | ||||||
|  |             :prefix-icon="iconCellphone" | ||||||
|  |           /> | ||||||
|  |         </el-form-item> | ||||||
|  |       </el-col> | ||||||
|  |       <!-- 验证码 --> | ||||||
|  |       <el-col :span="24" style="padding-left: 10px; padding-right: 10px"> | ||||||
|  |         <el-form-item prop="code"> | ||||||
|  |           <el-row justify="space-between" style="width: 100%" :gutter="5"> | ||||||
|  |             <el-col :span="24"> | ||||||
|  |               <el-input | ||||||
|  |                 v-model="loginData.loginForm.code" | ||||||
|  |                 :placeholder="t('login.codePlaceholder')" | ||||||
|  |                 :prefix-icon="iconCircleCheck" | ||||||
|  |               > | ||||||
|  |                 <!-- <el-button class="w-[100%]"> --> | ||||||
|  |                 <template #append> | ||||||
|  |                   <span | ||||||
|  |                     v-if="mobileCodeTimer <= 0" | ||||||
|  |                     @click="getSmsCode" | ||||||
|  |                     class="getMobileCode" | ||||||
|  |                     style="cursor: pointer" | ||||||
|  |                   > | ||||||
|  |                     {{ t('login.getSmsCode') }} | ||||||
|  |                   </span> | ||||||
|  |                   <span v-if="mobileCodeTimer > 0" class="getMobileCode" style="cursor: pointer"> | ||||||
|  |                     {{ mobileCodeTimer }}秒后可重新获取 | ||||||
|  |                   </span> | ||||||
|  |                 </template> | ||||||
|  |               </el-input> | ||||||
|  |               <!-- </el-button> --> | ||||||
|  |             </el-col> | ||||||
|  |           </el-row> | ||||||
|  |         </el-form-item> | ||||||
|  |       </el-col> | ||||||
|  |       <!-- 登录按钮 / 返回按钮 --> | ||||||
|  |       <el-col :span="24" style="padding-left: 10px; padding-right: 10px"> | ||||||
|  |         <el-form-item> | ||||||
|  |           <el-button :loading="loginLoading" type="primary" class="w-[100%]" @click="signIn"> | ||||||
|  |             {{ t('login.login') }} | ||||||
|  |           </el-button> | ||||||
|  |         </el-form-item> | ||||||
|  |       </el-col> | ||||||
|  |       <el-col :span="24" style="padding-left: 10px; padding-right: 10px"> | ||||||
|  |         <el-form-item> | ||||||
|  |           <el-button :loading="loginLoading" class="w-[100%]" @click="handleBackLogin"> | ||||||
|  |             {{ t('login.backLogin') }} | ||||||
|  |           </el-button> | ||||||
|  |         </el-form-item> | ||||||
|  |       </el-col> | ||||||
|  |     </el-row> | ||||||
|  |   </el-form> | ||||||
|  | </template> | ||||||
| <script setup lang="ts"> | <script setup lang="ts"> | ||||||
| import { useIcon } from '@/hooks/web/useIcon' | import { useIcon } from '@/hooks/web/useIcon' | ||||||
| import { reactive, ref, unref, watch, computed } from 'vue' | import { reactive, ref, unref, watch, computed } from 'vue' | ||||||
| @@ -111,92 +197,7 @@ const signIn = async () => { | |||||||
|     }) |     }) | ||||||
| } | } | ||||||
| </script> | </script> | ||||||
| <template> |  | ||||||
|   <el-form |  | ||||||
|     :model="loginData.loginForm" |  | ||||||
|     :rules="rules" |  | ||||||
|     label-position="top" |  | ||||||
|     class="login-form" |  | ||||||
|     label-width="120px" |  | ||||||
|     size="large" |  | ||||||
|     v-show="getShow" |  | ||||||
|     ref="formSmsLogin" |  | ||||||
|   > |  | ||||||
|     <el-row style="margin-left: -10px; margin-right: -10px"> |  | ||||||
|       <!-- 租户名 --> |  | ||||||
|       <el-col :span="24" style="padding-left: 10px; padding-right: 10px"> |  | ||||||
|         <el-form-item> |  | ||||||
|           <LoginFormTitle style="width: 100%" /> |  | ||||||
|         </el-form-item> |  | ||||||
|       </el-col> |  | ||||||
|       <el-col :span="24" style="padding-left: 10px; padding-right: 10px"> |  | ||||||
|         <el-form-item prop="tenantName"> |  | ||||||
|           <el-input |  | ||||||
|             type="text" |  | ||||||
|             v-model="loginData.loginForm.tenantName" |  | ||||||
|             :placeholder="t('login.tenantNamePlaceholder')" |  | ||||||
|             :prefix-icon="iconHouse" |  | ||||||
|           /> |  | ||||||
|         </el-form-item> |  | ||||||
|       </el-col> |  | ||||||
|       <!-- 手机号 --> |  | ||||||
|       <el-col :span="24" style="padding-left: 10px; padding-right: 10px"> |  | ||||||
|         <el-form-item prop="mobileNumber"> |  | ||||||
|           <el-input |  | ||||||
|             v-model="loginData.loginForm.mobileNumber" |  | ||||||
|             :placeholder="t('login.mobileNumberPlaceholder')" |  | ||||||
|             :prefix-icon="iconCellphone" |  | ||||||
|           /> |  | ||||||
|         </el-form-item> |  | ||||||
|       </el-col> |  | ||||||
|       <!-- 验证码 --> |  | ||||||
|       <el-col :span="24" style="padding-left: 10px; padding-right: 10px"> |  | ||||||
|         <el-form-item prop="code"> |  | ||||||
|           <el-row justify="space-between" style="width: 100%" :gutter="5"> |  | ||||||
|             <el-col :span="24"> |  | ||||||
|               <el-input |  | ||||||
|                 v-model="loginData.loginForm.code" |  | ||||||
|                 :placeholder="t('login.codePlaceholder')" |  | ||||||
|                 :prefix-icon="iconCircleCheck" |  | ||||||
|               > |  | ||||||
|                 <!-- <el-button class="w-[100%]"> --> |  | ||||||
|                 <template #append> |  | ||||||
|                   <span |  | ||||||
|                     v-if="mobileCodeTimer <= 0" |  | ||||||
|                     @click="getSmsCode" |  | ||||||
|                     class="getMobileCode" |  | ||||||
|                     style="cursor: pointer" |  | ||||||
|                   > |  | ||||||
|                     {{ t('login.getSmsCode') }} |  | ||||||
|                   </span> |  | ||||||
|                   <span v-if="mobileCodeTimer > 0" class="getMobileCode" style="cursor: pointer"> |  | ||||||
|                     {{ mobileCodeTimer }}秒后可重新获取 |  | ||||||
|                   </span> |  | ||||||
|                 </template> |  | ||||||
|               </el-input> |  | ||||||
|               <!-- </el-button> --> |  | ||||||
|             </el-col> |  | ||||||
|           </el-row> |  | ||||||
|         </el-form-item> |  | ||||||
|       </el-col> |  | ||||||
|       <!-- 登录按钮 / 返回按钮 --> |  | ||||||
|       <el-col :span="24" style="padding-left: 10px; padding-right: 10px"> |  | ||||||
|         <el-form-item> |  | ||||||
|           <el-button :loading="loginLoading" type="primary" class="w-[100%]" @click="signIn"> |  | ||||||
|             {{ t('login.login') }} |  | ||||||
|           </el-button> |  | ||||||
|         </el-form-item> |  | ||||||
|       </el-col> |  | ||||||
|       <el-col :span="24" style="padding-left: 10px; padding-right: 10px"> |  | ||||||
|         <el-form-item> |  | ||||||
|           <el-button :loading="loginLoading" class="w-[100%]" @click="handleBackLogin"> |  | ||||||
|             {{ t('login.backLogin') }} |  | ||||||
|           </el-button> |  | ||||||
|         </el-form-item> |  | ||||||
|       </el-col> |  | ||||||
|     </el-row> |  | ||||||
|   </el-form> |  | ||||||
| </template> |  | ||||||
| <style lang="less" scoped> | <style lang="less" scoped> | ||||||
| :deep(.anticon) { | :deep(.anticon) { | ||||||
|   &:hover { |   &:hover { | ||||||
|   | |||||||
| @@ -1,17 +1,3 @@ | |||||||
| <script setup lang="ts"> |  | ||||||
| import { computed, unref } from 'vue' |  | ||||||
| import { ElRow, ElCol, ElCard, ElDivider } from 'element-plus' |  | ||||||
| import { useI18n } from '@/hooks/web/useI18n' |  | ||||||
| import { useLoginState, LoginStateEnum } from './useLogin' |  | ||||||
| import LoginFormTitle from './LoginFormTitle.vue' |  | ||||||
| import { Qrcode } from '@/components/Qrcode' |  | ||||||
| import logoImg from '@/assets/imgs/logo.png' |  | ||||||
|  |  | ||||||
| const { t } = useI18n() |  | ||||||
| const { handleBackLogin, getLoginState } = useLoginState() |  | ||||||
| const getShow = computed(() => unref(getLoginState) === LoginStateEnum.QR_CODE) |  | ||||||
| </script> |  | ||||||
|  |  | ||||||
| <template> | <template> | ||||||
|   <el-row v-show="getShow" style="maring-left: -10px; maring-right: -10px"> |   <el-row v-show="getShow" style="maring-left: -10px; maring-right: -10px"> | ||||||
|     <el-col :span="24" style="padding-left: 10px; padding-right: 10px"> |     <el-col :span="24" style="padding-left: 10px; padding-right: 10px"> | ||||||
| @@ -32,3 +18,16 @@ const getShow = computed(() => unref(getLoginState) === LoginStateEnum.QR_CODE) | |||||||
|     </el-col> |     </el-col> | ||||||
|   </el-row> |   </el-row> | ||||||
| </template> | </template> | ||||||
|  | <script setup lang="ts"> | ||||||
|  | import { computed, unref } from 'vue' | ||||||
|  | import { ElRow, ElCol, ElCard, ElDivider } from 'element-plus' | ||||||
|  | import { useI18n } from '@/hooks/web/useI18n' | ||||||
|  | import { useLoginState, LoginStateEnum } from './useLogin' | ||||||
|  | import LoginFormTitle from './LoginFormTitle.vue' | ||||||
|  | import { Qrcode } from '@/components/Qrcode' | ||||||
|  | import logoImg from '@/assets/imgs/logo.png' | ||||||
|  |  | ||||||
|  | const { t } = useI18n() | ||||||
|  | const { handleBackLogin, getLoginState } = useLoginState() | ||||||
|  | const getShow = computed(() => unref(getLoginState) === LoginStateEnum.QR_CODE) | ||||||
|  | </script> | ||||||
|   | |||||||
| @@ -1,3 +1,39 @@ | |||||||
|  | <template> | ||||||
|  |   <Form | ||||||
|  |     :schema="schema" | ||||||
|  |     :rules="rules" | ||||||
|  |     label-position="top" | ||||||
|  |     hide-required-asterisk | ||||||
|  |     size="large" | ||||||
|  |     v-show="getShow" | ||||||
|  |     class="dark:(border-1 border-[var(--el-border-color)] border-solid)" | ||||||
|  |     @register="register" | ||||||
|  |   > | ||||||
|  |     <template #title> | ||||||
|  |       <LoginFormTitle style="width: 100%" /> | ||||||
|  |     </template> | ||||||
|  |  | ||||||
|  |     <template #code="form"> | ||||||
|  |       <div class="w-[100%] flex"> | ||||||
|  |         <el-input v-model="form['code']" :placeholder="t('login.codePlaceholder')" /> | ||||||
|  |       </div> | ||||||
|  |     </template> | ||||||
|  |  | ||||||
|  |     <template #register> | ||||||
|  |       <div class="w-[100%]"> | ||||||
|  |         <el-button type="primary" class="w-[100%]" :loading="loading" @click="loginRegister"> | ||||||
|  |           {{ t('login.register') }} | ||||||
|  |         </el-button> | ||||||
|  |       </div> | ||||||
|  |       <div class="w-[100%] mt-15px"> | ||||||
|  |         <el-button class="w-[100%]" @click="handleBackLogin"> | ||||||
|  |           {{ t('login.hasUser') }} | ||||||
|  |         </el-button> | ||||||
|  |       </div> | ||||||
|  |     </template> | ||||||
|  |   </Form> | ||||||
|  | </template> | ||||||
|  |  | ||||||
| <script setup lang="ts"> | <script setup lang="ts"> | ||||||
| import { Form } from '@/components/Form' | import { Form } from '@/components/Form' | ||||||
| import { computed, reactive, ref, unref } from 'vue' | import { computed, reactive, ref, unref } from 'vue' | ||||||
| @@ -104,39 +140,3 @@ const loginRegister = async () => { | |||||||
|   }) |   }) | ||||||
| } | } | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <template> |  | ||||||
|   <Form |  | ||||||
|     :schema="schema" |  | ||||||
|     :rules="rules" |  | ||||||
|     label-position="top" |  | ||||||
|     hide-required-asterisk |  | ||||||
|     size="large" |  | ||||||
|     v-show="getShow" |  | ||||||
|     class="dark:(border-1 border-[var(--el-border-color)] border-solid)" |  | ||||||
|     @register="register" |  | ||||||
|   > |  | ||||||
|     <template #title> |  | ||||||
|       <LoginFormTitle style="width: 100%" /> |  | ||||||
|     </template> |  | ||||||
|  |  | ||||||
|     <template #code="form"> |  | ||||||
|       <div class="w-[100%] flex"> |  | ||||||
|         <el-input v-model="form['code']" :placeholder="t('login.codePlaceholder')" /> |  | ||||||
|       </div> |  | ||||||
|     </template> |  | ||||||
|  |  | ||||||
|     <template #register> |  | ||||||
|       <div class="w-[100%]"> |  | ||||||
|         <el-button type="primary" class="w-[100%]" :loading="loading" @click="loginRegister"> |  | ||||||
|           {{ t('login.register') }} |  | ||||||
|         </el-button> |  | ||||||
|       </div> |  | ||||||
|       <div class="w-[100%] mt-15px"> |  | ||||||
|         <el-button class="w-[100%]" @click="handleBackLogin"> |  | ||||||
|           {{ t('login.hasUser') }} |  | ||||||
|         </el-button> |  | ||||||
|       </div> |  | ||||||
|     </template> |  | ||||||
|   </Form> |  | ||||||
| </template> |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 xingyu4j
					xingyu4j