提交数据

This commit is contained in:
zouzhibing 2022-06-10 15:04:07 +08:00
parent 03444338c9
commit acbc11794a
14 changed files with 824 additions and 749 deletions

View File

@ -1,24 +1,75 @@
# ad
# 简介
vue-element-perfect 是一个后台前端解决方案, 基于Vue3.0+TS+Element-plus实现。它使用了最新的前端技术栈、动态路由权限验证并且有着丰富的组件。
## 效果预览
### 在线预览点击 —— [企业级、通用型中后台前端解决方案 ](http://182.61.5.190:8889/)
### 附上github地址点击跳转 [vue-admin-perfect](https://github.com/zouzhibin/vue-admin-perfect)
## 目录结构介绍
## Project setup
```
yarn install
```
### Compiles and hot-reloads for development
├─assets 放置一些静态文件
├─components 放置组件
├─layout 首页布局
│ ├─components
│ │ ├─Sidebar 侧边栏配置
│ │ ├─TagsView 标签栏配置
│ │ └─UHeader 头部内容配置
│ └─hooks
├─router 路由配置
├─store 数据存储
├─styles 样式文件
├─utils 工具方法
└─views 页面配置方法
└─permission 路由拦截 权限配置
```
## 技术栈
vue3.0 + Typescript + vuex + vue-router + Element-Plus scss
## 实现功能
- 登录逻辑
- 权限校验
- 侧边栏导航显示
- 打印
- 地图
- 头像裁剪
- 无限滚动
- 多标签显示
- 退出
- 其他各组件
## 项目 master 分支 基于vue3.0 + Typescript + vuex + vue-router + Element-Plus scss
```
# 克隆项目
git clone https://github.com/zouzhibin/vue-admin-perfect.git
# 安装依赖
yarn
# 本地开发 启动项目
yarn serve
```
### Compiles and minifies for production
## 项目 uniapp 分支 基于 uniapp +vuex +element scss
```
yarn build
# 克隆项目 切换 uniapp分支
git clone https://github.com/zouzhibin/vue-admin-perfect.git
# 安装依赖
yarn
# 本地开发 启动项目
hbuilder运行浏览器启动
```
### Lints and fixes files
```
yarn lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).

18
deploy.sh Normal file
View File

@ -0,0 +1,18 @@
#强制推送
#!/usr/bin/env bash
set -e
npm run build
cd dist
touch .nojekyll
git init
git add -A
git commit -m 'deploy'
git push -f "https://${access_token}@gitee.com/yuanzbz/vue-admin-perfect.git" master:gh-pages
git push -f "https://${access_token}@github.com/zouzhibin/vue-admin-perfect.git" master:gh-pages
cd -
exec /bin/bash

View File

