CzRger 1 settimana fa
parent
commit
30d6b1d35c

+ 43 - 24
src/components/czr-ui/czr-form-link/datetime.vue

@@ -1,27 +1,37 @@
 <template>
-  <el-date-picker
-    style="width: 100%"
-    :type="type"
-    v-bind="$attrs"
-    v-model="state.paramVal"
-    clearable
-    :placeholder="
-      (typeof $attrs.disabled !== 'undefined' && $attrs.disabled !== false) ||
-      state.formView
-        ? ''
-        : $attrs.placeholder
-          ? $attrs.placeholder
-          : `请选择${label}`
-    "
-    :valueFormat="valueFormat"
-    :format="format"
-    unlink-panels
-    :disabled="isValue($attrs.disabled) ? $attrs.disabled : state.formView"
-  >
-    <template #default="cell">
-      <slot name="default" :cell="cell"></slot>
-    </template>
-  </el-date-picker>
+  <div style="width: 100%">
+    <el-date-picker
+      style="width: 100%; height: 100%"
+      :type="type"
+      v-bind="$attrs"
+      v-model="state.paramVal"
+      clearable
+      :start-placeholder="
+        (typeof $attrs.disabled !== 'undefined' && $attrs.disabled !== false) ||
+        state.formView
+          ? ''
+          : $attrs.placeholder
+            ? $attrs.placeholder + '起始'
+            : `请选择${label}起始`
+      "
+      :end-placeholder="
+        (typeof $attrs.disabled !== 'undefined' && $attrs.disabled !== false) ||
+        state.formView
+          ? ''
+          : $attrs.placeholder
+            ? $attrs.placeholder + '终止'
+            : `请选择${label}终止`
+      "
+      :valueFormat="valueFormat"
+      :format="format"
+      unlink-panels
+      :disabled="isValue($attrs.disabled) ? $attrs.disabled : state.formView"
+    >
+      <template #default="cell">
+        <slot name="default" :cell="cell"></slot>
+      </template>
+    </el-date-picker>
+  </div>
 </template>
 
 <script setup lang="ts">
@@ -59,4 +69,13 @@ watch(
 )
 </script>
 
-<style scoped lang="scss"></style>
+<style scoped lang="scss">
+:deep(.el-range-editor) {
+  .el-range-input {
+    flex: 1;
+  }
+  .el-range-separator {
+    flex: unset !important;
+  }
+}
+</style>

+ 1 - 1
src/layout/top-left/head/index.vue

@@ -10,7 +10,7 @@
           class="menu-item __hover"
           :class="{
             active:
-              $route.matched.some((v) => v.path === item.path) ||
+              $route.matched.some((v) => v.name === item.name) ||
               $route.meta.root === item.name,
           }"
           @click="$router.push(item.path)"

+ 1 - 1
src/router/modules/big-model.ts

