DESKTOP-HN5QP3V\Administrator 1 месяц назад
Родитель
Сommit
4fd01a094b

+ 6 - 0
.idea/MarsCodeWorkspaceAppSettings.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="com.codeverse.userSettings.MarscodeWorkspaceAppSettingsState">
+    <option name="progress" value="1.0" />
+  </component>
+</project>

+ 26 - 5
mock/role/index.mock.ts

@@ -17,13 +17,34 @@ const adminList = [
     children: [
       {
         path: 'version',
-        component: 'views/Version/Version',
-        name: 'VersionList',
+        name: 'VersionRoot',
+        redirect: '/version/version/version_server',
+        component: '#',
         meta: {
           title: 'router.version_list',
-          noCache: true,
-          affix: true
-        }
+          alwaysShow: true
+        },
+        children: [
+          {
+            path: 'version_server',
+            component: 'views/Version/VersionServer',
+            name: 'VersionServer',
+            meta: {
+              title: 'router.version_server',
+              noCache: true,
+              affix: true
+            }
+          },
+          {
+            path: 'version_client',
+            component: 'views/Version/VersionClient',
+            name: 'VersionClient',
+            meta: {
+              title: 'router.version_client',
+              noCache: true
+            }
+          }
+        ]
       },
       {
         path: 'test',

+ 17 - 1
src/api/version/index.ts

@@ -1,5 +1,5 @@
 import request from '@/axios'
-import type { VersionData } from './types'
+import { HotVersionData, VersionData } from './types'
 
 export const getVersionListApi = (params: any) => {
   return request.get({ url: '/web/v1/versions', params })
@@ -28,3 +28,19 @@ export const test1VersionApi = (data) => {
 export const test2VersionApi = () => {
   return request.post({ url: `/api/v1/version/server` })
 }
+
+export const getHotVersionListApi = (params: any) => {
+  return request.get({ url: '/internal/getversionlist', params })
+}
+
+export const newHotVersionApi = (data: Partial<HotVersionData>): Promise<IResponse> => {
+  return request.post({ url: '/internal/addversion', data })
+}
+
+export const editHotVersionApi = (data: Partial<HotVersionData>): Promise<IResponse> => {
+  return request.put({ url: '/internal/changestatus', data })
+}
+
+export const delHotVersionApi = (key: any): Promise<IResponse> => {
+  return request.delete({ url: `/internal/version/${key}` })
+}

+ 11 - 0
src/api/version/types.ts

@@ -13,3 +13,14 @@ export type VersionData = {
   name: string
   default: boolean
 }
+
+export type HotVersionData = {
+  id: any
+  proj: string
+  os: string
+  version: string
+  packageUrl: string
+  remoteManifestUrl: string
+  remoteVersionUrl: string
+  status: number
+}

+ 19 - 1
src/locales/zh-CN.ts

@@ -121,6 +121,8 @@ export default {
     login: '登录',
     version: '版本管理',
     version_list: '版本列表',
+    version_server: '后端版本',
+    version_client: '前端版本',
     version_test: '接口测试',
     level: '多级菜单',
     menu: '菜单',
@@ -231,7 +233,7 @@ export default {
     pushCode: 'Archer 推送 代码到 Github',
     follow: '关注'
   },
-  version: {
+  version_server: {
     title: '描述',
     number: '版本号',
     url: 'gm地址',
@@ -241,6 +243,22 @@ export default {
     edit: '版本修改',
     new: '新增版本',
     delete: '删除',
+    refresh: '刷新',
+    channelSelect: '渠道选择',
+    allChannels: '全部渠道',
+    confirm: '确定'
+  },
+  version_client: {
+    proj: '项目',
+    os: '平台',
+    packageUrl: '包地址',
+    remoteManifestUrl: '远程资源',
+    remoteVersionUrl: '远程版本',
+    default: '状态',
+    action: '操作',
+    edit: '版本修改',
+    new: '新增版本',
+    delete: '删除',
     refresh: '刷新'
   },
   formDemo: {

+ 26 - 5
src/router/index.ts

@@ -60,7 +60,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
     path: '/version',
     name: 'Version',
     component: Layout,
-    redirect: '/version/version',
+    redirect: '/version/version/version_server',
     meta: {
       title: t('router.version'),
       icon: 'vi-cib:telegram-plane',
@@ -69,12 +69,33 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
     children: [
       {
         path: 'version',
-        component: () => import('@/views/Version/Version.vue'),
-        name: 'VersionView',
+        name: 'VersionRoot',
+        component: Layout, // 🔥 这里变成父级
+        redirect: '/version/version/version_server',
         meta: {
           title: t('router.version_list'),
-          noCache: true
-        }
+          alwaysShow: true
+        },
+        children: [
+          {
+            path: 'version_server',
+            name: 'VersionServer',
+            component: () => import('@/views/Version/VersionServer.vue'),
+            meta: {
+              title: t('router.version_server'),
+              noCache: true
+            }
+          } /*,
+          {
+            path: 'version_client',
+            name: 'VersionClient',
+            component: () => import('@/views/Version/VersionClient.vue'),
+            meta: {
+              title: t('router.version_client'),
+              noCache: true
+            }
+          }*/
+        ]
       },
       {
         path: 'test',

+ 248 - 0
src/views/Version/VersionClient.vue

@@ -0,0 +1,248 @@
+<script setup lang="tsx">
+import { ElButton, ElSwitch, ElDrawer, ElForm, ElFormItem, ElInput } from 'element-plus'
+import { ContentWrap } from '@/components/ContentWrap'
+import { useI18n } from '@/hooks/web/useI18n'
+import { Table, TableColumn } from '@/components/Table'
+import { HotVersionData } from '@/api/version/types'
+import { ref, h, reactive } from 'vue'
+import { BaseButton } from '@/components/Button'
+import { editHotVersionApi, getHotVersionListApi, newHotVersionApi } from '@/api/version'
+
+interface Params {
+  pageIndex?: number
+  pageSize?: number
+}
+
+const { t } = useI18n()
+
+const columns: TableColumn[] = [
+  {
+    field: 'proj',
+    label: t('version_client.proj')
+  },
+  {
+    field: 'os',
+    label: t('version_client.os')
+  },
+  {
+    field: 'packageUrl',
+    label: t('version_client.packageUrl')
+  },
+  {
+    field: 'remoteManifestUrl',
+    label: t('version_client.remoteManifestUrl')
+  },
+  {
+    field: 'remoteVersionUrl',
+    label: t('version_client.remoteVersionUrl')
+  },
+  {
+    field: 'default',
+    label: t('version_client.default'),
+    slots: {
+      default: (data) => {
+        return (
+          <ElSwitch
+            modelValue={data.row.default}
+            onUpdate:modelValue={(val) => updateDefaultStatus(data.row, val)}
+            class="ml-2"
+            style="--ElSwitch-on-color: #13ce66; --ElSwitch-off-color: #ff4949"
+          />
+        )
+      }
+    }
+  },
+  {
+    field: 'action',
+    label: t('version_client.action'),
+    slots: {
+      default: (data) => {
+        return (
+          <>
+            <BaseButton type="primary" onClick={() => actionFn('edit', data.row)}>
+              {t('version_client.action')}
+            </BaseButton>
+          </>
+        )
+      }
+    }
+  }
+]
+const drawer = ref(false)
+const loading = ref(true)
+const drawerText = ref('')
+
+const versionDataList = ref<HotVersionData[]>([])
+
+const form = reactive({
+  type: 'new',
+  data: {
+    id: '',
+    proj: '',
+    os: '',
+    packageUrl: '',
+    remoteManifestUrl: '',
+    remoteVersionUrl: '',
+    status: 0
+  }
+})
+
+const formReset = () => {
+  form.data.id = ''
+  form.data.proj = ''
+  form.data.os = ''
+  form.data.packageUrl = ''
+  form.data.remoteManifestUrl = ''
+  form.data.remoteVersionUrl = ''
+  form.data.status = 0
+}
+
+const getVersionList = async (params?: Params) => {
+  const res = await getHotVersionListApi(
+    params || {
+      start: 1,
+      limit: 10
+    }
+  )
+    .catch(() => {})
+    .finally(() => {
+      loading.value = false
+    })
+
+  if (res) {
+    versionDataList.value = res.data
+  }
+}
+
+const newVersion = async () => {
+  await newHotVersionApi(form.data)
+    .catch(() => {})
+    .finally(() => {
+      loading.value = false
+    })
+}
+
+// const deleteVersion = async (key) => {
+//   await delVersionApi(key)
+//     .catch(() => {})
+//     .finally(() => {
+//       loading.value = false
+//     })
+// }
+
+const editVersion = async (params) => {
+  await editHotVersionApi(params)
+    .catch(() => {})
+    .finally(() => {
+      loading.value = false
+    })
+}
+
+getVersionList()
+
+const updateDefaultStatus = async (row: HotVersionData, val) => {
+  row.status = val
+  const params = {
+    id: row.id.id,
+    version: '',
+    status: 0
+  }
+  params.version = row.version
+  params.status = row.status
+  await editHotVersionApi(params)
+  getVersionList()
+
+  console.log(`更新版本 ${row.version} 的 default 状态为: ${val}`)
+}
+
+const onSubmit = async () => {
+  if (form.type === 'new') {
+    await newVersion()
+  } else {
+    await editVersion(form.data)
+  }
+
+  drawer.value = !drawer.value
+  getVersionList()
+}
+
+// const deleteFn = async (data: any) => {
+//   // deleteVersion(data.id.id)
+//   getVersionList()
+// }
+
+// const syncVersion = async () => {
+//   await syncVersionApi()
+//     .catch(() => {})
+//     .finally(() => {
+//       loading.value = false
+//     })
+// }
+
+const actionFn = (type: string, data: any) => {
+  if (type == 'new') {
+    formReset()
+    form.type = 'new'
+    drawerText.value = t('version_client.new')
+  }
+  if (type == 'edit') {
+    form.type = 'edit'
+    drawerText.value = t('version_client.edit')
+    form.data.id = data.id.id
+    form.data.proj = data.proj
+    form.data.os = data.os
+    form.data.packageUrl = data.packageUrl
+    form.data.remoteManifestUrl = data.remoteManifestUrl
+    form.data.remoteVersionUrl = data.remoteVersionUrl
+  }
+  drawer.value = !drawer.value
+}
+
+const closeDrawer = () => {
+  drawer.value = false
+}
+</script>
+
+<template>
+  <ContentWrap>
+    <div style="display: flex; justify-content: space-between; align-items: center">
+      <ElButton type="primary" @click="() => actionFn('new', null)">
+        {{ t('version_client.new') }}
+      </ElButton>
+    </div>
+  </ContentWrap>
+  <ContentWrap>
+    <Table
+      :columns="columns"
+      :data="versionDataList"
+      :loading="loading"
+      :defaultSort="{ prop: 'display_time', order: 'descending' }"
+    />
+  </ContentWrap>
+  <ElDrawer v-model="drawer" direction="rtl" size="40%" :z-index="4000">
+    <template #header>
+      <span class="text-16px font-700">{{ drawerText }}</span>
+    </template>
+    <ElForm :model="form" label-width="auto" style="max-width: 600px">
+      <ElFormItem :label="t('version_client.proj')">
+        <ElInput v-model="form.data.proj" />
+      </ElFormItem>
+      <ElFormItem :label="t('version_client.os')">
+        <el-input v-model="form.data.os" />
+      </ElFormItem>
+      <ElFormItem :label="t('version_client.packageUrl')">
+        <el-input v-model="form.data.packageUrl" />
+      </ElFormItem>
+      <ElFormItem :label="t('version_client.remoteManifestUrl')">
+        <el-input v-model="form.data.remoteManifestUrl" />
+      </ElFormItem>
+      <ElFormItem :label="t('version_client.remoteVersionUrl')">
+        <el-input v-model="form.data.remoteVersionUrl" />
+      </ElFormItem>
+      <ElFormItem>
+        <el-button type="primary" @click="onSubmit">确定</el-button>
+        <el-button @click="closeDrawer">取消</el-button>
+      </ElFormItem>
+    </ElForm>
+  </ElDrawer>
+</template>

+ 71 - 21
src/views/Version/Version.vue → src/views/Version/VersionServer.vue

@@ -1,10 +1,20 @@
 <script setup lang="tsx">
-import { ElButton, ElSwitch, ElDrawer, ElForm, ElFormItem, ElInput, ElTooltip } from 'element-plus'
+import {
+  ElButton,
+  ElSwitch,
+  ElDrawer,
+  ElForm,
+  ElFormItem,
+  ElInput,
+  ElTooltip,
+  ElSelect,
+  ElOption
+} from 'element-plus'
 import { ContentWrap } from '@/components/ContentWrap'
 import { useI18n } from '@/hooks/web/useI18n'
 import { Table, TableColumn } from '@/components/Table'
 import { VersionData } from '@/api/version/types'
-import { ref, h, reactive } from 'vue'
+import { ref, h, reactive, computed } from 'vue'
 import { Connection } from '@element-plus/icons-vue'
 import { BaseButton } from '@/components/Button'
 import {
@@ -25,23 +35,23 @@ const { t } = useI18n()
 const columns: TableColumn[] = [
   {
     field: 'name',
-    label: t('version.title')
+    label: t('version_server.title')
   },
   {
     field: 'version',
-    label: t('version.number')
+    label: t('version_server.number')
   },
   {
     field: 'url',
-    label: t('version.url')
+    label: t('version_server.url')
   },
   {
     field: 'cdn',
-    label: t('version.cdn')
+    label: t('version_server.cdn')
   },
   {
     field: 'default',
-    label: t('version.default'),
+    label: t('version_server.default'),
     slots: {
       default: (data) => {
         return (
@@ -57,16 +67,16 @@ const columns: TableColumn[] = [
   },
   {
     field: 'action',
-    label: t('version.action'),
+    label: t('version_server.action'),
     slots: {
       default: (data) => {
         return (
           <>
             <BaseButton type="primary" onClick={() => actionFn('edit', data.row)}>
-              {t('version.action')}
+              {t('version_server.action')}
             </BaseButton>
             <BaseButton type="danger" onClick={() => deleteFn(data.row)}>
-              {t('version.delete')}
+              {t('version_server.delete')}
             </BaseButton>
           </>
         )
@@ -79,6 +89,21 @@ const loading = ref(true)
 const drawerText = ref('')
 
 const versionDataList = ref<VersionData[]>([])
+const selectedChannel = ref<string>('wx')
+const appliedChannel = ref<string>('wx')
+
+// 渠道选项:写死 wx 和 抖音
+const channelOptions = ['wx', '抖音']
+
+// 根据渠道筛选后的列表(点击确定后应用)
+const filteredVersionList = computed(() => {
+  if (!appliedChannel.value) return versionDataList.value
+  return versionDataList.value.filter((item) => item.name === appliedChannel.value)
+})
+
+const applyChannelFilter = () => {
+  appliedChannel.value = selectedChannel.value
+}
 
 const form = reactive({
   type: 'new',
@@ -187,11 +212,11 @@ const actionFn = (type: string, data: any) => {
   if (type == 'new') {
     formReset()
     form.type = 'new'
-    drawerText.value = t('version.new')
+    drawerText.value = t('version_server.new')
   }
   if (type == 'edit') {
     form.type = 'edit'
-    drawerText.value = t('version.edit')
+    drawerText.value = t('version_server.edit')
     form.data.id = data.id.id
     form.data.cdn = data.cdn
     form.data.url = data.url
@@ -209,10 +234,35 @@ const closeDrawer = () => {
 
 <template>
   <ContentWrap>
-    <div style="display: flex; justify-content: space-between; align-items: center">
-      <ElButton type="primary" @click="() => actionFn('new', null)">
-        {{ t('version.new') }}
-      </ElButton>
+    <div
+      style="
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        flex-wrap: wrap;
+        gap: 12px;
+      "
+    >
+      <div style="display: flex; align-items: center; gap: 12px">
+        <ElButton type="primary" @click="() => actionFn('new', null)">
+          {{ t('version_server.new') }}
+        </ElButton>
+        <div style="display: flex; align-items: center; gap: 8px">
+          <span style="font-size: 14px; color: var(--el-text-color-regular)">
+            {{ t('version_server.channelSelect') }}:
+          </span>
+          <ElSelect
+            v-model="selectedChannel"
+            :placeholder="t('version_server.channelSelect')"
+            style="width: 180px"
+          >
+            <ElOption v-for="opt in channelOptions" :key="opt" :label="opt" :value="opt" />
+          </ElSelect>
+          <ElButton type="primary" @click="applyChannelFilter">
+            {{ t('version_server.confirm') }}
+          </ElButton>
+        </div>
+      </div>
       <ElTooltip content="同步版本列表" placement="top">
         <ElButton type="primary" circle @click="() => syncVersion()">
           <template #icon>
@@ -225,7 +275,7 @@ const closeDrawer = () => {
   <ContentWrap>
     <Table
       :columns="columns"
-      :data="versionDataList"
+      :data="filteredVersionList"
       :loading="loading"
       :defaultSort="{ prop: 'display_time', order: 'descending' }"
     />
@@ -235,16 +285,16 @@ const closeDrawer = () => {
       <span class="text-16px font-700">{{ drawerText }}</span>
     </template>
     <ElForm :model="form" label-width="auto" style="max-width: 600px">
-      <ElFormItem :label="t('version.title')">
+      <ElFormItem :label="t('version_server.title')">
         <ElInput v-model="form.data.name" />
       </ElFormItem>
-      <ElFormItem :label="t('version.number')">
+      <ElFormItem :label="t('version_server.number')">
         <el-input v-model="form.data.version" />
       </ElFormItem>
-      <ElFormItem :label="t('version.url')">
+      <ElFormItem :label="t('version_server.url')">
         <el-input v-model="form.data.url" />
       </ElFormItem>
-      <ElFormItem :label="t('version.cdn')">
+      <ElFormItem :label="t('version_server.cdn')">
         <el-input v-model="form.data.cdn" />
       </ElFormItem>
       <ElFormItem>

+ 4 - 0
vite.config.ts

@@ -146,6 +146,10 @@ export default ({ command, mode }: ConfigEnv): UserConfig => {
         '/api/v1': {
           target: 'http://127.0.0.1:8765',
           changeOrigin: true,
+        },
+        '/internal': {
+          target: 'http://127.0.0.1:8765',
+          changeOrigin: true,
         }
       },
       hmr: {