@ -60,9 +60,6 @@
"sass-loader": "^8.0.2",
"typescript": "~4.1.5"
},
"gitHooks": {
"pre-commit": "lint-staged"
},
"lint-staged": {
"*.{js,jsx,vue,ts,tsx}": [
"vue-cli-service lint",

13
push.sh Normal file
View File

@ -0,0 +1,13 @@
#强制推送
#!/usr/bin/env bash
set -e
git init
git add -A
git commit -m '🎉 feat: init project'
git push -f "https://${access_token}@gitee.com/yuanzbz/vue-admin-perfect.git" master
git push -f "https://${access_token}@github.com/zouzhibin/vue-admin-perfect.git" master
exec /bin/bash

View File

@ -20,7 +20,6 @@
</div>
</el-popover>
</div>
</template>

View File

@ -14,8 +14,8 @@
<script lang="ts" setup>
import USetting from '@/components/u-setting/index.vue'
import {useStore} from "vuex";
import {computed, ref,} from 'vue'
import { useStore } from 'vuex'
import { computed, ref } from 'vue'
const store = useStore()
const cachedViews = computed(() => {
@ -41,7 +41,6 @@
// background: white;
}
////
//.main-enter-active {
// transition: 0.2s;

View File

@ -1,6 +1,6 @@
/** When your routing table is too long, you can split it into small modules**/
import Layout from "@/layout/index.vue";
import Layout from '@/layout/index.vue'
const othersRouter = {
path: '/other',
@ -28,19 +28,19 @@ const othersRouter = {
path: 'print',
component: () => import('@/views/other/print.vue'),
name: 'print',
meta: { title: '打印', }
meta: { title: '打印' }
},
{
path: 'cropper',
component: () => import('@/views/other/cropper/index.vue'),
name: 'cropper',
meta: { title: '头像裁剪' , }
meta: { title: '头像裁剪' }
},
{
path: 'grid-sorter',
component: () => import('@/views/other/grid-sorter.vue'),
name: 'grid-sorter',
meta: { title: '卡片拖拽', }
meta: { title: '卡片拖拽' }
},
// {
// path: 'splitpane',
@ -52,20 +52,20 @@ const othersRouter = {
path: 'qrcode',
component: () => import('@/views/other/qrcode.vue'),
name: 'qrcode',
meta: { title: '生成二维码', }
meta: { title: '生成二维码' }
},
{
path: 'right-menu',
component: () => import('@/views/other/right-menu.vue'),
name: 'right-menu',
meta: { title: '右键菜单',}
meta: { title: '右键菜单' }
},
{
path: 'count',
component: () => import('@/views/other/count.vue'),
name: 'count',
meta: { title: '数字自增长',}
},
meta: { title: '数字自增长' }
}
]
}

View File

@ -4,11 +4,11 @@
</template>
<script lang="ts" setup>
import { geoJson } from './get.js'
import * as echarts from "echarts";
import {EChartsType} from "echarts/core";
import {onMounted} from "vue";
import * as echarts from 'echarts'
import { EChartsType } from 'echarts/core'
import { onMounted } from 'vue'
let props = defineProps({
const props = defineProps({
className: {
type: String,
default: 'chart'
@ -33,107 +33,103 @@
var geoGpsMap = [109.1162, 34.2004]
var geoCoordMap = {
"江苏": [118.8062, 31.9208],
'内蒙古': [110.3467, 41.4899],
"辽宁": [123.1238, 42.1216],
"陕西": [109.1162, 34.2004],
"甘肃": [103.5901, 36.3043],
"青海": [101.4038, 36.8207],
"新疆": [87.9236, 43.5883],
江苏: [118.8062, 31.9208],
内蒙古: [110.3467, 41.4899],
辽宁: [123.1238, 42.1216],
陕西: [109.1162, 34.2004],
甘肃: [103.5901, 36.3043],
青海: [101.4038, 36.8207],
新疆: [87.9236, 43.5883],
"河南": [113.4668, 34.6234],
"西藏": [116.3896, 39.91],
"浙江": [119.5313, 29.8773],
"福建": [119.4543, 25.9222],
"湖南": [113.0823, 28.2568],
"四川": [113.0823, 28.2568],
"云南": [102.9199, 25.4663],
"广东": [113.12244, 23.009505],
"海南": [110.3893, 19.8516]
};
河南: [113.4668, 34.6234],
西藏: [116.3896, 39.91],
浙江: [119.5313, 29.8773],
福建: [119.4543, 25.9222],
湖南: [113.0823, 28.2568],
四川: [113.0823, 28.2568],
云南: [102.9199, 25.4663],
广东: [113.12244, 23.009505],
海南: [110.3893, 19.8516]
}
var value = {
'江苏': 10000,
'内蒙古': 10000,
'辽宁': 10000,
'陕西': 10000,
'福建': 10000,
'甘肃': 10000,
'青海': 10000,
'新疆': 10000,
'湖北': 10000,
'浙江': 10000,
'河南': 10000,
'湖南': 10000,
'云南': 10000,
'广东': 10000,
'海南': 10000,
'西藏': 10000,
江苏: 10000,
内蒙古: 10000,
辽宁: 10000,
陕西: 10000,
福建: 10000,
甘肃: 10000,
青海: 10000,
新疆: 10000,
湖北: 10000,
浙江: 10000,
河南: 10000,
湖南: 10000,
云南: 10000,
广东: 10000,
海南: 10000,
西藏: 10000
}
var colors = '#f9b207'
};
var colors = '#f9b207';
var year = ["长春", "长春", "青岛", "青岛", "成都", "成都"];
var mapData = [];
var year = ['长春', '长春', '青岛', '青岛', '成都', '成都']
var mapData = []
/* 柱子Y名称 */
var categoryData = [];
var barData = [];
var categoryData = []
var barData = []
for (var key in geoCoordMap) {
mapData.push({
"year": '陕西',
"name": key,
"value": value[key] / 100,
"value1": value[key] / 100,
});
year: '陕西',
name: key,
value: value[key] / 100,
value1: value[key] / 100
})
}
mapData.sort(function sortNumber (a, b) {
return a.value - b.value
});
})
for (var j = 0; j < mapData.length; j++) {
barData.push(mapData[j].value1);
categoryData.push(mapData[j].name);
barData.push(mapData[j].value1)
categoryData.push(mapData[j].name)
}
echarts.registerMap('china', geoJson);
echarts.registerMap('china', geoJson)
var convertData = function (data) {
var res = [];
var res = []
for (var i = 0; i < data.length; i++) {
var geoCoord = geoCoordMap[data[i].name];
var geoCoord = geoCoordMap[data[i].name]
if (geoCoord) {
res.push({
name: data[i].name,
value: geoCoord.concat(data[i].value)
});
})
}
}
return res;
};
return res
}
var convertToLineData = function (data, gps) {
var res = [];
var res = []
for (var i = 0; i < data.length; i++) {
var dataItem = data[i];
var toCoord = geoCoordMap[dataItem.name];
var dataItem = data[i]
var toCoord = geoCoordMap[dataItem.name]
// debugger;
var fromCoord = gps; //
var fromCoord = gps //
// var toCoord = geoGps[Math.random()*3];
if (fromCoord && toCoord) {
res.push([{
coord: fromCoord,
value: dataItem.value
}, {
coord: toCoord,
}]);
coord: toCoord
}])
}
}
return res;
};
return res
}
const options = {
backgroundColor: '#001540',
@ -202,7 +198,7 @@
itemStyle: {
normal: {
areaColor: '#031525',
borderColor: '#FFFFFF',
borderColor: '#FFFFFF'
},
emphasis: {
areaColor: '#2B91B7'
@ -216,10 +212,10 @@
type: 'effectScatter',
coordinateSystem: 'geo',
data: convertData(mapData.sort(function (a, b) {
return b.value - a.value;
return b.value - a.value
}).slice(0, 20)),
symbolSize: function (val) {
return val[2] / 10;
return val[2] / 10
},
showEffectOn: 'render',
rippleEffect: {
@ -251,23 +247,23 @@
period: 4, //
trailLength: 0.02, // [0,1]
symbol: 'arrow', //
symbolSize: 3, //
symbolSize: 3 //
},
lineStyle: {
normal: {
color: colors,
width: 0.1, // 线
opacity: 0.5, // 线
curveness: .3 //线
curveness: 0.3 // 线
}
},
data: convertToLineData(mapData, geoGpsMap)
}
]
};
let chart:EChartsType;
}
let chart:EChartsType
const initChart = () => {
let chart = echarts.init(document.getElementById(props.id))
const chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
@ -276,6 +272,5 @@
window.addEventListener('resize', function () {
chart && chart.resize()
})
})
</script>