@@ -104,7 +104,7 @@ const BigModelRouter = [
   {
     path: '/center',
     name: '3b046708-5a14-450f-9dcd-9d869e336ed7',
-    component: () => import('@/views/manage/app/index_back.vue'),
+    component: () => import('@/views/manage/center/index.vue'),
     meta: {
       title: '管理中心',
     },

+ 9 - 0
src/views/manage/center/api/index.vue

@@ -0,0 +1,9 @@
+<template>API服务管控</template>
+
+<script setup lang="ts">
+import { reactive } from 'vue'
+
+const state: any = reactive({})
+</script>
+
+<style lang="scss" scoped></style>

+ 9 - 0
src/views/manage/center/approve/index.vue

@@ -0,0 +1,9 @@
+<template>审批流程配置管理</template>
+
+<script setup lang="ts">
+import { reactive } from 'vue'
+
+const state: any = reactive({})
+</script>
+
+<style lang="scss" scoped></style>

+ 89 - 3
src/views/manage/center/index.vue

@@ -1,12 +1,98 @@
-<template>管理中心</template>
+<template>
+  <div class="bm-main-box" style="padding: 0">
+    <div class="flex gap-4 px-4 pt-4">
+      <template v-for="item in menus">
+        <div
+          class="__hover flex flex-col items-center"
+          :class="
+            state.menu === item.value
+              ? 'text-base font-bold text-[var(--czr-main-color)]'
+              : 'text-sm text-[#576275]'
+          "
+          @click="
+            () => {
+              state.menu = item.value
+              $router.replace({
+                name: '3b046708-5a14-450f-9dcd-9d869e336ed7',
+                query: { menu: item.value },
+              })
+            }
+          "
+        >
+          <div class="flex h-4 items-center justify-center">
+            {{ item.label }}
+          </div>
+          <div class="mt-1.75 w-full px-2">
+            <div
+              class="h-0.5 w-full"
+              :class="
+                state.menu === item.value ? 'bg-[var(--czr-main-color)]' : ''
+              "
+            />
+          </div>
+        </div>
+      </template>
+    </div>
+    <div class="flex-1">
+      <component :is="menus.filter((v) => v.value === state.menu)[0]?.com" />
+    </div>
+  </div>
+</template>
 
 <script setup lang="ts">
-import { getCurrentInstance, reactive, ref } from 'vue'
+import {
+  defineAsyncComponent,
+  getCurrentInstance,
+  onBeforeMount,
+  reactive,
+  ref,
+} from 'vue'
+import { useRoute } from 'vue-router'
 
+const route = useRoute()
 const emit = defineEmits([])
 const props = defineProps({})
 const { proxy }: any = getCurrentInstance()
-const state: any = reactive({})
+const menus = [
+  {
+    label: '用户管理',
+    value: 'user',
+    com: defineAsyncComponent(() => import('./user/index.vue')),
+  },
+  {
+    label: '租户管理',
+    value: 'tenant',
+    com: defineAsyncComponent(
+      () => import('@/views/manage/center/tenant/index.vue'),
+    ),
+  },
+  {
+    label: '审批流程配置管理',
+    value: 'approve',
+    com: defineAsyncComponent(() => import('./approve/index.vue')),
+  },
+  {
+    label: '安全管理',
+    value: 'safe',
+    com: defineAsyncComponent(() => import('./safe/index.vue')),
+  },
+  {
+    label: 'API服务管控',
+    value: 'api',
+    com: defineAsyncComponent(() => import('./api/index.vue')),
+  },
+]
+const state: any = reactive({
+  menu: null,
+})
+onBeforeMount(() => {
+  const m = route.query.menu
+  if (m && menus.some((v) => v.value === m)) {
+    state.menu = m
+  } else {
+    state.menu = menus[0].value
+  }
+})
 </script>
 
 <style lang="scss" scoped></style>

+ 9 - 0
src/views/manage/center/safe/index.vue

@@ -0,0 +1,9 @@
+<template>安全管理</template>
+
+<script setup lang="ts">
+import { reactive } from 'vue'
+
+const state: any = reactive({})
+</script>
+
+<style lang="scss" scoped></style>

+ 331 - 0
src/views/manage/center/tenant/index.vue

@@ -0,0 +1,331 @@
+<template>
+  <div class="bm-main-box">
+    <div class="flex items-center">
+      <div class="ml-auto flex items-center gap-2.5">
+        <CzrForm class="bm-filter" label-width="0px" @handleEnter="onSearch">
+          <CzrFormColumn
+            width="23rem"
+            class="__czr-table-form-column"
+            :span="24"
+            label-width="0px"
+            v-model:param="state.query.form.time1"
+            link="datetime"
+            type="datetimerange"
+            placeholder="租户启用时间"
+          />
+          <CzrFormColumn
+            width="23rem"
+            class="__czr-table-form-column"
+            :span="24"
+            label-width="0px"
+            v-model:param="state.query.form.time2"
+            link="datetime"
+            type="datetimerange"
+            placeholder="租户到期时间"
+          />
+          <CzrFormColumn
+            width="6.68rem"
+            class="__czr-table-form-column"
+            :span="24"
+            label-width="0px"
+            v-model:param="state.query.form.status"
+            link="select"
+            :options="DictionaryStore.appStatus"
+            placeholder="租户状态"
+          />
+          <CzrFormColumn
+            width="15.63rem"
+            class="__czr-table-form-column"
+            :span="24"
+            label-width="0px"
+            v-model:param="state.text"
+            placeholder="输入关键词以检索"
+            :prefix-icon="Search"
+          />
+          <CzrButton type="add" @click="onAdd" />
+        </CzrForm>
+      </div>
+    </div>
+    <div class="mt-4 flex-1 overflow-hidden" v-loading="state.query.loading">
+      <CzrTableCard
+        class="table-card"
+        :page="state.query.page.pageNum"
+        :pageSize="state.query.page.pageSize"
+        :total="state.query.result.total"
+        :data="state.query.result.data"
+        @handlePage="onPage"
+        :col="4"
+      >
+        <template #model="{ row, index }">
+          <div
+            class="model __hover"
+            @click="
+              $router.push({
+                name: 'e16b6e20-4ea1-4160-9624-e775949b0c32',
+                params: {
+                  id: row.id,
+                },
+              })
+            "
+          >
+            <div class="flex">
+              <template v-if="row.icon">
+                <img :src="row.icon" class="mr-2.5 h-[3.25rem] w-[3.25rem]" />
+              </template>
+              <template v-else>
+                <img
+                  src="@/assets/images/app/app-default-logo.png"
+                  class="mr-2.5 h-[3.25rem] w-[3.25rem]"
+                />
+              </template>
+              <div class="flex flex-1 flex-col overflow-hidden">
+                <div class="flex">
+                  <template v-if="row.status == 0">
+                    <div
+                      class="rounded-xs bg-[#A7ADB9] px-2.5 py-1 text-xs text-white"
+                    >
+                      草稿
+                    </div>
+                  </template>
+                  <template v-else-if="row.status == 1">
+                    <div
+                      class="rounded-xs bg-[#5AD8A6] px-2.5 py-1 text-xs text-white"
+                    >
+                      已发布
+                    </div>
+                  </template>
+                  <template v-if="row.type == 0">
+                    <div
+                      class="ml-auto rounded-2xl bg-gradient-to-r from-[#C3E3FC] to-[#86C4FF] px-3 py-1 text-xs text-[#0876FF]"
+                    >
+                      简洁
+                    </div>
+                  </template>
+                  <template v-else-if="row.type == 1">
+                    <div
+                      class="ml-auto rounded-2xl bg-gradient-to-r from-[#E0DAFF] to-[#BABCFF] px-3 py-1 text-xs text-[#1E3F92]"
+                    >
+                      高级
+                    </div>
+                  </template>
+                </div>
+                <div
+                  class="mt-1.5 text-xl font-bold text-[#2E3238]"
+                  style="line-height: 1.3"
+                  v-title
+                >
+                  {{ row.name }}
+                </div>
+              </div>
+            </div>
+            <div
+              class="mt-3 flex items-center gap-2.5 text-[0.75rem] text-[#6F7889]"
+            >
+              <div>{{ row.userNickName }}</div>
+              <div>|</div>
+              <div>{{ YMDHms(row.updateTime) }}</div>
+              <div class="ml-auto">
+                <el-dropdown :teleported="true">
+                  <SvgIcon name="omit" />
+                  <template #dropdown>
+                    <el-dropdown-menu>
+                      <el-dropdown-item @click="onCopy(row)">
+                        创建副本
+                      </el-dropdown-item>
+                      <el-dropdown-item @click="onEdit(row)">
+                        设置
+                      </el-dropdown-item>
+                      <el-dropdown-item @click="onDel(row)">
+                        删除
+                      </el-dropdown-item>
+                      <template v-if="row.status == 1">
+                        <el-dropdown-item @click="onMonitor(row)">
+                          监测
+                        </el-dropdown-item>
+                      </template>
+                    </el-dropdown-menu>
+                  </template>
+                </el-dropdown>
+              </div>
+            </div>
+          </div>
+        </template>
+      </CzrTableCard>
+    </div>
+    <!--    <detailCom-->
+    <!--      v-model:show="state.detail.show"-->
+    <!--      :transfer="state.detail.transfer"-->
+    <!--      @refresh="onSearch"-->
+    <!--    />-->
+  </div>
+</template>
+
+<script setup lang="ts">
+import { getCurrentInstance, onMounted, reactive, ref, watch } from 'vue'
+import { Search } from '@element-plus/icons-vue'
+import { debounce } from 'lodash'
+import { useAppStore, useDialogStore, useDictionaryStore } from '@/stores'
+import { ElMessage } from 'element-plus'
+// import detailCom from './detail.vue'
+import {
+  pluginDel,
+  pluginGetInstanceList,
+  pluginUpdateStatus,
+} from '@/api/modules/model'
+import { YMDHms } from '@/utils/czr-util'
+import SvgIcon from '@/components/SvgIcon/index.vue'
+import { useRouter } from 'vue-router'
+import { appDel, appSearch } from '@/api/modules/app'
+
+const router = useRouter()
+const AppStore = useAppStore()
+const DialogStore = useDialogStore()
+const DictionaryStore = useDictionaryStore()
+const emit = defineEmits([])
+const props = defineProps({})
+const { proxy }: any = getCurrentInstance()
+const state: any = reactive({
+  text: '',
+  query: {
+    init: false,
+    loading: false,
+    page: {
+      pageNum: 1,
+      pageSize: 20,
+    },
+    form: {},
+    formReal: {},
+    result: {
+      total: 0,
+      data: [],
+    },
+  },
+  detail: {
+    show: false,
+    transfer: {},
+  },
+})
+const setText = debounce((v) => {
+  state.query.form.keyword = v
+}, 1000)
+watch(
+  () => state.text,
+  (n) => {
+    setText(n)
+  },
+)
+watch(
+  () => state.query.form,
+  (n) => {
+    if (state.query.init) {
+      onSearch()
+    }
+  },
+  { deep: true },
+)
+const onPage = (pageNum, pageSize) => {
+  setTimeout(() => {
+    state.query.init = true
+  }, 100)
+  state.query.page = {
+    pageNum: pageNum,
+    pageSize: pageSize,
+  }
+  const params = {
+    page: state.query.page.pageNum,
+    size: state.query.page.pageSize,
+  }
+  //  添加表单参数
+  for (const [k, v] of Object.entries(state.query.formReal)) {
+    if (proxy.$czrUtil.isValue(v)) {
+      params[k] = v
+    }
+  }
+  state.query.loading = true
+  appSearch(params)
+    .then(({ data }: any) => {
+      state.query.result.total = data.total
+      state.query.result.data = data.records
+    })
+    .catch(() => {})
+    .finally(() => {
+      state.query.loading = false
+    })
+}
+const onSearch = () => {
+  state.query.formReal = JSON.parse(JSON.stringify(state.query.form))
+  onPage(1, state.query.page.pageSize)
+}
+const onReset = () => {
+  state.query.page = {
+    pageNum: 1,
+    pageSize: 20,
+  }
+  state.query.form = {}
+  onSearch()
+}
+const onAdd = () => {
+  state.detail.transfer = {
+    mode: 'add',
+  }
+  state.detail.show = true
+}
+const onCopy = (row) => {
+  state.detail.transfer = {
+    mode: 'copy',
+    id: row.id,
+  }
+  state.detail.show = true
+}
+const onEdit = (row) => {
+  state.detail.transfer = {
+    mode: 'edit',
+    id: row.id,
+  }
+  state.detail.show = true
+}
+const onDel = (row: any) => {
+  DialogStore.confirm({
+    title: '删除确认',
+    content: `请确认是否删除`,
+    onSubmit: () => {
+      appDel(row.id)
+        .then(() => {
+          ElMessage.success('删除成功!')
+        })
+        .catch(() => {})
+        .finally(() => {
+          onSearch()
+        })
+    },
+  })
+}
+const onMonitor = (row) => {
+  router.push({
+    name: 'a36ccd46-f399-4bf6-8db9-157ca8d3e8c8',
+    params: {
+      id: row.id,
+    },
+  })
+}
+onMounted(() => {
+  initDictionary()
+  onReset()
+})
+const initDictionary = () => {}
+</script>
+
+<style lang="scss" scoped>
+.model {
+  width: 100%;
+  background-image: url('@/assets/images/model/model-icon-7.png');
+  background-repeat: no-repeat;
+  background-size: 100% 100%;
+  padding: 1rem;
+  border-radius: 10px;
+  box-shadow: 0rem 0.25rem 0.63rem 0rem rgba(40, 83, 247, 0.05);
+  border: var(--czr-border);
+  display: flex;
+  flex-direction: column;
+}
+</style>

+ 9 - 0
src/views/manage/center/user/index.vue

@@ -0,0 +1,9 @@
+<template>用户管理</template>
+
+<script setup lang="ts">
+import { reactive } from 'vue'
+
+const state: any = reactive({})
+</script>
+
+<style lang="scss" scoped></style>