Merge remote-tracking branch 'origin/dev' into dev
commit
815b8e956b
|
@ -366,14 +366,17 @@ CAPTCHA_CHALLENGE_FUNCT = "captcha.helpers.math_challenge" # 加减乘除验证
|
|||
# ================================================= #
|
||||
|
||||
DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
|
||||
API_LOG_ENABLE = True
|
||||
# 是否启动API日志记录
|
||||
API_LOG_ENABLE = locals().get("API_LOG_ENABLE", True)
|
||||
# API 日志记录的请求方式
|
||||
API_LOG_METHODS = locals().get("API_LOG_METHODS", ["POST", "UPDATE", "DELETE", "PUT"])
|
||||
# API_LOG_METHODS = 'ALL' # ['POST', 'DELETE']
|
||||
API_LOG_METHODS = ["POST", "UPDATE", "DELETE", "PUT"] # ['POST', 'DELETE']
|
||||
API_MODEL_MAP = {
|
||||
# 在操作日志中详细记录的请求模块映射
|
||||
API_MODEL_MAP = locals().get("API_MODEL_MAP", {
|
||||
"/token/": "登录模块",
|
||||
"/api/login/": "登录模块",
|
||||
"/api/plugins_market/plugins/": "插件市场",
|
||||
}
|
||||
"/api/logout/": "登录模块",
|
||||
})
|
||||
|
||||
DJANGO_CELERY_BEAT_TZ_AWARE = False
|
||||
CELERY_TIMEZONE = "Asia/Shanghai" # celery 时区问题
|
||||
|
|
|
@ -39,6 +39,11 @@ DEBUG = True
|
|||
ENABLE_LOGIN_ANALYSIS_LOG = True
|
||||
# 登录接口 /api/token/ 是否需要验证码认证,用于测试,正式环境建议取消
|
||||
LOGIN_NO_CAPTCHA_AUTH = True
|
||||
# 是否启动API日志记录
|
||||
API_LOG_ENABLE = locals().get("API_LOG_ENABLE", True)
|
||||
# API 日志记录的请求方式
|
||||
API_LOG_METHODS = locals().get("API_LOG_METHODS", ["POST", "UPDATE", "DELETE", "PUT"])
|
||||
# API_LOG_METHODS = 'ALL' # ['POST', 'DELETE']
|
||||
# ================================================= #
|
||||
# ****************** 其他 配置 ******************* #
|
||||
# ================================================= #
|
||||
|
|
|
@ -21,18 +21,21 @@ class FileSerializer(CustomModelSerializer):
|
|||
fields = "__all__"
|
||||
|
||||
def create(self, validated_data):
|
||||
file_engine = dispatch.get_system_config_values("fileStorageConfig.file_engine")
|
||||
file_engine = dispatch.get_system_config_values("fileStorageConfig.file_engine") or 'local'
|
||||
file_backup = dispatch.get_system_config_values("fileStorageConfig.file_backup")
|
||||
file = self.initial_data.get('file')
|
||||
file_size = file.size
|
||||
validated_data['name'] = file.name
|
||||
validated_data['size'] = file_size
|
||||
validated_data['md5sum'] = hashlib.md5().hexdigest()
|
||||
md5 = hashlib.md5()
|
||||
for chunk in file.chunks():
|
||||
md5.update(chunk)
|
||||
validated_data['md5sum'] = md5.hexdigest()
|
||||
validated_data['engine'] = file_engine
|
||||
validated_data['mime_type'] = file.content_type
|
||||
if file_backup:
|
||||
validated_data['url'] = file
|
||||
if file_engine =='oss':
|
||||
if file_engine == 'oss':
|
||||
from dvadmin_cloud_storage.views.aliyun import ali_oss_upload
|
||||
file_path = ali_oss_upload(file)
|
||||
if file_path:
|
||||
|
|
|
@ -21,9 +21,9 @@ def import_to_data(file_url, field_data, m2m_fields=None):
|
|||
file_path_dir = os.path.join(settings.BASE_DIR, file_url)
|
||||
workbook = openpyxl.load_workbook(file_path_dir)
|
||||
table = workbook[workbook.sheetnames[0]]
|
||||
theader = tuple(table.values)[0] #Excel的表头
|
||||
is_update = '更新主键(勿改)' in theader #是否导入更新
|
||||
if is_update is False: #不是更新时,删除id列
|
||||
theader = tuple(table.values)[0] # Excel的表头
|
||||
is_update = '更新主键(勿改)' in theader # 是否导入更新
|
||||
if is_update is False: # 不是更新时,删除id列
|
||||
field_data.pop('id')
|
||||
# 获取参数映射
|
||||
validation_data_dict = {}
|
||||
|
@ -35,9 +35,10 @@ def import_to_data(file_url, field_data, m2m_fields=None):
|
|||
for k, v in choices.get("data").items():
|
||||
data_dict[k] = v
|
||||
elif choices.get("queryset") and choices.get("values_name"):
|
||||
data_list = choices.get("queryset").values(choices.get("values_name"), "id")
|
||||
data_list = choices.get("queryset").values(choices.get("values_name"),
|
||||
choices.get("values_value", "id"))
|
||||
for ele in data_list:
|
||||
data_dict[ele.get(choices.get("values_name"))] = ele.get("id")
|
||||
data_dict[ele.get(choices.get("values_name"))] = ele.get(choices.get("values_value", "id"))
|
||||
else:
|
||||
continue
|
||||
validation_data_dict[key] = data_dict
|
||||
|
@ -53,12 +54,11 @@ def import_to_data(file_url, field_data, m2m_fields=None):
|
|||
values = items[1]
|
||||
value_type = 'str'
|
||||
if isinstance(values, dict):
|
||||
value_type = values.get('type','str')
|
||||
value_type = values.get('type', 'str')
|
||||
cell_value = table.cell(row=row + 1, column=index + 2).value
|
||||
if cell_value is None or cell_value=='':
|
||||
if cell_value is None or cell_value == '':
|
||||
continue
|
||||
elif value_type == 'date':
|
||||
print(61, datetime.strptime(str(cell_value), '%Y-%m-%d %H:%M:%S').date())
|
||||
try:
|
||||
cell_value = datetime.strptime(str(cell_value), '%Y-%m-%d %H:%M:%S').date()
|
||||
except:
|
||||
|
@ -66,7 +66,7 @@ def import_to_data(file_url, field_data, m2m_fields=None):
|
|||
elif value_type == 'datetime':
|
||||
cell_value = datetime.strptime(str(cell_value), '%Y-%m-%d %H:%M:%S')
|
||||
else:
|
||||
# 由于excel导入数字类型后,会出现数字加 .0 的,进行处理
|
||||
# 由于excel导入数字类型后,会出现数字加 .0 的,进行处理
|
||||
if type(cell_value) is float and str(cell_value).split(".")[1] == "0":
|
||||
cell_value = int(str(cell_value).split(".")[0])
|
||||
elif type(cell_value) is str:
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from types import FunctionType, MethodType
|
||||
from urllib.parse import quote
|
||||
|
||||
from django.db import transaction
|
||||
|
@ -68,6 +69,8 @@ class ImportSerializerMixin:
|
|||
:return:
|
||||
"""
|
||||
assert self.import_field_dict, "'%s' 请配置对应的导出模板字段。" % self.__class__.__name__
|
||||
if isinstance(self.import_field_dict, MethodType) or isinstance(self.import_field_dict, FunctionType):
|
||||
self.import_field_dict = self.import_field_dict()
|
||||
# 导出模板
|
||||
if request.method == "GET":
|
||||
# 示例数据
|
||||
|
@ -160,6 +163,8 @@ class ImportSerializerMixin:
|
|||
assert self.import_field_dict, "'%s' 请配置对应的导入模板字段。" % self.__class__.__name__
|
||||
assert self.import_serializer_class, "'%s' 请配置对应的导入序列化器。" % self.__class__.__name__
|
||||
data = self.import_serializer_class(queryset, many=True, request=request).data
|
||||
if isinstance(self.import_field_dict, MethodType) or isinstance(self.import_field_dict, FunctionType):
|
||||
self.import_field_dict = self.import_field_dict()
|
||||
# 导出excel 表
|
||||
response = HttpResponse(content_type="application/msexcel")
|
||||
response["Access-Control-Expose-Headers"] = f"Content-Disposition"
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
"vue": "2.7.14",
|
||||
"vue-echarts": "^6.5.4",
|
||||
"vue-grid-layout": "^2.4.0",
|
||||
"vue-html2pdf": "^1.8.0",
|
||||
"vue-i18n": "^8.15.1",
|
||||
"vue-infinite-scroll": "^2.0.2",
|
||||
"vue-router": "^3.6.5",
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,176 @@
|
|||
<template>
|
||||
<div>
|
||||
<div style="position: absolute;z-index: 10000">
|
||||
<el-button
|
||||
type="success"
|
||||
round
|
||||
size="small"
|
||||
v-if="downloadButtonShow"
|
||||
:style="downloadButtonStyle"
|
||||
@click="generateReport"
|
||||
:loading="downloadLoading"
|
||||
>{{ downloadButtonTitle }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
round
|
||||
size="small"
|
||||
v-if="previewButtonShow"
|
||||
style="position: fixed; right: 50px; bottom: 70px"
|
||||
@click="previewPdf"
|
||||
:loading="previewLoading"
|
||||
>{{ previewButtonTitle }}
|
||||
</el-button>
|
||||
</div>
|
||||
<vue-html2pdf
|
||||
:show-layout="true"
|
||||
:float-layout="false"
|
||||
:enable-download="false"
|
||||
:preview-modal="preview"
|
||||
:filename="filename"
|
||||
:paginate-elements-by-height="1100"
|
||||
:pdf-quality="2"
|
||||
pdf-format="a4"
|
||||
pdf-orientation="portrait"
|
||||
pdf-content-width="100%"
|
||||
:manual-pagination="true"
|
||||
:html-to-pdf-options="{ margin: [5, 5, 0, 5] }"
|
||||
@beforeDownload="beforeDownload($event)"
|
||||
ref="html2Pdf"
|
||||
>
|
||||
<section slot="pdf-content">
|
||||
<slot></slot>
|
||||
</section>
|
||||
</vue-html2pdf>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SongtiSCBlack from '@/assets/fonts/SongtiSCBlack'
|
||||
import VueHtml2pdf from 'vue-html2pdf'
|
||||
|
||||
export default {
|
||||
name: 'dvaHtml2pdf',
|
||||
components: {
|
||||
VueHtml2pdf
|
||||
},
|
||||
props: {
|
||||
filename: { // 导出pdf文件名称
|
||||
type: String,
|
||||
require: true
|
||||
},
|
||||
company: { // 企业名称
|
||||
type: String,
|
||||
default: 'xxx '
|
||||
},
|
||||
// 是否显示下载按钮
|
||||
downloadButtonShow: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 下载按钮样式
|
||||
downloadButtonStyle: {
|
||||
type: Object,
|
||||
default () {
|
||||
return {
|
||||
position: 'fixed', right: '50px', bottom: '30px'
|
||||
}
|
||||
}
|
||||
},
|
||||
// 下载按钮标题
|
||||
downloadButtonTitle: {
|
||||
type: String,
|
||||
default: '下载报告'
|
||||
},
|
||||
// 是否显示预览按钮
|
||||
previewButtonShow: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 预览按钮样式
|
||||
previewButtonStyle: {
|
||||
type: Object,
|
||||
default () {
|
||||
return {
|
||||
position: 'fixed', right: '50px', bottom: '70px'
|
||||
}
|
||||
}
|
||||
},
|
||||
// 预览按钮标题
|
||||
previewButtonTitle: {
|
||||
type: String,
|
||||
default: '预览报告'
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
preview: false,
|
||||
downloadLoading: false,
|
||||
previewLoading: false
|
||||
}
|
||||
},
|
||||
created () {
|
||||
},
|
||||
mounted () {
|
||||
},
|
||||
methods: {
|
||||
async beforeDownload ({ html2pdf, options, pdfContent }) {
|
||||
if (this.preview) return
|
||||
await html2pdf()
|
||||
.set(options)
|
||||
.from(pdfContent)
|
||||
.toPdf()
|
||||
.get('pdf')
|
||||
.then((pdf) => {
|
||||
const totalPages = pdf.internal.getNumberOfPages()
|
||||
for (let i = 1; i <= totalPages; i++) {
|
||||
pdf.setPage(i)
|
||||
pdf.addFileToVFS('MyFont.ttf', SongtiSCBlack)
|
||||
pdf.addFont('MyFont.ttf', 'MyFont', 'normal')
|
||||
pdf.setFont('MyFont')
|
||||
pdf.setFontSize(10)
|
||||
pdf.setTextColor(150)
|
||||
pdf.text(
|
||||
'第 ' + i + '页 共 ' + totalPages + '页',
|
||||
pdf.internal.pageSize.getWidth() * 0.45,
|
||||
pdf.internal.pageSize.getHeight() - 2
|
||||
)
|
||||
pdf.text(
|
||||
this.company,
|
||||
pdf.internal.pageSize.getWidth() * 0.79,
|
||||
pdf.internal.pageSize.getHeight() - 2
|
||||
)
|
||||
}
|
||||
})
|
||||
.save(this.filename)
|
||||
},
|
||||
generateReport () {
|
||||
this.preview = false
|
||||
this.downloadLoading = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs.html2Pdf.generatePdf()
|
||||
const _this = this
|
||||
setTimeout(function () {
|
||||
_this.downloadLoading = false
|
||||
}, 4000)
|
||||
})
|
||||
},
|
||||
previewPdf () {
|
||||
this.preview = true
|
||||
this.previewLoading = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs.html2Pdf.generatePdf()
|
||||
const _this = this
|
||||
setTimeout(function () {
|
||||
_this.previewLoading = false
|
||||
}, 4000)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -1,7 +1,7 @@
|
|||
import Vue from 'vue'
|
||||
|
||||
import d2Container from './d2-container'
|
||||
|
||||
import tableProgress from './table-progress/lib/table-progress.vue'
|
||||
// 注意 有些组件使用异步加载会有影响
|
||||
Vue.component('d2-container', d2Container)
|
||||
Vue.component('d2-icon', () => import('./d2-icon'))
|
||||
|
@ -11,3 +11,5 @@ Vue.component('foreignKey', () => import('./foreign-key/index.vue'))
|
|||
Vue.component('manyToMany', () => import('./many-to-many/index.vue'))
|
||||
Vue.component('d2p-tree-selector', () => import('./tree-selector/lib/tree-selector.vue'))
|
||||
Vue.component('dept-format', () => import('./dept-format/lib/dept-format.vue'))
|
||||
Vue.component('dvaHtml2pdf', () => import('./dvaHtml2pdf/index.vue'))
|
||||
Vue.component('table-progress', tableProgress)
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* @创建文件时间: 2021-08-02 23:55:30
|
||||
* @Auther: 猿小天
|
||||
* @最后修改人: 猿小天
|
||||
* @最后修改时间: 2021-08-08 12:27:45
|
||||
* 联系Qq:1638245306
|
||||
* @文件介绍:
|
||||
*/
|
||||
export default {
|
||||
// 字段类型配置,注册之后即可在crud.js中使用了
|
||||
'selector-table': {
|
||||
// 表单组件配置
|
||||
form: { component: { name: 'selector-table-input', props: { color: 'danger' } } },
|
||||
// 行组件配置
|
||||
component: { name: 'values-format', props: {} },
|
||||
// 行展示时居中
|
||||
align: 'center'
|
||||
// 您还可以写更多默认配置
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
import { d2CrudPlus } from 'd2-crud-plus'
|
||||
import group from './group'
|
||||
|
||||
function install (Vue, options) {
|
||||
Vue.component('selector-table-input', () => import('./selector-table'))
|
||||
if (d2CrudPlus != null) {
|
||||
// 注册字段类型`demo-extend`
|
||||
d2CrudPlus.util.columnResolve.addTypes(group)
|
||||
}
|
||||
}
|
||||
// 导出install
|
||||
export default {
|
||||
install
|
||||
}
|
|
@ -0,0 +1,397 @@
|
|||
<template>
|
||||
<div ref="selectedTableRef">
|
||||
<el-popover
|
||||
placement="bottom"
|
||||
width="400"
|
||||
trigger="click"
|
||||
@show="visibleChange">
|
||||
<div class="option">
|
||||
<el-input style="margin-bottom: 10px" v-model="search" clearable placeholder="请输入关键词" @change="getDict"
|
||||
@clear="getDict">
|
||||
<el-button style="width: 100px" slot="append" icon="el-icon-search"></el-button>
|
||||
</el-input>
|
||||
<el-table
|
||||
ref="tableRef"
|
||||
:data="tableData"
|
||||
size="mini"
|
||||
border
|
||||
:row-key="dict.value"
|
||||
style="width: 400px"
|
||||
max-height="200"
|
||||
height="200"
|
||||
:highlight-current-row="!_elProps.tableConfig.multiple"
|
||||
@selection-change="handleSelectionChange"
|
||||
@row-click="handleCurrentChange"
|
||||
>
|
||||
<el-table-column v-if="_elProps.tableConfig.multiple" fixed type="selection" reserve-selection width="55"/>
|
||||
<el-table-column fixed type="index" label="#" width="50"/>
|
||||
<el-table-column :prop="item.prop" :label="item.label" :width="item.width"
|
||||
v-for="(item,index) in _elProps.tableConfig.columns" :key="index"/>
|
||||
</el-table>
|
||||
<el-pagination style="margin-top: 10px;max-width: 200px" background
|
||||
small
|
||||
:current-page="pageConfig.page"
|
||||
:page-size="pageConfig.limit"
|
||||
layout="prev, pager, next"
|
||||
:total="pageConfig.total"
|
||||
@current-change="handlePageChange"
|
||||
/>
|
||||
</div>
|
||||
<div slot="reference" ref="divRef" :style="{'pointerEvents': disabled?'none':''}">
|
||||
<div v-if="currentValue" class="div-input el-input__inner" :class="disabled?'div-disabled':''">
|
||||
<div>
|
||||
<el-tag
|
||||
style="margin-right: 5px"
|
||||
v-for="(item,index) in currentValue"
|
||||
:key="index"
|
||||
:closable="disabled"
|
||||
size="small"
|
||||
:hit="false"
|
||||
type="info"
|
||||
@close="itemClosed(item,index)"
|
||||
disable-transitions
|
||||
>
|
||||
<span>{{ item[dict.label] }}</span>
|
||||
</el-tag>
|
||||
</div>
|
||||
</div>
|
||||
<el-input v-else placeholder="请选择" slot:reference :disabled="disabled"></el-input>
|
||||
</div>
|
||||
</el-popover>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { request } from '@/api/service'
|
||||
import XEUtils from 'xe-utils'
|
||||
import { d2CrudPlus } from 'd2-crud-plus'
|
||||
|
||||
export default {
|
||||
name: 'selector-table-input',
|
||||
model: {
|
||||
prop: 'value',
|
||||
event: ['change', 'input']
|
||||
},
|
||||
mixins: [d2CrudPlus.input, d2CrudPlus.inputDict],
|
||||
props: {
|
||||
// 值
|
||||
value: {
|
||||
type: [String, Number, Array],
|
||||
required: false,
|
||||
default: ''
|
||||
},
|
||||
// 数据字典配置
|
||||
dict: {
|
||||
type: Object,
|
||||
require: false
|
||||
},
|
||||
// 其他配置
|
||||
elProps: {
|
||||
type: Object,
|
||||
require: false,
|
||||
default () {
|
||||
return {
|
||||
tableConfig: {
|
||||
multiple: false,
|
||||
columns: []
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
// 你可以定义一些参数,通过component.props传进来
|
||||
color: {
|
||||
required: false
|
||||
},
|
||||
styleName: {
|
||||
type: [Object, String],
|
||||
required: false,
|
||||
default () {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
// 由于value值是props参数,是不允许修改的,需要用别的值存起来
|
||||
currentValue: [],
|
||||
pageConfig: {
|
||||
page: 1,
|
||||
limit: 5,
|
||||
total: 0
|
||||
},
|
||||
search: null,
|
||||
tableData: [],
|
||||
multipleSelection: [],
|
||||
collapseTags: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 你也可以通过computed来监听value的变化,跟watch作用类似,根据实际情况选用
|
||||
_elProps () {
|
||||
return this.elProps
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value: {
|
||||
handler (value, oldVal) {
|
||||
// 父组件收到input事件后会通过v-model改变value参数的值
|
||||
// 然后此处会watch到value的改变,发出change事件
|
||||
// change事件放在此处发射的好处是,当外部修改value值时,也能够触发form-data-change事件
|
||||
this.$emit('change', value)
|
||||
this.$emit('input', value)
|
||||
// 如果值是被外部改变的,则修改本组件的currentValue
|
||||
if (Array.isArray(value) && value.length === 0) {
|
||||
this.currentValue = null
|
||||
this.multipleSelection = null
|
||||
} else {
|
||||
if (value && this.dispatch) {
|
||||
this.dispatch('ElFormItem', 'el.form.blur')
|
||||
}
|
||||
}
|
||||
},
|
||||
deep: true,
|
||||
immediate: true
|
||||
},
|
||||
multipleSelection: {
|
||||
handler (newValue, oldVal) {
|
||||
const { tableConfig } = this._elProps
|
||||
// 是否多选
|
||||
if (!tableConfig.multiple) {
|
||||
this.currentValue = [newValue]
|
||||
} else {
|
||||
this.currentValue = newValue
|
||||
}
|
||||
},
|
||||
deep: true,
|
||||
immediate: true
|
||||
}
|
||||
// currentValue (newValue, oldVal) {
|
||||
// const { tableConfig } = this._elProps
|
||||
// const { value } = this.dict
|
||||
// if (newValue) {
|
||||
// if (!tableConfig.multiple) {
|
||||
// if (newValue[0]) {
|
||||
// this.$emit('input', newValue[0][value])
|
||||
// this.$emit('change', newValue[0][value])
|
||||
// }
|
||||
// } else {
|
||||
// console.log(newValue)
|
||||
// const result = newValue.map((item) => {
|
||||
// return item[value]
|
||||
// })
|
||||
// this.$emit('input', result)
|
||||
// this.$emit('change', result)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
},
|
||||
mounted () {
|
||||
// 给currentValue设置初始值
|
||||
this.setCurrentValue(this.value)
|
||||
},
|
||||
methods: {
|
||||
// 设置显示值
|
||||
setCurrentValue (val) {
|
||||
if (val.toString().length > 0) {
|
||||
// 在这里对 传入的value值做处理
|
||||
const { url, value, label } = this.dict
|
||||
const params = {}
|
||||
params[value] = val
|
||||
return request({
|
||||
url: url,
|
||||
params: params,
|
||||
method: 'get'
|
||||
}).then(res => {
|
||||
const { data } = res.data
|
||||
if (data && data.length > 0) {
|
||||
this.currentValue = data
|
||||
} else {
|
||||
this.currentValue = null
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.currentValue = null
|
||||
}
|
||||
},
|
||||
// 获取数据
|
||||
getDict () {
|
||||
const that = this
|
||||
let url
|
||||
if (typeof that.dict.url === 'function') {
|
||||
const form = that.d2CrudContext.getForm()
|
||||
url = that.dict.url(that.dict, { form })
|
||||
} else {
|
||||
url = that.dict.url
|
||||
}
|
||||
let dictParams = {}
|
||||
if (that.dict.params) {
|
||||
dictParams = { ...that.dict.params }
|
||||
}
|
||||
const params = {
|
||||
page: that.pageConfig.page,
|
||||
limit: that.pageConfig.limit
|
||||
}
|
||||
if (that.search) {
|
||||
params.search = that.search
|
||||
params.page = 1
|
||||
}
|
||||
if (that._elProps.tableConfig.data === undefined || that._elProps.tableConfig.data.length === 0) {
|
||||
request({
|
||||
url: url,
|
||||
method: 'get',
|
||||
params: { ...params, ...dictParams }
|
||||
}).then(res => {
|
||||
const { data, page, limit, total } = res.data
|
||||
that.pageConfig.page = page
|
||||
that.pageConfig.limit = limit
|
||||
that.pageConfig.total = total
|
||||
if (that._elProps.tableConfig.isTree) {
|
||||
that.tableData = XEUtils.toArrayTree(data, { parentKey: 'parent', key: 'id', children: 'children' })
|
||||
} else {
|
||||
that.tableData = data
|
||||
}
|
||||
})
|
||||
} else {
|
||||
that.tableData = that._elProps.tableConfig.data
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 下拉框展开/关闭
|
||||
* @param bool
|
||||
*/
|
||||
visibleChange () {
|
||||
const that = this
|
||||
that.getDict()
|
||||
const { tableConfig } = that._elProps
|
||||
if (tableConfig.multiple) {
|
||||
that.$refs.tableRef.clearSelection() // 先清空选择,再赋值选择
|
||||
that.currentValue ? that.currentValue.forEach(item => {
|
||||
that.$refs.tableRef.toggleRowSelection(item, true)
|
||||
}) : null
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 分页
|
||||
* @param page
|
||||
*/
|
||||
handlePageChange (page) {
|
||||
this.pageConfig.page = page
|
||||
this.getDict()
|
||||
},
|
||||
/**
|
||||
* 表格多选
|
||||
* @param val:Array
|
||||
*/
|
||||
handleSelectionChange (val) {
|
||||
this.multipleSelection = val
|
||||
this.$emit('checkChange', val)
|
||||
const result = val.map((item) => {
|
||||
return item[this.dict.value]
|
||||
})
|
||||
this.$emit('input', result)
|
||||
this.$emit('change', result)
|
||||
},
|
||||
/**
|
||||
* 表格单选
|
||||
* @param val:Object
|
||||
*/
|
||||
handleCurrentChange (val) {
|
||||
const { tableConfig } = this._elProps
|
||||
if (!tableConfig.multiple) {
|
||||
this.multipleSelection = val
|
||||
this.$emit('radioChange', val)
|
||||
this.$emit('input', val[this.dict.value])
|
||||
this.$emit('change', val[this.dict.value])
|
||||
}
|
||||
},
|
||||
/***
|
||||
* 清空
|
||||
*/
|
||||
onClear () {
|
||||
const { tableConfig } = this._elProps
|
||||
if (!tableConfig.multiple) {
|
||||
this.$emit('input', '')
|
||||
this.$emit('change', '')
|
||||
} else {
|
||||
this.$emit('input', [])
|
||||
this.$emit('change', [])
|
||||
}
|
||||
},
|
||||
/**
|
||||
* tag删除事件
|
||||
* @param obj
|
||||
*/
|
||||
itemClosed (obj, index) {
|
||||
const { tableConfig } = this._elProps
|
||||
XEUtils.remove(this.multipleSelection, index)
|
||||
XEUtils.remove(this.currentValue, index)
|
||||
if (!tableConfig.multiple) {
|
||||
this.$emit('input', '')
|
||||
this.$emit('change', '')
|
||||
} else {
|
||||
this.$refs.tableRef?.toggleRowSelection(obj, false)
|
||||
// const { value } = this.dict
|
||||
// const result = this.currentValue.map((item) => {
|
||||
// return item[value]
|
||||
// })
|
||||
// this.$emit('input', result)
|
||||
// this.$emit('change', result)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
.option {
|
||||
height: auto;
|
||||
line-height: 1;
|
||||
padding: 5px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
</style>
|
||||
<style lang="scss">
|
||||
.popperClass {
|
||||
height: 320px;
|
||||
}
|
||||
|
||||
.el-select-dropdown__wrap {
|
||||
max-height: 310px !important;
|
||||
}
|
||||
|
||||
.tableSelector {
|
||||
.el-icon, .el-tag__close {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.div-input {
|
||||
-webkit-appearance: none;
|
||||
background-color: #FFF;
|
||||
background-image: none;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #DCDFE6;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
color: #606266;
|
||||
display: inline-block;
|
||||
min-height: 40px;
|
||||
line-height: 40px;
|
||||
outline: 0;
|
||||
padding: 0 15px;
|
||||
-webkit-transition: border-color .2s cubic-bezier(.645, .045, .355, 1);
|
||||
transition: border-color .2s cubic-bezier(.645, .045, .355, 1);
|
||||
min-width: 120px;
|
||||
}
|
||||
.div-disabled{
|
||||
background-color: #F5F7FA;
|
||||
border-color: #E4E7ED;
|
||||
color: #C0C4CC;
|
||||
cursor: not-allowed;
|
||||
pointer-events: none;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,12 @@
|
|||
export default {
|
||||
// 字段类型配置,注册之后即可在crud.js中使用了
|
||||
'table-progress': {
|
||||
// 表单组件配置
|
||||
form: { component: { name: 'form-input', props: { color: 'danger' } } },
|
||||
// 行组件配置
|
||||
component: { name: 'table-progress', props: {} },
|
||||
// 行展示时居中
|
||||
align: 'center'
|
||||
// 您还可以写更多默认配置
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
import { d2CrudPlus } from 'd2-crud-plus'
|
||||
import group from './group'
|
||||
function install (Vue) {
|
||||
Vue.component('table-progress', () => import('./lib/table-progress'))
|
||||
if (d2CrudPlus != null) {
|
||||
// 注册字段类型`demo-extend`
|
||||
d2CrudPlus.util.columnResolve.addTypes(group)
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
install
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-progress :percentage="currentValue" :color="setColor" :format="format"></el-progress>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
// 行展示组件进阶版
|
||||
// 本示例演示要对传入的值做一些改变,然后再展示
|
||||
export default {
|
||||
name: 'table-progress',
|
||||
props: {
|
||||
// 接收row.xxx的值
|
||||
value: {
|
||||
type: String || Number,
|
||||
required: false
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
currentValue: ''
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value (value) {
|
||||
// this.$emit('change', value)
|
||||
if (this.currentValue === value) {
|
||||
return
|
||||
}
|
||||
this.setValue(value)
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.setValue(this.value)
|
||||
},
|
||||
methods: {
|
||||
setValue (value) {
|
||||
// 在这里对 传入的value值做处理
|
||||
this.currentValue = Number(this.value)
|
||||
// 根据值的key 递归获取对应的名称
|
||||
},
|
||||
setColor () {
|
||||
if (this.value <= 50) {
|
||||
return '#F56C6C'
|
||||
} else if (this.value > 50 && this.value < 80) {
|
||||
return '#E6A23C'
|
||||
} else {
|
||||
return '#67C23A'
|
||||
}
|
||||
},
|
||||
format (percentage) {
|
||||
return `${percentage}%`
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -104,7 +104,7 @@ export default {
|
|||
},
|
||||
grid: {
|
||||
top: 40,
|
||||
left: 40,
|
||||
left: 50,
|
||||
right: 65,
|
||||
bottom: 75
|
||||
},
|
||||
|
|
|
@ -95,7 +95,7 @@ export default {
|
|||
},
|
||||
grid: {
|
||||
top: 40,
|
||||
left: 40,
|
||||
left: 50,
|
||||
right: 65,
|
||||
bottom: 60
|
||||
},
|
||||
|
|
|
@ -98,7 +98,7 @@ export default {
|
|||
},
|
||||
grid: {
|
||||
top: 40,
|
||||
left: 40,
|
||||
left: 50,
|
||||
right: 65,
|
||||
bottom: 60
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue