gemercheung 2 gadi atpakaļ
vecāks
revīzija
f710130fee

+ 2 - 1
package.json

@@ -36,7 +36,8 @@
     "vue": "^3.2.37",
     "vue-i18n": "^9.2.2",
     "vue-router": "4",
-    "vue3-autocounter": "^1.0.6"
+    "vue3-autocounter": "^1.0.6",
+    "vue3-otp-input": "^0.3.6"
   },
   "devDependencies": {
     "@types/lodash-es": "^4.17.6",

+ 11 - 0
pnpm-lock.yaml

@@ -38,6 +38,7 @@ specifiers:
   vue-router: '4'
   vue-tsc: ^0.40.4
   vue3-autocounter: ^1.0.6
+  vue3-otp-input: ^0.3.6
 
 dependencies:
   '@ant-design/icons-vue': 6.1.0_vue@3.2.41
@@ -56,6 +57,7 @@ dependencies:
   vue-i18n: 9.2.2_vue@3.2.41
   vue-router: 4.1.6_vue@3.2.41
   vue3-autocounter: 1.0.6_vue@3.2.41
+  vue3-otp-input: 0.3.6_vue@3.2.41
 
 devDependencies:
   '@types/lodash-es': 4.17.6
@@ -2694,6 +2696,15 @@ packages:
       vue: 3.2.41
     dev: false
 
+  /vue3-otp-input/0.3.6_vue@3.2.41:
+    resolution: {integrity: sha512-08A/33P3dvk8DBQ6ACJ6ajNCNdkJL2Di5CVVLxcYK7+izM4KFMeWsFnZsx2fD0VfLE7t6jpi+cNgNU83nP7/TQ==}
+    engines: {node: '>=14.0.0', npm: '>=7.0.0'}
+    peerDependencies:
+      vue: ^3.0.*
+    dependencies:
+      vue: 3.2.41
+    dev: false
+
   /warning/4.0.3:
     resolution: {integrity: sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==}
     dependencies:

+ 2 - 1
src/App.vue

@@ -23,7 +23,7 @@ import browser from '@/utils/browser'
 import { useLocale } from './locales/useLocale'
 import { LocaleType } from '#/config'
 import { useI18n } from './hook/useI18n'
-provide('getImgSrc', getImgSrc)
+
 export const contentRef = ref<HTMLDivElement>()
 
 export default defineComponent({
@@ -32,6 +32,7 @@ export default defineComponent({
     LayoutHeader
   },
   setup() {
+    provide('getImgSrc', getImgSrc)
     onMounted(() => {
       const { t } = useI18n()
       const websiteTitle = t('base.websiteTitle')

+ 6 - 0
src/components.d.ts

@@ -11,10 +11,12 @@ declare module '@vue/runtime-core' {
     AButton: typeof import('ant-design-vue/es')['Button']
     ACard: typeof import('ant-design-vue/es')['Card']
     ACol: typeof import('ant-design-vue/es')['Col']
+    AConfigProvider: typeof import('ant-design-vue/es')['ConfigProvider']
     ADropdown: typeof import('ant-design-vue/es')['Dropdown']
     AForm: typeof import('ant-design-vue/es')['Form']
     AFormItem: typeof import('ant-design-vue/es')['FormItem']
     AInput: typeof import('ant-design-vue/es')['Input']
+    AInputNumber: typeof import('ant-design-vue/es')['InputNumber']
     ALayout: typeof import('ant-design-vue/es')['Layout']
     ALayoutContent: typeof import('ant-design-vue/es')['LayoutContent']
     ALayoutHeader: typeof import('ant-design-vue/es')['LayoutHeader']
@@ -25,6 +27,9 @@ declare module '@vue/runtime-core' {
     AModal: typeof import('ant-design-vue/es')['Modal']
     APopover: typeof import('ant-design-vue/es')['Popover']
     AppstoreOutlined: typeof import('@ant-design/icons-vue')['AppstoreOutlined']
+    ARadio: typeof import('ant-design-vue/es')['Radio']
+    ARadioGroup: typeof import('ant-design-vue/es')['RadioGroup']
+    ARangePicker: typeof import('ant-design-vue/es')['RangePicker']
     ARow: typeof import('ant-design-vue/es')['Row']
     ATable: typeof import('ant-design-vue/es')['Table']
     ATabPane: typeof import('ant-design-vue/es')['TabPane']
@@ -42,6 +47,7 @@ declare module '@vue/runtime-core' {
     RouterLink: typeof import('vue-router')['RouterLink']
     RouterView: typeof import('vue-router')['RouterView']
     SearchOutlined: typeof import('@ant-design/icons-vue')['SearchOutlined']
+    UserOutlined: typeof import('@ant-design/icons-vue')['UserOutlined']
     VerticalAlignTopOutlined: typeof import('@ant-design/icons-vue')['VerticalAlignTopOutlined']
   }
 }

+ 2 - 1
src/locales/lang/en/room.ts

@@ -23,7 +23,8 @@ export default {
     scene: 'scene',
     name: 'name',
     time: 'time',
-    addLeastScene: 'Add a minimum of one scene'
+    addLeastScene: 'Add a minimum of one scene',
+    advanceConfig:'advanceConfig'
   },
   roomOnfired:
     'The studio is livestreaming; please stop the livestream before making any changes!',

+ 2 - 1
src/locales/lang/zh/room.ts

@@ -22,7 +22,8 @@ export default {
     scene: '场景',
     name: '名称',
     time: '时间',
-    addLeastScene: '至少添加一个场景'
+    addLeastScene: '至少添加一个场景',
+    advanceConfig:'高级配置'
   },
   roomOnfired: '房间直播中, 请先关闭直播再修改 !',
   copyLink: '复制链接',

+ 5 - 5
src/locales/useLocale.ts

@@ -31,9 +31,9 @@ export function useLocale() {
   const getLocale = computed(() => localeStore.getLocale)
   // const getShowLocalePicker = computed(() => localeStore.getShowPicker);
 
-  // const getAntdLocale = computed((): any => {
-  //   return i18n.global.getLocaleMessage(unref(getLocale))?.antdLocale ?? {};
-  // });
+  const getAntdLocale = computed((): any => {
+    return i18n.global.getLocaleMessage(unref(getLocale))?.antdLocale ?? {};
+  });
 
   // Switching the language will change the locale of useI18n
   // And submit to configuration modification
@@ -67,7 +67,7 @@ export function useLocale() {
   return {
     getLocale,
     // getShowLocalePicker,
-    changeLocale
-    // getAntdLocale,
+    changeLocale,
+    getAntdLocale,
   }
 }

+ 16 - 17
src/style.css

@@ -1,26 +1,25 @@
 ::-webkit-scrollbar {
-  width: 14px;
-  height: 18px;
+  background-color: #fff;
+  width: 16px;
 }
 
-::-webkit-scrollbar-thumb {
-  height: 6px;
-  border: 4px solid rgba(0, 0, 0, 0);
-  background-clip: padding-box;
-  background-color: rgba(0, 0, 0, 0, 0.2);
-  -webkit-border-radius: 7px;
-  -webkit-box-shadow: inset -1px -1px 0px rgba(0, 0, 0, 0.05),
-    inset 1px 1px 0px rgba(0, 0, 0, 0.05);
+/* background of the scrollbar except button or resizer */
+::-webkit-scrollbar-track {
+  background-color: #fff;
 }
-
-::-webkit-scrollbar-button {
-  display: none;
-  width: 0;
-  height: 0;
+::-webkit-scrollbar-track:hover {
+  background-color: #f4f4f4;
 }
 
-::-webkit-scrollbar-corner {
-  background-color: transparent;
+/* scrollbar itself */
+::-webkit-scrollbar-thumb {
+  background-color: #babac0;
+  border-radius: 16px;
+  border: 5px solid #fff;
+}
+::-webkit-scrollbar-thumb:hover {
+  background-color: #a0a0a5;
+  border: 4px solid #f4f4f4;
 }
 #app {
   height: 100%;

+ 205 - 110
src/views/room/edit-room/index.vue

@@ -1,28 +1,29 @@
 <template>
-  <a-modal
-    :visible="visible"
-    :title="!room ? t('room.createRoom') : t('room.editRoom')"
-    :after-close="onCancel"
-    width="912px"
-    :style="{
-      top: '10px',
-      minWidth: '912px'
-    }"
-    @cancel="visible = false"
-  >
-    <template #footer>
-      <a-button class="action-bottom" size="middle" @click="visible = false">
-        {{ t('base.cancel') }}
-      </a-button>
-      <a-button
-        class="action-bottom"
-        type="primary"
-        size="middle"
-        @click="saveRoom"
-      >
-        {{ t('base.save') }}
-      </a-button>
-      <!-- <a-button
+  <a-config-provider :locale="getAntdLocale">
+    <a-modal
+      :visible="visible"
+      :title="!room ? t('room.createRoom') : t('room.editRoom')"
+      :after-close="onCancel"
+      width="912px"
+      :style="{
+        top: '10px',
+        minWidth: '912px'
+      }"
+      @cancel="visible = false"
+    >
+      <template #footer>
+        <a-button class="action-bottom" size="middle" @click="visible = false">
+          {{ t('base.cancel') }}
+        </a-button>
+        <a-button
+          class="action-bottom"
+          type="primary"
+          size="middle"
+          @click="saveRoom"
+        >
+          {{ t('base.save') }}
+        </a-button>
+        <!-- <a-button
         v-if="room"
         class="action-bottom"
         type="primary"
@@ -31,86 +32,150 @@
       >
         开始带看
       </a-button> -->
-    </template>
-    <div class="edit-room-layout">
-      <div class="scene">
-        <iframe
-          v-if="current.scenes.length"
-          :src="`${mainURL}/smg.html?m=${current.scenes[0].num}&mobile=true&lang=${returnLocale}`"
-          frameborder="0"
-        />
-        <img v-else :src="unScenePng" />
-      </div>
-      <a-form
-        ref="formRef"
-        class="info"
-        :label-col="{ span: 24 }"
-        :wrapper-col="{ span: 24 }"
-        :model="current"
-      >
-        <h4>{{ t('room.roomInfo') }}</h4>
-        <a-form-item
-          :label="t('room.form.title')"
-          name="title"
-          :rules="[{ required: true, message: t('room.form.titleRequired') }]"
-        >
-          <a-input
-            v-model:value.trim="current.title"
-            :placeholder="t('room.form.titleplaceHolder')"
-            :maxlength="15"
-            show-count
-          />
-        </a-form-item>
-        <a-form-item :label="t('room.form.desc')" name="desc">
-          <a-textarea
-            v-model:value="current.desc"
-            :placeholder="t('room.form.descplaceHolder')"
-            :maxlength="200"
-            show-count
+      </template>
+      <div class="edit-room-layout">
+        <div class="scene">
+          <iframe
+            v-if="current.scenes.length"
+            :src="`${mainURL}/smg.html?m=${current.scenes[0].num}&mobile=true&lang=${returnLocale}`"
+            frameborder="0"
           />
-        </a-form-item>
-        <h4>{{ t('room.form.host') }}</h4>
-        <a-form-item
-          :label="t('room.form.nickname')"
-          name="leaderName"
-          :rules="[
-            { required: true, message: t('room.form.nicknameRequired') },
-            { validator: handleNickRegex }
-          ]"
+          <img v-else :src="unScenePng" />
+        </div>
+        <a-form
+          ref="formRef"
+          class="info"
+          :label-col="{ span: 24 }"
+          :wrapper-col="{ span: 24 }"
+          :model="current"
         >
-          <a-input
-            v-model:value.trim="current.leaderName"
-            :placeholder="t('room.form.nicknameDesc')"
-            :maxlength="15"
-            show-count
+          <h4>{{ t('room.roomInfo') }}</h4>
+          <a-form-item
+            :label="t('room.form.title')"
+            name="title"
+            :rules="[{ required: true, message: t('room.form.titleRequired') }]"
+          >
+            <a-input
+              v-model:value.trim="current.title"
+              :placeholder="t('room.form.titleplaceHolder')"
+              :maxlength="15"
+              show-count
+            />
+          </a-form-item>
+          <a-form-item :label="t('room.form.desc')" name="desc">
+            <a-textarea
+              v-model:value="current.desc"
+              :placeholder="t('room.form.descplaceHolder')"
+              :maxlength="200"
+              show-count
+            />
+          </a-form-item>
+          <h4>{{ t('room.form.host') }}</h4>
+          <a-form-item
+            :label="t('room.form.nickname')"
+            name="leaderName"
+            :rules="[
+              { required: true, message: t('room.form.nicknameRequired') },
+              { validator: handleNickRegex }
+            ]"
+          >
+            <a-input
+              v-model:value.trim="current.leaderName"
+              :placeholder="t('room.form.nicknameDesc')"
+              :maxlength="15"
+              show-count
+            />
+          </a-form-item>
+          <h4>{{ t('room.form.selectScene') }}</h4>
+          <a-form-item
+            :label="t('room.form.addScene')"
+            class="select-scene"
+            name="scenes"
+            style="margin-bottom: 2px"
+          >
+          </a-form-item>
+          <EditScenes
+            :scenes="current.scenes"
+            @delete="deleteScene"
+            @insert="scene => current.scenes.push(scene)"
           />
-        </a-form-item>
-        <h4>{{ t('room.form.selectScene') }}</h4>
-        <a-form-item
-          :label="t('room.form.addScene')"
-          class="select-scene"
-          name="scenes"
-          style="margin-bottom: 2px"
-        >
-        </a-form-item>
-        <EditScenes
-          :scenes="current.scenes"
-          @delete="deleteScene"
-          @insert="scene => current.scenes.push(scene)"
-        />
-        <h4>{{ t('room.form.advanceConfig') }}</h4>
-        <a-form-item
-          label="使用时间"
-          class="select-scene"
-          name="scenes"
-          style="margin-bottom: 2px"
-        >
-        <a-range-picker v-model:value="current.period" />
-        
-        </a-form-item>
-      </a-form>
-    </div>
-  </a-modal>
+          <h4>{{ t('room.form.advanceConfig') }}</h4>
+          <a-form-item
+            label="使用时间"
+            class="select-scene"
+            name="scenes"
+            style="margin-bottom: 2px"
+          >
+            <a-range-picker
+              :show-time="{ format: 'HH:mm' }"
+              format="YYYY-MM-DD HH:mm"
+              style="width: 80%"
+              v-model:value="current.period"
+            />
+          </a-form-item>
+
+          <a-form-item
+            label="设置密码"
+            class="select-scene"
+            name="scenes"
+            style="margin-bottom: 2px"
+          >
+            <v-otp-input
+              class="otp-container"
+              ref="otpInput"
+              input-classes="otp-input"
+              separator="-"
+              :num-inputs="4"
+              :should-auto-focus="true"
+              :is-input-num="true"
+              :conditionalClass="['one', 'two', 'three', 'four']"
+              :placeholder="['*', '*', '*', '*']"
+            />
+          </a-form-item>
+          <a-form-item
+            label="授权"
+            class="select-scene"
+            name="scenes"
+            style="margin-bottom: 2px"
+          >
+            <a-button type="primary" ghost>
+              <template #icon><plus-outlined /></template>添加用户</a-button
+            >
+          </a-form-item>
+          <a-form-item
+            label="设置房间人数"
+            class="select-scene"
+            name="scenes"
+            style="margin-bottom: 2px"
+          >
+            <a-input-number
+              placeholder="请输入房间人数"
+              :min="5"
+              :max="50"
+              style="width: 80%"
+            >
+              <template #addonBefore>
+                <UserOutlined />
+              </template>
+            </a-input-number>
+          </a-form-item>
+
+          <a-form-item
+            label="设置模式"
+            class="select-scene"
+            name="mode"
+            style="margin-bottom: 2px"
+          >
+            <!-- v-model:value="value" -->
+            <a-radio-group name="radioGroup">
+              <a-radio value="1">带看</a-radio>
+              <a-radio value="2">自由观看模式</a-radio>
+            </a-radio-group>
+          </a-form-item>
+        </a-form>
+      </div>
+    </a-modal>
+  </a-config-provider>
 </template>
 
 <script lang="ts">
@@ -121,14 +186,12 @@ import { message } from 'ant-design-vue'
 import { mainURL } from '@/env'
 import EditScenes from './scene-list.vue'
 import unScenePng from '@/assets/images/un-scene.png'
-
+import VOtpInput from 'vue3-otp-input'
 import type { Scene } from '@/store/modules/scene'
 import type { FormInstance } from 'ant-design-vue'
 import { useI18n } from '@/hook/useI18n'
 import { useLocale } from '@/locales/useLocale'
 
-
-
 // const titleValidator = ref({
 //   validator: (_, value) =>
 //     !value.includes(' ')
@@ -138,10 +201,11 @@ import { useLocale } from '@/locales/useLocale'
 
 export default defineComponent({
   name: 'EditRoom',
-  components: { EditScenes },
+  components: { EditScenes, VOtpInput },
   props,
   setup(props) {
     const visible = ref(true)
+    const { getAntdLocale } = useLocale()
     const roomStore = useRoomStore()
     const { getLocale } = useLocale()
     const { t } = useI18n()
@@ -181,9 +245,7 @@ export default defineComponent({
         '^([\u4E00-\uFA29]|[\uE7C7-\uE7F3]|[a-zA-Z0-9_]){1,15}$'
       )
       if (value?.length && !regex.test(value)) {
-        return Promise.reject(
-          t('room.nickNameRegrexError')
-        )
+        return Promise.reject(t('room.nickNameRegrexError'))
       }
       return Promise.resolve('')
     }
@@ -199,7 +261,8 @@ export default defineComponent({
       saveRoom,
       // startSync,
       mainURL,
-      unScenePng
+      unScenePng,
+      getAntdLocale
     }
   }
 })
@@ -208,8 +271,16 @@ export default defineComponent({
 <style lang="scss" scoped>
 .edit-room-layout {
   display: flex;
-  min-width: 864px;
+  max-height: 700px;
+  overflow: hidden;
+
+  .info {
+    max-height: 700px;
+    overflow-y: scroll;
+    overflow-x: hidden;
+  }
 }
+
 .scene {
   flex: none;
   width: 320px;
@@ -302,4 +373,28 @@ export default defineComponent({
   line-height: 1;
   content: '*';
 }
+.otp-container {
+  input::placeholder {
+    font-size: 15px;
+    text-align: center;
+    font-weight: 600;
+  }
+}
+.otp-input {
+  width: 40px;
+  height: 40px;
+  padding: 5px;
+  margin: 0 10px;
+  font-size: 20px;
+  border-radius: 4px;
+  border: 1px solid rgba(0, 0, 0, 0.3);
+  text-align: center;
+  &.is-complete {
+    background-color: #e4e4e4;
+  }
+  &::-webkit-inner-spin-button {
+    -webkit-appearance: none;
+    margin: 0;
+  }
+}
 </style>