一.53项目
1.1在表单域中展示图片与上传图片
-
处理方式一
- 展示图片UI
- 上传图片UI
- 业务代码
// 模板内容 // ref="elForm"用来做校验 <el-form ref="elForm" :model="formData" :rules="rules" size="medium" label-width="120px"> <div class="form-container" style="padding: 12px 34px 40px"> <el-row> <p class="textTitle">店铺信息</p> <el-col :span="12"> // 店铺标志的prop值是动态的,当上传图片组件出现时prop就是为图片,消失时就位‘’ <el-form-item label="店铺标志:" :prop="this.disabledTypeProp"> <!-- <img :src="formData.shopLogo" v-show="pointer === 1" style="width:200px;height:40px" /> --> <span v-if="pointer === 1"> <el-image :src="formData.shopLogo" style="width: 200px; height: 40px"> <div slot="error"> <div> <i class="el-icon-picture-outline"></i> <div>暂无图片</div> </div> </div> </el-image> </span> <div style="display: flex; align-items: center" v-show="pointer === 2"> // 使用上传图片组件 // ref="upload"用来获取该组件,以便后续操作 <avatar-upload ref="upload" :disabledType="disabledType" class="avatar-uploader_logo" @ok="handleAvatarSuccess" :img="formData.shopLogo" :title="'上传照片'" :Options="cropperOption" :fileType="4" Name="storeLogo" ></avatar-upload> <el-button type="text" style="magin-left: 10px; color: #165dff" @click="backImg">恢复默认</el-button> </div> <div v-if="pointer === 2"> <span class="el-icon-warning-outline"></span> <span class="tips">*建议上传长度为200px,高度为40px,背景透明的PNG格式图片</span> </div> </el-form-item> <el-form-item label="店铺名称:" prop="shopName" :rules="pointer === 1 ? [] : rules.shopName"> <span v-if="pointer === 1">{{ formData.shopName }}</span> <el-input v-if="pointer === 2" v-model="formData.shopName" placeholder="请输入店铺名称" :maxlength="20" clearable :style="{ width: '80%' }" ></el-input> </el-form-item> <el-form-item label="店铺介绍:" prop="shopDesc" :rules="pointer === 1 ? [] : rules.shopDesc"> <span v-if="pointer === 1">{{ formData.shopDesc }}</span> <el-input v-if="pointer === 2" v-model="formData.shopDesc" type="textarea" placeholder="店铺介绍" :autosize="{ minRows: 4, maxRows: 4 }" :style="{ width: '80%' }" :maxlength="500" ></el-input> </el-form-item> </el-col> </el-row> </div> </el-form> ———————————————————————————————————— // 脚本内容 import avatarUpload from '@/components/avatar-upload'; import { developerService } from '@/api'; components: { avatarUpload }, data(){ return { formData: {}, disabledTypeProp: '', pointer: 1, disabledType: true, cropperOption: { autoCropWidth: '200px', autoCropHeight: '40px', }, } }, mounted() { // 获取店铺信息,进入路由页面获取数据进行渲染 this.getShop(); }, methods:{ handleAvatarSuccess(file) { this.formData.shopLogo = file; }, // 恢复默认,通过ref控制组件的imageUrl属性值为‘’。为表单的shopLogo赋值为‘’,用来做必填校验。 backImg() { this.$refs.upload.imageUrl = ''; this.formData.shopLogo = ''; }, // 获取店铺信息 getShop() { developerService .getShopInfo() .then((res) => { if (res.code !== 0) { return this.$message.error(res.msg); } this.formData = res.data; }) .catch(() => {}); }, // 点击取消按钮,上传组件禁止点击,上传组件消失 cancel() { this.disabledType = true; // 此处可不处理,因为下面控制的上传组件已经消失 this.pointer = 1; }, // 点击编辑按钮,上传组件可点击,上传组件出现 editInfo() { this.disabledType = false; this.disabledTypeProp = 'shopLogo'; this.pointer = 2; }, // 提交,校验通过,进行弹窗询问 submitForm() { this.$refs['elForm'].validate(async (valid) => { if (!valid) { return false; } var message = '提交信息修改后需重新审核,审核中无法使用任何功能'; this.$confirm('确定提交信息修改?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning', center: true, }) .then(() => { developerService .updateShopInfo(this.formData) .then((res) => { if (res.code !== 0) { return this.$message.error(res.msg); } this.$message({ message: '提交成功', type: 'success', duration: 500, onClose: () => { this.disabledType = true; this.pointer = 1; }, }); }) .catch(() => {}); }) .catch(() => {}); }); }, } ———————————————————————————————————— <style lang="scss" rel="stylesheet/scss" scoped> .form-container { min-width: 800px; padding: 0 30px 30px 30px; .my-tip { color: #ff9500; margin-bottom: 30px; } } .textTitle { width: 100%; height: 32px; font-size: 16px; font-family: PingFangSC-Semibold, PingFang SC; font-weight: 600; color: #1d2129; line-height: 24px; margin-bottom: 16px; position: relative; margin-left: 11px; &::before { content: ''; position: absolute; top: 4px; left: -11px; width: 4px; height: 16px; background: #1d74f1; border-radius: 3px; } } .avatar-uploader_logo { /deep/.avatar-uploader { img { width: 200px; height: 40px; border-radius: 4px; } } } .el-icon-warning-outline:before { content: '\E6C9'; color: rgb(22, 93, 255); } .tips { margin-left: 5px; color: rgb(100, 106, 116); } </style>
- 引入封装好的上传图片组件,引入模块化api接口。
- 上传图片组件说明
<template> <div class="clearfix"> // auto-upload:默认值为true,当选中文件后立即执行上传。通过为其赋值为false关闭选中文件后立即上传功能。 // show-file-list:默认值为true,显示已上传文件列表。通过为其赋值为false关闭显示已上传文件的列表。 // on-change:文件状态改变时的钩子,添加文件、上传成功和上传失败时都会被调用 <el-upload class="avatar-uploader" action="" :disabled="disabledType" :auto-upload="false" :show-file-list="false" :on-change="changeUpload" ref="myUpload" > <img v-if="imageUrl" :src="imageUrl" class="avatar" :style="fixedSize" /> <div v-else class="avatar-uploader-icon"> <i class="el-icon-plus"></i> <h3>{{ title }}</h3> </div> </el-upload> <el-dialog title="图片剪裁" :visible.sync="dialogVisible" append-to-body> <div class="cropper-content"> <div class="cropper" style="text-align: center"> <vueCropper ref="cropper" :img="option.img" :outputType="option.outputType" :outputSize="option.outputSize" :info="option.info" :full="option.full" :canMove="option.canMove" :canMoveBox="option.canMoveBox" :original="option.original" :autoCrop="option.autoCrop" :fixed="option.fixed" :autoCropWidth="option.autoCropWidth" :autoCropHeight="option.autoCropHeight" :centerBox="option.centerBox" :infoTrue="option.infoTrue" :fixedBox="option.fixedBox" ></vueCropper> </div> </div> <div slot="footer" class="dialog-footer"> <el-button @click="dialogVisible = false">取 消</el-button> <el-button type="primary" @click="finish('blob', fileType)" :loading="loading">确认</el-button> </div> </el-dialog> </div> </template> <script> import { VueCropper } from 'vue-cropper'; import { getUuid } from '@/utils/index'; export default { props: { // 外部传递的图片URL地址 img: { type: String, default: '', }, // 外部传递的图片描述 title: { type: String, default: '', }, // 外部传递的图片展示尺寸 fixedSize: { type: Object, default: () => {}, }, // 外部传递的裁切框配置项 Options: { type: Object, default: () => {}, }, // 外部传递的文件名 Name: { type: String, default: '', }, // 外部传递的是否禁用 disabledType: { type: Boolean, default: false, }, // 外部传递的上传文件的一个标识,只是53项目的上传接口需要这个标识入参 fileType: { type: Number, default: 0, }, // 外部传递的上传图片的接口路径 uploadUrl: { type: String, default: '/server/user/uploadLeImg', }, }, components: { VueCropper, }, data() { return { imageUrl: '', dialogVisible: false, option: { img: '', // 图片 outputType: 'png', // 输出类型 outputSize: 1, // 剪切后的图片质量(0.1-1) full: true, // 输出原图比例截图 props名full info: true, canMove: true, // 是否拖拽裁剪框 original: true, canMoveBox: true, // 是否可移动裁剪框 autoCrop: true, autoCropWidth: '300px', // 裁切默认宽度 autoCropHeight: '200px', // 裁切默认高度 fixedBox: false, // 是否是固定大小盒子 centerBox: true, // 截图框是否被限制在图片里面 infoTrue: false, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高 }, // 防止重复提交 loading: false, fileName: this.Name + getUuid() + '.png', }; }, watch: { // 监听裁切框显示及隐藏 dialogVisible(val) { if (val) { this.option = Object.assign({}, this.option, this.Options); this.loading = false; } }, // 监听外部传入的图片URL变化 img: { handler(val) { if (val) { this.imageUrl = val; console.log('选定的图片', val); } }, deep: true, immediate: true, }, }, mounted() {}, methods: { // 没啥用 sPhoto(value) { this.imageUrl(value); }, // 选中文件 changeUpload(file) { // 1.0 先校验图片格式 const isJPG = file.raw.type === 'image/jpeg' || file.raw.type === 'image/png' || file.raw.type === 'image/jpg' || file.raw.type === 'image/bmp'; // 2.0 再校验图片大小 const isLt2M = file.size / 1024 / 1024 < 2; if (!isJPG) { this.$message.error('上传图片只能是 JPG 格式!'); return false; } if (!isLt2M) { this.$message.error('上传图片大小不能超过 2MB!'); return false; } // 上传成功后将图片地址赋值给裁剪框显示图片 console.log(file); this.$nextTick(() => { // 通过window.URL.createObjectURL()方法将图片构建为URL形式赋值给裁切框 this.option.img = window.URL.createObjectURL(file.raw); this.dialogVisible = true; }); }, // 上传图片(点击上传按钮) finish(type, fileType) { this.loading = true; let _this = this; let formData = new FormData(); // 输出 if (type === 'blob') { this.$refs.cropper.getCropBlob((data) => { let img = window.URL.createObjectURL(data); this.model = true; this.imageUrl = img; formData.append('file', data, this.fileName); if (this.uploadUrl === '/server/user/uploadLeImg') { formData.append('type', this.fileType); } this.$http .post(this.uploadUrl, formData) .then((response) => { this.loading = false; this.dialogVisible = false; var res = response.data; if (res.code === 0) { // 输出 // _this.$emit('ok', res.data[0].filepath); _this.$emit('ok', res.data); } }) .catch(() => { this.loading = false; }); }); } // else { // this.$refs.cropper.getCropData((data) => { // this.model = true // this.modelSrc = data // }) // } }, }, }; </script> <style lang="scss" rel="stylesheet/scss" scoped> .clearfix { /deep/ .avatar-uploader { display: inline-block; } /deep/ .avatar-uploader .el-upload { border: 1px dashed #d9d9d9; border-radius: 6px; cursor: pointer; position: relative; overflow: hidden; } /deep/ .avatar-uploader .el-upload:hover { border-color: #409eff; } /deep/ .avatar-uploader-icon { font-size: 28px; color: #8c939d; width: 156px; height: 156px; padding-top: 42px; //line-height: 104px; text-align: center; h3 { font-size: 12px; } } /deep/ .avatar { // width: 104px; // height: 104px; width: 82px; height: 82px; display: block; } } //图片上传 .card-photo { width: 200px; float: left; /deep/ .avatar-uploader-icon { width: 159px !important; height: 96px !important; } /deep/ .avatar { width: 159px !important; height: 96px !important; } } .big-card-photo { width: 16.7vw; height: 11.13vw; float: left; /deep/ .avatar-uploader { width: 100%; height: 100%; .el-upload { width: 100%; height: 100%; } } /deep/ .avatar-uploader-icon { width: 100% !important; height: 100%; padding-top: 20%; //height: 80%!important; } /deep/ .avatar { width: 100% !important; height: 100%; //height: 100% !important; } } .big-square { width: 10.5vw; height: 10.5vw; float: left; /deep/ .avatar-uploader { width: 100%; height: 100%; .el-upload { width: 100%; height: 100%; } } /deep/ .avatar-uploader-icon { width: 100% !important; height: 100%; padding-top: 30%; //height: 80%!important; } /deep/ .avatar { width: 100% !important; height: 100%; //height: 100% !important; } } .cropper-content { .cropper { width: auto; height: 500px; } } </style>
<template> <avatar-upload class="avatar-uploader" :fixedSize="{ width: '104px', height: '104px' }" :options="{ autoCropWidth: '208px', autoCropHeight: '208px', fixedBox: true }" @ok="handleAvatarSuccess" :img="data.headUrl" :title="'上传头像'" > </avatar-upload> // 上传图片的提示 <div> <span class="el-icon-warning-outline"></span> <span class="tips">*建议上传长度为104px,高度为104px,背景透明的PNG格式图片</span> </div> </template> <script> import avatarUpload from '@/components/avatar-upload'; export default { components: { avatarUpload }, } </script>
-
上传图片使用规范
1.4.1:组件原理说明:对el-upload组件进行了二次封装,对vueCropper组件进行了二次封装。
在外层引用并使用该组件时,通过给组件传值来控制其功能与展示。
外部传入的fixedSize属性控制图片的展示,组件<el-upload>的部分样式从fixedSize中取值运行,fixedSize属性默认为空对象,此时图片尺寸等不受限制。fixedSize属性由外部传入时,需要以style类型的样式出现,图片尺寸等受其控制。
外部传入的Options属性控制截图功能,裁切组件<vueCropper>从Options中取值来运行,Options可以控制裁切组件的初始功能。
组件<el-upload>完成上传功能后,会去触发引用并使用他的组件身上的ok事件,在他的回调中去修改img的值。
外部传入的img属性控制组件展示那个图片,组件<el-upload>从img中取值来展示图片,img可以控制组件展示哪张图片。
1.4.2:上传图片的提示:组件下面补充的提示根据需要来判断是否使用。
1.4.3:使用场景。
- 图片尺寸固定
- 类名class="avatar-uploader"是组件自带的,无需改动。
- 属性fixedSize:控制图片是否需要固定尺寸进行展示、需要什么样的尺寸进行展示。 应用详解 :fixedSize="{ width: '104px', height: '104px' }"控制图片展示的固定尺寸为宽度104px、高度104px,可人为修改。
- 属性Options:控制图片截图。
- 应用详解 :Options="{ autoCropWidth: '104px', autoCropHeight: '104px' ,fixedBox: true}"控制初始截图尺寸为宽度104px、高度104px,无法进行拖拽修改。此配置项可人为修改初始尺寸,也可修改是否固定裁切尺寸。
- fixedBox控制裁切区域是否可拖拽修改,值为false则可拖拽修改,值为true则不可拖拽修改。
- 属性@ok:为图片上传成功以后的回调,无需改动。
- 属性img:展示的图片,无需改动。
- 属性title:组件的标题,可人为修改。如图
- 图片尺寸非固定
- 删除fixedSize属性即可,其他属性无需变化。
-
- 接口文件
import axios from '@/utils/newRequestHttp';
const developerService = {
// async getApplicationList(data) {
// return axios({
// url: '/server/item/list',
// method: 'post',
// data
// })
// },
// 查看数据表
async queryTableNames (id) {
return axios({
url: `/server/dataSource/queryTableNames?sourceId=${id}`,
method: 'get',
})
},
// 新建应用
async addNewApp (data) {
return axios({
url: `/server/item/create`,
method: 'post',
data
})
},
// 首页--热门资产表
async querySource (data) {
return axios({
url: `/server/item/queryOrderByNum`,
method: 'post',
data
})
},
// 首页应用统计
async queryApp (data) {
return axios({
url: `/server/item/queryApplicationNum`,
method: 'post',
data
})
},
// 首页交易数据
async queryTradeNum (data) {
return axios({
url: `/server/item/queryTradeNum`,
method: 'post',
data
})
},
// 店铺浏览量
async queryShop (data) {
return axios({
url: `/server/item/queryStoreViewNum`,
method: 'post',
data
})
},
// 关联资产
async queryPageItem (data) {
return axios({
url: `/server/item/queryPageRelateSources`,
method: 'post',
data
})
},
// 预览
async getPreview (id) {
return axios({
url: `/server/item/dataApplicationPreview?itemId=${id}`,
method: 'get',
})
},
// 新增数据源
async addSources (data) {
return axios({
url: '/server/item/dataSourceAdd',
method: 'post',
data
})
},
// 修改数据源
async updateSources (data) {
return axios({
url: '/server/item/dataSourceUpdate',
method: 'post',
data
})
},
// 获取数据资产表
async getSources (data) {
return axios({
url: '/server/dataSource/querySourcesPage',
method: 'post',
data
})
},
// 数据资产表详情查看
async getSourcesDetail (id) {
return axios({
url: `/server/dataSource/querySourceDetail?sourceId=${id}`,
method: 'post',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
})
},
// 获取数据应用关联资产-表数据
async getSourcesTable (data) {
return axios({
url: '/server/dataSource/queryRelateSources',
method: 'post',
data
})
},
// 配置数据源sql测试
async testSql (data) {
return axios({
url: '/server/item/connectionTestSql',
method: 'post',
data
})
},
// 修改商品
async updateGoods (data) {
return axios({
url: '/server/item/update',
method: 'post',
data
})
},
// 获取店铺信息
async getShopInfo () {
return axios({
url: '/server/user/queryShopInfo',
method: 'post',
})
},
// 获取公司信息
async getEnterpriseInfo () {
return axios({
url: '/server/user/queryEnterpriseInfo',
method: 'post',
})
},
// 编辑店铺信息
async updateShopInfo (data) {
return axios({
url: '/server/user/updateShopInfo',
method: 'post',
data
})
},
// 订单管理--查看详情
async getOrderDetail (id) {
return axios({
url: `/server/order/orderDetailByseller/${id}`,
headers: {
'content-type': 'application/x-www-form-urlencoded'
},
method: 'post',
})
},
// 查看数据源详情
async getDataSourceDetail (data) {
return axios({
url: '/server/item/dataSourceDetail',
method: 'post',
data
})
},
// 查看源数据字典
async getDataDictionary (data) {
return axios({
url: '/server/dataSource/queryRelateSources',
method: 'post',
data
})
},
// 上传应用图片
async uploadImg (data) {
return axios({
url: '/server/item/uploadApplicationImgPath',
method: 'post',
data
})
},
// 上传附件
async uploadFile (data) {
return axios({
url: '/server/item/uploadApplicationDemoFilePath',
method: 'post',
data
})
},
// 批量删除数据源
async deleteDataSource (data) {
return axios({
url: '/server/item/dataSourceBatchDelete',
method: 'post',
data
})
},
// 批量导入输入源
async batchImport (url, data) {
return axios({
url: url,
method: 'post',
data
})
},
// 批量导入输出源
async batchDown (data) {
return axios({
url: '/server/item/uploadOutputExcel',
method: 'post',
data
})
},
// 校验能否下架
async checkItemOff (data) {
return axios({
url: '/server/item/checkItemOff',
method: 'post',
data
})
},
// 上下架
async putOnApplication (data) {
return axios({
url: '/server/item/statusChange',
method: 'post',
data
})
},
// 查看应用详情
async getApplicationDetail (id) {
return axios({
url: `/server/item/itemDetail?itemId=${id}`,
method: 'get',
})
},
// 删除订单
// async deleteOrder(id) {
// return axios({
// url: `/server/order?orderId=${id}`,
// method: 'delete',
// })
// },
// 获取数据源字典列表
async getDataSourceDictionaryList(data){
return axios({
url: '/server/dataSource/queryPageDataDictionary',
method: 'post',
data
})
}
}
export default developerService;
1.2 在表单域中上传图片并且进行图片必填校验
-
<el-form-item label="应用图标:" prop="images"> // 隐藏表单input框 <el-input v-show="false" v-model="formData.images" /> <el-tooltip placement="right" effect="light"> <div slot="content"> <div class="img-desc"> <h3>支持图片格式:jpg/jpeg/png/bmp格式;</h3> </div> </div> // 使用组件 <avatar-upload class="avatar-uploader" uploadUrl="/server/item/uploadApplicationImgPath" :fixedSize="{ width: '156px', height: '156px' }" :Options="{ autoCropWidth: '208px', autoCropHeight: '208px' }" @ok="handleAvatarSuccess" :img="formData.images" :title="'上传照片'" ></avatar-upload> </el-tooltip> </el-form-item> ———————————————————————————— // 上传照片 handleAvatarSuccess(file) { this.imageUrl = this.formData.images = file; },
1.3在表单域上传附件
-
<el-form-item prop="uploadAttachment"> <el-input v-show="false" v-model="formData.uploadAttachment" /> // drag:是否启用拖拽上传 <el-upload class="upload-demo" drag :before-upload="beforeUpload" action="#" :http-request="uploadFile" :on-remove="handleRemove" :limit="1" accept=".zip" :on-exceed="handleExceed" > <i class="el-icon-plus"></i> <div class="el-upload__text"> <div>点击此处或拖拽文件到此处上传文件</div> 支持zip格式文件,单个文件最大为10M </div> </el-upload> </el-form-item> —————————————————————————————————————— // 附件上传前校验 beforeUpload(file) { const sizeLimit = file.size / 1024 / 1024 > 10; if (sizeLimit) { this.$message.warning('上传文件大小不能超过 10MB!'); } const fileFamart = file.name.split('.')[file.name.split('.').length - 1]; if (fileFamart !== 'zip') { this.$message.warning('必须上传zip格式的文件!'); } return !sizeLimit && fileFamart === 'zip'; }, // 附件上传 uploadFile(item) { const fileObj = item.file; let formData = new FormData(); formData.append('file', fileObj); developerService .uploadFile(formData) .then((res) => { if (res.code === 0) { this.$message.success('上传成功!'); this.formData.uploadAttachment = res.data; this.formData.uploadAttachmentName = item.file.name; } }) .catch(() => {}); }, // 移除文件 handleRemove() { this.formData.uploadAttachment = ''; }, // 上传个数限制 handleExceed(files, fileList) { this.$message.warning(`当前限制选择 1个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`); },
2.时间查询
- 处理方式一
-
<el-form-item label="创建时间:"> <el-date-picker v-model="dataForm.dateRange" type="daterange" value-format="yyyy-MM-dd HH:mm:ss" :range-separator="$t('datePicker.range')" start-placeholder="开始时间" end-placeholder="结束时间" > </el-date-picker> </el-form-item> —————————————————————————— // 脚本 dataForm: { type: 'DATA_APPLICATION', categoryId: '', categoryName: '', code: '', name: '', dateRange: [], }, // 点击查询,先看时间是否有值,有值的话就是数组中2个元素。第一个就是开始时间,第二个就是结束时间 getList() { if (this.dataForm.dateRange) { var array = this.dataForm.dateRange; // 将开始时间赋值给startTime,将结束时间赋值给endTime if (array.length === 2) { this.dataForm.startTime = array[0]; this.dataForm.endTime = array[1]; } else { // 时间不为2个元素的数组时,将开始时间与结束时间都置空 this.dataForm.startTime = ''; this.dataForm.endTime = ''; } } else { // 无时间时,将开始时间与结束时间都置空 this.dataForm.startTime = ''; this.dataForm.endTime = ''; } // 将当前页置为1 this.current = 1; // 发起请求 this.getDataList(); }, // 重置,将表单的每一项单独的重置为空。开始时间与结束时间在每次查询时再进行处理。 clearData() { this.dataForm.dateRange = []; this.current = 1; this.getList(); },
-
2.处理方式二
<el-form-item label="录入时间:" prop="createDate">
<el-date-picker
v-model="dataForm.createDate"
@change="changeTime"
type="daterange"
value-format="yyyy-MM-dd HH:mm:ss"
:range-separator="$t('datePicker.range')"
start-placeholder="开始时间"
end-placeholder="结束时间"
>
</el-date-picker>
</el-form-item>
————————————————————————————————————
// 表单域数据
dataForm: {
startTime: '', // 数据库查询开始时间
endTime: '', // 数据库查询结束时间
},
// 查询时间(开始时间、结束时间)
async changeTime(e) {
if (!e) {
this.dataForm.startTime = '';
this.dataForm.endTime = '';
return;
}
this.dataForm.startTime = e[0];
this.dataForm.endTime = e[1];
},
// 重置表单域
clearData() {
this.$refs['elForm'].resetFields();
this.dataForm.startTime = '';
this.dataForm.endTime = '';
this.getDataList();
},
3.选择框单选
- 处理方式一
-
<el-form-item label="订单状态:"> <el-select v-model="dataForm.status" clearable placeholder="请选择订单状态"> <el-option v-for="item in statusList" :key="item.value" :label="item.label" :value="item.value"> </el-option> </el-select> </el-form-item> —————————————————————————————— // 脚本 dataForm: { status: '', }, statusList: [ { label: '待支付', value: 'TO_PAY', }, { label: '已支付', value: 'PAY_SUCCESS', }, { label: '已失效', value: 'CANCEL', }, ],
-
4. 表格格式化处理
- 处理方式一
-
<el-table v-loading="dataListLoading" :data="dataList" style="width: 100%"> // show-overflow-tooltip:当内容过长被隐藏时显示 tooltip <el-table-column prop="orderId" label="订单编号" header-align="left" align="left" show-overflow-tooltip></el-table-column> // 表格的插槽技术 <el-table-column prop="status" label="订单状态" header-align="left" align="left"> <template slot-scope="scope"> <span :class="getColumnClass(scope.row.status)"> {{ scope.row.statusDesc }} </span> </template> </el-table-column> // 插槽内部使用全局过滤器 <el-table-column label="下单时间" show-overflow-tooltip header-align="left" align="left" width="150px;" prop="createDate"> <template slot-scope="scope">{{ scope.row.createDate | dateformat('YYYY-MM-DD HH:mm:ss') }}</template> </el-table-column> <el-table-column label="完成时间" header-align="left" align="left" width="150px;" show-overflow-tooltip prop="orderPayment"> <template slot-scope="scope" v-if="scope.row.orderPayment.payDate"> <span v-if="scope.row.orderPayment.payDate"> {{ scope.row.orderPayment.payDate | dateformat('YYYY-MM-DD HH:mm:ss') }}</span> <span v-else>-</span> </template> </el-table-column> <el-table-column prop="itemId" label="应用编号" header-align="left" align="left" show-overflow-tooltip></el-table-column> <el-table-column prop="itemName" label="应用名称" header-align="left" align="left" show-overflow-tooltip></el-table-column> <el-table-column prop="itemCount" label="应用数量" header-align="left" align="left"></el-table-column> <el-table-column prop="totalAmount" label="订单金额" header-align="left" align="left"> <template slot-scope="scope"> <!-- {{ $moneyFormat(scope.row.totalAmount) }} --> {{ scope.row.totalAmount }} </template> </el-table-column> <el-table-column prop="userName" label="消费者账号" header-align="left" align="left"></el-table-column> <el-table-column prop="blockchainId" label="区块链交易码" header-align="left" align="left" show-overflow-tooltip> <template slot-scope="scope"> {{ scope.row.blockchainId || '-' }} </template> </el-table-column> <el-table-column :label="$t('handle')" fixed="right" header-align="left" align="left"> <template slot-scope="scope"> <el-button type="text" size="" @click="detail(scope.row.orderId)">查看</el-button> <!-- <el-button type="text" size="" @click="del(scope.row.orderId)">删除</el-button> --> </template> </el-table-column> </el-table> —————————————————————————————— 全局过滤器在main.js内部使用 import moment from 'moment'; Vue.filter('dateformat', function (dataStr, pattern = 'YYYY-MM-DD HH:mm:ss') { if (dataStr) { return moment(dataStr).format(pattern); } else { return ''; } });
-
5.表单域校验图片必填
- 处理方式一
-
<el-form-item label="应用图标:" prop="images"> <el-input v-show="false" v-model="formData.images" /> <el-tooltip placement="right" effect="light"> <div slot="content"> <div class="img-desc"> <h3>支持图片格式:jpg/jpeg/png/bmp格式;</h3> </div> </div> <avatar-upload class="avatar-uploader" uploadUrl="/server/item/uploadApplicationImgPath" :fixedSize="{ width: '156px', height: '156px' }" :Options="{ autoCropWidth: '208px', autoCropHeight: '208px' }" @ok="handleAvatarSuccess" :img="formData.images" :title="'上传照片'" ></avatar-upload> </el-tooltip> </el-form-item> ———————————————————————————— 隐藏表单input框
-
6.表单域标签必填校验
-
<el-form-item label="标签:" prop="tags" class="tbgswidth"> <el-input v-show="false" v-model="formData.tags" /> <span v-for="(item, index) in sourceTags" :key="index" class="showTagsBtn"> {{ item.tagName }} <i @click="deltag(item)" class="el-icon-arrow-right el-icon-close"></i> </span> <span class="pushTagsBtn" @click="addTags"><i class="el-icon-arrow-right el-icon-plus"></i> 添加标签</span> <span v-show="isHasTags" class="noHasTags">该分类下暂无标签,请重新选择分类</span> </el-form-item> <!-- 标签弹层 --> <el-dialog title="添加标签" :visible.sync="dialogVisible" width="30%"> <el-tabs tab-position="left" style="height: 200px; margin-top: 12px"> <el-tab-pane :label="paneLabel"> <el-tag v-for="(item, index) in tagschild" :key="index" @click="pushTags(item)"> {{ item.tagName }} </el-tag> </el-tab-pane> </el-tabs> </el-dialog> ———————————————————————————————————— dialogVisible: false, sourceTags: [], // 新增标签 addTags() { if (!this.formData.categoryId) { this.$message.error('请先选择应用分类'); return; } else { this.dialogVisible = true; } }, // 推送标签 pushTags(obj) { if (this.sourceTags.length >= 4) { return this.$message.error('标签不得超过4个'); } let temp = this.sourceTags.some((item) => item == obj); if (temp) { return this.$message.error('请勿重复添加标签!'); } this.sourceTags.push(obj); let arr = []; // 收集标签id this.sourceTags.forEach((item) => { arr.push(item.id); }); this.formData.tags = JSON.stringify(arr); // 此处转为字符串,做表单校验用 }, // 删除标签 deltag(obj) { this.sourceTags = this.sourceTags.filter((item) => item !== obj); let arr = []; // 收集标签id this.sourceTags.forEach((item) => { arr.push(item.id); }); this.formData.tags = JSON.stringify(arr) === '[]' ? '' : JSON.stringify(arr); // 此处转为字符串,做表单校验用 },
7.表单无数据,新增参数可添加 ,可批量删除,可批量导入
-
<el-table ref="multipleTable" :data="dataList" @selection-change="dataListSelectionChangeHandle" :header-cell-class-name="DisableSelection ? 'cellClass' : ''" style="color: #202328; margin: 20px 0px" > <el-table-column type="selection" width="50" :selectable="isSelectable"> </el-table-column> <el-table-column prop="fieldName" label="参数名称" header-align="left" align="left"></el-table-column> <el-table-column prop="fieldType" label="数据类型" header-align="left" align="left"></el-table-column> <el-table-column prop="description" label="定义说明" header-align="left" align="left"></el-table-column> <el-table-column prop="algorithmType" label="加密类型"> <template slot-scope="scope">{{ getType(scope.row.algorithmType) }}</template> </el-table-column> </el-table> <!-- 新增参数 --> <el-dialog title="新增参数" :visible.sync="addNewVisible" width="30%" :before-close="handleClose"> <el-form label-width="100px" :model="formLabelAlign" ref="formLabelAlign" style="margin: 20px" :rules="formRules"> <el-form-item label="参数名称:" prop="fieldName"> <el-input v-model="formLabelAlign.fieldName"></el-input> </el-form-item> <el-form-item label="数据类型:" prop="fieldType"> <el-input v-model="formLabelAlign.fieldType"></el-input> </el-form-item> <el-form-item label="定义说明:" prop="description"> <el-input v-model="formLabelAlign.description"></el-input> </el-form-item> <el-form-item label="加密类型:" prop="algorithmType"> <el-select v-model="formLabelAlign.algorithmType" placeholder="请选择加密类型" clearable :style="{ width: '100%' }"> <el-option v-for="item in algorithmType" :key="item.id" :label="item.name" :value="item.id"></el-option> </el-select> </el-form-item> </el-form> <span slot="footer" class="dialog-footer"> <el-button @click="resetForm('formLabelAlign')" class="cancelBtn">返回</el-button> <el-button type="primary" @click="addNewBtn('formLabelAlign')">确认</el-button> </span> </el-dialog> <!-- 批量导入 --> <el-dialog title="批量导入" :visible.sync="importVisible" width="50%" :before-close="handleClose"> // 使用组件 <batch-import ref="batchImport" @closeDialog="closeDialog" :batchType="batchType" :batchdownloadUrl="batchdownloadUrl" :batchImportUrl="batchImportUrl" ></batch-import> <span slot="footer" class="dialog-footer"> <el-button @click="importVisible = false" class="cancelBtn">返回</el-button> <el-button type="primary" @click="newUpload">确定</el-button> </span> </el-dialog> __________________________________ // 数据 dataList: [], outSelectedList: [], // 所勾选的数据定义 batchType: '', importVisible: false, batchdownloadUrl: '/server/item/downloadInputTempGYS', batchImportUrl: '/server/item/uploadInputExcelGYS', // 方法 // 新增参数--确认 addNewBtn(formLabelAlign) { this.$refs[formLabelAlign].validate((valid) => { if (valid) { const newForm = { fieldName: this.formLabelAlign.fieldName, fieldType: this.formLabelAlign.fieldType, description: this.formLabelAlign.description, algorithmType: this.formLabelAlign.algorithmType, dataSourceProvider: 2, }; this.dataList.unshift(newForm); // 做复选框回显 this.$nextTick(() => { this.toggleSelection(); }); this.addNewVisible = false; // 重置表单域字段 this.$refs[formLabelAlign].resetFields(); } else { console.log('error submit!!'); return false; } }); }, // 做复选框回显 toggleSelection(rows) { if (rows) { rows.forEach((row) => { this.$refs.multipleTable.toggleRowSelection(row); }); } else { this.$refs.multipleTable.clearSelection(); } }, // 用于保存选中的行 dataListSelectionChangeHandle(val) { this.outSelectedList = val; }, // 批量删除 deleteSelected() { if (this.outSelectedList.length > 0) { this.$confirm('此操作将批量删除, 是否继续?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning', }).then(() => { let val = this.outSelectedList; //选中的值 if (val) { val.forEach((val, index) => { this.dataList.forEach((v, i) => { if (val.fieldName === v.fieldName) { this.dataList.splice(i, 1); } }); }); } this.$message.success('删除成功'); }); } else { this.$message.error('请选择删除项!'); } }, // 批量导入 batchImport() { this.importVisible = true; this.batchType = 'in'; }, closeDialog(data) { // list数组去除相同参数数据,以导入的表格数据为准 let newList = this.dataList.filter((item) => !data.some((ele) => ele.fieldName === item.fieldName)); this.dataList = data.concat(newList); },
上传与下载组件
<template> <div class="uploadBox"> <el-upload class="upload-demo" :before-upload="beforeAvatarUpload" :on-change="changeData" action="#" :http-request="downLoad" :on-error="uploadFalse" :on-remove="handleRemove" accept=".xlsx" :file-list="fileList" > <el-button size="small" type="primary">上传文件</el-button> <div slot="tip" class="el-upload__tip">支持拓展名: .xlsx<el-button type="text" @click="downloadFile">下载模板</el-button></div> </el-upload> </div> </template> <script> import { developerService, operationService } from '@/api'; import { readFile } from 'vxe-table'; export default { data() { return { fileList: [], fileListTemp: [], }; }, props: { batchType: String, batchdownloadUrl: String, batchImportUrl: String, }, methods: { // 下载模板 async downloadFile() { if (this.batchType === 'in') { operationService .downloadFileIn(this.batchdownloadUrl) .then(async (res) => { if (res.data.type == 'application/json') { const readF = new FileReader(); readF.readAsText(res, 'utf-8'); readF.onload = () => { const { msg } = JSON.parse(readF.result); this.$message.error(msg); }; } const disposition = res.headers['content-disposition']; const matches = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/.exec(disposition); const filename = matches[1].replace(/['"]/g, ''); const rfilename = decodeURI(filename); const blob = new Blob([res.data], { type: 'application/vnd.ms-excel', }); const url = window.URL.createObjectURL(blob); const link = document.createElement('a'); link.style.display = 'none'; link.href = url; link.download = `${rfilename}`; document.body.appendChild(link); link.click(); document.body.removeChild(link); this.$message({ type: 'success', message: '下载模板成功!', }); }) .catch(() => {}); } else if ((this.batchType = 'out')) { operationService .downloadFileOut() .then((res) => { if (res.data.type == 'application/json') { const readF = new FileReader(); readF.readAsText(res, 'utf-8'); readF.onload = () => { const { msg } = JSON.parse(readF.result); this.$message.error(msg); }; } const disposition = res.headers['content-disposition']; const matches = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/.exec(disposition); const filename = matches[1].replace(/['"]/g, ''); const rfilename = decodeURI(filename); const blob = new Blob([res.data], { type: 'application/vnd.ms-excel', }); const url = window.URL.createObjectURL(blob); const link = document.createElement('a'); link.style.display = 'none'; link.href = url; link.download = `${rfilename}`; document.body.appendChild(link); link.click(); document.body.removeChild(link); this.$message({ type: 'success', message: '下载模板成功!', }); }) .catch(() => {}); } // const a = document.createElement('a'); // a.href = this.uploadAddress; // a.click(); // window.URL.revokeObjectURL(this.uploadAddress); }, // 上传 downLoad(item) { console.log(this.batchType); const fileObj = item.file; let formData = new FormData(); formData.append('file', fileObj); if (this.batchType === 'in') { developerService .batchImport(this.batchImportUrl, formData) .then((res) => { if (res.code !== 0) { this.fileList = []; return this.$message.error(res.msg); } if (res.code === 0) { this.$message.success('上传成功!'); let data = res.data; this.fileList = this.fileListTemp; this.$emit('closeDialog', data); } }) .catch(() => {}); } else if ((this.batchType = 'out')) { developerService .batchImport(this.batchImportUrl, formData) .then((res) => { if (res.code !== 0) { this.fileList = []; return this.$message.error(res.msg); } if (res.code === 0) { this.$message.success('上传成功!'); let data = res.data; this.fileList = this.fileListTemp; this.$emit('closeDialog', data); } }) .catch(() => {}); } }, // 上传失败时的钩子 uploadFalse(response, file, fileList) { this.$message({ message: 'excel文件上传失败!', type: 'error', }); }, // 移除文件 handleRemove() { this.fileList = []; }, // 上传前对文件的大小的判断 beforeAvatarUpload(file) { const isLt10M = file.size / 1024 / 1024 > 10; const extension = file.name.split('.')[1] === 'xlsx'; if (isLt10M) { this.$message.warning('上传模板大小不能超过 10MB!'); } if (!extension) { this.$message.warning('上传模板只能是xlsx格式!'); } return extension || isLt10M; }, // 文件变化执行 changeData(file, fileList) { this.fileList = []; // 再次上传覆盖之前的文件 if (fileList.length > 1) { fileList.splice(0, 1); } this.fileListTemp = fileList; }, }, }; </script> <style lang="scss" scoped> /deep/.el-upload__tip { font-size: 14px; } .uploadBox { padding: 30px; } </style>
引入模块化URL
import axios from '@/utils/newRequestHttp'; const developerService = { // async getApplicationList(data) { // return axios({ // url: '/server/item/list', // method: 'post', // data // }) // }, // 查看数据表 async queryTableNames (id) { return axios({ url: `/server/dataSource/queryTableNames?sourceId=${id}`, method: 'get', }) }, // 新建应用 async addNewApp (data) { return axios({ url: `/server/item/create`, method: 'post', data }) }, // 首页--热门资产表 async querySource (data) { return axios({ url: `/server/item/queryOrderByNum`, method: 'post', data }) }, // 首页应用统计 async queryApp (data) { return axios({ url: `/server/item/queryApplicationNum`, method: 'post', data }) }, // 首页交易数据 async queryTradeNum (data) { return axios({ url: `/server/item/queryTradeNum`, method: 'post', data }) }, // 店铺浏览量 async queryShop (data) { return axios({ url: `/server/item/queryStoreViewNum`, method: 'post', data }) }, // 关联资产 async queryPageItem (data) { return axios({ url: `/server/item/queryPageRelateSources`, method: 'post', data }) }, // 预览 async getPreview (id) { return axios({ url: `/server/item/dataApplicationPreview?itemId=${id}`, method: 'get', }) }, // 新增数据源 async addSources (data) { return axios({ url: '/server/item/dataSourceAdd', method: 'post', data }) }, // 修改数据源 async updateSources (data) { return axios({ url: '/server/item/dataSourceUpdate', method: 'post', data }) }, // 获取数据资产表 async getSources (data) { return axios({ url: '/server/dataSource/querySourcesPage', method: 'post', data }) }, // 数据资产表详情查看 async getSourcesDetail (id) { return axios({ url: `/server/dataSource/querySourceDetail?sourceId=${id}`, method: 'post', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, }) }, // 获取数据应用关联资产-表数据 async getSourcesTable (data) { return axios({ url: '/server/dataSource/queryRelateSources', method: 'post', data }) }, // 配置数据源sql测试 async testSql (data) { return axios({ url: '/server/item/connectionTestSql', method: 'post', data }) }, // 修改商品 async updateGoods (data) { return axios({ url: '/server/item/update', method: 'post', data }) }, // 获取店铺信息 async getShopInfo () { return axios({ url: '/server/user/queryShopInfo', method: 'post', }) }, // 获取公司信息 async getEnterpriseInfo () { return axios({ url: '/server/user/queryEnterpriseInfo', method: 'post', }) }, // 编辑店铺信息 async updateShopInfo (data) { return axios({ url: '/server/user/updateShopInfo', method: 'post', data }) }, // 订单管理--查看详情 async getOrderDetail (id) { return axios({ url: `/server/order/orderDetailByseller/${id}`, headers: { 'content-type': 'application/x-www-form-urlencoded' }, method: 'post', }) }, // 查看数据源详情 async getDataSourceDetail (data) { return axios({ url: '/server/item/dataSourceDetail', method: 'post', data }) }, // 查看源数据字典 async getDataDictionary (data) { return axios({ url: '/server/dataSource/queryRelateSources', method: 'post', data }) }, // 上传应用图片 async uploadImg (data) { return axios({ url: '/server/item/uploadApplicationImgPath', method: 'post', data }) }, // 上传附件 async uploadFile (data) { return axios({ url: '/server/item/uploadApplicationDemoFilePath', method: 'post', data }) }, // 批量删除数据源 async deleteDataSource (data) { return axios({ url: '/server/item/dataSourceBatchDelete', method: 'post', data }) }, // 批量导入输入源 async batchImport (url, data) { return axios({ url: url, method: 'post', data }) }, // 批量导入输出源 async batchDown (data) { return axios({ url: '/server/item/uploadOutputExcel', method: 'post', data }) }, // 校验能否下架 async checkItemOff (data) { return axios({ url: '/server/item/checkItemOff', method: 'post', data }) }, // 上下架 async putOnApplication (data) { return axios({ url: '/server/item/statusChange', method: 'post', data }) }, // 查看应用详情 async getApplicationDetail (id) { return axios({ url: `/server/item/itemDetail?itemId=${id}`, method: 'get', }) }, // 删除订单 // async deleteOrder(id) { // return axios({ // url: `/server/order?orderId=${id}`, // method: 'delete', // }) // }, // 获取数据源字典列表 async getDataSourceDictionaryList(data){ return axios({ url: '/server/dataSource/queryPageDataDictionary', method: 'post', data }) } } export default developerService;
import axios from '@/utils/requestHttp'; const operationService = { // 下载输入附件 async downloadFileIn(url) { return axios({ url: url, method: 'get', responseType: 'blob', }); }, // 下载输出附件 async downloadFileOut() { return axios({ url: '/server/item/downloadOutputTemp', method: 'get', responseType: 'blob', }); }, // 消費者列表 async getApplicationList(data) { return axios({ url: '/server/item/list', method: 'post', data, }); }, // 更换u盾 async updateStatus(data) { return axios({ url: '/server/user/updateUShield', method: 'post', data, }); }, // 更新额度 async updateQuota(data) { return axios({ url: '/server/user/updateQuota', method: 'post', data, }); }, // 查看额度明细 async queryQuotaDetail(data) { return axios({ url: '/server/user/queryQuotaByPage', method: 'post', data, }); }, // 修改用户状态--启用/禁用 async updateUser(data) { return axios({ url: '/server/user/updateUserStatus', method: 'post', data, }); }, // 查看详情 async getApplicationDetail(id) { return axios({ url: `/server/user/queryConsumerDetail?id=${id}`, method: 'get', }); }, //订单管理--使用明细 async useDetail(data) { return axios({ url: `/server/order/orderUserDetail/${data}`, method: 'post', }); }, // 查询资产/商品分类列表 async getAssetsList(data) { return axios({ url: `/server/sourceClassification/queryAll?classify=${data}`, method: 'get', }); }, // 查询资产/商品分页查询 async querySourceClassification(data) { return axios({ url: `/server/sourceClassification/querySourceClassification`, method: 'post', data, }); }, // 查询资产/商品分类详情 async getAssetsDetail(data) { return axios({ url: `/server/sourceClassification/queryTagsByParentId`, method: 'post', data, }); }, // 新增资产/商品分类 async addAssets(data) { return axios({ url: `/server/sourceClassification/addSourceClassification`, method: 'post', data, }); }, // 修改资产/商品分类 async updateAssets(data) { return axios({ url: `/server/sourceClassification/updateSourceClassification`, method: 'post', data, }); }, // 分页查询资产/商品分类 async queryAssets(data) { return axios({ url: `/server/sourceClassification/querySourceClassification`, method: 'post', data, }); }, // 删除资产/商品分类 async deleteAssets(data) { return axios({ url: `/server/sourceClassification/deleteSourceClassification?id=${data}`, method: 'delete', }); }, //新增标签 async addTags(data) { return axios({ url: `/server/sourceClassification/addTag`, method: 'post', data, }); }, // 删除标签 async deleteTags(data) { return axios({ url: `/server/sourceClassification/deleteTag?id=${data}`, method: 'delete', }); }, // 修改标签 async updateTags(data) { return axios({ url: `/server/sourceClassification/updateTag`, method: 'POST', data, }); }, }; export default operationService;
8.下载解析
import { operationService } from '@/api';
// 接口请求
operationService.downloadFileIn(this.batchdownloadUrl)
.then(async (res) => {
// 返回流文件,如果流文件的data中的type为json,那么返回的信息我们要解析出来看看是不是报错了
if (res.data.type == 'application/json') {
const readF = new FileReader();
readF.readAsText(res, 'utf-8');
readF.onload = () => {
const { msg } = JSON.parse(readF.result);
this.$message.error(msg);
};
}
// 在返回的信息headers中读取content-disposition,再通过正则找到文件名
const disposition = res.headers['content-disposition'];
const matches = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/.exec(disposition);
const filename = matches[1].replace(/['"]/g, '');
const rfilename = decodeURI(filename);
// 将流文件解析成具体的文件并下载
const blob = new Blob([res.data], {
type: 'application/vnd.ms-excel',
});
const url = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.style.display = 'none';
link.href = url;
link.download = `${rfilename}`;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
this.$message({
type: 'success',
message: '下载模板成功!',
});
})
.catch(() => {});
src / api / index.js
import operationService from './operationService';
export { operationService };
src / api / operationService.js
import axios from '@/utils/requestHttp';
const operationService = {
// 下载输入附件
async downloadFileIn(url) {
return axios({
url: url,
method: 'get',
responseType: 'blob',
});
},
};
export default operationService;
9.代码编辑器
<div class="editorExample">
<div class="editor">
<editor-box
:value="JSON.parse(JSON.stringify(codeValue, null, '\t'))"
language="dockerfile"
:optionsP="options"
@change="change"
></editor-box>
</div>
</div>
___________________
codeValue: '',
options: {
enableBasicAutocompletion: true, // 启用基本自动完成
enableSnippets: true, // 启用代码段
enableLiveAutocompletion: true, // 启用实时自动完成
printMarginColumn: 30,
displayIndentGuides: false, // 显示参考线
enableEmmet: true, // 启用Emmet
tabSize: 6, // 标签大小
fontSize: 14, // 设置字号
useWorker: true, // 使用辅助对象
showPrintMargin: false, // 去除编辑器里的竖线
enableMultiselect: true, // 选中多处
readOnly: false, // 是否只读
showFoldWidgets: true, // 显示折叠部件
fadeFoldWidgets: true, // 淡入折叠部件
wrap: this.iswrap === 'yes' ? true : false, // 换行
},
// 接收codevalue数据
change(val) {
let value = val;
this.codeValue = JSON.parse(JSON.stringify(value));
},
代码编辑器:使用vue2-ace-editor库
<template>
<div class="echart-pie-wrap">
<div class="myEditorTop"></div>
<editor ref="myEditor" @init="editorInit" :value="value" width="100%" :lang="language" theme="monokai" :options="options"></editor>
</div>
</template>
<script>
import '@/utils/archives/flexible';
import Editor from 'vue2-ace-editor';
// 主题
import 'brace/theme/monokai';
// 代码片段
import 'brace/snippets/javascript';
import 'brace/snippets/dockerfile';
import 'brace/snippets/python';
import 'brace/snippets/php';
import 'brace/snippets/html';
import 'brace/snippets/css';
import 'brace/snippets/ruby';
// 代码语言
import 'brace/mode/javascript';
import 'brace/mode/dockerfile';
import 'brace/mode/python';
import 'brace/mode/php';
import 'brace/mode/html';
import 'brace/mode/ruby';
import 'brace/mode/css';
// 语言扩展
import 'brace/ext/language_tools';
import 'brace/ext/emmet';
import 'brace/ext/beautify';
import 'brace/ext/searchbox';
import 'brace/ext/chromevox';
import 'brace/ext/error_marker';
import 'brace/ext/keybinding_menu';
import 'brace/ext/linking';
import 'brace/ext/modelist';
import 'brace/ext/old_ie';
import 'brace/ext/settings_menu';
import 'brace/ext/spellcheck';
import 'brace/ext/split';
import 'brace/ext/static_highlight';
import 'brace/ext/statusbar';
import 'brace/ext/whitespace';
import 'brace/ext/textarea';
import 'brace/ext/themelist';
export default {
components: {
Editor,
},
props: {
title: { type: String, default: '编辑器' },
value: { type: String, default: '' },
language: { type: String, default: 'html' },
iswrap: { type: String, default: 'no' },
optionsP: { type: Object, default: {} },
},
model: {
prop: 'value',
event: 'change',
},
data() {
return {
options: {
enableBasicAutocompletion: true, // 启用基本自动完成
enableSnippets: true, // 启用代码段
enableLiveAutocompletion: true, // 启用实时自动完成
printMarginColumn: 30,
displayIndentGuides: false, // 显示参考线
enableEmmet: true, // 启用Emmet
tabSize: 6, // 标签大小
fontSize: 14, // 设置字号
useWorker: true, // 使用辅助对象
showPrintMargin: false, // 去除编辑器里的竖线
enableMultiselect: true, // 选中多处
readOnly: true, // 是否只读
showFoldWidgets: true, // 显示折叠部件
fadeFoldWidgets: true, // 淡入折叠部件
wrap: this.iswrap === 'yes' ? true : false, // 换行
},
};
},
watch: {
optionsP: {
handler(newVal) {
this.options = newVal;
},
deep: true,
immediate: true,
},
},
methods: {
editorInit: function (editor) {
editor.getSession().on('change', (val) => {
let data = editor.getValue();
this.$emit('change', data);
});
},
format() {
const ace = require('brace');
const editor = this.$refs.codeEditor.editor;
const beautify = ace.acequire('ace/ext/beautify');
beautify.beautify(editor.session);
},
},
};
</script>
<style lang="scss" scoped>
.echart-pie-wrap {
width: 100%;
height: 100%;
margin-bottom: 0.475rem;
.myEditorTop {
height: 0.3125rem;
display: flex;
align-items: center;
background-color: #333;
padding-left: 0.625rem;
color: rgb(241, 238, 8);
font-weight: bold;
}
}
</style>
10.laoding的使用,表格格式化
<!-- 表格 -->
<el-table
v-loading="dataListLoading"
:data="dataList"
@selection-change="dataListSelectionChangeHandle"
style="width: 100%"
:header-cell-style="{ 'font-weight': '600' }"
>
<!-- <el-table-column type="selection" header-align="left" align="left" width="50"></el-table-column> -->
<el-table-column prop="id" label="数据库编号" header-align="left" align="left"></el-table-column>
<el-table-column prop="baseName" label="数据库名称" header-align="left" align="left"></el-table-column>
// 表格数据的解析
<el-table-column prop="baseType" label="数据库类型" :formatter="typeDataTable" header-align="left" align="left"></el-table-column>
<el-table-column prop="createTime" label="录入时间" header-align="left" align="left"></el-table-column>
<el-table-column prop="nodeIp" label="节点IP" header-align="left" align="left"></el-table-column>
// 表格数据解析,通过函数返回值的形式
<el-table-column prop="nodeStatus" label="节点状态" header-align="left" align="left">
<template slot-scope="scope">
<span :class="typeSpotClass(scope.row)" style="width: 7px; height: 7px; border-radius: 50%; display: inline-block"></span>
<span :class="typeDataClass(scope.row)">{{ nodeStatusType(scope.row) }}</span>
</template>
</el-table-column>
<el-table-column :label="$t('handle')" fixed="right" header-align="left" align="left" width="160">
<template slot-scope="scope">
<el-button class="table-operate-btn" type="text" size="small" @click="toInfo(scope.row)"> 查看 </el-button>
<el-button class="table-operate-btn" type="text" size="small" @click="toUpdata(scope.row)"> 编辑 </el-button>
<el-tooltip placement="right" content="删除数据库,需输入PIN码">
<el-button class="table-operate-btn" type="text" size="small" @click="deleteHandle(scope.row)">
{{ $t('deleteBatch') }}
</el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
————————————————————————————————
dataListLoading: false, // 数据列表,loading状态
// 获取数据列表
query() {
this.dataListLoading = true;
axios
.post(this.mixinViewModuleOptions.getDataListURL, {
current: this.mixinViewModuleOptions.getDataListIsPage ? this.current : 1, // 当前页码
size: this.mixinViewModuleOptions.getDataListIsPage ? this.size : 10, // 每页多少条
...this.dataForm
})
.then(({ data }) => {
this.dataListLoading = false;
if (data.code !== 0) {
this.dataList = [];
this.total = 0;
return;
}
this.dataList = this.mixinViewModuleOptions.getDataListIsPage ? data.data.records || data.data.list : [data.data];
this.total = this.mixinViewModuleOptions.getDataListIsPage ? parseInt(data.data.total) : 0;
})
.catch(() => {
this.dataListLoading = false;
this.dataList = [];
this.total = 0;
this.$message.error('服务器异常,请联系管理员');
});
},
// 数据库类型格式
typeDataTable(row) {
if (row.baseType === 'MYSQL5.7' || row.baseType === '1' || row.baseType === 'MYSQL') {
return 'MYSQL5.7';
} else if (row.baseType === 'POSTGRE' || row.baseType === '2') {
return 'POSTGRE';
} else {
return '';
}
},
// 节点前的原点
typeSpotClass(row) {
if (row.nodeStatus == 1) {
return 'tobe-reviewed-spot';
} else if (row.nodeStatus == 2) {
return 'success-spot';
} else {
return '';
}
},
// 节点状态颜色
typeDataClass(row) {
if (row.nodeStatus == 1) {
return 'tobe-reviewed';
} else if (row.nodeStatus == 2) {
return 'success';
} else {
return '';
}
},
// 节点状态内容格式
nodeStatusType(row) {
if (row.nodeStatus == 1) {
return '等待部署';
} else if (row.nodeStatus == 2) {
return '在线';
} else {
return '';
}
},
11.表单域文字描述前缀插槽
<el-form-item>
<span slot="label">
<span class="span-box">
<span class="avatar">密码 :</span>
<i class="el-icon-dish-1 ico-eye" v-if="!isShowPassword" @click="switchStatus"></i>
<i class="el-icon-dish-1 ico-pre" v-else @click="switchStatus"></i>
</span>
</span>
<span v-if="!isShowPassword">**********</span>
<span v-else>{{ toInfoData.password }}</span>
</el-form-item>
——————————————————————————
isShowPassword: false,
switchStatus() {
this.isShowPassword = !this.isShowPassword;
},
12.按钮自点击
<!-- 表格 -->
<el-table
v-loading="dataListLoading"
ref="multipleTable"
:data="dataList"
@selection-change="dataListSelectionChangeHandle"
style="width: 100%"
:header-cell-style="{ 'font-weight': '600' }"
>
<el-table-column prop="id" label="节点编号" header-align="left" align="left"></el-table-column>
<el-table-column prop="nodeName" label="节点名称" header-align="left" align="left"></el-table-column>
<el-table-column prop="nodeIp" label="节点IP" header-align="left" align="left"></el-table-column>
<el-table-column prop="nodeCreateTime" label="创建时间" header-align="left" align="left"></el-table-column>
<el-table-column prop="nodeUpdateTime" label="更新时间" header-align="left" align="left"></el-table-column>
<el-table-column prop="status" label="节点状态" header-align="left" align="left">
<template slot-scope="scope">
<span
:class="typeSpotClass(scope.row.status)"
style="width: 7px; height: 7px; border-radius: 50%; display: inline-block"
></span>
<span :class="typeDataClass(scope.row.status)">{{ typeData(scope.row) }}</span>
<el-button v-show="false" id="selectedNode" type="text" size="small" @click="saveNOdeInfo(scope.row)">
查看
</el-button>
</template>
</el-table-column>
</el-table>
————————————————————————————————————————
// 下一步
async nextStep() {
if (this.dataList[0].status != 2) {
return this.$message.warning('请先部署好节点,再新建数据库');
}
if (this.currentStep === 0) {
const btn = document.getElementById('selectedNode');
btn.click();
}
this.currentStep++;
},
13.动态表单域
后端返回的数据
// label-position="right":字段描述位于label内部右边位置
<el-form label-position="right" :model="databaseForm" :rules="dataRule" ref="databaseFormRef" label-width="380px">
<el-form-item label="数据库类型:" prop="databaseType">
<el-select
v-model="databaseForm.databaseType"
placeholder="请选择数据库类型"
@change="getInfo"
:style="{ width: '90%' }"
clearable
>
<el-option
v-for="(item, index) in typeOptions"
:key="index"
:label="item.label"
:value="item.value"
:disabled="item.disabled"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="数据库名称:" :rules="requiredType" prop="baseName">
<el-input
v-model="databaseForm.baseName"
placeholder="请输入数据库名称"
:style="{ width: '90%' }"
clearable
></el-input>
</el-form-item>
<el-form-item label="数据库实例名称:" :rules="requiredType" prop="databaseName">
<el-input
v-model="databaseForm.databaseName"
placeholder="请输入数据库名称"
:style="{ width: '90%' }"
clearable
></el-input>
<el-popover placement="right" width="400" trigger="hover">
<span slot="reference" :style="{ cursor: 'pointer' }">
<i class="el-icon-warning-outline"></i>
</span>
<p v-html="encryptionAgreement"></p>
</el-popover>
</el-form-item>
// rules是el-form-item上的一个属性,用来做表单验证规则。此处以函数返回值的方式处理。
<el-form-item v-for="item in inputList" :key="item.key" :label="item.desc" :rules="inputBoxCheck(item)" :prop="item.key">
// :show-password="item.key == 'password'":当对象的key是‘password’时启动密码框
// autocomplete="new-password":关闭密码框自动与chrome联动的功能
<el-input
:show-password="item.key == 'password'"
autocomplete="new-password"
v-model="databaseForm[item.key]"
:placeholder="item.defaultValue"
:style="{ width: '90%' }"
clearable
></el-input>
</el-form-item>
</el-form>
————————————————————————————————————
// 选择数据库录入模块的表单
databaseForm: {
current: 1,
databaseType: '',
baseName: '',
databaseName: '',
size: 10,
},
// 数据库类型下拉选项
typeOptions: [
{
label: 'MYSQL5.7',
value: 1,
},
{
label: 'POSTGRE',
value: 2,
},
],
requiredType: [{ required: true, message: this.$t('validate.required'), trigger: 'blur' }], // 必填校验
inputList: [], // 输入列表
numberType: [
{
validator: function (rule, value, callback) {
if (/^[0-9]*$/.test(value) === false) {
callback(new Error('请输入数字'));
} else {
// 校验通过
callback();
}
},
trigger: 'blur',
},
],
booleanType: [
{
validator: function (rule, value, callback) {
if (value !== 'false' && value !== 'true') {
callback(new Error('请输入布尔值true或false'));
} else {
// 校验通过
value = value === 'true' ? true : false;
callback();
}
},
trigger: 'blur',
},
],
// 监听数据库类型
watch: {
'databaseForm.databaseType'(newVal) {
if (!newVal) {
this.inputList = [];
}
},
},
// 计算属性内也可以放数据-校验规则
computed: {
dataRule() {
return {
databaseType: [{ required: true, message: this.$t('validate.required'), trigger: 'change' }],
},
},
// 选择数据库类型
async getInfo(code) {
try {
const { data } = await supplierService.queryDatabaseTemplate({ templateDatabaseType: code });
data.data.templateInfoList.forEach((item) => {
item.defaultValue = item.defaultValue == false ? 'false' : item.defaultValue;
item.defaultValue = item.defaultValue == true ? 'true' : item.defaultValue;
this.$set(this.databaseForm, item.key, item.defaultValue);
});
this.inputList = data.data.templateInfoList;
} catch (error) {
this.inputList = [];
}
},
// 输入框核验
inputBoxCheck(item) {
if (item.required === 'true') {
if (item.type == 'string') {
return this.requiredType;
} else if (item.type == 'number') {
return [...this.requiredType, ...this.numberType];
} else if (item.type == 'boolean') {
return this.booleanType;
}
} else {
if (item.type == 'string') {
return [];
} else if (item.type == 'number') {
return this.numberType;
} else if (item.type == 'boolean') {
return this.booleanType;
}
}
},