019e51eac5228b87f85b4602cd21bc7f5c5d7665..fd13b0017518273406ee1a9906c07d079e4a9ac4
2024-11-27 houzhongjian
租户列表 套餐宽度固定180
fd13b0 对比 | 目录
2024-11-27 houzhongjian
进入应用事件修改 租户套餐分页位置调整
bc910a 对比 | 目录
2024-11-27 houzhongjian
修改进入脚手架菜单缓存
3f4d4e 对比 | 目录
2024-11-27 houzhongjian
Merge remote-tracking branch 'origin/master'
533610 对比 | 目录
2024-11-27 houzhongjian
修改home页样式
0eebf7 对比 | 目录
2024-11-27 dengzedong
loading bug
e0b3e4 对比 | 目录
2024-11-27 houzhongjian
修改条件查询列表数据不变bug
e7a566 对比 | 目录
2024-11-27 houzhongjian
排查并解决租户套餐列表不展示并且卡死浏览器的bug
2346dc 对比 | 目录
2024-11-27 dengzedong
predictLength
9b24e4 对比 | 目录
2024-11-27 houzhongjian
解决双重遍历index定义重复bug
4c081a 对比 | 目录
2024-11-27 houzhongjian
Merge remote-tracking branch 'origin/master'
9e876a 对比 | 目录
2024-11-27 houzhongjian
1、修改首页 2、修改租户套餐页面 3、修改logo图标 4、点击左上角平台名称和logo,展示所有菜单等
94d91d 对比 | 目录
2024-11-25 Jay
测点启用和禁用
aba8b4 对比 | 目录
2024-11-25 Jay
测点启用和禁用
616b13 对比 | 目录
2024-11-25 Jay
测点导入和导出
5d8c73 对比 | 目录
2024-11-22 dengzedong
pyd配置不可修改
627a6b 对比 | 目录
2024-11-22 潘志宝
运行耗时(ms)
f2de70 对比 | 目录
2024-11-22 潘志宝
预测项输出描述
32396c 对比 | 目录
2024-11-22 潘志宝
MEASURE_VALUE_TYPE
df90c0 对比 | 目录
2024-11-22 Jay
Merge remote-tracking branch 'origin/master'
328968 对比 | 目录
2024-11-12 Jay
计划数据导出功能问题解决,新增查询loading功能
3f10e7 对比 | 目录
已修改25个文件
已删除2个文件
已添加1个文件
3241 ■■■■■ 文件已修改
index.html 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pnpm-lock.yaml 2574 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/favicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
public/logo.gif 补丁 | 查看 | 原始文档 | blame | 历史
src/api/data/da/point/index.ts 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/data/plan/item/index.ts 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/system/tenantPackage/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/imgs/logo.png 补丁 | 查看 | 原始文档 | blame | 历史
src/config/axios/index.ts 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/hooks/web/useCache.ts 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/hooks/web/useMessage.ts 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/Logo/src/Logo.vue 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/locales/zh-CN.ts 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/modules/user.ts 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Home/Index.vue 92 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/data/plan/item/ItemChart.vue 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/data/point/DaPointChart.vue 51 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/data/point/index.vue 66 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/micro/index.vue 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/model/mpk/file/MpkForm.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/model/mpk/file/MpkRun.vue 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/model/pre/analysis/index.vue 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/model/pre/item/MmPredictItemForm.vue 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/model/pre/item/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/report/drag/index.vue 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/tenant/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/tenantPackage/TenantPackageForm.vue 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/tenantPackage/index.vue 235 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
index.html
@@ -2,7 +2,7 @@
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" href="/favicon.ico" />
    <link rel="icon" href="/src/assets/imgs/logo.png" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta
@@ -136,7 +136,7 @@
      <div class="app-loading">
        <div class="app-loading-wrap">
          <div class="app-loading-title">
            <img src="/logo.gif" class="app-loading-logo" alt="Logo" />
            <img src="/src/assets/imgs/logo.png" class="app-loading-logo" alt="Logo" />
            <div class="app-loading-title">%VITE_APP_TITLE%</div>
          </div>
          <div class="app-loading-item">
