|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706 |
- <template>
- <div>
- <div class="ui header">
- <div class="ui breadcrumb">
- <a class="section" :href="`${repo}/modelmanage/show_model`">{{ $t('modelManage.modelManage') }}</a>
- <div class="divider"> / </div>
- <div class="active section">{{ this.state.name }}</div>
- </div>
- <div class="version">
- <el-select v-model="curVersion" @change="changeVersion" placeholder="">
- <el-option v-for="item in modelList" :value="item.version" :key="item.version" :label="item.version">
- </el-option>
- </el-select>
- </div>
- </div>
- <div class="content">
- <div class="detail-info">
- <div class="title">{{ $t('modelManage.basicInfo') }}:</div>
- <div class="area-c">
- <div class="area">
- <div class="row">
- <div class="tit">{{ $t('modelManage.useCluster') }}:</div>
- <div class="val">
- <div class="txt-wrap" :title="state.typeStr">
- {{ state.typeStr }}
- </div>
- </div>
- </div>
- <div class="row">
- <div class="tit">{{ $t('modelManage.modelSize') }}:</div>
- <div class="val">
- <div class="txt-wrap" :title="state.modelSize">{{ state.modelSize }}</div>
- </div>
- </div>
- <div class="row" :class="isEidtDescr ? 'edit-row' : ''">
- <div class="tit">{{ $t('modelManage.descr') }}:</div>
- <div class="val" :class="isEidtDescr ? 'edit-val' : ''">
- <div v-if="!isEidtDescr" class="txt-wrap" :title="state.description"
- style="max-width:100%;width:unset;padding-right:20px;">
- <span>{{ state.description }}</span>
- <i v-if="canOperate" style="position:absolute;right:0;top:3px;color:rgb(22, 132, 252);cursor:pointer;"
- class="el-icon-edit" @click="editDescr = state._description; isEidtDescr = true;"></i>
- </div>
- <div class="txt-edit" v-if="isEidtDescr">
- <el-input type="textarea" v-model="editDescr" :maxLength="255"
- :placeholder="$t('modelManage.modelDescrInputTips')"></el-input>
- <i style="position:absolute;right:-4px;bottom:20px;color:rgb(255, 37, 37);cursor:pointer;"
- class="icon times" @click="isEidtDescr = false;"></i>
- <i style="position:absolute;right:-5px;bottom:2px;color:rgb(39, 177, 72);cursor:pointer;"
- @click="submitEidt('descr')" class="icon check"></i>
- </div>
- </div>
- </div>
- </div>
- <div class="area">
- <div class="row">
- <div class="tit">{{ $t('modelManage.modelEngine') }}:</div>
- <div class="val">
- <div class="txt-wrap" :title="state.engineName">{{ state.engineName }}</div>
- </div>
- </div>
- <div class="row">
- <div class="tit">{{ $t('modelManage.createTime') }}:</div>
- <div class="val">
- <div class="txt-wrap" :title="state.createTime">{{ state.createTime }}</div>
- </div>
- </div>
- <div class="row" :class="isEidtLabel ? 'edit-row' : ''">
- <div class="tit">{{ $t('modelManage.label') }}:</div>
- <div class="val" :class="isEidtLabel ? 'edit-val' : ''">
- <div v-if="!isEidtLabel" class="txt-wrap" :title="state.label"
- style="max-width:100%;width:unset;padding-right:20px;">
- <span>{{ state.label }}</span>
- <i v-if="canOperate" style="position:absolute;right:0;top:3px;color:rgb(22, 132, 252);cursor:pointer;"
- class="el-icon-edit" @click="editLabel = state._label; isEidtLabel = true;"></i>
- </div>
- <div class="txt-edit" v-if="isEidtLabel">
- <el-input v-model="editLabel" :maxLength="255" :placeholder="$t('modelManage.modelLabelInputTips')"
- @input="labelInput"></el-input>
- <i style="position:absolute;right:-5px;bottom:20px;color:rgb(255, 37, 37);cursor:pointer;"
- class="icon times" @click="isEidtLabel = false;"></i>
- <i style="position:absolute;right:-5px;bottom:2px;color:rgb(39, 177, 72);cursor:pointer;"
- @click="submitEidt('label')" class="icon check"></i>
- </div>
- </div>
- </div>
- </div>
- </div>
- <div v-show="isExpanded" style="margin-top:8px;" class="title">{{ $t('modelManage.trainTaskInfo') }}:</div>
- <div v-show="isExpanded" class="area-c">
- <div class="area">
- <div class="row">
- <div class="tit">{{ $t('modelManage.trainTask') }}:</div>
- <div class="val">
- <div class="txt-wrap" v-html="state.displayJobName"></div>
- </div>
- </div>
- <div class="row">
- <div class="tit">{{ $t('modelManage.codeBranch') }}:</div>
- <div class="val">
- <div class="txt-wrap" v-html="state.branchName"></div>
- </div>
- </div>
- <div class="row">
- <div class="tit">{{ $t('modelManage.bootFile') }}:</div>
- <div class="val">
- <div class="txt-wrap" :title="state.bootFile">{{ state.bootFile }}</div>
- </div>
- </div>
- <div class="row">
- <div class="tit">{{ $t('modelManage.trainDataset') }}:</div>
- <div class="val">
- <div class="txt-wrap" :title="state.datasetName">{{ state.datasetName }}</div>
- </div>
- </div>
- </div>
- <div class="area">
- <div class="row">
- <div class="tit">{{ $t('modelManage.specInfo') }}:</div>
- <div class="val">
- <div class="txt-wrap" :title="state.specStr">{{ state.specStr }}</div>
- </div>
- </div>
- <div class="row">
- <div class="tit">{{ $t('modelManage.workServerNumber') }}:</div>
- <div class="val">
- <div class="txt-wrap" :title="state.workServerNumber">{{ state.workServerNumber }}</div>
- </div>
- </div>
- <div class="row">
- <div class="tit">{{ $t('modelManage.runParameters') }}:</div>
- <div class="val">
- <div class="txt-wrap" :title="state.parameters">{{ state.parameters }}</div>
- </div>
- </div>
- </div>
- </div>
- </div>
- <div class="expand-line">
- <div class="line"></div>
- <div class="expand-btn" @click="isExpanded = !isExpanded">
- <i class="icon chevron circle down" :class="isExpanded ? 'up' : ''"></i>
- <span>{{ isExpanded ? $t('modelManage.collapseDetails') : $t('modelManage.seeMore') }}</span>
- </div>
- <div class="line"></div>
- </div>
- <div class="files-info">
- <div class="top">
- <div style="width:100%;margin-right:20px;">
- <div class="title">{{ $t('modelManage.modelFilesList') }}:</div>
- <div class="title files-path-c" style="margin-top:8px;margin-bottom:4px">
- <div class="file-path" v-for="(item, index) in filePath">
- <span v-if="index == filePath.length - 1" class="path-name">{{ item.label }}</span>
- <a v-if="index != filePath.length - 1" class="path-name canback" @click="goBackDir(item)">{{ item.label
- }}</a>
- <span style="color:rgba(0,0,0,.4);" class="divider"> / </span>
- </div>
- </div>
- </div>
- <div>
- <el-button v-if="modelType == 1 && canOperate" type="primary" icon="el-icon-upload" @click="goUploadPage">
- {{ $t('modelManage.uploadModelFiles') }}
- </el-button>
- </div>
- </div>
- <div class="table-container">
- <el-table ref="tableRef" :data="filesList" row-key="sn" style="width: 100%" v-loading="loading" stripe>
- <el-table-column column-key="FileName" prop="FileName" sortable
- :sort-method="(a, b) => a.FileName.toLocaleLowerCase().localeCompare(b.FileName.toLocaleLowerCase())"
- :label="$t('modelManage.fileName')" align="left" header-align="left">
- <template slot-scope="scope">
- <div class="tbl-file-name">
- <a v-if="scope.row.IsDir" @click="goNextDir(scope.row)" href="javascript:;">
- <div class="fitted" :title="scope.row.FileName">
- <i class="icon folder" width="16" height="16" aria-hidden="true"></i>
- <span>{{ scope.row.FileName }}</span>
- </div>
- </a>
- <a v-else :class="!canOperate ? 'disabled-download' : ''"
- :href="canOperate ? `${repo}/modelmanage/${state.id}/downloadsingle?parentDir=${filePath.length > 1 ? encodeURIComponent(filePath.map(item => item.path).join('/').slice(1) + '/') : ''}&fileName=${scope.row.FileName}` : 'javascript:;'">
- <div class="fitted" :title="scope.row.FileName">
- <i class="icon file" width="16" height="16" aria-hidden="true"></i>
- <span>{{ scope.row.FileName }}</span>
- </div>
- </a>
- </div>
- </template>
- </el-table-column>
- <el-table-column column-key="SizeShow" prop="SizeShow" sortable :sort-method="(a, b) => a.Size - b.Size"
- :label="$t('modelManage.fileSize')" align="center" header-align="center" width="200">
- </el-table-column>
- <el-table-column column-key="ModTime" prop="ModTime" sortable
- :sort-method="(a, b) => a.ModTimeNum - b.ModTimeNum" :label="$t('modelManage.updateTime')" align="center"
- header-align="center" width="200">
- </el-table-column>
- <el-table-column v-if="modelType == 1 && canDelete" column-key="operate" prop="operate"
- :label="$t('modelManage.operate')" align="center" header-align="center" width="200">
- <template slot-scope="scope">
- <span v-if="!scope.row.IsDir" class="btn-del" @click="deleteFile(scope.row)">{{ $t('modelManage.delete')
- }}</span>
- </template>
- </el-table-column>
- </el-table>
- </div>
- </div>
- </div>
- </div>
- </template>
-
- <script>
-
- import { getModelInfoByName, modifyModel, getModelFiles, deleteModelFile } from '~/apis/modules/modelmanage';
- import { getUrlSearchParams, getListValueWithKey, transFileSize, renderSpecStr } from '~/utils';
- import { MODEL_ENGINES } from '~/const';
- import { formatDate } from 'element-ui/lib/utils/date-util';
-
- const REPO_NAME = location.pathname.split('/')[2];
- const MAX_LABEL_COUNT = 5;
-
- export default {
- data() {
- return {
- modelType: '0', // 1-本地, 0-线上
- canOperate: false,
- canDelete: false,
- isExpanded: false,
- loading: false,
- repo: location.pathname.split('/').slice(0, 3).join('/'),
- state: {
- type: 0,
- id: '',
- name: '',
- version: '0.0.1',
- engine: '0',
- label: '',
- description: '',
- },
- editDescr: '',
- isEidtDescr: false,
- editLabel: '',
- isEidtLabel: false,
- engineList: MODEL_ENGINES,
- curVersion: '',
- modelList: [],
- filesList: [],
- filePath: [],
- };
- },
- components: {},
- methods: {
- getDirFiles(dir) {
- dir = dir.length ? dir.slice(1) : '';
- getModelFiles({
- repo: this.repo,
- ID: this.state.id,
- parentDir: dir,
- }).then(res => {
- const list = res.data || [];
- list.forEach(item => {
- item.SizeShow = item.IsDir ? '' : transFileSize(item.Size);
- item.ModTimeNum = new Date(item.ModTime).getTime();
- })
- list.sort((a, b) => b.ModTimeNum - a.ModTimeNum);
- this.filesList = list;
- this.$refs['tableRef']?.clearSort();
- }).catch(err => {
- console.log(err);
- });
- },
- goNextDir(item) {
- this.filePath.push({
- label: item.FileName,
- path: item.FileName
- });
- const dir = this.filePath.map((item) => item.path).join('/');
- this.getDirFiles(dir);
- },
- goBackDir(item) {
- const index = this.filePath.findIndex(pth => item === pth);
- this.filePath = this.filePath.slice(0, index + 1);
- const dir = this.filePath.map((item) => item.path).join('/');
- this.getDirFiles(dir);
- },
- changeVersion(version, noFileRefresh) {
- const data = this.modelList.filter((model) => model.version == version)[0];
- this.modelType = data.modelType;
- this.canOperate = data.isCanOper;
- this.canDelete = data.isCanDelete;
- this.state.type = data.type;
- this.state.typeStr = data.type == 0 ? 'CPU/GPU' : data.type == 1 ? 'NPU' : '';
- this.state.id = data.id;
- this.state.name = data.name;
- this.state.version = data.version;
- this.state.engine = data.engine.toString();
- this.state.engineName = getListValueWithKey(MODEL_ENGINES, data.engine.toString());
- this.state.modelSize = transFileSize(data.size);
- this.state.label = data.label || '--';
- this.state._label = data.label;
- this.state.description = data.description || '--';
- this.state._description = data.description;
- this.state.createTime = formatDate(new Date(data.createdUnix * 1000), 'yyyy-MM-dd HH:mm:ss');
-
- const trainTaskInfo = data.trainTaskInfo ? JSON.parse(data.trainTaskInfo) : '';
- Object.assign(this.state, {
- displayJobName: '--',
- branchName: '--',
- bootFile: '--',
- datasetName: '--',
- parameters: '--',
- workServerNumber: '--',
- specStr: '--',
- });
- if (trainTaskInfo) {
- const parameters = trainTaskInfo.Parameters ? JSON.parse(trainTaskInfo.Parameters).parameter : [];
- const parametersStr = parameters.map((item) => { return item.label + '=' + item.value }).join('; ');
- const taskType = trainTaskInfo.Type;
- let taskUrl = location.href.split('modelmanage')[0];
- if (taskType == 0) {
- taskUrl = taskUrl + 'cloudbrain/train-job/' + trainTaskInfo.JobID;
- } else if (taskType == 1) {
- taskUrl = taskUrl + 'modelarts/train-job/' + trainTaskInfo.JobID;
- } else if (taskType == 2) {
- taskUrl = taskUrl + 'grampus/train-job/' + trainTaskInfo.JobID;
- }
- const versionName = trainTaskInfo.VersionName;
- const versionHtml = versionName ? `<span class="append-txt" title="${versionName}">${versionName}</span>` : '';
- const codeCommitID = data.codeCommitID;
- const codeCommitIDHtml = codeCommitID ? `<span class="append-txt" title="${codeCommitID}">${codeCommitID.slice(0, 10)}</span>` : '';
- let specObj;
- try {
- specObj = trainTaskInfo.FlavorName ? JSON.parse(trainTaskInfo.FlavorName) : '';
- } catch (e) {
- specObj = trainTaskInfo.FlavorName;
- }
- const sepcStr = typeof specObj == 'object' ? renderSpecStr(specObj, false) : specObj;
- Object.assign(this.state, {
- displayJobName: `<a href="${taskUrl}" title="${trainTaskInfo.DisplayJobName}">${trainTaskInfo.DisplayJobName}</a>${versionHtml}`,
- branchName: `<span>${trainTaskInfo.BranchName}</span>${codeCommitIDHtml}`,
- bootFile: trainTaskInfo.BootFile,
- datasetName: trainTaskInfo.DatasetName,
- parameters: parametersStr || '--',
- workServerNumber: trainTaskInfo.WorkServerNumber || '--',
- specStr: sepcStr || '--',
- });
- }
- this.curVersion = version;
- if (!noFileRefresh) {
- this.filePath = [{ label: version, path: '' }];
- this.getDirFiles('')
- }
- },
- goUploadPage() {
- window.location.href = `${this.repo}/modelmanage/create_local_model_2?type=1&name=${encodeURIComponent(this.state.name)}&id=${this.state.id}`;
- },
- backToModelListPage() {
- const list = window.location.href.split('/');
- list.pop();
- list.push('show_model');
- window.location.href = list.join('/');
- },
- labelInput() {
- const hasEndSpace = this.editLabel[this.editLabel.length - 1] == ' ';
- const list = this.editLabel.trim().split(' ').filter(label => label != '');
- this.editLabel = list.slice(0, MAX_LABEL_COUNT).join(' ') + (hasEndSpace && list.length < MAX_LABEL_COUNT ? ' ' : '');
- },
- submitEidt(type) {
- const obj = {
- repo: this.repo,
- type: this.state.type,
- id: this.state.id,
- name: this.state.name,
- version: this.state.version,
- engine: this.state.engine,
- label: type == 'label' ? this.editLabel : this.state.label,
- description: type == 'descr' ? this.editDescr : this.state.description,
- };
- modifyModel(obj).then(res => {
- res = res.data;
- if (res && res.code == '0') {
- if (type == 'label') {
- this.state.label = this.editLabel;
- this.state._label = this.editLabel;
- this.isEidtLabel = false;
- } else if (type == 'descr') {
- this.state.description = this.editDescr;
- this.state._description = this.editDescr;
- this.isEidtDescr = false;
- }
- } else {
- this.$message({
- type: 'error',
- message: this.$t('modelManage.infoModificationFailed'),
- });
- }
- }).catch(err => {
- console.log(err);
- this.$message({
- type: 'error',
- message: this.$t('modelManage.infoModificationFailed'),
- });
- });
- },
- deleteFile(file) {
- this.$confirm(this.$t('modelManage.deleteModelFileConfirmTips'), this.$t('tips'), {
- confirmButtonText: this.$t('confirm1'),
- cancelButtonText: this.$t('cancel'),
- type: 'warning',
- lockScroll: false,
- }).then(() => {
- this.loading = true;
- deleteModelFile({
- repo: this.repo,
- id: this.state.id,
- fileName: file.FileName,
- }).then(res => {
- res = res.data;
- if (res.code == '0') {
- setTimeout(() => {
- this.loading = false;
- this.updateModelInfo();
- const dir = this.filePath.map((item) => item.path).join('/');
- this.getDirFiles(dir);
- }, 30);
- } else {
- this.loading = false;
- this.$message({
- type: 'error',
- message: this.$t('modelManage.modelFileDeleteFailed'),
- });
- }
- }).catch(err => {
- console.log(err);
- this.$message({
- type: 'error',
- message: this.$t('modelManage.modelFileDeleteFailed'),
- });
- });
- }).catch(() => { });
- },
- updateModelInfo() {
- getModelInfoByName({
- repo: this.repo,
- name: this.state.name,
- }).then(res => {
- const list = res.data || [];
- this.modelList = list;
- const noFileRefresh = true;
- this.changeVersion(this.curVersion, noFileRefresh);
- }).catch(err => {
- console.log(err);
- });
- },
- },
- mounted() {
- const urlParams = getUrlSearchParams();
- if (urlParams.name) {
- this.state.name = urlParams.name;
- this.loading = true;
- getModelInfoByName({
- repo: this.repo,
- name: urlParams.name,
- }).then(res => {
- this.loading = false;
- const list = res.data || [];
- this.modelList = list;
- if (list && list.length) {
- const data = list[0];
- this.changeVersion(data.version);
- }
- }).catch(err => {
- this.loading = false;
- console.log(err);
- this.backToModelListPage();
- });
- } else {
- this.backToModelListPage();
- }
- },
- beforeDestroy() {
- },
- };
- </script>
-
- <style scoped lang="less">
- .header {
- display: flex;
- align-items: center;
-
- .version {
- margin-left: 16px;
- width: 90px;
- }
- }
-
- .content {
- .title {
- font-weight: 550;
- font-size: 14px;
- color: rgb(16, 16, 16);
- margin-bottom: 10px;
- }
-
- .detail-info {
- border: 1px solid rgb(232, 232, 232);
- border-bottom: none;
- padding: 22px;
- padding-bottom: 1px;
-
- .area-c {
- display: flex;
-
- .area {
- flex: 1;
-
- .row {
- display: flex;
- height: 32px;
- margin-bottom: 4px;
- align-items: center;
-
- &.edit-row {
- height: unset;
- }
-
- .tit {
- width: 160px;
- text-align: right;
- color: rgb(136, 136, 136);
- }
-
- .val {
- flex: 1;
- color: rgb(16, 16, 16);
- position: relative;
- height: 20px;
-
- &.edit-val {
- height: unset;
- }
-
- .txt-wrap {
- position: absolute;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- width: 100%;
-
- /deep/.append-txt {
- margin-left: 6px;
- background-color: gainsboro;
- padding: 2px;
- border-radius: 2px;
- font-size: 12px;
- }
- }
- }
-
- .txt-edit {
- padding-right: 20px;
- }
- }
- }
- }
- }
-
- .expand-line {
- display: flex;
- align-items: center;
- border: 1px solid rgb(232, 232, 232);
- border-top: none;
- border-bottom: none;
- padding: 16px 0;
-
- .line {
- flex: 1;
- height: 1px;
- background-color: rgb(232, 232, 232);
- margin: 0 22px;
- }
-
- .expand-btn {
- color: rgba(22, 132, 252, 1);
- cursor: pointer;
-
- .icon {
- margin-right: 2px;
- font-size: 14px;
- color: rgba(22, 132, 252, 0.8),
- }
- }
- }
-
-
- .files-info {
- border: 1px solid rgb(232, 232, 232);
- border-top: none;
- border-bottom: none;
-
- .top {
- padding: 0 22px 8px 22px;
- display: flex;
- align-items: center;
- justify-content: space-between;
- }
-
- .files-path-c {
- margin-bottom: 4px;
- height: 20px;
-
- .file-path {
- margin-right: 6px;
- float: left;
-
- .path-name {
- &.canback {
- color: #4183c4;
- }
- }
- }
- }
-
- .table-container {
- /deep/ .el-table__header {
- th {
- background: rgb(245, 245, 246);
- color: rgb(16, 16, 16);
- font-weight: 400;
- font-size: 14px;
- }
- }
-
- /deep/ .el-table__body {
- td {
- color: rgb(16, 16, 16);
- font-weight: 400;
- font-size: 14px;
- }
- }
-
- .tbl-file-name {
- height: 32px;
- display: flex;
- align-items: center;
- overflow: hidden;
- font-size: 16px;
- font-weight: 500;
- position: relative;
-
- a {
- max-width: 100%;
-
- .fitted {
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- max-width: 100%;
- }
- }
-
- .disabled-download {
- cursor: default;
- pointer-events: none;
- color: rgba(0, 0, 0, .6) !important;
- opacity: .45 !important;
- }
- }
-
- .btn-del {
- color: #0366d6;
- cursor: pointer;
- }
- }
- }
- }
-
-
- .el-select-dropdown__item.selected {
- color: rgba(0, 0, 0, .95);
- }
-
- /deep/ .el-select {
- .is-focus {
- .el-input__inner {
- border-color: #85b7d9;
- }
- }
- }
-
- .el-select {
- /deep/ .el-input__inner {
- font-weight: 600;
- }
- }
-
- /deep/ .el-input__inner {
- &:focus {
- border-color: #85b7d9;
- }
- }
-
- /deep/ .el-textarea__inner {
- &:focus {
- border-color: #85b7d9;
- }
- }
- </style>
|