parent
c785dd6479
commit
cd3350bd2c
@ -0,0 +1,2 @@
|
||||
VITE_BASE_URL=https://gateway.mashibing.cn
|
||||
VITE_REQUEST_TIMEOUT=20000
|
@ -0,0 +1,4 @@
|
||||
include:
|
||||
- project: 'yunwei/cicd/xuexipingtai/entrypoint'
|
||||
ref: main
|
||||
file: '/main.yml'
|
@ -1,59 +1,29 @@
|
||||
const mock = (data) =>
|
||||
new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve(data);
|
||||
}, Math.random() * 1500 + 500);
|
||||
import request from '@/utils/request.js';
|
||||
export const search = (params) => {
|
||||
return request({
|
||||
url: '/employee',
|
||||
method: 'get',
|
||||
params,
|
||||
});
|
||||
let list = [
|
||||
{
|
||||
id: 1,
|
||||
username: 'user001',
|
||||
nickname: '张三',
|
||||
sex: 1,
|
||||
avatar: 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fup.enterdesk.com%2Fedpic%2Ffd%2Ff1%2Fda%2Ffdf1dacb8ff0b8f13ed29bcbee42f328.jpeg&refer=http%3A%2F%2Fup.enterdesk.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1650201540&t=ba213738d8f11e79302fab71602856f2',
|
||||
loginTime: Date.now(),
|
||||
enabled: true,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
username: 'user003',
|
||||
nickname: '李四',
|
||||
sex: 0,
|
||||
avatar: 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fup.enterdesk.com%2Fedpic%2Ffd%2Ff1%2Fda%2Ffdf1dacb8ff0b8f13ed29bcbee42f328.jpeg&refer=http%3A%2F%2Fup.enterdesk.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1650201540&t=ba213738d8f11e79302fab71602856f2',
|
||||
loginTime: Date.now(),
|
||||
enabled: true,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
username: 'user003',
|
||||
nickname: '王五',
|
||||
sex: 1,
|
||||
avatar: 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fup.enterdesk.com%2Fedpic%2Ffd%2Ff1%2Fda%2Ffdf1dacb8ff0b8f13ed29bcbee42f328.jpeg&refer=http%3A%2F%2Fup.enterdesk.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1650201540&t=ba213738d8f11e79302fab71602856f2',
|
||||
loginTime: Date.now(),
|
||||
enabled: false,
|
||||
},
|
||||
];
|
||||
export const findUserList = (data) => {
|
||||
console.info(data);
|
||||
return mock({ content: list, totalElements: list.length });
|
||||
};
|
||||
export const createUser = (data) => {
|
||||
data = {
|
||||
id: new Date().getTime(),
|
||||
...data,
|
||||
};
|
||||
list.push(data);
|
||||
return mock(data);
|
||||
};
|
||||
export const updateUser = (data) => {
|
||||
let old = list.find((item) => item.id === data.id);
|
||||
Object.assign(old, data);
|
||||
return mock(old);
|
||||
export const create = (data) => {
|
||||
return request({
|
||||
url: '/employee',
|
||||
method: 'post',
|
||||
data,
|
||||
});
|
||||
};
|
||||
export const removeUser = (ids) => {
|
||||
list = list.filter((item) => !ids.includes(item.id));
|
||||
return mock(true);
|
||||
export const update = (data) => {
|
||||
return request({
|
||||
url: '/employee',
|
||||
method: 'put',
|
||||
data,
|
||||
});
|
||||
};
|
||||
export const getUserDetail = (id) => {
|
||||
return mock(list.find((item) => item.id === id));
|
||||
export const remove = (params) => {
|
||||
return request({
|
||||
url: '/employee',
|
||||
method: 'delete',
|
||||
params,
|
||||
});
|
||||
};
|
||||
|
@ -0,0 +1,147 @@
|
||||
<template>
|
||||
<div class="upload-box">
|
||||
<el-upload
|
||||
v-bind="props"
|
||||
:before-upload="handleBeforeUpload"
|
||||
:file-list="imgList"
|
||||
:headers="headers"
|
||||
list-type="picture-card"
|
||||
:on-exceed="handleExceed"
|
||||
:on-preview="handlePreview"
|
||||
>
|
||||
<el-icon name="Plus" />
|
||||
</el-upload>
|
||||
<el-image
|
||||
v-if="preview"
|
||||
ref="refsPreview"
|
||||
alt="图片预览"
|
||||
:src="preview"
|
||||
style="position: absolute; z-index: -9999"
|
||||
@close="preview = null"
|
||||
@load="$event.path[0].click()"
|
||||
/>
|
||||
<div class="el-upload__tip">支持小于 {{ fmtSize }} 的 文件</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="jsx">
|
||||
import config from '@/configs';
|
||||
import { ElMessage } from '@/plugins/element-plus';
|
||||
import 'element-plus/es/components/image/style/css';
|
||||
const store = useStore();
|
||||
const props = defineProps({
|
||||
action: {
|
||||
type: String,
|
||||
default: config.baseURL + '/edu-oss/oss/fileUpload',
|
||||
},
|
||||
data: {
|
||||
type: Object,
|
||||
default() {
|
||||
return { service: 'msb-edu-course' };
|
||||
},
|
||||
},
|
||||
headers: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {};
|
||||
},
|
||||
},
|
||||
drag: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
defualt: false,
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
defualt: false,
|
||||
},
|
||||
limit: {
|
||||
type: Number,
|
||||
default: 1,
|
||||
},
|
||||
size: {
|
||||
type: Number,
|
||||
default: 1024 * 1024 * 20,
|
||||
},
|
||||
accept: {
|
||||
type: String,
|
||||
default: 'image/*',
|
||||
},
|
||||
});
|
||||
const emits = defineEmits(['update:modelValue']);
|
||||
let headers = { ...props.headers };
|
||||
headers['Authorization'] = store.state.local.token;
|
||||
const imgList = ref([]);
|
||||
const attrs = useAttrs();
|
||||
watch(
|
||||
() => attrs.modelValue,
|
||||
(value) => {
|
||||
if (
|
||||
unref(imgList)
|
||||
.map((item) => item.url)
|
||||
.join(',') !== value.join(',')
|
||||
) {
|
||||
imgList.value = (value instanceof Array ? value : [value])
|
||||
.filter((item) => item)
|
||||
.map((item) => {
|
||||
return {
|
||||
name: item,
|
||||
response: {
|
||||
data: item,
|
||||
},
|
||||
url: item,
|
||||
};
|
||||
});
|
||||
}
|
||||
},
|
||||
{ immediate: true, deep: true }
|
||||
);
|
||||
watch(
|
||||
() => imgList,
|
||||
() => {
|
||||
const arr = unref(imgList).map((item) => item.response?.data);
|
||||
if (arr.every((item) => !!item)) {
|
||||
const value = props.limit === 1 ? arr[0] : arr;
|
||||
emits('update:modelValue', value);
|
||||
}
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
const refsPreview = ref(null);
|
||||
const preview = ref('');
|
||||
const handlePreview = (file) => {
|
||||
console.info('[upload] preview', file);
|
||||
preview.value = file.url;
|
||||
};
|
||||
const handleExceed = (list) => {
|
||||
console.info('[upload] exceed', list);
|
||||
ElMessage.error('超出最大上传数量');
|
||||
};
|
||||
const handleBeforeUpload = (file) => {
|
||||
console.info('[upload] upload', file);
|
||||
let res = true;
|
||||
if (file.type.startsWith('image/')) {
|
||||
if (file.size >= props.size) {
|
||||
ElMessage.error('超出文件大小限制');
|
||||
res = false;
|
||||
}
|
||||
} else {
|
||||
ElMessage.error('只允许上传图片');
|
||||
res = false;
|
||||
}
|
||||
return res;
|
||||
};
|
||||
const fmtSize = computed(() => {
|
||||
const units = ['byte', 'KB', 'MB', 'GB', 'TB'];
|
||||
let res = props.size,
|
||||
unit = 0;
|
||||
while (res >= 800) {
|
||||
res /= 1024;
|
||||
unit++;
|
||||
}
|
||||
return res + units[unit];
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped></style>
|
@ -1,212 +0,0 @@
|
||||
<template>
|
||||
<component :is="render" />
|
||||
</template>
|
||||
<script setup lang="jsx">
|
||||
import config from '@/configs';
|
||||
import { ElMessage } from '@/plugins/element-plus';
|
||||
import { ElUpload } from 'element-plus/es/components/upload/index';
|
||||
import 'element-plus/es/components/upload/style/css';
|
||||
import { ElImage } from 'element-plus/es/components/image/index';
|
||||
import 'element-plus/es/components/image/style/css';
|
||||
const store = useStore();
|
||||
const props = defineProps({
|
||||
action: {
|
||||
type: String,
|
||||
default: config.baseURL + '/edu-oss/oss/fileUpload',
|
||||
},
|
||||
data: {
|
||||
type: Object,
|
||||
default() {
|
||||
return { service: 'msb-edu-course' };
|
||||
},
|
||||
},
|
||||
headers: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {};
|
||||
},
|
||||
},
|
||||
drag: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
defualt: false,
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
defualt: false,
|
||||
},
|
||||
limit: {
|
||||
type: Number,
|
||||
default: 1,
|
||||
},
|
||||
size: {
|
||||
type: Number,
|
||||
default: 1024 * 1024 * 20,
|
||||
},
|
||||
accept: {
|
||||
type: String,
|
||||
default: '*.*',
|
||||
},
|
||||
});
|
||||
const attrs = useAttrs();
|
||||
const emits = defineEmits(['update:modelValue']);
|
||||
let headers = { ...props.headers };
|
||||
headers['Authorization'] = 'Bearer ' + store.state.local.token;
|
||||
let imgList = ref([]);
|
||||
const refsUpload = ref(null);
|
||||
watch(
|
||||
() => imgList,
|
||||
() => {
|
||||
if (props.limit === 1) {
|
||||
emits('update:modelValue', unref(imgList)[0]?.response.data);
|
||||
} else {
|
||||
emits('update:modelValue', unref(imgList));
|
||||
}
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
const handleSuccess = (res, file, list) => {
|
||||
console.info('[upload] success', list);
|
||||
imgList.value = list;
|
||||
};
|
||||
const handleRemove = (file, list) => {
|
||||
console.info('[upload] remove', list);
|
||||
imgList.value = list;
|
||||
};
|
||||
const handleExceed = (list) => {
|
||||
console.info('[upload] exceed', list);
|
||||
ElMessage.error('超出最大上传数量');
|
||||
};
|
||||
const handleBeforeUpload = (file) => {
|
||||
console.info('[upload] upload', file);
|
||||
if (file.size >= props.size) {
|
||||
ElMessage.error('超出文件大小限制');
|
||||
return false;
|
||||
}
|
||||
};
|
||||
const fmtSize = computed(() => {
|
||||
const units = ['byte', 'KB', 'MB', 'GB', 'TB'];
|
||||
let res = props.size,
|
||||
unit = 0;
|
||||
while (res >= 800) {
|
||||
res /= 1024;
|
||||
unit++;
|
||||
}
|
||||
return res + units[unit];
|
||||
});
|
||||
watch(
|
||||
() => attrs.modelValue,
|
||||
(value) => {
|
||||
if (props.limit === 1 && value) {
|
||||
imgList.value = [
|
||||
{
|
||||
name: value,
|
||||
response: {
|
||||
data: value,
|
||||
},
|
||||
},
|
||||
];
|
||||
} else {
|
||||
imgList.value = value || [];
|
||||
}
|
||||
},
|
||||
{ immediate: true, deep: true }
|
||||
);
|
||||
const handleDeleteImage = (index) => {
|
||||
if (unref(refsUpload)) {
|
||||
unref(refsUpload).handleRemove(imgList[index]);
|
||||
} else {
|
||||
unref(imgList).splice(index, 1);
|
||||
}
|
||||
};
|
||||
const render = () => (
|
||||
<div class="upload-box">
|
||||
<div class="upload-image">
|
||||
{unref(imgList).map((item, index) => (
|
||||
<div class="img-li">
|
||||
<ElImage src={item?.response?.data} alt={item.name} />
|
||||
{!props.disabled ? (
|
||||
<div class="img-li-cover" onClick={() => handleDeleteImage(index)}>
|
||||
<ElIcon class="upload-del-icon" name="delete-bin-fill" size="20" />
|
||||
</div>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
{props.limit !== unref(imgList).length ? (
|
||||
<ElUpload
|
||||
ref={refsUpload}
|
||||
{...{ ...props, headers }}
|
||||
{...attrs}
|
||||
before-upload={handleBeforeUpload}
|
||||
on-exceed={handleExceed}
|
||||
on-remove={handleRemove}
|
||||
on-success={handleSuccess}
|
||||
show-file-list={false}
|
||||
>
|
||||
<ElIcon class="el-icon--upload" name="add-fill" size="20" />
|
||||
</ElUpload>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
</div>
|
||||
<div class="el-upload__tip">支持小于 {unref(fmtSize)} 的 文件</div>
|
||||
</div>
|
||||
);
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.upload-box {
|
||||
:deep(.upload-image) {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
.img-li {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
margin-right: 20px;
|
||||
overflow: hidden;
|
||||
.img-li-cover {
|
||||
display: none;
|
||||
}
|
||||
&:hover {
|
||||
.img-li-cover {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
cursor: pointer;
|
||||
.upload-del-icon {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
:deep(.el-upload) {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
.el-upload-dragger {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.el-icon--upload {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,20 +0,0 @@
|
||||
const state = () => ({
|
||||
count: 0,
|
||||
});
|
||||
const getters = {
|
||||
doubleCount: (state) => state.count * 2,
|
||||
};
|
||||
const mutations = {
|
||||
add: (state, num = 1) => (state.count += num),
|
||||
};
|
||||
const actions = {
|
||||
clear: ({ state, commit }) => {
|
||||
commit('add', state.count * -1);
|
||||
},
|
||||
};
|
||||
export default {
|
||||
state,
|
||||
getters,
|
||||
mutations,
|
||||
actions,
|
||||
};
|
@ -1,39 +1,7 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<h1>{{ $route.name }}</h1>
|
||||
<h1>
|
||||
<el-icon name="app-store" size="30" />
|
||||
<span>马士兵严选</span>
|
||||
<el-icon name="msb" size="30" svg />
|
||||
<el-icon color="red" name="vue" size="30" svg />
|
||||
<el-icon color="red" name="Avatar" size="30" />
|
||||
</h1>
|
||||
<p>count:{{ count }}, double count:{{ doubleCount }}</p>
|
||||
<el-button type="primary" @click="handleAdd">增加</el-button>
|
||||
<el-button type="danger" @click="handleClear">清除</el-button>
|
||||
<br />
|
||||
<el-date-picker />
|
||||
{{ form }}
|
||||
<el-input v-model="form.msg" />
|
||||
<el-editor v-model="form.msg" preview="pc" />
|
||||
</div>
|
||||
<div class="container">欢迎使用马士兵管理平台</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const store = useStore();
|
||||
const count = computed(() => store.state.demo.count);
|
||||
const doubleCount = computed(() => store.getters['demo/doubleCount']);
|
||||
const handleAdd = () => {
|
||||
store.commit('demo/add');
|
||||
};
|
||||
const handleClear = () => {
|
||||
store.dispatch('demo/clear');
|
||||
};
|
||||
const form = reactive({ msg: '123' });
|
||||
</script>
|
||||
<script setup></script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.container {
|
||||
height: 2000px !important;
|
||||
}
|
||||
</style>
|
||||
<style lang="less" scoped></style>
|
||||
|
Loading…
Reference in new issue