pnpm-lock.yaml
文件太大
public/favicon.ico
Binary files differ
public/logo.gif
Binary files differ
src/api/data/da/point/index.ts
@@ -23,6 +23,7 @@
  pointName?: string
}
// 查询DaPoint列表
export const getDaPointPage = (params: DaPointPageReqVO) => {
  return request.get({ url: '/data/da/point/page', params })
@@ -62,3 +63,15 @@
export const importPointTemplate = () => {
  return request.download({ url: '/data/da/point/get-import-template' })
}
// 启用
export const enable = (ids) => {
  const data = ids
  return request.put({ url: '/data/da/point/enable', data })
}
// 禁用
export const disable = (ids) => {
  const data = ids
  return request.put({ url: '/data/da/point/disable', data })
}
src/api/data/plan/item/index.ts
@@ -60,5 +60,5 @@
// 导出Plan值
export const exportPlanValue = (data: PlanChartReqVO) => {
  return request.post({ url: '/data/api/export-plan/history-value', data })
  return request.downloadByPost({ url: '/data/api/export-plan/history-value', data })
}
src/api/system/tenantPackage/index.ts
@@ -4,6 +4,9 @@
  id: number
  name: string
  status: number
  icon: string
  labels: string
  description: string
  remark: string
  creator: string
  updater: string
src/assets/imgs/logo.png

src/config/axios/index.ts
@@ -43,6 +43,10 @@
    const res = await request({ method: 'GET', responseType: 'blob', ...option })
    return res as unknown as Promise<T>
  },
  downloadByPost: async <T = any>(option: any) => {
    const res = await request({ method: 'POST', responseType: 'blob', ...option })
    return res as unknown as Promise<T>
  },
  upload: async <T = any>(option: any) => {
    option.headersType = 'multipart/form-data'
    const res = await request({ method: 'POST', ...option })
src/hooks/web/useCache.ts
@@ -37,3 +37,19 @@
  wsCache.delete(CACHE_KEY.ROLE_ROUTERS)
  // 注意,不要清理 LoginForm 登录表单
}
export const useSessionCache = (type: CacheType = 'sessionStorage') => {
  const wsSessionCache: WebStorageCache = new WebStorageCache({
    storage: type
  })
  return {
    wsSessionCache
  }
}
export const deleteUserSessionCache = () => {
  const { wsSessionCache } = useSessionCache()
  wsSessionCache.delete(CACHE_KEY.ROLE_ROUTERS)
  // 注意,不要清理 用户和 LoginForm 登录表单
}
src/hooks/web/useMessage.ts
@@ -90,6 +90,30 @@
        cancelButtonText: t('common.cancel'),
        type: 'warning'
      })
    },
    // 启用窗体
    enableConfirm(ids, content?: string, tip?: string) {
      return ElMessageBox.confirm(
        content ? content : t('确定启用选中的'+ ids.length +'项数据?'),
        tip ? tip : t('common.confirmTitle'),
        {
          confirmButtonText: t('common.ok'),
          cancelButtonText: t('common.cancel'),
          type: 'warning'
        }
      )
    },
    // 禁用窗体
    disableConfirm(ids, content?: string, tip?: string) {
      return ElMessageBox.confirm(
        content ? content : t('确定禁用选中的'+ ids.length +'项数据?'),
        tip ? tip : t('common.confirmTitle'),
        {
          confirmButtonText: t('common.ok'),
          cancelButtonText: t('common.cancel'),
          type: 'warning'
        }
      )
    }
  }
}
src/layout/components/Logo/src/Logo.vue
@@ -1,8 +1,14 @@
<script lang="ts" setup>
import { computed, onMounted, ref, unref, watch } from 'vue'
import { useAppStore } from '@/store/modules/app'
import { useUserStoreWithOut } from '@/store/modules/user'
import { usePermissionStoreWithOut } from '@/store/modules/permission'
import { useDesign } from '@/hooks/web/useDesign'
import * as authUtil from "@/utils/auth";
import {isRelogin} from "@/config/axios/service";
import router from "@/router";
import type {RouteRecordRaw} from "vue-router";
import {CACHE_KEY, useCache} from "@/hooks/web/useCache";
const { wsCache } = useCache()
defineOptions({ name: 'Logo' })
@@ -59,6 +65,22 @@
    }
  }
)
/** 刷新所有菜单权限 */
const gotoHome = async () => {
  const userStore = useUserStoreWithOut()
  const permissionStore = usePermissionStoreWithOut()
  isRelogin.show = true
  wsCache.set(CACHE_KEY.USER, null)
  await userStore.setUserInfoAction()
  isRelogin.show = false
  // 后端过滤菜单
  await permissionStore.generateRoutes()
  permissionStore.getAddRouters.forEach((route) => {
    router.addRoute(route as unknown as RouteRecordRaw) // 动态添加可访问路由表
  })
}
</script>
<template>
@@ -69,6 +91,7 @@
        layout !== 'classic' ? `${prefixCls}__Top` : '',
        'flex !h-[var(--logo-height)] items-center cursor-pointer pl-8px relative decoration-none overflow-hidden'
      ]"
      @click="gotoHome"
      :to="homePath"
    >
      <img
