Commit b2839d72 authored by mhw's avatar mhw

新增插件编排

parent b5fd853c
export default class plugOrchestration {
static list (sender, params, axiosOption, httpOption) {
return sender.doUrl('/admin/app/pluginManage/list', 'post', params, axiosOption, httpOption);
}
static view (sender, params, axiosOption, httpOption) {
return sender.doUrl('/admin/app/pluginManage/view', 'get', params, axiosOption, httpOption);
}
static export (sender, params, fileName) {
return sender.download('/admin/app/pluginManage/export', params, fileName);
}
static add (sender, params, axiosOption, httpOption) {
return sender.doUrl('/admin/app/pluginManage/add', 'post', params, axiosOption, httpOption);
}
static update (sender, params, axiosOption, httpOption) {
return sender.doUrl('/admin/app/pluginManage/update', 'post', params, axiosOption, httpOption);
}
static delete (sender, params, axiosOption, httpOption) {
return sender.doUrl('/admin/app/pluginManage/delete', 'post', params, axiosOption, httpOption);
}
}
...@@ -19,7 +19,8 @@ import DatasetData from './GptController/DatasetData.js'; ...@@ -19,7 +19,8 @@ import DatasetData from './GptController/DatasetData.js';
import ModelDeployment from './GptController/ModelDeployment.js'; import ModelDeployment from './GptController/ModelDeployment.js';
import KnowledgeGraph from './GptController/KnowledgeGraph.js'; import KnowledgeGraph from './GptController/KnowledgeGraph.js';
import DataSetCleaning from './GptController/DataSetCleaning.js'; import DataSetCleaning from './GptController/DataSetCleaning.js';
import applicationAccess from './GptController/applicationAccess.js'; import applicationAccess from './GptController/applicationAccess.js'
import plugOrchestration from './GptController/plugOrchestration.js';
export { export {
TemplateController, TemplateController,
...@@ -42,5 +43,6 @@ export { ...@@ -42,5 +43,6 @@ export {
ModelDeployment, ModelDeployment,
KnowledgeGraph, KnowledgeGraph,
DataSetCleaning, DataSetCleaning,
applicationAccess applicationAccess,
plugOrchestration
} }
<svg height="72" width="140" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><rect id="a" height="8" rx="4" width="8"/><rect id="b" height="8" rx="4" width="8"/><ellipse id="c" cx="18" cy="17.967" rx="18" ry="17.967"/><filter id="d" height="161.2%" width="161.1%" x="-19.4%" y="-27.8%"><feOffset dx="4" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"/><feGaussianBlur in="shadowOffsetOuter1" result="shadowBlurOuter1" stdDeviation="3"/><feComposite in="shadowBlurOuter1" in2="SourceAlpha" operator="out" result="shadowBlurOuter1"/><feColorMatrix in="shadowBlurOuter1" values="0 0 0 0 0.103182954 0 0 0 0 0.242371171 0 0 0 0 0.467360344 0 0 0 0.108555507 0"/></filter><mask id="e" fill="#fff"><use fill="#fff" fill-rule="evenodd" xlink:href="#a"/></mask><mask id="f" fill="#fff"><use fill="#fff" fill-rule="evenodd" xlink:href="#b"/></mask></defs><g fill="none" fill-rule="evenodd"><path d="m0 0h140v72h-140z"/><g transform="translate(8 8)"><rect fill="#f9f9f9" height="2.646" rx="1.323" width="2.65" x="79.622" y="23.969"/><rect fill="#f9f9f9" height="2.646" rx="1.323" width="2.65" x="83.725" y="23.969"/><rect fill="#e6f0ff" height="56" rx="1" width="81.5" x="22"/><g fill="#a8caff"><rect height="2.5" rx="1" width="24" x="26" y="10"/><rect height="2.5" rx="1" width="24" x="26" y="17"/><rect height="2.5" rx="1" width="24" x="26" y="23"/></g><rect fill="#2468f2" height="2.5" rx="1" width="6" x="30" y="23"/><rect fill="#2468f2" height="2.5" rx="1" width="6" x="35" y="17"/><rect fill="#2468f2" height="2.5" rx="1" width="6" x="29" y="10"/><g transform="translate(57.686 6.535)"><rect fill="#fff" height="41" rx="1" width="42"/><path d="m0 33h42v7a1 1 0 0 1 -1 1h-40a1 1 0 0 1 -1-1z" fill="#2468f2"/><path d="m37.314 37.465h2a1 1 0 0 1 0 2h-2a1 1 0 1 1 0-2z" fill="#fff"/><path d="m16.314 4.465h20a1 1 0 0 1 1 1v6a1 1 0 0 1 -1 1h-20a1 1 0 0 1 -1-1v-6a1 1 0 0 1 1-1zm-9.874 12h20a1 1 0 0 1 1 1v6a1 1 0 0 1 -1 1h-20a1 1 0 0 1 -1-1v-6a1 1 0 0 1 1-1z" fill="#a8caff"/><g transform="translate(4.314 4.465)"><rect fill="#a8caff" height="8" rx="4" width="8"/><use fill="#2468f2" xlink:href="#a"/><g fill="#e6f0ff"><circle cx="4" cy="7.648" mask="url(#e)" r="3.658"/><circle cx="4" cy="2.76" mask="url(#e)" r="1"/></g></g><g transform="translate(29.314 16.465)"><rect fill="#a8caff" height="8" rx="4" width="8"/><use fill="#2468f2" xlink:href="#b"/><g fill="#e6f0ff"><circle cx="4" cy="7.648" mask="url(#f)" r="3.658"/><circle cx="4" cy="2.76" mask="url(#f)" r="1"/></g></g></g><path d="m13.681 51h94.989a1.562 1.562 0 0 1 1.25 2.5 6.254 6.254 0 0 1 -5.003 2.5h-86.61a5.853 5.853 0 0 1 -4.797-2.5l-.648-.927a1 1 0 0 1 .82-1.573z" fill="#2468f2"/><g transform="translate(0 21)"><use fill="#000" filter="url(#d)" xlink:href="#c"/><use fill="#add3ff" fill-opacity=".159" xlink:href="#c"/></g><g fill-rule="nonzero"><path d="m13.333 32h9.334a3.333 3.333 0 1 1 0 6.667h-9.334a3.333 3.333 0 1 1 0-6.667zm0 8.444h9.334a3.333 3.333 0 1 1 0 6.667h-9.334a3.333 3.333 0 1 1 0-6.667z" fill="#a7c8fc"/><path d="m10.445 35.333a2.889 2.889 0 1 0 5.777 0 2.889 2.889 0 0 0 -5.777 0zm9.333 8.445a2.889 2.889 0 1 0 5.777 0 2.889 2.889 0 0 0 -5.777 0z" fill="#2468f2"/></g></g></g></svg>
\ No newline at end of file
<svg height="72" width="141" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><ellipse id="a" cx="18" cy="17.967" rx="18" ry="17.967"/><filter id="b" height="161.2%" width="161.1%" x="-19.4%" y="-27.8%"><feOffset dx="4" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"/><feGaussianBlur in="shadowOffsetOuter1" result="shadowBlurOuter1" stdDeviation="3"/><feComposite in="shadowBlurOuter1" in2="SourceAlpha" operator="out" result="shadowBlurOuter1"/><feColorMatrix in="shadowBlurOuter1" values="0 0 0 0 0.103182954 0 0 0 0 0.242371171 0 0 0 0 0.467360344 0 0 0 0.108555507 0"/></filter></defs><g fill="none" fill-rule="evenodd"><path d="m0 0h140v72h-140z"/><g transform="translate(19.762 8)"><rect fill="#f9f9f9" height="2.646" rx="1.323" width="2.65" x="67.86" y="23.969"/><rect fill="#f9f9f9" height="2.646" rx="1.323" width="2.65" x="71.963" y="23.969"/><rect fill="#e6f0ff" height="56" rx="1" width="81.5" x="10.238"/><g transform="translate(15.238 13)"><rect fill="#a8caff" height="9" rx="1" width="12"/><path d="m15.01 3 1.99 1.987-2 1.999v-1.136l.82-.82-.82-.82v-1.2zm20 0 1.99 1.987-2 1.999v-1.136l.82-.82-.82-.82v-1.2zm20 0 1.99 1.987-2 1.999v-1.136l.82-.82-.82-.82v-1.2z" fill="#2468f2"/><g fill="#a8caff"><rect height="9" rx="1" width="12" x="20"/><rect height="9" rx="1" width="12" x="40"/><rect height="9" rx="1" width="12" x="60"/></g></g><rect fill="#fff" height="9" rx="1" width="70" x="14.238" y="26"/><rect fill="#a8caff" height="7" rx="1" width="7" x="16.238" y="27"/><rect fill="#a8caff" height="2" rx="1" width="9" x="49.238" y="30"/><rect fill="#a8caff" height="2" rx="1" width="7" x="63.238" y="30"/><rect fill="#2468f2" height="2" rx="1" width="7" x="75.238" y="30"/><g fill="#a8caff"><rect height="2" rx="1" width="17" x="27.238" y="30"/><rect height="7" rx="1" width="7" x="16.238" y="27"/><rect height="2" rx="1" width="9" x="49.238" y="30"/><rect height="2" rx="1" width="7" x="63.238" y="30"/></g><rect fill="#2468f2" height="2" rx="1" width="7" x="75.238" y="30"/><rect fill="#a8caff" height="2" rx="1" width="17" x="27.238" y="30"/><rect fill="#fff" height="9" rx="1" width="70" x="14.238" y="37"/><rect fill="#a8caff" height="7" rx="1" width="7" x="16.238" y="38"/><rect fill="#a8caff" height="2" rx="1" width="9" x="49.238" y="41"/><rect fill="#a8caff" height="2" rx="1" width="7" x="63.238" y="41"/><rect fill="#2468f2" height="2" rx="1" width="7" x="75.238" y="41"/><rect fill="#a8caff" height="2" rx="1" width="17" x="27.238" y="41"/><rect fill="#a8caff" height="7" rx="1" width="7" x="16.238" y="38"/><rect fill="#a8caff" height="2" rx="1" width="9" x="49.238" y="41"/><rect fill="#a8caff" height="2" rx="1" width="7" x="63.238" y="41"/><rect fill="#2468f2" height="2" rx="1" width="7" x="75.238" y="41"/><rect fill="#a8caff" height="2" rx="1" width="17" x="27.238" y="41"/><rect fill="#2468f2" height="3" rx="1" width="8" x="14.238" y="6"/><path d="m1.919 51h94.989a1.562 1.562 0 0 1 1.25 2.5 6.254 6.254 0 0 1 -5.003 2.5h-86.61a5.853 5.853 0 0 1 -4.798-2.5l-.648-.927a1 1 0 0 1 .821-1.573z" fill="#2468f2"/><g transform="translate(75.238 20)"><use fill="#000" filter="url(#b)" xlink:href="#a"/><use fill="#add3ff" fill-opacity=".159" xlink:href="#a"/></g><path d="m98.73 34.06a1.2 1.2 0 0 1 .46.96l-.09 7.947a1.2 1.2 0 0 1 -1.938.93l-1.88-1.468c-3.54 3.96-7.515 3.783-11.926-.53 3.328.796 6.033-.02 8.115-2.448l-1.907-1.49a1.2 1.2 0 0 1 .434-2.106l7.69-2.01a1.2 1.2 0 0 1 1.042.216z" fill="#2468f2"/></g></g></svg>
\ No newline at end of file
module.exports = { module.exports = {
// baseUrl: 'http://218.76.0.69:8082/', // baseUrl: 'http://218.76.0.69:8082/',
// baseUrl: 'http://192.168.0.34:8082/', // baseUrl: 'http://192.168.0.34:8082/',
baseUrl: 'http://192.168.0.36:8082/', // baseUrl: 'http://192.168.0.36:8082/',
baseUrl: 'http://192.168.0.168:8082/',
// baseUrl: 'http://192.168.0.34:8082/', // baseUrl: 'http://192.168.0.34:8082/',
wsUrl: 'ws://218.76.0.69:7860/', wsUrl: 'ws://218.76.0.69:7860/',
projectName: '灵境大模型平台' projectName: '灵境大模型平台'
......
...@@ -59,6 +59,8 @@ const routers = [ ...@@ -59,6 +59,8 @@ const routers = [
{ path: 'applicationAccess', component: _import('gptTraining/modelService/applicationAccess/index'), name: 'applicationAccess', props: getProps, meta: { title: '应用接入' } }, { path: 'applicationAccess', component: _import('gptTraining/modelService/applicationAccess/index'), name: 'applicationAccess', props: getProps, meta: { title: '应用接入' } },
{ path: 'testOnline', component: _import('gptTraining/modelService/testOnline/index'), name: 'testOnline', props: getProps, meta: { title: '在线测试' } }, { path: 'testOnline', component: _import('gptTraining/modelService/testOnline/index'), name: 'testOnline', props: getProps, meta: { title: '在线测试' } },
{ path: 'callStatistics', component: _import('gptTraining/modelService/callStatistics/index'), name: 'callStatistics', props: getProps, meta: { title: '调用统计' } }, { path: 'callStatistics', component: _import('gptTraining/modelService/callStatistics/index'), name: 'callStatistics', props: getProps, meta: { title: '调用统计' } },
{ path: 'plugOrchestration', component: _import('gptTraining/modelService/plugOrchestration/index'), name: 'plugOrchestration', props: getProps, meta: { title: '插件编排' } },
// Prompt工程 // Prompt工程
{ path: 'promptTemplate', component: _import('gptTraining/promptProject/promptTemplate/index'), name: 'promptTemplate', props: getProps, meta: { title: 'Prompt模板' } }, { path: 'promptTemplate', component: _import('gptTraining/promptProject/promptTemplate/index'), name: 'promptTemplate', props: getProps, meta: { title: 'Prompt模板' } },
// { path: 'presetTemplate', component: _import('gptTraining/promptProject/presetTemplate/index'), name: 'presetTemplate', props: getProps, meta: { title: '预置模板' } }, // { path: 'presetTemplate', component: _import('gptTraining/promptProject/presetTemplate/index'), name: 'presetTemplate', props: getProps, meta: { title: '预置模板' } },
......
...@@ -724,6 +724,37 @@ const CleaningMethod = new DictionaryBase('清洗方式', [ ...@@ -724,6 +724,37 @@ const CleaningMethod = new DictionaryBase('清洗方式', [
]); ]);
Vue.prototype.CleaningMethod = CleaningMethod; Vue.prototype.CleaningMethod = CleaningMethod;
const sceneType = new DictionaryBase('知识格式', [
{
id: 1,
name: '对话类场景',
symbol: 'ConversationalScene'
},
{
id: 2,
name: '生成类场景',
symbol: 'GeneratedClassScene'
}
]);
Vue.prototype.sceneType = sceneType;
const status = new DictionaryBase('知识格式', [
{
id: 1,
name: '编辑中',
symbol: 'editing'
},
{
id: 2,
name: '已上线',
symbol: 'logged'
},
{
id: 3,
name: '已下线',
symbol: 'offline'
}
]);
Vue.prototype.status = status;
export { export {
TemplateLabelDict, TemplateLabelDict,
ScenarioTypeDict, ScenarioTypeDict,
......
<!-- 基本信息-->
<template>
<el-form label-position="left" ref="form" label-width="100px" :model="form" :size="defaultFormItemSize" :rules="rules">
<el-form-item label="场景:">
<el-radio-group v-model="form.pluginManageDto.sceneType">
<el-radio v-for="item in sceneType.getList()" :key="item.id" :label="item.id">{{item.name}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="名称:" prop="pluginManageDto.pluginName">
<el-input v-model="form.pluginManageDto.pluginName" class="inputWidth" :size="defaultFormItemSize" minlength="2" maxlength="20"></el-input>
<el-row> <span class="introduce">支持中英文、数字、下划线(_),2-20个字符,不能以下划线为开头</span></el-row>
</el-form-item>
<el-form-item label="描述:">
<el-input type="textarea" :rows="2" v-model="form.pluginManageDto.remark" class="inputWidth" :size="defaultFormItemSize" minlength="0" maxlength="200"></el-input>
</el-form-item>
<el-row type="flex" justify="end" class="dialog-btn-layer mt20">
<el-button :size="defaultFormItemSize" :plain="true" @click="onCancel(false)">取消</el-button>
<el-button type="primary" :size="defaultFormItemSize" @click="onSubmit">确定</el-button>
</el-row>
</el-form>
</template>
<script>
import { plugOrchestration } from '@/api/gptController.js'
export default {
data() {
return {
taskList: [],
runNameList: [],
form: {
pluginManageDto: {
pluginName: '',
remark: '',
sceneType: 1
}
},
rules: {
'pluginManageDto.pluginName': [{ required: true, message: '请输入名称', trigger: 'blur' }]
}
}
},
props: ['isEdit', 'item'],
components: {},
computed: {},
mounted() {
this.intFrom()
},
methods: {
intFrom() {
this.form = { ...this.form, ...this.item }
try {
this.form.templateLabel = JSON.parse(this.item.templateLabel)
} catch (error) {
// console.log(error);
}
},
onCancel(isSuccess) {
if (this.observer != null) {
this.observer.cancel(isSuccess)
}
},
onSubmit() {
return new Promise((resolve, reject) => {
this.$refs['form'].validate((valid) => {
if (valid) {
let params = {}
params = { ...this.form }
if (this.isEdit) {
plugOrchestration
.update(this, params)
.then((res) => {
resolve(res)
this.$message.success('编辑成功')
this.onCancel(true)
})
.catch((e) => {
reject(e)
})
} else {
plugOrchestration
.add(this, params)
.then((res) => {
resolve(res)
this.$message.success('添加成功')
this.onCancel(true)
})
.catch((e) => {
reject(e)
})
}
} else {
// reject();
}
})
})
}
}
}
</script>
<style scoped>
.inputWidth {
width: 600px;
}
.title {
font-size: 20px;
margin-bottom: 16px;
}
.introduce {
font-size: 12px;
color: #909399;
}
</style>
<!--插件编排-->
<template>
<div style="position: relative">
<el-collapse v-model="activeName" accordion ref="collapse" v-resize="resize" style="margin-bottom:20px">
<el-collapse-item name="1">
<template slot="title">
<div class="title">操作指引</div>
</template>
<div class="instructions">
<div class="describe">
插件应用创建、管理入口模块,用户可以通过对大模型 + 插件的组合进行大模型应用服务创建工作,并可以对创建的服务进行状态查看、状态管理等操作。
</div>
<div class="instructionsList">
<div class="item" v-for="(item, index) in instructionsList" :key="index">
<div style="height:100%">
<img class="img" :src="item.img" alt="" />
<div class="itemTitle">
<span class="head-index">{{ index + 1 }} &nbsp;</span>{{ item.title }}
</div>
<div class="itemDescribe">{{ item.describe }}</div>
</div>
<i v-if="instructionsList.length!==index+1" class="el-icon-arrow-right" style="margin-left: 50px; font-size: 30px; font-weight: bolder;color:#b8babf"></i>
</div>
</div>
</div>
</el-collapse-item>
</el-collapse>
<div class="tableBox" :style="{ height: tableHeight }">
<el-form ref="myDataSetPage" :model="myDataSetPage" label-width="75px" :size="defaultFormItemSize" label-position="right" @submit.native.prevent>
<filter-box :item-width="350" @search="refresh()" @reset="onReset">
<el-form-item label-width="0px">
<el-button class="add" type="primary" icon="el-icon-plus" :size="defaultFormItemSize" @click="add">配置插件应用服务</el-button>
</el-form-item>
<el-form-item label="服务名称" prop="formFilter.pluginName" label-width="120px">
<el-input class="filter-item" v-model="myDataSetPage.formFilter.pluginName" :clearable="true" placeholder="应用名称" />
</el-form-item>
</filter-box>
</el-form>
<vxe-table border show-header-overflow show-overflow :row-config="{ isHover: true }" :data="myDataSetPage.tableData.impl.dataList" min-height="96">
<vxe-column field="pluginName" title="服务名称"></vxe-column>
<vxe-column field="status" title="服务状态">
<template slot-scope="scope">
{{status.getValue(scope.row.status) }}
</template>
</vxe-column>
<vxe-column field="sceneType" title="服务类型">
<template slot-scope="scope">
{{sceneType.getValue(scope.row.sceneType) }}
</template>
</vxe-column>
<vxe-column field="remark" title="服务描述"></vxe-column>
<vxe-column field="updateTime" title="更新时间"></vxe-column>
<vxe-column field="operation" title="操作" width='120'>
<template slot-scope="scope">
<!-- <el-button
type="text"
:size="defaultFormItemSize"
@click="dataImport(scope.row)"
>导入</el-button
> -->
<el-button type="text" icon="el-icon-delete" :size="defaultFormItemSize" @click="del(scope.row)">删除</el-button>
</template>
</vxe-column>
</vxe-table>
<el-row slot="pagination" type="flex" justify="end" style="margin-top: 16px;width: 100%;">
<el-pagination :total="myDataSetPage.tableData.impl.totalCount" :current-page="myDataSetPage.tableData.impl.currentPage" :page-size="myDataSetPage.tableData.impl.pageSize" :page-sizes="[10, 20, 50, 100]" layout="total, prev, pager, next, sizes" @current-change="myDataSetPage.tableData.impl.onCurrentPageChange" @size-change="myDataSetPage.tableData.impl.onPageSizeChange">
</el-pagination>
</el-row>
</div>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
/* eslint-disable-next-line */
import { DropdownWidget, TableWidget, UploadWidget, ChartWidget } from '@/utils/widget.js'
import { plugOrchestration } from '@/api/gptController.js'
import editOrAdd from './dialog/editOrAdd'
export default {
data() {
return {
activeName: '1',
collapseHeight: 0,
instructionsList: [
{
title: '创建插件服务',
describe: '进入插件列表页面,点击配置插件应用服务,选择业务场景',
img: require('@/assets/img/step1-d9ec9a71.png')
},
{
title: '配置插件服务',
describe: '配置Prompt和知识库,选择对应的插件',
img: require('@/assets/img/step2-ada915de.png')
},
{
title: '在线调试',
describe: '在线调试,回显信息即时呈现,实时反馈配置效果',
img: require('@/assets/img/step3-e23801d8.svg')
},
{
title: '发布上线',
describe: '将配置发布为在线服务,方便集成业务应用',
img: require('@/assets/img/step4-2b85a87b.svg')
}
],
myDataSetPage: {
formFilter: {
pluginName: ''
},
tableData: {
impl: new TableWidget(this.getwidgetData, true, true, false, undefined, false)
}
}
}
},
components: {},
computed: {
...mapGetters(['getMainContextHeight']),
tableHeight() {
return this.getMainContextHeight - this.collapseHeight - 55 + 'px'
}
},
methods: {
getwidgetData(params) {
if (params == null) params = {}
params = {
...params,
pluginManageDtoFilter: { ...this.myDataSetPage.formFilter }
}
return new Promise((resolve, reject) => {
plugOrchestration
.list(this, params)
.then((res) => {
resolve({
dataList: res.data.dataList,
totalCount: res.data.totalCount
})
})
.catch((e) => {
reject(e)
})
})
},
add() {
this.$dialog
.show(
'创建服务',
editOrAdd,
{
area: ['50%', '70%']
},
{ isEdit: false }
)
.then((res) => {
this.refresh()
})
.catch((e) => {
this.refresh()
})
},
del(item) {
this.$confirm('是否确认删除', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
let params = { pluginId: item.pluginId }
plugOrchestration
.delete(this, params)
.then((res) => {
this.$message.success('删除成功')
this.refresh()
})
.catch((e) => {
console.log(e)
})
})
},
refresh(reloadData = false) {
if (reloadData) {
this.myDataSetPage.tableData.impl.refreshTable(true, 1)
} else {
this.myDataSetPage.tableData.impl.refreshTable()
}
},
onReset() {
this.$refs.myDataSetPage.resetFields()
this.refresh(true)
},
formInit() {
this.refresh()
},
resize(e) {
setTimeout(() => {
this.collapseHeight = e?.height
}, 300)
}
},
mounted() {
this.formInit()
}
}
</script>
<style lang="scss" scoped>
@import '@/assets/style/element-variables.scss';
.title {
font-size: 16px;
}
.instructions {
background-color: white;
width: 100%;
padding: 0px 20px 20px 20px;
height: 210px;
.instructionsList {
display: flex;
flex-direction: row;
justify-content: space-around;
.item {
display: flex;
align-items: center;
}
}
.title {
color: $--color-text-primary;
font-size: 16px;
font-weight: 500;
margin-bottom: 8px;
}
.describe {
color: $--color-text-secondary;
margin-bottom: 16px;
}
.itemTitle {
color: $--color-text-primary;
font-size: 16px;
font-weight: 500;
margin-bottom: 8px;
}
.head-index {
font-size: 24px;
color: #e8e9eb;
line-height: 32px;
}
.itemDescribe {
width: 170px;
color: $--color-text-secondary;
}
.img {
height: 72px;
width: 140px;
}
}
.tableBox {
background-color: white;
width: 100%;
padding: 20px;
overflow: auto;
.add {
margin-bottom: 20px;
}
}
div /deep/ .el-collapse-item__content {
padding-bottom: 0;
}
div /deep/ .el-collapse-item__header {
padding-left: 20px;
}
</style>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment