no message

This commit is contained in:
小陌 2023-07-04 19:03:42 +08:00
parent 3990dbb966
commit 2acc1dac76
11 changed files with 1623 additions and 87 deletions

View File

@ -0,0 +1,81 @@
<template>
<div
:class="{
'vux-flex-col': orient === 'vertical',
'vux-flex-row': orient === 'horizontal'
}"
:style="styles"
class="vux-flexbox">
<slot/>
</div>
</template>
<script>
export default {
name: 'Flexbox',
props: {
gutter: {
type: Number,
default: 8
},
orient: {
type: String,
default: 'horizontal'
},
justify: String,
align: String,
wrap: String,
direction: String
},
computed: {
styles() {
const styles = {
'justify-content': this.justify,
'-webkit-justify-content': this.justify,
'align-items': this.align,
'-webkit-align-items': this.align,
'flex-wrap': this.wrap,
'-webkit-flex-wrap': this.wrap,
'flex-direction': this.direction,
'-webkit-flex-direction': this.direction
}
return styles
}
}
}
</script>
<style lang="scss">
.vux-flexbox {
width: 100%;
text-align: left;
display: flex;
display: -webkit-flex;
box-align: center;
align-items: center;
.vux-flexbox-item {
flex: 1;
-webkit-flex: 1;
min-width: 20px;
width: 0%;
&:first-child {
margin-left: 0 !important;
margin-top: 0 !important;
}
}
}
.vux-flex-row {
box-direction: row;
box-orient: horizontal;
flex-direction: row;
}
.vux-flex-col {
box-orient: vertical;
flex-direction: column;
> .vux-flexbox-item {
width: 100%;
}
}
</style>

View File

@ -0,0 +1,62 @@
<template>
<div
:style="style"
class="vux-flexbox-item">
<slot/>
</div>
</template>
<script>
const prefixList = ['-moz-box-', '-webkit-box-', '']
export default {
name: 'FlexboxItem',
props: {
span: [Number, String],
order: [Number, String]
},
data() {
return {
bodyWidth: 0
}
},
computed: {
style() {
const styles = {}
const marginName =
this.$parent.orient === 'horizontal' ? 'marginLeft' : 'marginTop'
if (this.$parent.gutter * 1 !== 0) {
styles[marginName] = `${this.$parent.gutter}px`
}
if (this.span) {
for (let i = 0; i < prefixList.length; i++) {
styles[`${prefixList[i]}flex`] = `0 0 ${this.buildWidth(this.span) *
100}%`
}
}
if (typeof this.order !== 'undefined') {
styles.order = this.order
}
return styles
}
},
beforeMount() {
this.bodyWidth = document.documentElement.offsetWidth
},
methods: {
buildWidth(width) {
if (typeof width === 'number') {
if (width < 1) {
return width
} else {
return width / 12
}
} else if (typeof width === 'string') {
return width.replace('px', '') / this.bodyWidth
}
}
}
}
</script>

View File

@ -0,0 +1,7 @@
import Flexbox from './Flexbox'
import FlexboxItem from './FlexboxItem'
export {
Flexbox,
FlexboxItem
}

View File