View File

@ -5,7 +5,6 @@
</template>
<script setup lang="ts">
import MigrationCharts from './components/migration/index.vue'

View File

@ -143,7 +143,6 @@
</div>
</el-card>
<el-card class="box-card">
<template #header>
<div class="card-header">
@ -173,7 +172,7 @@ import {
Message,
Search,
Share,
Star,
Star
} from '@element-plus/icons-vue'
</script>
<style>

View File

@ -39,19 +39,19 @@
<script lang="ts" setup>
// https://sortablejs.github.io/vue.draggable.next/#/transition-example-2
// https://github.com/SortableJS/vue.draggable.next/blob/master/package.json
import draggable from "vuedraggable";
import {computed, ref,reactive} from "vue";
import draggable from 'vuedraggable'
import { computed, ref, reactive } from 'vue'
import { getColor } from '@/utils/index'
const message = ref([]);
const tags = ref([]);
const message = ref([])
const tags = ref([])
let icon = ['management','baseball','Basketball','BellFilled','Bell',
const icon = ['management', 'baseball', 'Basketball', 'BellFilled', 'Bell',
'AddLocation', 'Aim', 'AlarmClock', 'Apple', 'ArrowDownBold', 'Burger',
'Brush', 'BrushFilled', 'RemoveFilled', 'QuestionFilled', 'Promotion', 'Printer',
'School', 'Setting', 'WarningFilled', 'ZoomOut', 'WalletFilled', 'User',
'ToiletPaper', 'Sunrise', 'Sunny', 'SwitchButton', 'TakeawayBox', 'Ticket',
'StarFilled','Stamp','Stopwatch','SortDown','SemiSelect','Search',
'StarFilled', 'Stamp', 'Stopwatch', 'SortDown', 'SemiSelect', 'Search'
]
//
@ -70,28 +70,28 @@
const dragOptions = computed(() => {
return {
animation: 200,
group: "description",
group: 'description',
disabled: false,
ghostClass: "ghost" //
};
ghostClass: 'ghost' //
}
})
const sorter = () => {
message.value = message.value.sort((a, b) => a.name - b.name);
message.value = message.value.sort((a, b) => a.name - b.name)
}
const onMoveCallback = (val) => {
console.log('拖动前的索引 :' + val.moved.newIndex);
console.log('拖动后的索引 :' + val.moved.oldIndex);
};
console.log('拖动前的索引 :' + val.moved.newIndex)
console.log('拖动后的索引 :' + val.moved.oldIndex)
}
//
const getdata = () => {
console.log(11111111);
};
console.log(11111111)
}
//
const getDataAction = () => {
console.log(message.value);
};
console.log(message.value)
}
</script>
<style lang="scss" scoped>

