Prechádzať zdrojové kódy

feat: 优化-2024/12/20 12:57:15

shuisheng 1 rok pred
rodič
commit
083d99bb91

+ 21 - 0
LICENSE

@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2023-PRESENT shuisheng<https://github.com/galaxy-s10>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 1 - 0
deploy/handleGiteeJenkins.mjs

@@ -81,6 +81,7 @@ if (process.cwd().indexOf('jenkins') !== -1) {
     const gitignoreTxt =
       'node_modules\ndist\ncomponents.d.ts\n.eslintcache\n.DS_Store\n';
     fs.writeFileSync(path.resolve(giteeDir, './.gitignore'), gitignoreTxt);
+    execSync(`git rm -r --cached .`, { cwd: giteeDir });
     execSync(`pnpm i`, { cwd: giteeDir });
     execSync(`git add .`, { cwd: giteeDir });
     execSync(`git commit -m 'feat: ${new Date().toLocaleString()}'`, {

+ 1 - 0
deploy/handleSyncPublic.mjs

@@ -108,6 +108,7 @@ if (process.cwd().indexOf('galaxy-s10') !== -1) {
       // @ts-ignore
       JSON.stringify({ ...newPkg }, {}, 2)
     );
+    execSync(`git rm -r --cached .`, { cwd: freeDir });
     execSync(`pnpm i`, { cwd: freeDir });
     execSync(`git add .`, { cwd: freeDir });
     execSync(`git commit -m 'feat: 优化-${new Date().toLocaleString()}'`, {

+ 31 - 0
public/worker.js

@@ -0,0 +1,31 @@
+self.addEventListener('message', function (e) {
+  if (e.data.type === 'request-start-msr-loop') {
+    if (e.data.delay > 0) {
+      const timer = setInterval(function () {
+        self.postMessage({
+          type: 'response-msr-looping',
+          timer,
+        });
+      }, e.data.delay);
+      self.postMessage({
+        type: 'response-start-msr-loop',
+        timer,
+      });
+    }
+  } else if (e.data.type === 'request-start-loop') {
+    if (e.data.delay > 0) {
+      const timer = setInterval(function () {
+        self.postMessage({
+          type: 'response-looping',
+          timer,
+        });
+      }, e.data.delay);
+      self.postMessage({
+        type: 'response-start-loop',
+        timer,
+      });
+    }
+  } else if (e.data.type === 'request-clear-loop') {
+    clearInterval(e.data.timer);
+  }
+});

+ 0 - 3
src/App.vue

@@ -51,9 +51,6 @@ const themeOverrides: GlobalThemeOverrides = {
 };
 
 onMounted(() => {
-  document.addEventListener('click', () => {
-    appStore.pageIsClick = true;
-  });
   handleGlobalMsgMyList();
   useGoogleAd();
   initGlobalData();

+ 5 - 0
src/api/tencentcloudChat.ts

@@ -0,0 +1,5 @@
+import request from '@/utils/request';
+
+export function fetchTencentcloudChatGenUserSig(userId: string) {
+  return request.post(`/tencentcloud_chat/gen_user_sig`, { userId });
+}

+ 7 - 0
src/api/tencentcloudCos.ts

@@ -0,0 +1,7 @@
+import request from '@/utils/request';
+
+export function fetchTencentcloudCosGetPolicyByRes(prefix: string) {
+  return request.get(`/tencentcloud_cos/policy_by_res`, {
+    params: { prefix },
+  });
+}

+ 10 - 1
src/api/user.ts

@@ -36,13 +36,22 @@ export function fetchQrcodeLoginStatus({ platform, login_id }) {
   });
 }
 
-export function fetchUsernameLogin({ username, password, exp }) {
+export function fetchUserIdLogin({ id, password, exp }) {
+  return request.post('/user/id_login', {
+    id,
+    password,
+    exp,
+  });
+}
+
+export function fetchUserUsernameLogin({ username, password, exp }) {
   return request.post('/user/username_login', {
     username,
     password,
     exp,
   });
 }
+
 export function fetchIdLogin({ id, password }) {
   return request.post('/user/login', {
     id,

BIN
src/assets/img/camera.png


BIN
src/assets/img/line_chart.png


BIN
src/assets/img/user.png


+ 93 - 6
src/components/LoginModal/index.vue

@@ -17,7 +17,65 @@
             :on-update:value="tabChange"
           >
             <n-tab-pane
-              name="pwdlogin"
+              :name="tabEnum.idlogin"
+              tab="ID登录"
+            >
+              <n-form
+                ref="loginFormRef"
+                label-placement="left"
+                size="large"
+                :model="loginForm"
+                :rules="loginRules"
+              >
+                <n-form-item path="id">
+                  <n-input
+                    v-model:value="loginForm.username"
+                    type="text"
+                    placeholder="请输入用户ID"
+                  >
+                    <template #prefix>
+                      <n-icon
+                        size="20"
+                        class="lang"
+                      >
+                        <PersonOutline></PersonOutline>
+                      </n-icon>
+                    </template>
+                  </n-input>
+                </n-form-item>
+                <n-form-item path="password">
+                  <n-input
+                    v-model:value="loginForm.password"
+                    type="password"
+                    show-password-on="mousedown"
+                    placeholder="请输入密码"
+                    @focus="onFocus"
+                    @blur="onBlur"
+                    @keyup.enter="handleLoginSubmit"
+                  >
+                    <template #prefix>
+                      <n-icon
+                        size="20"
+                        class="lang"
+                      >
+                        <LockClosedOutline></LockClosedOutline>
+                      </n-icon>
+                    </template>
+                  </n-input>
+                </n-form-item>
+              </n-form>
+              <n-button
+                type="primary"
+                block
+                secondary
+                strong
+                @click="handleLoginSubmit"
+              >
+                登录
+              </n-button>
+            </n-tab-pane>
+            <n-tab-pane
+              :name="tabEnum.usernamelogin"
               tab="账密登录"
             >
               <n-form
@@ -75,7 +133,7 @@
               </n-button>
             </n-tab-pane>
             <n-tab-pane
-              name="pwdregister"
+              :name="tabEnum.register"
               tab="注册"
             >
               <n-form
@@ -182,7 +240,12 @@ const loginForm = ref({
   password: '',
 });
 const loginFormRef = ref(null);
-const currentTab = ref('pwdlogin'); // pwdlogin
+enum tabEnum {
+  idlogin,
+  usernamelogin,
+  register,
+}
+const currentTab = ref(tabEnum.idlogin);
 const loopTimer = ref();
 const emits = defineEmits(['close']);
 
@@ -200,7 +263,7 @@ function handleClose() {
   emits('close');
 }
 
-const handleLogin = async () => {
+async function handleUsernameLogin() {
   if (
     loginForm.value.username.length < 3 ||
     loginForm.value.username.length > 12
@@ -225,7 +288,27 @@ const handleLogin = async () => {
     userStore.getUserInfo();
     appStore.showLoginModal = false;
   }
-};
+}
+
+async function handleUserIdLogin() {
+  if (
+    loginForm.value.password.length < 6 ||
+    loginForm.value.password.length > 18
+  ) {
+    window.$message.warning('密码长度要求6-18位!');
+    return;
+  }
+  let token = null;
+  token = await userStore.idLogin({
+    id: Number(loginForm.value.username),
+    password: loginForm.value.password,
+  });
+  if (token) {
+    window.$message.success('登录成功!');
+    userStore.getUserInfo();
+    appStore.showLoginModal = false;
+  }
+}
 
 function handleUserRegister(e) {
   e.preventDefault();
@@ -248,7 +331,11 @@ const handleLoginSubmit = (e) => {
   // @ts-ignore
   loginFormRef.value.validate((errors) => {
     if (!errors) {
-      handleLogin();
+      if (currentTab.value === tabEnum.usernamelogin) {
+        handleUsernameLogin();
+      } else if (currentTab.value === tabEnum.idlogin) {
+        handleUserIdLogin();
+      }
     }
   });
 };

+ 44 - 6
src/layout/pc/head/index.vue

@@ -393,14 +393,41 @@
                 class="item"
                 @click.prevent="
                   router.push({
-                    name: routerName.my,
-                    params: {
-                      userId: userStore.userInfo.id,
-                    },
+                    name: routerName.wallet,
                   })
                 "
               >
-                <div class="txt">{{ t('layout.my') }}</div>
+                <div class="txt">
+                  {{ t('layout.wallet') }}:{{
+                    formatMoney(userStore.userInfo.wallet?.balance || 0)
+                  }}元
+                </div>
+              </a>
+              <a
+                class="item"
+                @click.prevent="
+                  router.push({
+                    name: routerName.centerUserInfo,
+                  })
+                "
+              >
+                <div class="txt">{{ t('layout.userCenter') }}</div>
+              </a>
+              <a
+                class="item"
+                @click.prevent="
+                  router.push({
+                    name: routerName.centerLiveRoomInfo,
+                  })
+                "
+              >
+                <div class="txt">{{ t('layout.liveCenter') }}</div>
+              </a>
+              <a
+                class="item"
+                @click.prevent="jumpToMyLiveRoom"
+              >
+                <div class="txt">{{ t('layout.myLiveRoom') }}</div>
               </a>
               <a
                 class="item"
@@ -459,6 +486,7 @@ import { useAppStore } from '@/store/app';
 import { useCacheStore } from '@/store/cache';
 import { useUserStore } from '@/store/user';
 import { LiveRoomTypeEnum } from '@/types/ILiveRoom';
+import { formatMoney, getLiveRoomPageUrl } from '@/utils';
 
 const { t, locale } = useI18n();
 const router = useRouter();
@@ -609,6 +637,16 @@ watch(
   }
 );
 
+function jumpToMyLiveRoom() {
+  const id = userStore.userInfo?.live_rooms?.[0]?.id;
+  if (!id) {
+    window.$message.warning('你还没有开通直播间!');
+    return;
+  }
+  const url = getLiveRoomPageUrl(id!);
+  openToTarget(url);
+}
+
 async function handleSignin() {
   const res = await fetchCreateSignin({});
   if (res.code === 200) {
@@ -1020,7 +1058,7 @@ function handleWebsiteJump() {
         }
         .list {
           padding: 10px 0;
-          width: 90px;
+          width: 170px;
 
           .item {
             position: relative;

+ 2 - 2
src/layout/pc/index.vue

@@ -24,8 +24,8 @@ const appStore = useAppStore();
 <style lang="scss" scoped>
 .layout {
   box-sizing: border-box;
-  padding-top: $header-height;
-  min-height: 100vh;
+  // padding-top: $header-height;
+  height: 100vh;
 
   .fixed-mask {
     position: fixed;

+ 4 - 0
src/locales/en/layout.ts

@@ -24,6 +24,10 @@ export default nameSpaceWrap('layout', {
   login: 'Login',
   logout: 'Logout',
   my: 'My',
+  wallet: 'Wallet',
+  userCenter: 'User Center',
+  liveCenter: 'Live Center',
+  myLiveRoom: 'My LiveRoom',
   resource: 'Resource',
   libraries: 'Official libraries',
   rank: 'Rank',

+ 5 - 1
src/locales/zh/layout.ts

@@ -23,8 +23,12 @@ export default nameSpaceWrap('layout', {
   remoteDesktop: '远程桌面',
   startLive: '我要开播',
   login: '登录',
-  logout: '退出',
+  logout: '退出登录',
   my: '个人信息',
+  wallet: '钱包',
+  userCenter: '用户中心',
+  liveCenter: '直播中心',
+  myLiveRoom: '我的直播间',
   resource: '资源',
   libraries: '官方库',
   rank: '排行榜',

+ 72 - 0
src/router/index.ts

@@ -54,6 +54,16 @@ export const routerName = {
   notFound: 'notFound',
   group: 'group',
   my: 'my',
+  center: 'center',
+  centerUser: 'centerUser',
+  centerUserInfo: 'centerUserInfo',
+  centerUserIncome: 'centerUserIncome',
+  centerLiveRoom: 'centerLiveRoom',
+  centerLiveRoomInfo: 'centerLiveRoomInfo',
+  centerLiveRoomStartLive: 'centerLiveRoomStartLive',
+  centerLiveData: 'centerLiveData',
+  centerLiveDataOverview: 'centerLiveDataOverview',
+  centerLiveDataRecord: 'centerLiveDataRecord',
   user: 'user',
   download: 'download',
   downloadLive: 'downloadLive',
@@ -166,6 +176,68 @@ export const defaultRoutes: RouteRecordRaw[] = [
         path: '/my',
         component: () => import('@/views/my/index.vue'),
       },
+      {
+        name: routerName.center,
+        path: '/center',
+        component: () => import('@/views/center/index.vue'),
+        children: [
+          {
+            name: routerName.centerUser,
+            path: 'user',
+            component: () => import('@/views/center/user/index.vue'),
+            children: [
+              {
+                name: routerName.centerUserInfo,
+                path: 'info',
+                component: () => import('@/views/center/user/info/index.vue'),
+              },
+              {
+                name: routerName.centerUserIncome,
+                path: 'income',
+                component: () => import('@/views/center/user/income/index.vue'),
+              },
+            ],
+          },
+          {
+            name: routerName.centerLiveRoom,
+            path: 'liveroom',
+            component: () => import('@/views/center/liveroom/index.vue'),
+            children: [
+              {
+                name: routerName.centerLiveRoomInfo,
+                path: 'info',
+                component: () =>
+                  import('@/views/center/liveroom/info/index.vue'),
+              },
+              {
+                name: routerName.centerLiveRoomStartLive,
+                path: 'start-live',
+                component: () =>
+                  import('@/views/center/liveroom/start-live/index.vue'),
+              },
+            ],
+          },
+          {
+            name: routerName.centerLiveData,
+            path: 'live-data',
+            component: () => import('@/views/center/live-data//index.vue'),
+            children: [
+              {
+                name: routerName.centerLiveDataOverview,
+                path: 'overview',
+                component: () =>
+                  import('@/views/center/live-data/overview/index.vue'),
+              },
+              {
+                name: routerName.centerLiveDataRecord,
+                path: 'record',
+                component: () =>
+                  import('@/views/center/live-data/record/index.vue'),
+              },
+            ],
+          },
+        ],
+      },
       {
         name: routerName.user,
         path: '/user/:id',

+ 4 - 3
src/spec-config.ts

@@ -19,12 +19,13 @@ export const TENCENTCLOUD_COS = {
     Region: 'ap-guangzhou',
     StorageClass: 'STANDARD',
     prefix: {
-      'common/': 'common/',
-      'images/': 'images/',
-      'msg-images/': 'msg-images/',
+      'billd-live/client/common/': 'billd-live/client/common/',
+      'billd-live/client/img/': 'billd-live/client/img/',
+      'billd-live/client/msg-img/': 'billd-live/client/msg-img/',
     },
   },
 };
+export const TENCENTCLOUD_CHAT_SDK_APPID = 1400815419; // 腾讯云即时通讯IM SDKAppID
 
 export const QINIU_KODO = {
   hssblog: {

+ 1 - 1
vite.config.ts

@@ -18,7 +18,7 @@ export default defineConfig(({ mode }) => {
 
   const outputStaticUrl = () => {
     if (isProduction) {
-      return 'https://resource.hsslive.cn/billd-live/client/dist/';
+      return 'https://live.hsslive.cn/dist/';
     } else {
       return './';
     }