较多改动,暂存
This commit is contained in:
13
frontend/src/api/qcloud-cos.js
Normal file
13
frontend/src/api/qcloud-cos.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import send_request from '../utils/send_request';
|
||||
|
||||
/**
|
||||
* 获取 COS 存储桶上传临时 Credential
|
||||
* @returns
|
||||
*/
|
||||
export function getTmpCosCredential(params) {
|
||||
return send_request({
|
||||
url: '/shop/good/manage/imageUpload/getTmpCosCredential',
|
||||
method: 'GET',
|
||||
params: params,
|
||||
});
|
||||
};
|
51
frontend/src/api/shop-good.js
Normal file
51
frontend/src/api/shop-good.js
Normal file
@@ -0,0 +1,51 @@
|
||||
import send_request from '../utils/send_request';
|
||||
|
||||
/**
|
||||
* 获取商品列表
|
||||
* @returns
|
||||
*/
|
||||
export function getGoodList(params) {
|
||||
return send_request({
|
||||
url: '/shop/good/manage/getGoodList',
|
||||
method: 'GET',
|
||||
params: params,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 添加/修改商品信息
|
||||
* @returns
|
||||
*/
|
||||
export function editGood(params) {
|
||||
return send_request({
|
||||
url: '/shop/good/manage/editGood',
|
||||
method: 'POST',
|
||||
useQS: true,
|
||||
params: params,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 删除商品
|
||||
* @returns
|
||||
*/
|
||||
export function deleteGood(params) {
|
||||
return send_request({
|
||||
url: '/shop/good/manage/deleteGood',
|
||||
method: 'POST',
|
||||
useQS: true,
|
||||
params: params,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 导出商品列表
|
||||
* @returns
|
||||
*/
|
||||
export function exportGoodList(params) {
|
||||
return send_request({
|
||||
url: '/shop/good/manage/exportGoodList',
|
||||
method: 'GET',
|
||||
params: params,
|
||||
});
|
||||
};
|
@@ -1,310 +0,0 @@
|
||||
<template>
|
||||
<div class="calender-container">
|
||||
<div class="calender-toolbox">
|
||||
<div style="width: 100%;">
|
||||
<slot name="toolbox"></slot>
|
||||
</div>
|
||||
</div>
|
||||
<div class="calender-title">
|
||||
<div v-for="w in week">
|
||||
<p>{{ w }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="calender-grid" :style="{ gridTemplateRows: `repeat(${rowCount}, ${Math.ceil(100 / rowCount)}fr)` }">
|
||||
<div v-for="item in dayItem" class="calender-grid-item" :class="item.class">
|
||||
<template v-if="item.type == 'day'">
|
||||
<!-- 控制按钮 -->
|
||||
<div class="calender-grid-item-ctrl-btn-container">
|
||||
<div class="calender-grid-item-ctrl-btn">
|
||||
<el-icon :size="20" @click="uploadFile(item)">
|
||||
<UploadFilled />
|
||||
</el-icon>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 日期编号 -->
|
||||
<p class="calender-grid-item-day">{{ item.day }}</p>
|
||||
<!-- 附件 -->
|
||||
<div v-if="item.event.length > 0" class="calender-grid-item-attachment-container">
|
||||
<div v-for="e in item.event" class="calender-grid-item-attachment">
|
||||
<a class="download-link" :href="e.file.downloadLink" :download="e.file.displayName"
|
||||
:title="e.file.displayName" @contextmenu.prevent.native="contextMenuRef.openMenu($event)"
|
||||
@mouseover="showPopover($event, e)" @mouseleave="hidePopover()">
|
||||
{{ e.file.displayName }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 鼠标悬浮弹窗 -->
|
||||
<filePopover ref="filePopoverRef" />
|
||||
|
||||
<!-- 鼠标右键菜单 -->
|
||||
<contextMenu ref="contextMenuRef" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, defineProps, onMounted, onBeforeUpdate, nextTick, defineExpose } from 'vue';
|
||||
import contextMenu from './context-menu.vue';
|
||||
import filePopover from '../components/file-popover.vue';
|
||||
|
||||
const filePopoverRef = ref()
|
||||
const contextMenuRef = ref()
|
||||
|
||||
const props = defineProps({
|
||||
'year': {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
'month': {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
'events': {
|
||||
type: Object,
|
||||
require: false,
|
||||
default: [],
|
||||
},
|
||||
'doUpload': {
|
||||
type: Function,
|
||||
require: true,
|
||||
},
|
||||
})
|
||||
|
||||
const week = [
|
||||
"星期一",
|
||||
"星期二",
|
||||
"星期三",
|
||||
"星期四",
|
||||
"星期五",
|
||||
"星期六",
|
||||
"星期日",
|
||||
]
|
||||
|
||||
const dayItem = ref([]);
|
||||
|
||||
const rowCount = ref(5);
|
||||
|
||||
let isMounted = false;
|
||||
|
||||
const filePopoverInfo = ref({
|
||||
visable: false,
|
||||
})
|
||||
|
||||
// 绘制月历
|
||||
function getMonthCander(year, month, file) {
|
||||
console.log("getMonthCander", isMounted)
|
||||
console.log("file", file)
|
||||
let firstDay = new Date(year, month - 1, 1);
|
||||
let nextMonthFirstDay = new Date(year, (month + 1) - 1, 1);
|
||||
|
||||
let dayOfWeek = firstDay.getDay();
|
||||
let space = (dayOfWeek - 1 + 7) % 7; // 前面填充的空白格
|
||||
// console.log("space", space);
|
||||
|
||||
let dayCountInMonth = (nextMonthFirstDay - firstDay) / (1000 * 3600 * 24);
|
||||
// console.log("dayCountInMonth", dayCountInMonth);
|
||||
|
||||
// 空白填充格
|
||||
dayItem.value.push(...(new Array(space)).fill({
|
||||
"type": "space",
|
||||
"class": "space-item",
|
||||
}));
|
||||
|
||||
// 日期格
|
||||
for (let i = 1; i <= dayCountInMonth; i++) {
|
||||
dayItem.value.push({
|
||||
"type": "day",
|
||||
"day": i,
|
||||
"class": "day-item",
|
||||
"event": file.filter((f) => f.day === i),
|
||||
"date": new Date(year, month - 1, i),
|
||||
});
|
||||
}
|
||||
// console.log(dayItem.value);
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
console.log("calender onMounted.", "props:", props)
|
||||
getMonthCander(props.year, props.month, props.events);
|
||||
nextTick(() => {
|
||||
console.log("calender onMounted nextTick.");
|
||||
isMounted = true;
|
||||
})
|
||||
})
|
||||
|
||||
onBeforeUpdate(() => {
|
||||
console.log("calender onBeforeUpdate.", "props:", props)
|
||||
if (isMounted) {
|
||||
dayItem.value = [];
|
||||
getMonthCander(props.year, props.month, props.events);
|
||||
}
|
||||
})
|
||||
|
||||
// TODO
|
||||
function uploadFile(item) {
|
||||
console.log("uploadFile item:", item);
|
||||
if (typeof (props.doUpload) === "function") {
|
||||
props.doUpload(item.date);
|
||||
}
|
||||
}
|
||||
|
||||
// 弹出鼠标悬浮窗
|
||||
function showPopover($event, fileInfo) {
|
||||
// console.log("showPopover $event:", $event, "fileInfo:", fileInfo, $event.target);
|
||||
filePopoverRef.value.updateInfo({
|
||||
visable: true,
|
||||
left: $event.clientX - $event.offsetX + $event.target.offsetWidth / 2,
|
||||
top: $event.clientY - $event.offsetY + $event.target.offsetHeight + 5,
|
||||
width: 100,
|
||||
height: 100,
|
||||
});
|
||||
}
|
||||
|
||||
function hidePopover() {
|
||||
filePopoverRef.value.updateInfo({
|
||||
visable: false,
|
||||
});
|
||||
}
|
||||
|
||||
// 删除文件
|
||||
// function removeFile(...args) {
|
||||
// console.log("removeFile args:", args)
|
||||
// }
|
||||
|
||||
// defineExpose({
|
||||
// removeFile
|
||||
// })
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.calender-container {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
.calender-container {
|
||||
width: 90%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 2400px) {
|
||||
.calender-container {
|
||||
width: 80%;
|
||||
}
|
||||
}
|
||||
|
||||
.calender-toolbox {
|
||||
/* background-color: aqua; */
|
||||
height: 80px;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
}
|
||||
|
||||
.calender-title {
|
||||
background-color: #A0CFFF;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(7, 1fr);
|
||||
place-items: center;
|
||||
height: 38px;
|
||||
}
|
||||
|
||||
.calender-grid {
|
||||
background-color: #C6E2FF;
|
||||
height: 100%;
|
||||
|
||||
display: grid;
|
||||
grid-template-columns: repeat(7, 1fr);
|
||||
gap: 8px;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.calender-grid-item {
|
||||
max-height: 160px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.calender-grid-item-day {
|
||||
padding-top: 8px;
|
||||
padding-left: 10px;
|
||||
/* padding-bottom: 2px; */
|
||||
|
||||
height: 30px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.calender-grid-item-ctrl-btn-container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.calender-grid-item-ctrl-btn {
|
||||
position: absolute;
|
||||
right: 7px;
|
||||
top: 5px;
|
||||
opacity: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.calender-grid-item:hover .calender-grid-item-ctrl-btn {
|
||||
opacity: .45;
|
||||
}
|
||||
|
||||
.calender-grid-item:hover .calender-grid-item-ctrl-btn:hover {
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.calender-grid-item-attachment-container {
|
||||
padding: 0 3px;
|
||||
height: 100%;
|
||||
height: calc(100% - 30px);
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
padding-bottom: 5px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.calender-grid-item.day-item {
|
||||
background-color: #ECF5FF;
|
||||
}
|
||||
|
||||
.calender-grid-item-attachment,
|
||||
.download-link {
|
||||
background-color: #A0CFFF;
|
||||
color: black;
|
||||
border-radius: 50px;
|
||||
padding: 0.2px 5px;
|
||||
transition: all 0.12s;
|
||||
cursor: pointer;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.calender-grid-item-attachment:hover,
|
||||
.calender-grid-item-attachment:hover>.download-link {
|
||||
background-color: #409EFF;
|
||||
color: white;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.download-link {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
|
||||
.calender-title,
|
||||
.calender-grid-item.space-item {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.calender-grid {
|
||||
grid-template-columns: repeat(1, 1fr);
|
||||
grid-template-rows: repeat(31, 120px) !important;
|
||||
}
|
||||
}
|
||||
</style>
|
@@ -1,79 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<ul v-show="visible" :style="{ left: left + 'px', top: top + 'px' }" class="contextmenu">
|
||||
<li>菜单一</li>
|
||||
<li>菜单二</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
components: {},
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
top: 0,
|
||||
left: 0,
|
||||
};
|
||||
},
|
||||
expose: ['openMenu'],
|
||||
watch: {
|
||||
// 监听属性对象,newValue为新的值,也就是改变后的值
|
||||
visible(newValue, oldValue) {
|
||||
if (newValue) {
|
||||
//菜单显示的时候
|
||||
// document.body.addEventListener,document.body.removeEventListener它们都接受3个参数
|
||||
// ("事件名" , "事件处理函数" , "布尔值");
|
||||
// 在body上添加事件处理程序
|
||||
document.body.addEventListener("click", this.closeMenu);
|
||||
} else {
|
||||
//菜单隐藏的时候
|
||||
// 移除body上添加的事件处理程序
|
||||
document.body.removeEventListener("click", this.closeMenu);
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
//右击
|
||||
openMenu(e) {
|
||||
var x = e.pageX; //这个应该是相对于整个浏览器页面的x坐标,左上角为坐标原点(0,0)
|
||||
var y = e.pageY; //这个应该是相对于整个浏览器页面的y坐标,左上角为坐标原点(0,0)
|
||||
this.top = y + 2;
|
||||
this.left = x + 2;
|
||||
this.visible = true; //显示菜单
|
||||
},
|
||||
//关闭菜单
|
||||
closeMenu() {
|
||||
this.visible = false; //关闭菜单
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.contextmenu {
|
||||
margin: 0;
|
||||
background: #fff;
|
||||
z-index: 3000;
|
||||
/* //关键样式设置固定定位 */
|
||||
position: fixed;
|
||||
list-style-type: none;
|
||||
padding: 5px 0;
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
color: #333;
|
||||
box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.contextmenu li {
|
||||
margin: 0;
|
||||
padding: 7px 16px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.contextmenu li:hover {
|
||||
background: #eee;
|
||||
}
|
||||
</style>
|
82
frontend/src/components/image-upload.vue
Normal file
82
frontend/src/components/image-upload.vue
Normal file
@@ -0,0 +1,82 @@
|
||||
<template>
|
||||
<el-upload class="avatar-uploader" :auto-upload="true" :show-file-list="false" accept="image/*"
|
||||
:on-success="handleSuccess" :before-upload="beforeUpload" :http-request="handleHttpRequest">
|
||||
<img v-if="props.imageUrl" :src="props.imageUrl" class="avatar" />
|
||||
<el-icon v-else class="avatar-uploader-icon">
|
||||
<Plus />
|
||||
</el-icon>
|
||||
</el-upload>
|
||||
imageUrl: {{ imageUrl }}
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue'
|
||||
import { ElMessage, UploadProps, UploadRequestOptions } from 'element-plus'
|
||||
import { Plus } from '@element-plus/icons-vue'
|
||||
import * as cos from '../utils/qcloud-cos-upload';
|
||||
|
||||
const props = defineProps({
|
||||
// 获取列表 接口函数
|
||||
'imageUrl': {
|
||||
type: String,
|
||||
required: true,
|
||||
default: '',
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['change'])
|
||||
|
||||
const handleHttpRequest = async (data: UploadRequestOptions) => {
|
||||
console.log('httpRequest', data)
|
||||
await cos.upload(data.file)
|
||||
}
|
||||
|
||||
const handleSuccess: UploadProps['onSuccess'] = (
|
||||
response,
|
||||
uploadFile
|
||||
) => {
|
||||
let url = URL.createObjectURL(uploadFile.raw!)
|
||||
emit('change', url)
|
||||
}
|
||||
|
||||
const beforeUpload: UploadProps['beforeUpload'] = (rawFile) => {
|
||||
console.log("rawFile", rawFile)
|
||||
if (!['image/jpeg', 'image/png'].includes(rawFile.type)) {
|
||||
ElMessage.error('仅支持 JPG、PNG 格式图片,请重新选择')
|
||||
return false
|
||||
} else if (rawFile.size > 2 * 1024 * 1024) {
|
||||
ElMessage.error('图片太大,请选择 2MB 以内的图片')
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.avatar-uploader .avatar {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.avatar-uploader .el-upload {
|
||||
border: 1px dashed var(--el-border-color);
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
transition: var(--el-transition-duration-fast);
|
||||
}
|
||||
|
||||
.avatar-uploader .el-upload:hover {
|
||||
border-color: var(--el-color-primary);
|
||||
}
|
||||
|
||||
.el-icon.avatar-uploader-icon {
|
||||
font-size: 28px;
|
||||
color: #8c939d;
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
@@ -28,8 +28,24 @@
|
||||
<!-- 表格 -->
|
||||
<el-table :data="tableData" border class="table" ref="multipleTable" header-cell-class-name="table-header">
|
||||
<el-table-column prop="id" label="ID" width="55" align="center"></el-table-column>
|
||||
<el-table-column v-for="field in tableFields" :prop="field.prop" :label="field.label"
|
||||
align="center"></el-table-column>
|
||||
<el-table-column v-for="(field, index) in tableFields" :prop="field.prop" :label="field.label" :key="index"
|
||||
align="center">
|
||||
<template #default="scope" v-if="field.type == 'image'">
|
||||
<el-image style="width: 100%; height: 100%;" :src="scope.row.picUrl" fit="cover" />
|
||||
</template>
|
||||
<template #default="scope" v-else-if="field.type == 'longtext'">
|
||||
<el-tooltip placement="top">
|
||||
<template #content>
|
||||
<p v-for="line in scope.row.detail.split(/[\r\n]/g)" style="max-width: 300px;">
|
||||
{{ line }}
|
||||
</p>
|
||||
</template>
|
||||
<div class="oneLine">
|
||||
{{scope.row.detail}}
|
||||
</div>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="220" align="center">
|
||||
<template #default="scope">
|
||||
<el-button text :icon="Edit" @click="handleEdit(scope.$index, scope.row)"
|
||||
@@ -61,11 +77,16 @@
|
||||
<el-input v-if="(formId > 0 ? field.editType : field.addType) == 'input'"
|
||||
:placeholder="formId > 0 ? field.editPlaceholder : field.addPlaceholder" class="popup-item"
|
||||
v-model="form[field.field]"></el-input>
|
||||
<el-input v-else-if="(formId > 0 ? field.editType : field.addType) == 'textarea'"
|
||||
:placeholder="formId > 0 ? field.editPlaceholder : field.addPlaceholder" class="popup-item"
|
||||
v-model="form[field.field]" type="textarea" :rows="4"></el-input>
|
||||
<el-select v-else-if="(formId > 0 ? field.editType : field.addType) == 'select'" class="popup-item"
|
||||
v-model="form[field.field]" :clearable="true">
|
||||
<el-option v-for="optKey in Object.keys(field.options)" :key="optKey" :label="field.options[optKey]"
|
||||
:value="optKey"></el-option>
|
||||
</el-select>
|
||||
<ImageUpload v-else-if="(formId > 0 ? field.editType : field.addType) == 'image'"
|
||||
:imageUrl="form[field.field]" @change="(value: any) => form[field.field] = value" />
|
||||
<el-input v-else-if="(formId > 0 ? field.editType : field.addType) == 'plainText'" class="popup-item"
|
||||
v-model="form[field.field]" :disabled="true"></el-input>
|
||||
<!-- {{ field }} -->
|
||||
@@ -112,6 +133,7 @@ import { FormInstance, FormRules, ElMessage, ElMessageBox } from 'element-plus';
|
||||
import { Delete, Edit, Search, Plus, Filter, Download } from '@element-plus/icons-vue';
|
||||
import * as xlsx from 'xlsx';
|
||||
import Mock from 'mockjs';
|
||||
import ImageUpload from './image-upload.vue';
|
||||
|
||||
const props = defineProps({
|
||||
// 获取列表 接口函数
|
||||
@@ -229,13 +251,13 @@ const getData = async () => {
|
||||
|
||||
// 表格列
|
||||
tableFields.value = data.columns
|
||||
.filter((field: any) => field.showInTable)
|
||||
.filter((field: any) => field.fieldType != "null")
|
||||
.map((field: any) => {
|
||||
// query 填充默认空字符串
|
||||
if (typeof (query[field.field]) === "undefined") {
|
||||
query[field.field] = ''
|
||||
}
|
||||
return { prop: field.prop, label: field.label }
|
||||
return { prop: field.prop, label: field.label, type: field.fieldType }
|
||||
});
|
||||
console.log("tableFields", tableFields.value)
|
||||
// 表格数据
|
||||
@@ -294,7 +316,7 @@ const getData = async () => {
|
||||
|
||||
// 导出 excel 字段映射
|
||||
exportFields = data.columns
|
||||
.filter((field: any) => field.showInTable)
|
||||
.filter((field: any) => field.fieldType != "null")
|
||||
.map((field: any) => {
|
||||
return { field: field.field, label: field.label }
|
||||
});
|
||||
@@ -544,6 +566,9 @@ const doMockData = (isEdit: boolean) => {
|
||||
case "DPD":
|
||||
form[mock.field] = Mock.mock(mock.str)
|
||||
break;
|
||||
case "IMG":
|
||||
form[mock.field] = Mock.Random.dataImage(...mock.str.split(','))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -591,4 +616,10 @@ onMounted(() => {
|
||||
.popup-item {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.oneLine {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
</style>
|
||||
|
54
frontend/src/utils/qcloud-cos-upload.js
Normal file
54
frontend/src/utils/qcloud-cos-upload.js
Normal file
@@ -0,0 +1,54 @@
|
||||
import COS from 'cos-js-sdk-v5';
|
||||
import * as qCloudCosApi from '../api/qcloud-cos';
|
||||
|
||||
export function upload(file) {
|
||||
console.log("file", file);
|
||||
return new Promise((resolve, reject) => {
|
||||
qCloudCosApi.getTmpCosCredential({
|
||||
ext: 'jpg'
|
||||
}).then((data) => {
|
||||
console.log("data", data)
|
||||
// {
|
||||
// "tmpSecretId": "",
|
||||
// "tmpSecretKey": "",
|
||||
// "sessionToken": "",
|
||||
// "objectKey": "",
|
||||
// "startTimestamp": 1680534188320,
|
||||
// "expiredTimestamp": 1680535988320,
|
||||
// "bucket": "epp-1302260381",
|
||||
// "region": "ap-shanghai"
|
||||
// }
|
||||
|
||||
let cos = new COS({
|
||||
// getAuthorization 必选参数
|
||||
getAuthorization: function (options, callback) {
|
||||
// 异步获取临时密钥
|
||||
callback({
|
||||
TmpSecretId: data.tmpSecretId,
|
||||
TmpSecretKey: data.tmpSecretKey,
|
||||
SecurityToken: data.sessionToken,
|
||||
// 建议返回服务器时间作为签名的开始时间,避免用户浏览器本地时间偏差过大导致签名错误
|
||||
StartTime: Math.floor(data.startTimestamp / 1000), // 时间戳,单位秒,如:1580000000
|
||||
ExpiredTime: Math.floor(data.expiredTimestamp / 1000), // 时间戳,单位秒,如:1580000000
|
||||
});
|
||||
}
|
||||
});
|
||||
console.log("cos", cos)
|
||||
|
||||
cos.putObject({
|
||||
Bucket: data.bucket, /* 填入您自己的存储桶,必须字段 */
|
||||
Region: data.region, /* 存储桶所在地域,例如ap-beijing,必须字段 */
|
||||
Key: data.objectKey, /* 存储在桶里的对象键(例如1.jpg,a/b/test.txt),必须字段 */
|
||||
Body: file,
|
||||
}, function (err, data) {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(data);
|
||||
}
|
||||
});
|
||||
}).catch((err) => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
};
|
@@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<manageList :list-func="userApi.getUserList" :add-func="userApi.editUser" :edit-func="userApi.editUser"
|
||||
:delete-func="userApi.deleteUser" :export-func="userApi.exportUserList" edit-permiss="privilege-user-setting" />
|
||||
<manageList :list-func="shopGoodApi.getGoodList" :add-func="shopGoodApi.editGood" :edit-func="shopGoodApi.editGood"
|
||||
:delete-func="shopGoodApi.deleteGood" :export-func="shopGoodApi.exportGoodList" edit-permiss="shop-good-setting" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import manageList from '../components/manage-list.vue';
|
||||
import * as userApi from '../api/user';
|
||||
import * as shopGoodApi from '../api/shop-good';
|
||||
</script>
|
||||
|
Reference in New Issue
Block a user