View File

@ -63,12 +63,13 @@
</div>
</template>
<script lang="ts" setup>
import {computed, ref} from "vue";
import { computed, ref, reactive } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import type { FormInstance } from 'element-plus'
const ruleFormRef = ref<FormInstance>()
const emit = defineEmits(['reset', 'onSubmit', 'selection-change'])
let props = defineProps({
const props = defineProps({
columns: {
type: Array,
default: () => []
@ -83,8 +84,6 @@ let props = defineProps({
}
})
const currentPage1 = ref(1)
const isExpand = ref(true)
const handleSizeChange = (val: number) => {
@ -96,11 +95,10 @@ const handleCurrentChange = (val: number) => {
}
const list = computed(() => {
let arr = JSON.parse(JSON.stringify(props.data))
const arr = JSON.parse(JSON.stringify(props.data))
return arr.splice((currentPage1.value - 1) * 10, 10)
})
const listLoading = ref(false)
const confirmEdit = (row) => {
row.edit = false
@ -109,11 +107,9 @@ const cancelEdit = (row)=>{
row.edit = false
}
import { reactive } from 'vue'
let obj = {}
let search = []
for(let item of props.columns){
const obj = {}
const search = []
for (const item of props.columns) {
if (item.inSearch) {
obj[item.name] = null
}
@ -143,21 +139,18 @@ const deleteAction = (row)=>{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
draggable: true,
draggable: true
}
)
.then(() => {
list.value = list.value.filter(item => item.id !== row.id)
ElMessage.success('删除成功')
})
.catch(() => {
})
}
</script>
<style scoped>
.edit-input {

View File

@ -73,15 +73,15 @@
</template>
<script lang="ts">
export default { name: 'comprehensive' };
</script>
<script lang="ts" setup>
import {ref, reactive, onMounted} from "vue";
import { ref, reactive, onMounted } from 'vue'
import * as dayjs from 'dayjs'
import { ElMessage, ElMessageBox } from 'element-plus'
import type { FormInstance } from 'element-plus'
const loading = ref(true)
import ComprehensiveTable from './components/comprehensive.vue'
export default { name: 'comprehensive' }
const loading = ref(true)
const data = []
for (let i = 0; i < 100; i++) {
data.push({
@ -89,7 +89,7 @@ export default { name: 'comprehensive' };
name: '王五' + i,
price: 1 + i,
province: '上海',
admin:"admin",
admin: 'admin',
sex: i % 2 ? 1 : 0,
checked: true,
id: i + 1,
@ -101,18 +101,21 @@ export default { name: 'comprehensive' };
}
const column = [
{ type: 'selection', width: 60 },
{ name: 'id', label: 'id',width:80, },
{ name: 'name',
{ name: 'id', label: 'id', width: 80 },
{
name: 'name',
label: '姓名',
inSearch: true,
valueType: 'input',
width: 80
},
{ name: 'age',
{
name: 'age',
label: '年龄',
align:'right',
align: 'right'
},
{ name: 'sex',
{
name: 'sex',
label: '性别',
slot: true,
inSearch: true,
@ -123,20 +126,33 @@ export default { name: 'comprehensive' };
value: 0,
label: '女'
}],
valueType:'select',
valueType: 'select'
},
{
name: 'price',
label: '价格',
inSearch: true,
valueType:'input',
valueType: 'input'
},
{
name: 'admin',
label: '账号',
inSearch: true,
valueType: 'input'
},
{
name: 'address',
label: '地址',
inSearch: true,
valueType: 'input'
},
{
name: 'date',
label: '日期',
sorter: true,
inSearch: true,
valueType: 'input'
},
{ name: 'admin', label: '账号', inSearch:true,
valueType:'input',},
{ name: 'address', label: '地址', inSearch:true,
valueType:'input', },
{ name: 'date', label: '日期',sorter:true, inSearch:true,
valueType:'input', },
{ name: 'province', label: '省份' },
{ name: 'city', label: '城市' },
{ name: 'zip', label: '邮编' },
@ -149,24 +165,24 @@ export default { name: 'comprehensive' };
const ruleForm = reactive({
name: '',
sex: null,
price:null,
price: null
})
const rules = reactive({
name: [
{ required: true, message: '请输入活动名称活动区域', trigger: 'blur' },
{ min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' },
{ min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' }
],
price: [
{ required: true, message: '请输入价格', trigger: 'blur' },
{ required: true, message: '请输入价格', trigger: 'blur' }
],
sex: [
{
required: true,
message: '请选择性别',
trigger: 'change',
},
],
trigger: 'change'
}
]
})
const dialogVisible = ref(false)
@ -177,7 +193,7 @@ export default { name: 'comprehensive' };
const handleClose = async (done: () => void) => {
await ruleFormRef.value.validate((valid, fields) => {
if (valid) {
let obj = {
const obj = {
id: Date.now(),
...ruleForm,
age: 0,
@ -185,7 +201,7 @@ export default { name: 'comprehensive' };
address: '上海市普上海',
zip: 200333,
province: '上海',
admin:"admin",
admin: 'admin',
date: dayjs().format('YYYY-MM-DD')
}
if (title.value === '新增') {
@ -224,11 +240,10 @@ export default { name: 'comprehensive' };
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
draggable: true,
draggable: true
}
)
.then(() => {
ElMessage.success('模拟删除成功')
list.value = list.value.concat([])
})
@ -258,7 +273,7 @@ export default { name: 'comprehensive' };
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
draggable: true,
draggable: true
}
)
.then(() => {

View File

@ -90,11 +90,12 @@
</template>
<script lang="ts">
export default { name: 'inline-table' };
</script>
<script lang="ts" setup >
import {computed, ref} from "vue";
import { computed, ref, reactive } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
export default { name: 'inline-table' }
const data = [
]
for (let i = 0; i < 100; i++) {
@ -103,11 +104,11 @@ export default { name: 'inline-table' };
name: '王五' + i,
price: 1 + i,
province: '上海',
admin:"admin",
admin: 'admin',
sex: i % 2 ? 1 : 0,
checked: true,
id: i + 1,
img:"https://img1.baidu.com/it/u=300787145,1214060415&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=500",
img: 'https://img1.baidu.com/it/u=300787145,1214060415&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=500',
age: 0,
city: '普陀区',
address: '上海市普上海',
@ -128,11 +129,10 @@ export default { name: 'inline-table' };
const loading = ref(false)
const list = computed(() => {
let arr = JSON.parse(JSON.stringify(transData.value))
const arr = JSON.parse(JSON.stringify(transData.value))
return arr.splice((currentPage1.value - 1) * 10, 10)
})
const listLoading = ref(false)
const confirmEdit = (row) => {
@ -143,10 +143,8 @@ export default { name: 'inline-table' };
row.edit = false
}
import { reactive } from 'vue'
const formInline1 = reactive({
username: '',
username: ''
})
const onSubmit = () => {
@ -165,7 +163,7 @@ export default { name: 'inline-table' };
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
draggable: true,
draggable: true
}
)
.then(() => {
@ -175,7 +173,6 @@ export default { name: 'inline-table' };
.catch(() => {
})
}
</script>