@ -8,7 +8,7 @@
</el-badge> </el-badge>
<div class="right-panel-search" v-if="filter.length>0"> <div class="right-panel-search" v-if="filter.length>0">
<el-form :inline="true" :model="data"> <el-form :inline="true" :model="data">
<el-form-item style="margin-bottom:0px;margin-right: 6px;" v-for="(i,index) in fieldTop" :key="index"> <el-form-item :style="{ 'margin-bottom': '0px', 'margin-right': '6px', 'width': getWidth(i) }" v-for="(i,index) in fieldTop" :key="index">
<x-item :item="i" v-model="data"></x-item> <x-item :item="i" v-model="data"></x-item>
</el-form-item> </el-form-item>
<el-form-item style="margin-bottom:0px;margin-right: 6px;"> <el-form-item style="margin-bottom:0px;margin-right: 6px;">
@ -122,10 +122,12 @@
obj[item.name] = item.operator ? this.data[item.name]+`${config.separator}${item.operator}` : this.data[item.name] obj[item.name] = item.operator ? this.data[item.name]+`${config.separator}${item.operator}` : this.data[item.name]
}) })
console.log(obj)
return obj return obj
},
getWidth() {
return function(item) {
return item.width ? item.width+'px' : 'auto';
}
} }
}, },
mounted(){ mounted(){

View File

@ -19,5 +19,12 @@
</script> </script>
<style scoped> <style scoped>
.sc-title {border-bottom: 1px solid #eee;margin-bottom: 20px;font-size: 17px;padding-bottom: 15px;color: #3c4a54;font-weight: bold;} .sc-title {
margin: 20px 0;
font-size: 17px;
/*border-bottom: 1px solid #eee;*/
/*padding-bottom: 15px;*/
color: #3c4a54;
font-weight: bold;
}
</style> </style>

View File

@ -1,94 +1,96 @@
<template> <template>
<el-card shadow="hover" header="统计" v-loading="loading"> <el-card shadow="hover" header="销售简报" v-loading="loading">
<scEcharts ref="c1" height="300px" :option="option"></scEcharts>
<div class="number-data">
<div class="item" v-for="(s, index) in briefList" :key="index">
<sc-statistic :title="s.label" :value="s.num" :description="s.status" :tips="s.rate" groupSeparator>
<sc-trend v-model="s.rate" v-if="s.rate"></sc-trend>
</sc-statistic>
</div>
</div>
</el-card> </el-card>
</template> </template>
<style scoped>
.el-card {margin-bottom: 15px;}
.number-data {display: flex;}
.number-data .item {flex:1;border-right: 1px solid #f0f0f0;padding:0 20px;}
.number-data .item:last-child {border: 0;}
.number-data .item h2 {font-size: 12px;color: #787a7d;font-weight: normal;display: flex;align-items: center;}
.number-data .item h2 i {margin-left: 5px;color: #8cc5ff;cursor: pointer;}
.number-data .item p {font-size: 20px;color: #121315;margin-top: 10px;}
</style>
<script> <script>
import scEcharts from '@/components/scEcharts'; import scStatistic from '@/components/scStatistic';
export default { export default {
title: "统计", title: "统计",
icon: "el-icon-data-line", icon: "el-icon-data-line",
description: "实时统计", description: "实时统计",
components: { components: {
scEcharts scStatistic
}, },
data() { data() {
return { return {
loading: true, loading: true,
option: {} briefList: [
{
color:'#fdsfdsf',
icon:0,
label:'fdsafafa',
num:100,
rate:10,
status:'fdsafa'
},
{
color:'#fdsfdsf',
icon:0,
label:'fdsafafa',
num:100,
rate:10,
status:'fdsafa'
},
{
color:'#fdsfdsf',
icon:0,
label:'fdsafafa',
num:100,
rate:10,
status:'fdsafa'
},
{
color:'#fdsfdsf',
icon:0,
label:'fdsafafa',
num:100,
rate:10,
status:'fdsafa'
},
{
color:'#fdsfdsf',
icon:0,
label:'fdsafafa',
num:100,
rate:10,
status:'fdsafa'
},
]
} }
}, },
created() { created() {
var _this = this;
setTimeout(function() {
_this.loading = false
}, 500);
var option = { this.loading = false;
tooltip: {
trigger: 'axis'
}, },
xAxis: { methods: {
boundaryGap: false, reportClick(){
type: 'category', alert(1)
data: (function (){
var now = new Date();
var res = [];
var len = 30;
while (len--) {
res.unshift(now.toLocaleTimeString().replace(/^\D*/,''));
now = new Date(now - 2000);
} }
return res;
})()
},
yAxis: [{
type: 'value',
name: '价格',
"splitLine": {
"show": false
}
}],
series: [
{
name: '收入',
type: 'line',
symbol: 'none',
lineStyle: {
width: 1,
color: '#409EFF'
},
areaStyle: {
opacity: 0.1,
color: '#79bbff'
},
data: (function (){
var res = [];
var len = 30;
while (len--) {
res.push(Math.round(Math.random() * 0));
}
return res;
})()
},
],
};
this.option = option;
},
mounted(){
var _this = this;
setInterval(function (){
var o = _this.option;
o.series[0].data.shift()
o.series[0].data.push(Math.round(Math.random() * 100));
o.xAxis.data.shift();
o.xAxis.data.push((new Date()).toLocaleTimeString().replace(/^\D*/, ''));
//_this.$refs.c1.myChart.setOption(o)
},2100)
}, },
} }
</script> </script>

View File

@ -1,11 +1,11 @@
<template> <template>
<el-container> <el-container>
<el-aside width="180px" v-if="aside.length>0"> <el-aside :width="(aside.width || 160)+'px'" v-if="aside.items.length>0">
<el-header> <el-header>
<el-input placeholder="输入关键字进行过滤" v-model="groupFilterText" clearable></el-input> <el-input placeholder="输入关键字进行过滤" v-model="groupFilterText" clearable></el-input>
</el-header> </el-header>
<el-main class="nopadding"> <el-main class="nopadding">
<el-tree ref="group" class="menu" node-key="id" :data="aside" :current-node-key="''" :highlight-current="true" :expand-on-click-node="false" :filter-node-method="groupFilterNode" @node-click="groupClick"></el-tree> <el-tree ref="group" class="menu" :node-key="aside.key || 'id'" :data="aside.items" :highlight-current="true" :expand-on-click-node="false" :filter-node-method="groupFilterNode" @node-click="groupClick"></el-tree>
</el-main> </el-main>
</el-aside> </el-aside>
<el-container> <el-container>
@ -20,7 +20,7 @@
<el-button v-if="operation.batchdeletion" type="danger" @click="batchdeletion" plain icon="el-icon-delete"></el-button> <el-button v-if="operation.batchdeletion" type="danger" @click="batchdeletion" plain icon="el-icon-delete"></el-button>
</div> </div>
<div class="right-panel" v-if="filter.length>0"> <div class="right-panel" v-if="filter.length>0">
<el-button v-for="(s,index) in statList" :key="index" @click="openStat(s)" v-bind="s">{{ s.title }}</el-button> <el-button v-for="(s,index) in statList" :key="index" @click="openStat(s)" v-bind="s">{{ s.label }}</el-button>
<scFilterBar v-if="filter.length>0" v-model="search" :filterName="$route.meta.tablename" :options="filter" @filterChange="filterChange"> <scFilterBar v-if="filter.length>0" v-model="search" :filterName="$route.meta.tablename" :options="filter" @filterChange="filterChange">
</scFilterBar> </scFilterBar>
</div> </div>
@ -36,10 +36,10 @@
<el-table-column :label="operation.label || '操作'" :width="operation.width || 124" :fixed="operation.fixed || 'right'" :align="operation.align || 'left'" v-if="operation.edit || operation.delete"> <el-table-column :label="operation.label || '操作'" :width="operation.width || 124" :fixed="operation.fixed || 'right'" :align="operation.align || 'left'" v-if="operation.edit || operation.delete">
<template #default="scope"> <template #default="scope">
<el-button-group> <el-button-group>
<el-button v-if="operation.edit" :type="operation.edit.type || 'primary'" :size="operation.edit.size || 'small'" @click="operationEdit(scope.row, scope.$index)">{{ operation.edit.name || '编辑' }}</el-button> <el-button v-if="operation.edit" :type="operation.edit.type || 'primary'" :size="operation.edit.size || 'small'" @click="operationEdit(scope.row, scope.$index)">{{ operation.edit.label || '编辑' }}</el-button>
<el-popconfirm v-if="operation.delete" :title="operation.delete.title || '确定删除吗?'" @confirm="operationDelete(scope.row, scope.$index)"> <el-popconfirm v-if="operation.delete" :title="operation.delete.title || '确定删除吗?'" @confirm="operationDelete(scope.row, scope.$index)">
<template #reference> <template #reference>
<el-button :type="operation.delete.type || 'info'" :size="operation.delete.size || 'small'">{{ operation.delete.name || '删除' }}</el-button> <el-button :type="operation.delete.type || 'info'" :size="operation.delete.size || 'small'">{{ operation.delete.label || '删除' }}</el-button>
</template> </template>
</el-popconfirm> </el-popconfirm>
</el-button-group> </el-button-group>
@ -81,7 +81,9 @@
isselection:true, isselection:true,
selection: [], selection: [],
column: [], column: [],
aside: [], aside: {
items:[]
},
filter: [], filter: [],
api: '', api: '',
operation:{}, operation:{},
@ -95,6 +97,7 @@
], ],
statList:[], statList:[],
chartoption: {}, chartoption: {},
groupFilterText:''
} }
}, },
mounted() { mounted() {
@ -123,13 +126,27 @@
return obj return obj
} }
}, },
watch: {
groupFilterText(val) {
this.$refs.group.filter(val);
}
},
methods: { methods: {
//
groupFilterNode(value, data){
if (!value) return true;
return data.label.indexOf(value) !== -1;
},
//
groupClick(data){
this.search[this.aside.searchkey||'groupid'] = data[this.aside.key || 'id'];
this.$refs.table.reload(this.search)
},
// //
filterChange(data){ filterChange(data){
var info = Object.assign({},this.search, data) var info = Object.assign({},this.search, data)
// if (data[this.operation.search.key] !== undefined) {
// this.search[this.operation.search.key] = data[this.operation.search.key];
// }
this.$refs.table.reload(info) this.$refs.table.reload(info)
}, },
// //

View File

@ -0,0 +1,355 @@
<template>
<el-drawer :title="titleMap[mode]" v-model="visible" :size="1200" :close-on-press-escape="false" :close-on-click-modal="false" destroy-on-close @closed="$emit('closed')">
<el-container v-loading="loading">
<el-main style="padding:0 20px 20px 20px">
<el-form ref="dialogForm" :model="form" label-width="100px" label-position="top">
<el-row :gutter="10">
<el-col :span="20">
<el-form-item label="表格标识" prop="name">
<el-input v-model="form.name" placeholder="用于识别"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="8">
<el-form-item label="表格名称" prop="title">
<el-input v-model="form.title" placeholder="请输入中文描述标题"></el-input>
</el-form-item>
</el-col>
<el-col :span="16">
<el-form-item label="数据请求 API" prop="api">
<el-input v-model="form.api" placeholder="数据请求API"></el-input>
</el-form-item>
</el-col>
<el-col :span="16">
<el-form-item label="主键" prop="key">
<el-input v-model="form.key" placeholder="主键键位, 默认 id"></el-input>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="备注" prop="key">
<el-input v-model="form.remark" placeholder="备注"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="8">
<el-form-item label="操作部分" prop="key">
<el-checkbox-group v-model="form.operationtype">
<el-checkbox-button label="plus">添加</el-checkbox-button>
<el-checkbox-button label="delete">删除</el-checkbox-button>
<el-checkbox-button label="edit">编辑</el-checkbox-button>
<el-checkbox-button label="batchdeletion">批量删除</el-checkbox-button>
</el-checkbox-group>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="10" v-show="form.operationtype.includes('batchdeletion')">
<el-col :span="8">
<el-form-item label="批量删除按钮" prop="key">
<el-input v-model="form.operation.batchdeletion.label" placeholder="名称"></el-input>
</el-form-item>
</el-col>
<el-col :span="16">
<el-form-item label="批量删除请求" prop="key">
<el-input v-model="form.operation.batchdeletion.url" placeholder="请求 URL"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="10" v-show="form.operationtype.includes('edit')">
<el-col :span="8">
<el-form-item label="编辑按钮" prop="key">
<el-input v-model="form.operation.edit.label" placeholder="名称"></el-input>
</el-form-item>
</el-col>
<el-col :span="16">
<el-form-item label="编辑请求" prop="key">
<el-input v-model="form.operation.edit.url" placeholder="请求 URL"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="10" v-show="form.operationtype.includes('delete')">
<el-col :span="8">
<el-form-item label="下架按钮" prop="key">
<el-input v-model="form.operation.delete.label" placeholder="名称"></el-input>
</el-form-item>
</el-col>
<el-col :span="16">
<el-form-item label="下架请求" prop="key">
<el-input v-model="form.operation.delete.url" placeholder="请求 URL"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="10" v-show="form.operationtype.includes('plus')">
<el-col :span="8">
<el-form-item label="添加按钮" prop="key">
<el-input v-model="form.operation.plus.label" placeholder="名称"></el-input>
</el-form-item>
</el-col>
<el-col :span="16">
<el-form-item label="添加请求" prop="key">
<el-input v-model="form.operation.plus.url" placeholder="请求 URL"></el-input>
</el-form-item>
</el-col>
</el-row>
<sc-title title="统计标签"></sc-title>
<sc-form-table v-model="form.stat" :addTemplate="addTemplate" drag-sort placeholder="暂无数据">
<el-table-column prop="label" label="名称">
<template #default="scope">
<el-input v-model="scope.row.label" placeholder="名称"></el-input>
</template>
</el-table-column>
<el-table-column prop="value" label="值">
<template #default="scope">
<el-input v-model="scope.row.value" :disabled="scope.row.component=='title'" placeholder="选中值"></el-input>
</template>
</el-table-column>
</sc-form-table>
<sc-title title="页头tabs"></sc-title>
<sc-form-table v-model="form.tabs" :addTemplate="addTemplate" drag-sort placeholder="暂无数据">
<el-table-column prop="label" label="名称">
<template #default="scope">
<el-input v-model="scope.row.label" placeholder="名称"></el-input>
</template>
</el-table-column>
<el-table-column prop="value" label="值">
<template #default="scope">
<el-input v-model="scope.row.value" :disabled="scope.row.component=='title'" placeholder="选中值"></el-input>
</template>
</el-table-column>
</sc-form-table>
<sc-title title="Column表格"></sc-title>
<sc-form-table v-model="form.column" :addTemplate="addcolumnTemplate" drag-sort placeholder="暂无数据">
<el-table-column prop="component" label="表单组件" width="120">
<template #default="scope">
<el-select v-model="scope.row.component" placeholder="选择">
<el-option value="input" key="input" label="Input"> Input </el-option>
<el-option value="title" key="title" label="标题占位"> 标题占位 </el-option>
<el-option value="checkbox" key="checkbox" label="复选框"> 复选框 </el-option>
<el-option value="radio" key="radio" label="单选"> 单选 </el-option>
<el-option value="select" key="select" label="下拉"> 下拉 </el-option>
<el-option value="checkboxGroup" key="checkboxGroup" label="复组组合"> 复组组合 </el-option>
<el-option value="upload" key="upload" label="文件上传"> 文件上传 </el-option>
<el-option value="updatemultiple" key="updatemultiple" label="多文件上传"> 多文件上传 </el-option>
<el-option value="switch" key="switch" label="开关"> 开关 </el-option>
<el-option value="cascader" key="cascader" label="级联选择器"> 级联选择器 </el-option>
<el-option value="date" key="date" label="日期选择"> 日期选择 </el-option>
<el-option value="number" key="number" label="数字"> 数字 </el-option>
<el-option value="color" key="color" label="颜色选择"> 颜色选择 </el-option>
<el-option value="rate" key="rate" label="评分"> 评分 </el-option>
<el-option value="slider" key="slider" label="滑块"> 滑块 </el-option>
<el-option value="tableselect" key="tableselect" label="表格选择"> 表格选择 </el-option>
<el-option value="editor" key="editor" label="编辑器"> 编辑器 </el-option>
<el-option value="text" key="text" label="文本"> 文本 </el-option>
<el-option value="avatar" key="avatar" label="头像"> 头像 </el-option>
<el-option value="formtable" key="formtable" label="表单表格"> 表单表格 </el-option>
</el-select>
</template>
</el-table-column>
<el-table-column prop="label" label="名称">
<template #default="scope">
<el-input v-model="scope.row.label" placeholder="名称"></el-input>
</template>
</el-table-column>
<el-table-column prop="name" label="字段">
<template #default="scope">
<el-input v-model="scope.row.name" :disabled="scope.row.component=='title'" placeholder="字段名"></el-input>
</template>
</el-table-column>
<el-table-column prop="width" label="宽" width="80">
<template #default="scope">
<el-input v-model="scope.row.width" :disabled="scope.row.component=='title'" placeholder="宽"></el-input>
</template>
</el-table-column>
<el-table-column prop="columntype" label="表格类型" width="120">
<template #default="scope">
<el-select v-model="scope.row.columntype" placeholder="选择">
<el-option value="avatar" key="avatar" label="用户"> 用户 </el-option>
<el-option value="badge" key="badge" label="徽章"> 徽章 </el-option>
<el-option value="imagegroup" key="imagegroup" label="图组"> 图组 </el-option>
<el-option value="image" key="image" label="单图"> 单图 </el-option>
<el-option value="status" key="status" label="状态"> 状态 </el-option>
<el-option value="input" key="input" label="Input"> Input </el-option>
<el-option value="select" key="select" label="下拉选择"> 下拉选择 </el-option>
</el-select>
</template>
</el-table-column>
<el-table-column prop="hide" label="隐藏" width="70" align="center">
<template #default="scope">
<el-switch v-model="scope.row.hide" active-value="1" inactive-value="0"></el-switch>
</template>
</el-table-column>
<el-table-column prop="span" label="表单跨度" width="110">
<template #default="scope">
<el-input v-model="scope.row.span" placeholder="表单跨度"></el-input>
</template>
</el-table-column>
<el-table-column prop="operator" label="筛选" width="110">
<template #default="scope">
<el-select v-model="scope.row.filter" placeholder="选择">
<el-option value="<" key="<" label="小于"> 小于 </el-option>
<el-option value="<=" key="<=" label="小于"> 小于等于 </el-option>
<el-option value=">" key=">" label="大于"> 大于 </el-option>
<el-option value=">=" key=">=" label="大于等于"> 大于等于 </el-option>
<el-option value="!=" key="!=" label="不等于"> 不等于 </el-option>
<el-option value="=" key="=" label="等于"> 等于 </el-option>
<el-option value="notin" key="notin" label="Input"> 不包含 </el-option>
<el-option value="in" key="in" label="包含"> 包含 </el-option>
<el-option value="like" key="like" label="模糊查询"> 模糊查询 </el-option>
<el-option value="between" key="between" label="区间查询"> 区间查询 </el-option>
</el-select>
</template>
</el-table-column>
<el-table-column prop="options" label="选项" width="80" align="center">
<template #default="scope">
<el-button text size="small" :type="Object.keys(scope.row.options).length==0?'':'primary'" @click="setoptions(scope.row)">
选项
<el-badge :hidden="Object.keys(scope.row.options).length==0" :value="Object.keys(scope.row.options).length" class="badge" type="danger"></el-badge>
</el-button>
</template>
</el-table-column>
</sc-form-table>
</el-form>
</el-main>
<el-footer>
<el-button type="primary" :loading="isSaveing" @click="submit">保存</el-button>
<el-button @click="visible=false">取消</el-button>
</el-footer>
</el-container>
<images ref="images" @success="function(a,o){o.close()}"></images>
<videos ref="videos" @success="function(a,o){o.close()}"></videos>
</el-drawer>
</template>
<script>
export default {
emits: ['success', 'closed'],
components: {
},
data() {
return {
token: null,
loading: false,
mode: "add",
titleMap: {
add: '新增',
edit: '编辑'
},
form: {
operationtype:[],
stat:[],
tabs:[],
column:[],
title:'',
name:'',
api:'',
key:'',
operation:{
plus:{
label:'',
url:'',
},
delete:{
label:'',
url:'',
},
edit:{
label:'',
url:'',
},
batchdeletion:{
label:'',
url:'',
}
}
},
addTemplate: {
label:'',
value:'',
},
addcolumnTemplate: {
component:'',
columntype:'',
label:'',
name:'',
width:'',
hide:'',
span:'',
filter:'',
options:{},
},
visible: false,
}
},
mounted() {
},
methods: {
//
open(mode='add'){
this.mode = mode;
this.visible = true;
return this;
},
close(){
this.visible = false;
},
//
submit(){
this.$refs.dialogForm.validate(async (valid) => {
if (valid) {
this.isSaveing = true;
var res = await this.$http.post('system/table/submit',{info:this.form, token:this.token});
this.isSaveing = false;
if(res.code == 200){
this.visible = false;
this.$message.success("操作成功")
this.$emit('success', this.form, this)
}else{
this.$alert(res.message, "提示", {type: 'error'})
}
}
})
},
//
setData(data){
this.loading = true
const params = {
id: data.id,
uniqid: data.uniqid,
}
this.form.title = data.title;
this.form.uniqid = data.uniqid;
setTimeout(async ()=>{
var res = await this.$http.get('system/table/info',params)
this.loading = false
this.form = res.data.data;
this.token = res.data.token;
}, 400)
},
//
setoptions(o){
this.$nextTick(() => {
this.$refs.videos.open().setData(o)
})
},
}
}
</script>
<style>
</style>

View File

@ -0,0 +1,182 @@
<template>
<el-container>
<el-header>
<div class="left-panel">
<el-button type="primary" icon="el-icon-plus" @click="add"></el-button>
</div>
<div class="right-panel">
<div class="right-panel-search">
<el-input v-model="search.keyword" placeholder="名称,标识,备注" clearable></el-input>
<el-button type="primary" icon="el-icon-search" @click="upsearch"></el-button>
</div>
</div>
</el-header>
<el-main class="nopadding">
<scTable ref="table" :api="api" row-key="id" @selection-change="selectionChange" :hideSetting="true" remoteSort remoteFilter stripe>
<el-table-column type="selection" width="30"></el-table-column>
<el-table-column label="ID" prop="id" width="50"></el-table-column>
<el-table-column label="" prop="status" width="38">
<template #default="scope">
<sc-status-indicator v-if="scope.row.status==1" pulse type="success"></sc-status-indicator>
<sc-status-indicator v-if="scope.row.status==0" pulse type="info"></sc-status-indicator>
</template>
</el-table-column>
<el-table-column label="名称" prop="title" minWidth="100">
<template #default="scope">
{{ scope.row.title }}
</template>
</el-table-column>
<el-table-column label="标识" prop="title" minWidth="100">
<template #default="scope">
{{ scope.row.name }}
</template>
</el-table-column>
<el-table-column label="主键" prop="key" width="150"></el-table-column>
<el-table-column label="请求" prop="viewnum" width="90">
<template #default="scope">
<el-link :underline="false" size="small" @click="setImage(scope.row)">
<el-badge :value="scope.row.viewnum" type="info"></el-badge>
</el-link>
</template>
</el-table-column>
<el-table-column label="Column" prop="column" width="80">
<template #default="scope">
<el-link :underline="false" size="small" @click="setImage(scope.row)">
<el-badge :value="scope.row.column.length" type="danger"></el-badge>
</el-link>
</template>
</el-table-column>
<el-table-column label="tabs" prop="tabs" width="80">
<template #default="scope">
<el-link :underline="false" size="small" @click="setImage(scope.row)">
<el-badge :value="scope.row.tabs.length" type="info"></el-badge>
</el-link>
</template>
</el-table-column>
<el-table-column label="操作" prop="operationtype" width="160">
<template #default="scope">
<input class="el-input__inner" type="text" readonly :value="scope.row.operationtype">
</template>
</el-table-column>
<el-table-column label="备注" prop="remark" width="160">
<template #default="scope">
<input class="el-input__inner" type="text" readonly :value="scope.row.remark">
</template>
</el-table-column>
<el-table-column label="Api" prop="api" width="150"></el-table-column>
<el-table-column label="添加时间" prop="timestamp" width="150"></el-table-column>
<el-table-column label="操作" fixed="right" align="left" width="120">
<template #default="scope">
<el-button-group>
<el-button type="primary" size="small" @click="table_edit(scope.row, scope.$index)">编辑</el-button>
<el-popconfirm :title="'确定删除吗?'" @confirm="table_del(scope.row, scope.$index)">
<template #reference>
<el-button :type="'info'" :size="'small'">{{ '删除' }}</el-button>
</template>
</el-popconfirm>
</el-button-group>
</template>
</el-table-column>
</scTable>
</el-main>
</el-container>
<column-dialog v-if="dialog.column" ref="column" @success="handleSuccess" @closed="dialog.column=false"></column-dialog>
</template>
<script>
import columnDialog from './column'
export default {
name: 'tablegen',
components: {
columnDialog,
},
data() {
return {
dialog: {
column: false,
},
api: 'system/table/lists',
selection: [],
search: {
keyword: "",
status:'0',
}
}
},
mounted() {
},
methods: {
open(o){
window.open(o.apartmentposter)
},
//
tabChange(status){
this.search.status = status;
this.$refs.table.reload(this.search)
},
//
upsearch(){
this.$refs.table.reload(this.search)
},
//
add(){
this.dialog.column = true
this.$nextTick(() => {
this.$refs.column.open()
})
},
//
table_edit(row){
this.dialog.column = true
this.$nextTick(() => {
this.$refs.column.open('edit').setData(row)
})
},
//
async table_del(row, index){
var res = await this.$http.post('system/table/delete', {id: row.id});
if(res.code == 200){
// OR /
this.$refs.table.tableData.splice(index, 1);
this.$message.success("删除成功")
}else{
this.$alert(res.message, "提示", {type: 'error'})
}
},
//
async batch_del(){
this.$confirm(`确定下架选中的 ${this.selection.length} 项吗?`, '提示', {
type: 'warning'
}).then(() => {
const loading = this.$loading();
this.selection.forEach(item => {
this.$refs.table.tableData.forEach((itemI, indexI) => {
if (item.id === itemI.id) {
this.$refs.table.tableData.splice(indexI, 1)
}
})
})
loading.close();
this.$message.success("操作成功")
}).catch(() => {
})
},
//
selectionChange(selection){
this.selection = selection;
},
//
async handleSuccess(){
this.$refs.table.reload({})
}
}
}
</script>
<style>
</style>

View File

@ -0,0 +1,818 @@
<template>
<div class="crm-update">
<div class="title-wrap">
<i class="el-icon-setting"/>
<div>
<p class="title">系统更新</p>
<p class="description">你可以随时检查使用系统是否是最新版本并进行一键升级</p>
</div>
</div>
<el-alert title="更新前,您需要备份您的数据,防止数据丢失。" type="warning" />
<!-- 登录状态 -->
<div v-if="isLogin" class="login-box">
<!-- 头像 -->
<div class="face">
<img v-if="userData.img" :src="userData.img" alt="">
<span v-else>{{ userData.name }}</span>
</div>
<!-- 信息 -->
<div class="info">
<span class="name">{{ userData.name }}</span>
<span class="title">{{ userData.title }}</span>
<p>{{ userData.companyName }}</p>
<p>
<i class="el-icon-mobile-phone"/>
{{ userData.mobile }}
</p>
<p>
<i class="wk wk-icon-email-outline"/>
{{ userData.email }}
</p>
</div>
<!-- 按钮 -->
<div>
<el-button type="primary" plain @click="logoutHandle">注销</el-button>
</div>
</div>
<!-- 未登录X-PHP账号的提示 -->
<div v-else class="login-box">
<!-- 头像 -->
<div class="face">登录</div>
<div class="info">
<!-- 提示 -->
<div class="login-box-title">
<span @click="dialogVisible = true">请点击登</span>
<p>更新前需要先登录X-PHP账号</p>
</div>
</div>
<!-- 按钮 -->
<el-button type="primary" plain @click="dialogVisible = true">登录</el-button>
</div>
<div v-loading="checkLoading" class="last-time">
<el-button :disabled="isClick" type="primary" plain @click="checkHandle">检查更新</el-button>
</div>
<!-- 检查更新后展示 -->
<div v-if="isCheckUpdate" class>
<!-- 已经是最新版本 -->
<div v-if="isNewest" class="version">
<p class="text">您当前是最新版本</p>
当前版本{{ version }}
</div>
<!-- 有新版本 -->
<div
v-loading="updateLoading"
v-else
:element-loading-text="progressTooltip"
class="version"
element-loading-background="#fff"
>
<p class="text">有新的版本可升级</p>
当前版本{{ serverVersion }}您可以升级到
<span>{{ version }}</span>
<div class="update-wrap">
<el-badge :value="1" class="update-badge">
<el-button :type="isCanUpdate ? 'primary' : 'info'" @click="updateHandle">现在更新</el-button>
</el-badge>
</div>
</div>
</div>
<!-- 备份 -->
<div class="data-back">
<p class="text">数据备份</p>
<div v-loading="backLoading" class="box" element-loading-text="努力备份中">
<el-button type="primary" plain @click="queryDatabaseHandle">查询数据库</el-button>
<el-button type="primary" plain @click="isCustom = 0">自定义数据库</el-button>
<div v-if="isCustom === 1" class="database-wrap">
<el-select v-model="database" placeholder="请选择">
<el-option v-for="(item, index) in databaseList" :key="index" :value="item"/>
</el-select>
<p class="way">
选择备份方式
<el-radio v-model="backupType" :label="1">本地备份</el-radio>
</p>
<el-button type="primary" @click="dataBackHandle">开始备份</el-button>
</div>
<!-- 自定义数据库 -->
<el-form
v-if="isCustom === 0"
ref="databaseForm"
:model="customDatabase"
:rules="databaseRules"
status-icon
class="custom1"
>
<el-form-item prop="host">
<el-input v-model="customDatabase.host" autocomplete="off" placeholder="请输入数据库地址"/>
</el-form-item>
<el-form-item prop="port">
<el-input
v-model.number="customDatabase.port"
autocomplete="off"
placeholder="请输入数据库端口号"
/>
</el-form-item>
<el-form-item prop="databaseName">
<el-input
v-model="customDatabase.databaseName"
autocomplete="off"
placeholder="请输入数据库名称"
/>
</el-form-item>
<el-form-item prop="DBUsername">
<el-input
v-model="customDatabase.DBUsername"
autocomplete="off"
placeholder="请输入数据库用户名"
/>
</el-form-item>
<el-form-item prop="DBPassword">
<el-input
v-model="customDatabase.DBPassword"
type="password"
autocomplete="off"
placeholder="请输入数据库密码"
/>
</el-form-item>
<el-button type="primary" @click="submitForm">开始备份</el-button>
</el-form>
<div v-if="isBackSuccess" class="back-success">备份成功文件路径{{ sql }}</div>
<div class="explain">
<p>备份说明:</p>
<p>1本地备份将只备份SQL并被备份到同级目录下</p>
<p>2云端备份数据将备份到云端在个人中心可以查看备份记录下载备份数据</p>
</div>
</div>
</div>
<!-- 登录X-PHP弹窗 -->
<el-dialog v-model="dialogVisible" title="登录X-PHP账号" width="500px">
<!-- <div slot="title" class="el-dialog__title">
登录X-PHP账号
<p class="description">您可以登录X-PHP账号来进行一键升级</p>
</div> -->
<!-- 登录表单 -->
<el-form
ref="loginRef"
:model="loginForm"
:rules="loginRules"
label-width="80px"
label-position="top"
class="login-form"
>
<div class="form-item">
<el-form-item prop="username">
<i class="wk wk-mobile"/>账号
<el-input v-model="loginForm.username" placeholder="请输入您的X-PHP账号"/>
</el-form-item>
</div>
<div class="form-item password">
<el-form-item prop="password">
<i class="wk wk-lock"/>密码
<el-input v-model="loginForm.password" type="password" placeholder="请输入您的X-PHP账号的密码"/>
</el-form-item>
</div>
<el-button type="primary" @click="loginHandle('loginRef')">确认登录</el-button>
</el-form>
</el-dialog>
</div>
</template>
<script>
// import Lockr from 'lockr'
// import {
// crmCheckVersionAPI,
// crmQueryDatabaseAPI,
// crmBackupDatabaseAPI,
// crmUpdateAPI,
// updateProgressAPI,
// loginWKAPI
// } from '@/api/admin/update'
export default {
/** 系统升级 */
name: 'Update',
components: {
},
data() {
var checkPort = (rule, value, callback) => {
if (!value) {
return callback(new Error('请输入数据库端口号'))
}
setTimeout(() => {
if (!Number.isInteger(value)) {
callback(new Error('请输入数字值'))
} else {
if (value > 65535 || value <= 0) {
callback(new Error('请输入0~65535之间的端口号'))
} else {
callback()
}
}
}, 1000)
}
return {
isClick: false,
isCanUpdate: false,
isLogin: false, // X-PHP
dialogVisible: true, //
dialogVisibleH: false, //
loginForm: {
username: '',
password: ''
},
loginRules: {
username: [
{ required: true, message: '请输入X-PHP账号', trigger: 'blur' }
],
password: [{ required: true, message: '请输入密码', trigger: 'blur' }]
},
userData: {},
isCheckUpdate: false, //
isNewest: false, //
checkLoading: false, // loading
version: '', //
serverVersion: '', //
isCustom: -1, // 0: 1:
backupType: 1, // 1: 2:
databaseList: [], //
database: '', //
databaseRules: {
host: [
{ required: true, message: '请输入数据库地址', trigger: 'blur' }
],
port: [{ validator: checkPort, trigger: 'blur' }],
databaseName: [
{ required: true, message: '请输入数据库名称', trigger: 'blur' }
],
DBUsername: [
{ required: true, message: '请输入数据库账号', trigger: 'blur' }
],
DBPassword: [
{ required: true, message: '请输入数据库密码', trigger: 'blur' }
]
},
customDatabase: {
//
host: '', //
port: '', //
databaseName: '', //
DBUsername: '', //
DBPassword: '' //
},
backLoading: false, // loading
isBackSuccess: false,
sql: '', //
backType: 1, // 1: 2:
updateLoading: false,
progressTooltip: '',
progress: 0 //
}
},
created() {
// const _this = this
// async function decorator() {
// var { data } = await crmCheckVersionAPI()
// _this.checkIsNewest(data.version, data.serverVersion)
// _this.checkLoading = false
// _this.version = data.version
// _this.serverVersion = data.serverVersion
// _this.isCheckUpdate = true
// }
// decorator()
},
methods: {
loginHandle(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
// var param = {
// username: this.loginForm.username,
// password: this.loginForm.password
// }
// loginWKAPI(param).then(res => {
// var { data } = res
// if (res.code === 0) {
// this.userData = data
// this.dialogVisible = false
// this.isLogin = true
// Object.assign(this.userData, this.loginForm)
// }
// }).catch(() => {
// })
} else {
return false
}
})
},
logoutHandle() {
this.isLogin = false
this.loginForm.username = ''
this.loginForm.password = ''
},
async checkHandle() {
// this.checkLoading = true
// var { data } = await crmCheckVersionAPI()
// this.isNewest = this.checkIsNewest(data.version, data.serverVersion)
// this.checkLoading = false
// this.version = data.version
// this.serverVersion = data.serverVersion
// this.isCheckUpdate = true
// this.isClick = true
},
checkIsNewest(a, b) {
// var a = toNum(a)
// var b = toNum(b)
if (a > b) {
return false
} else {
return true
}
// function toNum(a) {
// var a = a.toString()
// var c = a.split('.')
// var num_place = ['', '0', '00', '000', '0000']
// var r = num_place.reverse()
// for (var i = 0; i < c.length; i++) {
// var len = c[i].length
// c[i] = r[len] + c[i]
// }
// var res = c.join('')
// return res
// }
},
async queryDatabaseHandle() {
this.isCustom = 1
// var res = await crmQueryDatabaseAPI()
var res = {
data:[
[]
],
code:0
};
this.databaseList = res.data
this.isShowDatabase = res.code === 0
},
submitForm() {
this.$refs.databaseForm.validate((valid) => {
if (valid) {
this.dataBackHandle()
} else {
return false
}
})
},
async dataBackHandle() {
if (!this.isLogin) {
this.$message({
showClose: true,
message: '请登陆X-PHP账号',
type: 'warning'
})
return
}
if (this.isCustom && !this.database) {
this.$message({
showClose: true,
message: '请选择要备份的数据库',
type: 'warning'
})
return
}
this.backLoading = true
// var data = this.isCustom
// ? {
// backupType: this.backupType,
// databaseName: this.database,
// username: this.loginForm.username,
// password: this.loginForm.password,
// isCustom: this.isCustom
// }
// : Object.assign(this.customDatabase, this.loginForm)
// var res = await crmBackupDatabaseAPI(data)
var res = {
code:0
}
this.backLoading = false
if (res.code === 0) {
this.isBackSuccess = true
this.sql = res.data
this.isCanUpdate = true
}
},
async updateHandle() {
if (!this.isLogin) {
this.$message({
message: '未进行登陆',
type: 'warning'
})
return
}
if (!this.isBackSuccess) {
this.$message({
message: '未进行数据备份',
type: 'warning'
})
return
}
this.updateLoading = true
// var data = this.isCustom
// ? {
// backupType: this.backupType,
// databaseName: this.database,
// username: this.loginForm.username,
// password: this.loginForm.password,
// isCustom: this.isCustom
// }
// : Object.assign(this.customDatabase, this.loginForm)
// var res = await crmUpdateAPI(data)
var res = {code:1}
if (res.code === 0) {
this.progressTooltip = '更新准备中'
var _this = this
var timer = setInterval(function() {
fn()
async function fn() {
// var res = await updateProgressAPI()
var res = {code:0, data:5}
switch (res.data) {
case 5:
_this.progressTooltip = '获取更新信息中'
break
case 15:
_this.progressTooltip = '备份数据库中'
break
case 25:
_this.progressTooltip = '备份文件中'
break
case 50:
_this.progressTooltip = '停止受影响的服务中'
break
case 70:
_this.progressTooltip = '执行升级中'
break
case 100:
_this.progressTooltip = '升级已完成'
setTimeout(function() {
_this.updateLoading = false
_this.isNewest = true
}, 500)
clearInterval(timer)
break
default:
_this.progressTooltip = '升级已完成'
setTimeout(function() {
_this.updateLoading = false
_this.isNewest = true
}, 500)
clearInterval(timer)
break
}
}
}, 3000)
}
},
//
handleSizeChange(val) {
// Lockr.set('crmPageSizes', val)
this.pageSize = val
},
//
handleCurrentChange(val) {
this.currentPage = val
}
}
}
</script>
<style lang="scss" scoped>
/*@import "../styles/table.scss";*/
$linkColor: #3b6ff1;
//
.text {
font-size: 18px;
font-weight: bold;
height: 38px;
line-height: 38px;
color: #000;
}
.link {
color: $linkColor;
cursor: pointer;
}
.crm-update {
width: 100%;
min-width: 1200px;
height: 100%;
padding: 15px 20px 20px;
background: #fff;
overflow: auto;
}
//
.title-wrap {
display: flex;
padding: 0 15px;
.el-icon-setting {
width: 30px;
height: 30px;
margin-right: 12px;
border-radius: 6px;
line-height: 30px;
text-align: center;
background: #2362fb;
color: #fff;
font-size: 18px;
}
.title {
font-size: 16px;
font-weight: bold;
}
.description {
height: 22px;
line-height: 22px;
color: #a2a2a2;
font-size: 13px;
}
}
.login-wrap {
display: flex;
height: 40px;
align-items: center;
.face {
width: 40px;
height: 40px;
border-radius: 50%;
overflow: hidden;
img {
width: 100%;
}
}
.name {
margin: 0 8px;
}
.phone {
margin-right: 8px;
}
}
//
.warning-box {
margin-top: 10px;
margin-bottom: 10px;
}
//
.login-box {
width: 600px;
background: #f8f8f8;
padding: 22px;
display: flex;
border-radius: 6px;
justify-content: space-between;
.face {
width: 40px;
height: 40px;
margin-right: 14px;
border-radius: 50%;
overflow: hidden;
line-height: 40px;
background: #2362fb;
font-size: 12px;
color: #fff;
text-align: center;
flex-grow: 0;
img {
width: 100%;
}
}
.info {
flex-grow: 1;
color: #a2a2a2;
font-size: 12px;
line-height: 20px;
}
.name {
height: 22px;
line-height: 22px;
font-weight: bold;
font-size: 16px;
color: #000;
margin-right: 10px;
}
.login-box-title {
height: 22px;
line-height: 22px;
font-weight: bold;
font-size: 16px;
color: #333;
cursor: pointer;
p {
height: 28px;
font-size: 14px;
color: #a2a2a2;
line-height: 28px;
font-weight: normal;
}
}
.el-button {
height: 31px;
}
}
//
.last-time {
margin: 16px 0;
padding: 16px 0;
}
.version {
a {
color: $linkColor;
}
button {
display: block;
}
}
//
.data-back {
margin-top: 40px;
.link {
margin-left: 20px;
}
}
.box {
width: 820px;
// border: 1px solid #000;
border-radius: 6px;
padding: 14px;
margin-top: 20px;
background: #fafafa;
.database-wrap {
margin-top: 20px;
}
.way {
margin: 14px 0;
// margin-bottom: 14px;
}
.back-success {
color: #f56c6c;
height: 30px;
line-height: 30px;
font-size: 18px;
margin-top: 12px;
}
.explain {
margin-top: 14px;
line-height: 22px;
font-size: 12px;
color: #aaa;
img {
width: 16px;
vertical-align: middle;
}
}
}
//
.custom {
width: 200px;
p {
width: 200px;
margin: 14px 0;
}
}
.custom1 {
width: 200px;
margin-top: 14px;
.el-button {
}
}
// dialog
.el-dialog__wrapper {
.el-dialog {
padding-left: 25px;
padding-right: 25px;
border-radius: 6px;
.el-dialog__title {
.description {
font-size: 14px;
color: #a2a2a2;
font-weight: normal;
}
}
}
}
//
.login-form {
.el-button {
width: 100%;
font-size: 16px;
height: 45px;
}
}
.form-item {
&.password {
margin-top: 28px;
}
p {
margin-bottom: 8px;
}
.el-input {
input {
height: 47px;
background: #f8f8f8;
}
}
}
.forget {
height: 40px;
line-height: 40px;
text-align: right;
color: #2362fb;
}
.register {
margin-top: 20px;
text-align: center;
color: #2362fb;
font-size: 16px;
}
.time {
display: flex;
.el-input {
width: 246px;
margin-left: 108px;
}
}
//
.p-contianer {
margin-top: 30px;
border-top: none;
.p-bar {
margin-right: 0;
}
}
//
.update-wrap{
// margin-top: 10px;
// margin-right: 40px;
margin-top: 20px;
}
</style>

View File

@ -20,6 +20,7 @@ import XItem from './components/scForm/item'
import scTitle from './components/scTitle' import scTitle from './components/scTitle'
import scWaterMark from './components/scWaterMark' import scWaterMark from './components/scWaterMark'
import scQrCode from './components/scQrCode' import scQrCode from './components/scQrCode'
import { Flexbox, FlexboxItem } from './components/Flexbox'
import scStatusIndicator from './components/scMini/scStatusIndicator' import scStatusIndicator from './components/scMini/scStatusIndicator'
import scTrend from './components/scMini/scTrend' import scTrend from './components/scMini/scTrend'
@ -48,6 +49,8 @@ export default {
//注册全局组件 //注册全局组件
app.component('XItem', XItem); app.component('XItem', XItem);
app.component('flexbox', Flexbox);
app.component('flexbox-item', FlexboxItem);
app.component('scTable', scTable); app.component('scTable', scTable);
app.component('scTableColumn', scTableColumn); app.component('scTableColumn', scTableColumn);
app.component('scFilterBar', scFilterBar); app.component('scFilterBar', scFilterBar);