src/locales/zh-CN.ts
@@ -54,7 +54,9 @@
    updateTime: '更新时间',
    copy: '复制',
    copySuccess: '复制成功',
    copyError: '复制失败'
    copyError: '复制失败',
    enableSuccess: '启用成功',
    disableSuccess: '禁用成功',
  },
  lock: {
    lockScreen: '锁定屏幕',
src/store/modules/user.ts
@@ -61,6 +61,7 @@
      this.roles = userInfo.roles
      this.user = userInfo.user
      this.isSetUser = true
      console.log(userInfo.menus)
      wsCache.set(CACHE_KEY.USER, userInfo)
      wsCache.set(CACHE_KEY.ROLE_ROUTERS, userInfo.menus)
    },
src/views/Home/Index.vue
@@ -1,13 +1,20 @@
<template>
  <div>
    <h1>IAILAB 平台主页</h1>
  <div id="title">
    <span>工业互联网平台</span>
  </div>
  <el-skeleton :loading="loading" animated>
    <div id="app" v-for="(item, index) in appList" :key="`dynamics-${index}`">
      <div class="card" @click="gotoApp(item)">
        <img :src="item.icon" style="width: 100px; height: 100px"/>
    <div id="app">
      <div class="card" v-for="(item, index) in appList" :key="`dynamics-${index}`">
        <div>
          {{ item.appName }}
          <img class="card-left" :src="item.icon"/>
          <div class="card-right">
            <div class="app-title">
              {{ item.appName }}
            </div>
            <div class="goto-app" @click="gotoApp(item)">
              <div>进入应用</div>
            </div>
          </div>
        </div>
      </div>
    </div>
@@ -78,24 +85,63 @@
</script>
<style lang="scss" scoped>
#app {
  width: 300px;
  height: 200px;
  display: inline-block;
  background: transparent;
#title {
  width: 280px;
  height: 51px;
  margin: 30px auto;
  font-family: Microsoft YaHei UI, Microsoft YaHei UI;
  font-weight: bold;
  font-size: 40px;
  color: #282F3D;
}
#app {
  margin: 0 96px;
  width: 100%;
}
.card {
  border: thin dashed gainsboro;
  width: 150px;
  height: 120px;
  padding: 30px;
  text-align: center;
  justify-content: center;
  font-size: 15px;
  font-weight: bolder;
  color: blue;
  background: aliceblue;
  border-radius: 10px;
  width: 354px;
  height: 200px;
  margin: 0 24px 24px 0;
  background: linear-gradient( 180deg, #E9F0FA 0%, #FFFFFF 100%);
  border-radius: 12px 12px 12px 12px;
  border: 2px solid;
  border-image: linear-gradient(180deg, rgba(255, 255, 255, 1), rgba(255, 255, 255, 1)) 2 2;
  display: inline-block;
}
.card > div{
  display: inline-block;
}
.card-left{
  height: 100px;
  width: 100px;
  float: left;
  margin: 50px 30px;
}
.card-right {
  float: right;
  margin: 61px 10px;
}
.app-title {
  width: 162px;
  font-family: Microsoft YaHei, Microsoft YaHei;
  font-weight: bold;
  font-size: 24px;
  color: #282F3D;
}
.goto-app {
  width: 96px;
  height: 35px;
  margin-top: 5px;
  background: #3A99FD;
  border-radius: 80px 80px 80px 80px;
  cursor: pointer;
}
.goto-app > div {
  padding: 6px;
  margin-left: 5px;
  font-family: Microsoft YaHei UI, Microsoft YaHei UI;
  font-weight: 400;
  font-size: 18px;
  color: #FFFFFF;
}
</style>
src/views/data/plan/item/ItemChart.vue
@@ -44,7 +44,7 @@
        </el-button>
      </el-form-item>
    </el-form>
    <div ref="chartDomPlan" class="result-chart"></div>
    <div ref="chartDomPlan" class="result-chart"  v-loading="loading"></div>
  </el-dialog>
</template>
@@ -70,6 +70,7 @@
  start: undefined,
  end: undefined,
})
const loading = ref(true) // 列表的加载中
function getYMDHMS() {
  let timestamp = new Date().getTime();
@@ -123,12 +124,14 @@
async function getDataList() {
  visible.value = true;
  loading.value = true
  if (dataForm.value.id) {
    try {
      queryParams.itemNos = [dataForm.value.itemNo];
      queryParams.start = dataForm.value.startTime;
      queryParams.end = dataForm.value.endTime;
      const data = await ItemApi.getPlanChart(queryParams)
      loading.value = false
      let seriesData = []
      data.series.forEach(item => {
        seriesData.push({
src/views/data/point/DaPointChart.vue
@@ -46,7 +46,7 @@
        </el-button>
      </el-form-item>
    </el-form>
    <div ref="chartDom" class="result-chart"></div>
    <div ref="chartDom" class="result-chart" v-loading="loading"></div>
  </el-dialog>
</template>
@@ -87,30 +87,33 @@
defineExpose({open}) // 提供 open 方法,用于打开弹窗
async function getDataList() {
  visible.value = true;
  if (dataForm.value.id) {
    try {
      chartParams.codes = [dataForm.value.pointNo];
      chartParams.startDate = dataForm.value.startTime;
      chartParams.endDate = dataForm.value.endTime;
      const data = await DaPoint.getPointDaChart(chartParams)
      let seriesData = []
      data.series.forEach(item => {
        seriesData.push({
          name: item.name,
          type: "line",
          data: item.data,
          showSymbol: true,
          smooth: false,
          lineStyle: {
            normal: {
              color: "#5B8FF9",
              width: 1,
  const loading = ref(false)
  async function getDataList() {
    visible.value = true;
    loading.value = true
    if (dataForm.value.id) {
      try {
        chartParams.codes=[dataForm.value.pointNo];
        chartParams.startDate = dataForm.value.startTime;
        chartParams.endDate = dataForm.value.endTime;
        const data = await DaPoint.getPointDaChart(chartParams)
        loading.value = false
        let seriesData = []
        data.series.forEach(item => {
          seriesData.push({
            name: item.name,
            type: "line",
            data: item.data,
            showSymbol: true,
            smooth: false,
            lineStyle: {
              normal: {
                color: "#5B8FF9",
                width: 1,
              },
            },
          },
        });
      })
          });
        })
      myChart = echarts.init(chartDom.value);
      const option = {
src/views/data/point/index.vue
@@ -14,7 +14,7 @@
          placeholder="请输入测点编码"
          clearable
          @keyup.enter="handleQuery"
          class="!w-240px"
          class="!w-200px"
        />
      </el-form-item>
      <el-form-item label="测点名称" prop="pointName">
@@ -23,7 +23,7 @@
          placeholder="请输入测点名称"
          clearable
          @keyup.enter="handleQuery"
          class="!w-240px"
          class="!w-200px"
        />
      </el-form-item>
      <el-form-item label="测点Tag" prop="tagNo">
@@ -32,7 +32,7 @@
          placeholder="请输入测点Tag"
          clearable
          @keyup.enter="handleQuery"
          class="!w-240px"
          class="!w-200px"
        />
      </el-form-item>
      <el-form-item>
@@ -70,15 +70,30 @@
        >
          <Icon icon="ep:download" />导出
        </el-button>
        <el-button
          type="success"
          plain
          @click="enable"
          v-hasPermi="['data:point:update']"
        >启用
        </el-button>
        <el-button
          type="danger"
          plain
          @click="disable"
          v-hasPermi="['data:point:update']"
        >禁用
        </el-button>
      </el-form-item>
    </el-form>
  </ContentWrap>
  <!-- 列表 -->
  <ContentWrap>
    <el-table border stripe v-loading="loading" :data="list">
      <el-table-column fixed label="测点编码" header-align="center" align="left" min-width="120" prop="pointNo" />
      <el-table-column label="测点名称" header-align="center" align="left" min-width="200" prop="pointName" />
    <el-table border stripe v-loading="loading" :data="list" @selection-change="selectionChangeHandle">
      <el-table-column type="selection" header-align="center" align="center" width="50"/>
      <el-table-column fixed label="测点编码" header-align="center" align="left" min-width="130" prop="pointNo" />
      <el-table-column label="测点名称" header-align="center" align="left" min-width="220" prop="pointName" />
      <el-table-column label="测点类型" align="center" prop="pointType" width="100">
        <template #default="scope">
          <dict-tag :type="DICT_TYPE.DATA_POINT_TYPE" :value="scope.row.pointType" />
@@ -91,7 +106,7 @@
      </el-table-column>
      <el-table-column label="值类型" align="center" prop="valueType" width="120">
        <template #default="scope">
          <dict-tag :type="DICT_TYPE.VALUETYPE" :value="scope.row.valueType" />
          <dict-tag :type="DICT_TYPE.MEASURE_VALUE_TYPE" :value="scope.row.valueType" />
        </template>
      </el-table-column>
      <el-table-column label="测量单位" align="center" prop="unit" width="80"/>
@@ -101,14 +116,14 @@
      <el-table-column label="数据源类型" align="center" prop="sourceType" min-width="100"/>
      <el-table-column label="数据源名称" align="center" prop="sourceName" min-width="100"/>
      <el-table-column label="测点Tag" header-align="center" align="left" prop="tagNo" min-width="150"/>
      <el-table-column label="是否启用" align="center" prop="isEnable" width="100">
      <el-table-column label="是否启用" align="center" prop="isEnable" width="85">
        <template #default="scope">
          <el-tag v-if="scope.row.isEnable === 1" size="small">是</el-tag>
          <el-tag v-else size="small" type="danger">否</el-tag>
        </template>
      </el-table-column>
      <el-table-column label="操作" align="center" min-width="130" fixed="right" width="160">
      <el-table-column label="操作" align="center" min-width="130" fixed="right" width="120">
        <template #default="scope">
          <el-button
            link
@@ -151,7 +166,7 @@
</template>
<script lang="ts" setup>
import * as DaPoint from '@/api/data/da/point'
import {ref} from "vue";
import {ref, reactive} from "vue";
import download from "@/utils/download";
import {DICT_TYPE, getDictOptions} from "@/utils/dict";
import DaPointForm from './DaPointForm.vue'
@@ -246,6 +261,37 @@
      exportLoading.value = false
    }
  }
  let dataListSelections = reactive([])
  // 多选
  function selectionChangeHandle (val) {
    dataListSelections = val
  }
  // 启用
  async function enable() {
    let ids = dataListSelections.map(item => {
      return item.id
    })
    // 启用的二次确认
    await message.enableConfirm(ids)
    await DaPoint.enable(ids)
    message.success(t('common.enableSuccess'))
    await getList()
  }
  // 禁用
  async function disable(){
    let ids = dataListSelections.map(item => {
      return item.id
    })
    // 启用的二次确认
    await message.disableConfirm(ids,)
    await DaPoint.disable(ids)
    message.success(t('common.disableSuccess'))
    await getList()
  }
  /** 初始化 **/
  onMounted(async () => {
    await getList()
src/views/micro/index.vue
@@ -1,22 +1,20 @@
<template>
  <div class="sub-app">
    <WujieVue width="100%" height="100%" :name="name" :url="url" :alive="true" sync />
    <WujieVue width="100%" height="100%" v-bind="computedOptions" :degrade="true" :alive="true" sync />
  </div>
</template>
<script lang="ts" setup>
import hostMap from "@/utils/hostMap";
import wujieVue from "wujie-vue3";
const route = useRoute()
const url = hostMap("//localhost:90/") + route.params.path
const name = 'fast'
watch(() => "$route.params.path",
  () => {
    wujieVue.bus.$emit("vue3-router-change", `/${route.params.path}`);
  },
  {
    immediate: true
  }
)
  import WujieVue from "wujie-vue3";
  import { useRoute } from 'vue-router'
  import { computed } from 'vue'
  const route = useRoute()
  const computedOptions = computed(() => {
    return {
      name: route.query.key,
      url: route.query.url,
    }
  })
</script>
<style scoped lang="scss">
.sub-app {
src/views/model/mpk/file/MpkForm.vue
@@ -210,6 +210,7 @@
                        @click="updateSetting(scope.row)"
                        key="danger"
                        type="primary"
                        :disabled="scope.row.settingKey === 'pyFile'"
                        link
                      >修改
                      </el-button>
@@ -217,6 +218,7 @@
                        @click="deleteSetting(props.row.methodSettings,scope.$index)"
                        key="danger"
                        type="danger"
                        :disabled="scope.row.settingKey === 'pyFile'"
                        link
                      >删除
                      </el-button>
@@ -449,7 +451,9 @@
    if (id) {
      formLoading.value = true
      try {
        debugger
        formData.value = await MpkApi.getMpk(id)
        debugger
      } finally {
        formLoading.value = false
      }
src/views/model/mpk/file/MpkRun.vue
@@ -90,7 +90,7 @@
          label="参数value"
          align="center">
          <template #default="scope">
            <el-input size="small" v-model="scope.row.settingValue" maxlength="50" clearable />
            <el-input size="small" v-model="scope.row.settingValue" :disabled="scope.row.settingKey === 'pyFile'" maxlength="50" clearable />
          </template>
        </el-table-column>
        <el-table-column label="操作" fixed="right" header-align="center" align="center" width="100">
@@ -99,6 +99,7 @@
              @click="deleteRow(scope.$index)"
              key="danger"
              type="danger"
              :disabled="scope.row.settingKey === 'pyFile'"
              link
            >删除</el-button>
          </template>
@@ -171,6 +172,9 @@
    ],
    className: [
      {required: true, message: '全类名不能为空', trigger: 'blur'}
    ],
    model: [
      {required: true, message: 'model不能为空', trigger: 'blur'}
    ]
  })
@@ -256,6 +260,24 @@
    if (!formRef) return
    const valid = await formRef.value.validate()
    if (!valid) return
    if (hasModel.value) {
      debugger
      if (!formData.model || formData.model === '') {
        message.error("model为必填项!")
        return
      }
      try {
        JSON.parse(formData.model)
      } catch (e) {
        message.error("model参数异常!")
        return
      }
    }
    // 提交请求
    modelRunloading.value = true
    try {
src/views/model/pre/analysis/index.vue
@@ -361,7 +361,7 @@
      })
      offset = offset + 40
      if (chartCheckArray.indexOf('真实值') !== -1) {
        let legendName = dataView.resultstr + '(真实)';
        let legendName = dataView.resultName + '(真实)';
        legendData.push(legendName);
        seriesData.push({
          name: legendName,
@@ -376,7 +376,7 @@
        });
      }
      if (chartCheckArray.indexOf('T+N') !== -1) {
        let legendName = dataView.resultstr + '(T+N)';
        let legendName = dataView.resultName + '(T+N)';
        seriesData.push({
          name: legendName,
          data: dataView.preDataN || [],
@@ -390,7 +390,7 @@
        });
      }
      if (chartCheckArray.indexOf('T+L') !== -1) {
        let legendName = dataView.resultstr + '(T+L)';
        let legendName = dataView.resultName + '(T+L)';
        legendData.push(legendName);
        seriesData.push({
          name: legendName,
@@ -406,7 +406,7 @@
        });
      }
      if (chartCheckArray.indexOf('当时') !== -1) {
        let legendName = dataView.resultstr + '(当时)';
        let legendName = dataView.resultName + '(当时)';
        legendData.push(legendName);
        seriesData.push({
          name: legendName,
@@ -421,7 +421,7 @@
        });
      }
      if (chartCheckArray.indexOf('调整值') !== -1) {
        let legendName = dataView.resultstr + '(调整值)';
        let legendName = dataView.resultName + '(调整值)';
        legendData.push(legendName);
        seriesData.push({
          name: legendName,
src/views/model/pre/item/MmPredictItemForm.vue
@@ -1,5 +1,5 @@
<template>
  <Dialog v-model="dialogVisible" :title="dialogTitle" width="50%">
  <Dialog v-model="dialogVisible" :title="dialogTitle" width="60%">
    <el-form
      ref="formRef"
      v-loading="formLoading"
@@ -212,12 +212,12 @@
        border
        style="width: 100%; margin-top: 5px;">
        <el-table-column prop="outputorder" label="排序" align="center" width="80px"/>
        <el-table-column label="结果" align="center" width="150px">
        <el-table-column label="结果KEY" align="center" width="150px">
          <template #default="scope">
            <el-input v-model="scope.row.resultstr" placeholder="请输入"/>
          </template>
        </el-table-column>
        <el-table-column label="结果数据类型" align="center" width="150px">
        <el-table-column label="结果类型" align="center" width="150px">
          <template #default="scope">
            <el-select
              v-model="scope.row.resultType"
@@ -232,11 +232,16 @@
            </el-select>
          </template>
        </el-table-column>
        <el-table-column label="索引" align="center" width="120px">
        <el-table-column label="索引" align="center" width="100px">
          <template #default="scope">
            <el-input-number style="width:100%;hight:100%" :disabled="scope.row.resultType !== 2"
                             v-model="scope.row.resultIndex" :min="0" step-strictly
                             controls-position="right"/>
          </template>
        </el-table-column>
        <el-table-column label="结果名称" align="center" width="150px">
          <template #default="scope">
            <el-input v-model="scope.row.resultName" placeholder="请输入"/>
          </template>
        </el-table-column>
        <el-table-column label="数据点" align="center">
@@ -275,7 +280,7 @@
        <el-table-column prop="key" label="键" align="center" min-width="150"/>
        <el-table-column prop="name" label="名称" align="center" min-width="150"/>
        <el-table-column prop="valuetype" label="类型" align="center" min-width="150"/>
        <el-table-column prop="" label="值" align="center" min-width="150">
        <el-table-column prop="" label="值" align="center" min-width="200">
          <template #default="scope">
            <el-input size="mini" v-model="scope.row.value" maxlength="256"
                      style="width:100%;height:100%"/>
@@ -626,7 +631,7 @@
    }
    if (dataForm.value.mmModelArithSettingsList) {
      for (let item of dataForm.value.mmModelArithSettingsList) {
        if (item.key === 'lenpredict') {
        if (item.key === 'predictLength') {
          dataForm.value.mmPredictItem.predictlength = item.value
        }
      }
src/views/model/pre/item/index.vue
@@ -86,7 +86,7 @@
          <dict-tag :type="DICT_TYPE.ITEM_RUN_STATUS" :value="scope.row.runStatus" />
        </template>
      </el-table-column>
      <el-table-column label="运行耗时(s)" align="center" prop="duration"/>
      <el-table-column label="运行耗时(ms)" align="center" prop="duration"/>
      <el-table-column label="操作" align="center" min-width="120" fixed="right">
        <template #default="scope">
          <el-button
src/views/report/drag/index.vue
对比新文件
@@ -0,0 +1,13 @@
<template>
  <ContentWrap>
    <IFrame :src="src" />
  </ContentWrap>
</template>
<script lang="ts" setup>
import { getAccessToken } from '@/utils/auth'
defineOptions({ name: 'Drag' })
const BASE_URL = import.meta.env.VITE_BASE_URL
const src = ref(BASE_URL + '/drag/list?token=' + getAccessToken())
</script>
src/views/system/tenant/index.vue
@@ -99,7 +99,7 @@
    <el-table v-loading="loading" :data="list">
      <el-table-column label="租户编号" align="center" prop="id" />
      <el-table-column label="租户名" align="center" prop="name" />
      <el-table-column label="租户套餐" align="center" prop="packageId">
      <el-table-column label="租户套餐" align="center" prop="packageId" width="180" >
        <template #default="scope">
          <el-tag v-if="scope.row.packageId === 0" type="danger">系统租户</el-tag>
          <template v-else v-for="item in packageList">
src/views/system/tenantPackage/TenantPackageForm.vue
@@ -10,6 +10,12 @@
      <el-form-item label="套餐名" prop="name">
        <el-input v-model="formData.name" placeholder="请输入套餐名" />
      </el-form-item>
      <el-form-item label="套餐介绍" prop="description">
        <el-input type="textarea" v-model="formData.description" placeholder="请输入套餐介绍" />
      </el-form-item>
      <el-form-item label="套餐图标">
        <UploadImg v-model="formData.icon" :limit="1" />
      </el-form-item>
      <el-form-item label="菜单权限">
        <el-card class="cardHeight">
          <template #header>
@@ -39,6 +45,18 @@
            show-checkbox
          />
        </el-card>
      </el-form-item>
      <el-form-item label="套餐标签" prop="labels">
        <el-select
          v-model="formData.labels"
          filterable
          multiple
          allow-create
          placeholder="请输入套餐标签"
          style="width: 500px"
        >
          <el-option v-for="label in formData.labels" :key="label" :label="label" :value="label" />
        </el-select>
      </el-form-item>
      <el-form-item label="状态" prop="status">
        <el-radio-group v-model="formData.status">
@@ -81,6 +99,9 @@
const formData = ref({
  id: null,
  name: null,
  icon: undefined,
  labels: [],
  description: null,
  remark: null,
  menuIds: [],
  status: CommonStatusEnum.ENABLE
@@ -161,6 +182,9 @@
  formData.value = {
    id: null,
    name: null,
    icon: undefined,
    labels: [],
    description: null,
    remark: null,
    menuIds: [],
    status: CommonStatusEnum.ENABLE
src/views/system/tenantPackage/index.vue
@@ -27,73 +27,83 @@
          />
        </el-select>
      </el-form-item>
      <el-form-item label="创建时间" prop="createTime">
        <el-date-picker
          v-model="queryParams.createTime"
          type="daterange"
          value-format="YYYY-MM-DD HH:mm:ss"
          start-placeholder="开始日期"
          end-placeholder="结束日期"
          class="!w-240px"
        />
      </el-form-item>
      <el-form-item>
        <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
        <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
        <el-button @click="handleQuery">
          <Icon icon="ep:search" class="mr-5px"/>
          搜索
        </el-button>
        <el-button @click="resetQuery">
          <Icon icon="ep:refresh" class="mr-5px"/>
          重置
        </el-button>
        <el-button
          type="primary"
          plain
          @click="openForm('create')"
          v-hasPermi="['system:tenant-package:create']"
        >
          <Icon icon="ep:plus" class="mr-5px" />
          <Icon icon="ep:plus" class="mr-5px"/>
          新增
        </el-button>
      </el-form-item>
    </el-form>
  </ContentWrap>
  <!-- 列表 -->
  <ContentWrap>
    <el-table v-loading="loading" :data="list">
      <el-table-column label="套餐编号" align="center" prop="id" width="120" />
      <el-table-column label="套餐名" align="center" prop="name" />
      <el-table-column label="状态" align="center" prop="status" width="100">
        <template #default="scope">
          <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
        </template>
      </el-table-column>
      <el-table-column label="备注" align="center" prop="remark" />
      <el-table-column
        label="创建时间"
        align="center"
        prop="createTime"
        width="180"
        :formatter="dateFormatter"
      />
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
        <template #default="scope">
          <el-button
            link
            type="primary"
            @click="openForm('update', scope.row.id)"
            v-hasPermi="['system:tenant-package:update']"
          >
            修改
          </el-button>
          <el-button
            link
            type="danger"
            @click="handleDelete(scope.row.id)"
            v-hasPermi="['system:tenant-package:delete']"
          >
            删除
          </el-button>
        </template>
      </el-table-column>
    </el-table>
    <el-skeleton :loading="loading">
      <div class="package-card" v-for="(item, index) in packages" :key="`dynamics-${index}`">
        <div class="card-content">
          <img class="card-icon" :src="item.icon"/>
          <div class="card-middle">
            <div class="tenant-title">{{ item.name }}</div>
            <div class="tenant-operation">
              <el-dropdown @command="(command) => handleCommand(command, item)"
                           v-hasPermi="[
                      'system:tenant-package:update',
                      'system:tenant-package:delete'
                    ]">
                <el-button type="primary" link>
                  <Icon icon="ep:more-filled"/>
                </el-button>
                <template #dropdown>
                  <el-dropdown-menu>
                    <el-dropdown-item
                      command="handleUpdate"
                      v-if="checkPermi(['system:tenant-package:update'])"
                    >
                      <Icon icon="ep:edit"/>
                      修改
                    </el-dropdown-item>
                    <el-dropdown-item
                      command="handleDelete"
                      v-if="checkPermi(['system:tenant-package:delete'])"
                    >
                      <Icon icon="ep:delete"/>
                      删除
                    </el-dropdown-item>
                  </el-dropdown-menu>
                </template>
              </el-dropdown>
            </div>
          </div>
          <div class="description">{{ item.description }}</div>
          <div class="label-areas">
            <el-tag
              :disable-transitions="true"
              :key="i"
              v-for="(label, i) in item.labels"
              :index="i"
              class="label"
            >
              {{ label }}
            </el-tag>
          </div>
        </div>
      </div>
    </el-skeleton>
    <!-- 分页 -->
    <Pagination
      class="pagination"
      :total="total"
      v-model:page="queryParams.pageNo"
      v-model:limit="queryParams.pageSize"
@@ -102,22 +112,24 @@
  </ContentWrap>
  <!-- 表单弹窗:添加/修改 -->
  <TenantPackageForm ref="formRef" @success="getList" />
  <TenantPackageForm ref="formRef" @success="getList"/>
</template>
<script lang="ts" setup>
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import {DICT_TYPE, getIntDictOptions} from '@/utils/dict'
import * as TenantPackageApi from '@/api/system/tenantPackage'
import TenantPackageForm from './TenantPackageForm.vue'
import {TenantPackageVO} from "@/api/system/tenantPackage";
import {checkPermi} from "@/utils/permission";
defineOptions({ name: 'SystemTenantPackage' })
defineOptions({name: 'SystemTenantPackage'})
const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
const {t} = useI18n() // 国际化
const loading = ref(true) // 列表的加载中
const total = ref(0) // 列表的总页数
const list = ref([]) // 列表的数据
const packages = ref([])
const queryParams = reactive({
  pageNo: 1,
  pageSize: 10,
@@ -130,10 +142,9 @@
/** 查询列表 */
const getList = async () => {
  loading.value = true
  try {
    const data = await TenantPackageApi.getTenantPackagePage(queryParams)
    list.value = data.list
    packages.value = data.list
    total.value = data.total
  } finally {
    loading.value = false
@@ -158,6 +169,20 @@
  formRef.value.open(type, id)
}
/** 操作分发 */
const handleCommand = (command: string, row: TenantPackageVO) => {
  switch (command) {
    case 'handleUpdate':
      openForm('update', row.id)
      break
    case 'handleDelete':
      handleDelete(row.id)
      break
    default:
      break
  }
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
  try {
@@ -168,11 +193,95 @@
    message.success(t('common.delSuccess'))
    // 刷新列表
    await getList()
  } catch {}
  } catch {
  }
}
const initData = async () => {
  await Promise.all([
    getList()
  ])
}
/** 初始化 **/
onMounted(() => {
  getList()
})
initData()
</script>
<style lang="scss" scoped>
.package-card {
  display: inline-block;
  width: 396px;
  height: 379px;
  background: #FFFFFF;
  border-radius: 4px 4px 4px 4px;
  border: 1px solid #EBEDF0;
  margin: 0px 8px 8px 0;
}
.card-content {
  margin-left: 10px;
}
.card-icon {
  width: 372px;
  height: 200px;
  margin: 10px 0 10px 2px;
}
.card-middle {
  width: 396px;
  height: 25px;
  margin: 0 12px;
  display: flex;
}
.tenant-title {
  width: 340px;
  height: 25px;
  font-family: Microsoft YaHei UI, Microsoft YaHei UI;
  font-weight: bold;
  font-size: 20px;
  color: #282F3D;
}
.tenant-operation {
  margin-right: 12px;
}
.description {
  margin: 8px 12px;
  width: 372px;
  height: 36px;
  font-family: Microsoft YaHei, Microsoft YaHei;
  font-weight: 400;
  font-size: 14px;
  color: #6B7785;
  line-height: 18px;
  word-wrap: break-word;
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.label-areas {
  display: flex;
  flex-wrap: wrap;
  height: 54px;
  width: 396px;
  margin: 0 8px;
}
.label {
  width: 80px;
  height: 20px;
  margin: 4px;
  border-radius: 80px 80px 80px 80px;
  border: 1px solid #417CFF;
}
.pagination {
  margin-right: 30px;
  margin-top: 400px;
}
</style>