mirror of
https://gitee.com/beijing_hongye_huicheng/lilishop-ui.git
synced 2026-08-06 02:47:29 +08:00
Merge branch 'vue3' of https://gitee.com/beijing_hongye_huicheng/lilishop-ui into vue3
This commit is contained in:
@@ -16,10 +16,12 @@
|
||||
"@amap/amap-jsapi-loader": "0.0.7",
|
||||
"@antv/g2": "^4.1.12",
|
||||
"@element-plus/icons-vue": "^2.3.2",
|
||||
"@tencentcloud/chat": "^3.6.6",
|
||||
"axios": "^1.7.9",
|
||||
"core-js": "^3.49.0",
|
||||
"dplayer": "^1.26.0",
|
||||
"element-plus": "^2.14.1",
|
||||
"hls.js": "^1.6.16",
|
||||
"js-cookie": "^2.2.1",
|
||||
"nprogress": "^0.2.0",
|
||||
"price-color": "1.0.2",
|
||||
@@ -39,7 +41,6 @@
|
||||
"xss": "^1.0.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"webpack": "^5.95.0",
|
||||
"@vue/cli-plugin-babel": "^5.0.9",
|
||||
"@vue/cli-plugin-router": "^5.0.9",
|
||||
"@vue/cli-plugin-vuex": "^5.0.9",
|
||||
@@ -51,7 +52,8 @@
|
||||
"less-loader": "^11.1.4",
|
||||
"style-loader": "^3.3.4",
|
||||
"style-resources-loader": "^1.5.0",
|
||||
"vue-cli-plugin-style-resources-loader": "^0.1.5"
|
||||
"vue-cli-plugin-style-resources-loader": "^0.1.5",
|
||||
"webpack": "^5.95.0"
|
||||
},
|
||||
"resolutions": {
|
||||
"minimatch": "^3.1.2",
|
||||
|
||||
22
manager/pnpm-lock.yaml
generated
22
manager/pnpm-lock.yaml
generated
@@ -21,6 +21,9 @@ importers:
|
||||
'@element-plus/icons-vue':
|
||||
specifier: ^2.3.2
|
||||
version: 2.3.2(vue@3.5.39)
|
||||
'@tencentcloud/chat':
|
||||
specifier: ^3.6.6
|
||||
version: 3.6.6
|
||||
axios:
|
||||
specifier: ^1.7.9
|
||||
version: 1.18.1
|
||||
@@ -33,6 +36,9 @@ importers:
|
||||
element-plus:
|
||||
specifier: ^2.14.1
|
||||
version: 2.14.2(vue@3.5.39)
|
||||
hls.js:
|
||||
specifier: ^1.6.16
|
||||
version: 1.6.16
|
||||
js-cookie:
|
||||
specifier: ^2.2.1
|
||||
version: 2.2.1
|
||||
@@ -829,36 +835,42 @@ packages:
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@parcel/watcher-linux-arm-musl@2.5.6':
|
||||
resolution: {integrity: sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@parcel/watcher-linux-arm64-glibc@2.5.6':
|
||||
resolution: {integrity: sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@parcel/watcher-linux-arm64-musl@2.5.6':
|
||||
resolution: {integrity: sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@parcel/watcher-linux-x64-glibc@2.5.6':
|
||||
resolution: {integrity: sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@parcel/watcher-linux-x64-musl@2.5.6':
|
||||
resolution: {integrity: sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@parcel/watcher-win32-arm64@2.5.6':
|
||||
resolution: {integrity: sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==}
|
||||
@@ -906,6 +918,9 @@ packages:
|
||||
'@sxzz/popperjs-es@2.11.8':
|
||||
resolution: {integrity: sha512-wOwESXvvED3S8xBmcPWHs2dUuzrE4XiZeFu7e1hROIJkm02a49N120pmOXxY33sBb6hArItm5W5tcg1cBtV+HQ==}
|
||||
|
||||
'@tencentcloud/chat@3.6.6':
|
||||
resolution: {integrity: sha512-PYPGUoZHw3GjDgM0N72qr0K/Wjp28HAoGaND077sbUQEwYFaMjZ1tuBQZugFG6v8OS8Ihx71yqNshR3xDHvYaA==}
|
||||
|
||||
'@types/body-parser@1.19.6':
|
||||
resolution: {integrity: sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==}
|
||||
|
||||
@@ -2353,6 +2368,9 @@ packages:
|
||||
highlight.js@10.7.3:
|
||||
resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==}
|
||||
|
||||
hls.js@1.6.16:
|
||||
resolution: {integrity: sha512-VSIRpLfRwlAAdGL4wiTucx2ScRipo0ed1FBatWkyt832jC4CReKstga6yIhYVwGu9LOBjuX9wzmRMeQdBJtzEA==}
|
||||
|
||||
hosted-git-info@2.8.9:
|
||||
resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==}
|
||||
|
||||
@@ -5147,6 +5165,8 @@ snapshots:
|
||||
|
||||
'@sxzz/popperjs-es@2.11.8': {}
|
||||
|
||||
'@tencentcloud/chat@3.6.6': {}
|
||||
|
||||
'@types/body-parser@1.19.6':
|
||||
dependencies:
|
||||
'@types/connect': 3.4.38
|
||||
@@ -6833,6 +6853,8 @@ snapshots:
|
||||
|
||||
highlight.js@10.7.3: {}
|
||||
|
||||
hls.js@1.6.16: {}
|
||||
|
||||
hosted-git-info@2.8.9: {}
|
||||
|
||||
hpack.js@2.1.6:
|
||||
|
||||
@@ -78,6 +78,9 @@ export const queryLiveMessagePage = params => getRequest('/live/message/page', p
|
||||
export const authLiveMessage = params =>
|
||||
putRequest('/live/message/auth', params, { 'Content-type': 'application/json' })
|
||||
|
||||
export const postSendMessage = params =>
|
||||
postRequest('/live/message/send', params, { 'Content-type': 'application/json' })
|
||||
|
||||
// ========== 直播用户 / 拉黑 ==========
|
||||
export const liveUserList = params => getRequest('/live/user/page', params)
|
||||
|
||||
|
||||
251
manager/src/views/live/components/LiveChatPanel.vue
Normal file
251
manager/src/views/live/components/LiveChatPanel.vue
Normal file
@@ -0,0 +1,251 @@
|
||||
<template>
|
||||
<div class="live-chat-panel">
|
||||
<div v-if="initError" class="chat-error">
|
||||
<el-alert :title="initError" type="warning" :closable="false" show-icon />
|
||||
</div>
|
||||
|
||||
<div ref="chatListRef" class="chat-list" @scroll="onScroll">
|
||||
<div v-if="isLoadingHistory" class="chat-loading">加载历史消息...</div>
|
||||
<div
|
||||
v-for="msg in messageList"
|
||||
:key="msg.messageId"
|
||||
class="chat-item"
|
||||
:class="{ 'is-system': msg.isSystem }"
|
||||
>
|
||||
<el-avatar v-if="!msg.isSystem" :src="msg.avatar" :size="28">
|
||||
{{ (msg.username || "用").charAt(0) }}
|
||||
</el-avatar>
|
||||
<div class="chat-bubble">
|
||||
<div v-if="!msg.isSystem" class="chat-user">{{ msg.username }}</div>
|
||||
<div class="chat-text">{{ msg.message }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-empty v-if="!messageList.length && !initError && !initializing" :image-size="64" description="暂无聊天消息" />
|
||||
<div ref="bottomAnchorRef" class="chat-bottom-anchor" />
|
||||
</div>
|
||||
|
||||
<div v-if="unreadCount > 0" class="chat-unread" @click="scrollToBottomAndClearUnread">
|
||||
{{ unreadCount }} 条新消息
|
||||
</div>
|
||||
|
||||
<div class="chat-input-bar">
|
||||
<el-input
|
||||
v-model="messageContent"
|
||||
placeholder="发送消息到直播间..."
|
||||
maxlength="200"
|
||||
@keyup.enter="createTextMessageByInput"
|
||||
/>
|
||||
<el-button type="primary" :disabled="!messageContent.trim()" @click="handleSend">
|
||||
发送
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Cookies from "js-cookie";
|
||||
import { toRef } from "vue";
|
||||
import { useChat } from "../composables/useChat";
|
||||
|
||||
export default {
|
||||
name: "LiveChatPanel",
|
||||
props: {
|
||||
liveId: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
liveDetail: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
active: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
let userInfo = {};
|
||||
try {
|
||||
userInfo = JSON.parse(Cookies.get("userInfoManager") || "{}");
|
||||
} catch {
|
||||
userInfo = {};
|
||||
}
|
||||
|
||||
return useChat(toRef(props, "liveId"), userInfo);
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
initializing: false,
|
||||
chatInited: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
/** 腾讯云 IM 群组:优先后端字段,否则用直播间 ID(与旧版中控台一致) */
|
||||
imGroupId() {
|
||||
return this.liveDetail?.imGroupId || this.liveDetail?.groupId || this.liveId || "";
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
imGroupId: {
|
||||
immediate: true,
|
||||
handler(id) {
|
||||
if (!id) return;
|
||||
this.setGroupID(id);
|
||||
if (this.active) {
|
||||
this.bootstrapChat();
|
||||
}
|
||||
},
|
||||
},
|
||||
active(val) {
|
||||
if (val && this.imGroupId && !this.chatInited) {
|
||||
this.bootstrapChat();
|
||||
}
|
||||
},
|
||||
liveId() {
|
||||
this.chatInited = false;
|
||||
this.cleanup();
|
||||
if (this.active && this.imGroupId) {
|
||||
this.bootstrapChat();
|
||||
}
|
||||
},
|
||||
},
|
||||
beforeUnmount() {
|
||||
this.cleanup();
|
||||
},
|
||||
methods: {
|
||||
handleSend() {
|
||||
this.createTextMessageByInput();
|
||||
},
|
||||
async bootstrapChat() {
|
||||
if (!this.liveId || this.chatInited || this.initializing) {
|
||||
return;
|
||||
}
|
||||
|
||||
const groupId = this.imGroupId;
|
||||
if (!groupId) {
|
||||
this.initError = "缺少直播间 ID,无法初始化聊天";
|
||||
return;
|
||||
}
|
||||
this.setGroupID(groupId);
|
||||
|
||||
this.initializing = true;
|
||||
try {
|
||||
await this.initTencentIm();
|
||||
if (!this.initError) {
|
||||
this.chatInited = true;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("初始化直播聊天失败:", error);
|
||||
this.initError = "聊天初始化失败,请刷新重试";
|
||||
this.chatInited = false;
|
||||
} finally {
|
||||
this.initializing = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.live-chat-panel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
min-height: 0;
|
||||
max-height: 100%;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.chat-error {
|
||||
flex-shrink: 0;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.chat-list {
|
||||
flex: 1 1 0;
|
||||
height: 0;
|
||||
min-height: 0;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
padding: 4px 0;
|
||||
overscroll-behavior: contain;
|
||||
}
|
||||
|
||||
.chat-bottom-anchor {
|
||||
height: 1px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.chat-loading {
|
||||
text-align: center;
|
||||
color: #909399;
|
||||
font-size: 12px;
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
.chat-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 8px;
|
||||
margin-bottom: 12px;
|
||||
|
||||
&.is-system {
|
||||
justify-content: center;
|
||||
|
||||
.chat-bubble {
|
||||
background: #f4f4f5;
|
||||
border-radius: 12px;
|
||||
padding: 4px 12px;
|
||||
}
|
||||
|
||||
.chat-text {
|
||||
color: #909399;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.chat-bubble {
|
||||
min-width: 0;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.chat-user {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.chat-text {
|
||||
font-size: 14px;
|
||||
color: #303133;
|
||||
line-height: 1.5;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.chat-unread {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
bottom: 56px;
|
||||
transform: translateX(-50%);
|
||||
padding: 4px 12px;
|
||||
background: $theme_color;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
border-radius: 12px;
|
||||
cursor: pointer;
|
||||
z-index: 2;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
.chat-input-bar {
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
padding-top: 12px;
|
||||
border-top: 1px solid #ebeef5;
|
||||
background: #fff;
|
||||
}
|
||||
</style>
|
||||
475
manager/src/views/live/composables/useChat.js
Normal file
475
manager/src/views/live/composables/useChat.js
Normal file
@@ -0,0 +1,475 @@
|
||||
/* eslint-disable no-console */
|
||||
import { nextTick, ref, unref, watch } from "vue";
|
||||
import { postSendMessage } from "@/api/live";
|
||||
import { Message } from "@/utils/message";
|
||||
import TencentCloudChat from "@tencentcloud/chat";
|
||||
import { fetchLiveSetting } from "./useLiveSetting";
|
||||
import { genTestUserSig } from "../utils/GenerateTestUserSig";
|
||||
|
||||
const MAX_MESSAGE_COUNT = 100;
|
||||
const ADMIN_IM_USER_ID = "admin";
|
||||
|
||||
export function useChat(liveId, userInfo) {
|
||||
const chat = ref(null);
|
||||
const groupID = ref("");
|
||||
const messageList = ref([]);
|
||||
const messageContent = ref("");
|
||||
const chatListRef = ref(null);
|
||||
const bottomAnchorRef = ref(null);
|
||||
const isAtBottom = ref(true);
|
||||
const unreadCount = ref(0);
|
||||
const isLoadingHistory = ref(false);
|
||||
const hasMoreHistory = ref(true);
|
||||
const nextReqMessageID = ref("");
|
||||
const imReady = ref(false);
|
||||
const initError = ref("");
|
||||
|
||||
let loginPromise = null;
|
||||
let historyLoaded = false;
|
||||
|
||||
function resetSessionState() {
|
||||
imReady.value = false;
|
||||
loginPromise = null;
|
||||
historyLoaded = false;
|
||||
hasMoreHistory.value = true;
|
||||
nextReqMessageID.value = "";
|
||||
isLoadingHistory.value = false;
|
||||
}
|
||||
|
||||
function detachChatEvents(instance) {
|
||||
if (!instance) return;
|
||||
instance.off(TencentCloudChat.EVENT.MESSAGE_RECEIVED, onMessageReceived);
|
||||
instance.off(TencentCloudChat.EVENT.SDK_READY, onSdkReady);
|
||||
instance.off(TencentCloudChat.EVENT.SDK_NOT_READY, onSdkNotReady);
|
||||
instance.off(TencentCloudChat.EVENT.KICKED_OUT, onKickedOut);
|
||||
}
|
||||
|
||||
function attachChatEvents(instance) {
|
||||
instance.on(TencentCloudChat.EVENT.MESSAGE_RECEIVED, onMessageReceived);
|
||||
instance.on(TencentCloudChat.EVENT.SDK_READY, onSdkReady);
|
||||
instance.on(TencentCloudChat.EVENT.SDK_NOT_READY, onSdkNotReady);
|
||||
instance.on(TencentCloudChat.EVENT.KICKED_OUT, onKickedOut);
|
||||
}
|
||||
|
||||
async function initTencentIm() {
|
||||
initError.value = "";
|
||||
resetSessionState();
|
||||
|
||||
if (!groupID.value) {
|
||||
const fallbackGroupId = unref(liveId);
|
||||
if (fallbackGroupId) {
|
||||
groupID.value = `${fallbackGroupId}`;
|
||||
}
|
||||
}
|
||||
if (!groupID.value) {
|
||||
initError.value = "直播间群组 ID 不存在";
|
||||
console.warn("groupID 不存在,跳过 IM 初始化");
|
||||
return;
|
||||
}
|
||||
|
||||
const setting = await fetchLiveSetting();
|
||||
if (!setting?.imSdkAppid) {
|
||||
initError.value = "请先在系统设置中配置直播 IM SDK APPID";
|
||||
return;
|
||||
}
|
||||
if (!setting?.imSdkSecretKey) {
|
||||
initError.value = "请先在系统设置中配置直播 IM SDK 密钥";
|
||||
return;
|
||||
}
|
||||
|
||||
const sdkAppId = Number(setting.imSdkAppid);
|
||||
const { userSig } = genTestUserSig({
|
||||
SDKAppID: sdkAppId,
|
||||
secretKey: setting.imSdkSecretKey,
|
||||
userID: ADMIN_IM_USER_ID,
|
||||
});
|
||||
|
||||
if (chat.value) {
|
||||
detachChatEvents(chat.value);
|
||||
try {
|
||||
await chat.value.logout?.();
|
||||
} catch (error) {
|
||||
console.warn("IM logout error:", error);
|
||||
}
|
||||
chat.value = null;
|
||||
}
|
||||
|
||||
const chatInstance = TencentCloudChat.create({ SDKAppID: sdkAppId });
|
||||
chat.value = chatInstance;
|
||||
chatInstance.setLogLevel(1);
|
||||
attachChatEvents(chatInstance);
|
||||
|
||||
try {
|
||||
await loginChat(userSig);
|
||||
await waitForSdkReady();
|
||||
await joinGroupAndLoadHistory();
|
||||
} catch (error) {
|
||||
initError.value = error?.message || "IM 初始化失败";
|
||||
console.warn("initTencentIm error:", error);
|
||||
}
|
||||
}
|
||||
|
||||
function waitForSdkReady(timeoutMs = 15000) {
|
||||
if (imReady.value) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
const timer = setTimeout(() => {
|
||||
reject(new Error("IM SDK 就绪超时"));
|
||||
}, timeoutMs);
|
||||
|
||||
const onReady = () => {
|
||||
clearTimeout(timer);
|
||||
chat.value?.off(TencentCloudChat.EVENT.SDK_READY, onReady);
|
||||
resolve();
|
||||
};
|
||||
|
||||
chat.value?.on(TencentCloudChat.EVENT.SDK_READY, onReady);
|
||||
});
|
||||
}
|
||||
|
||||
function loginChat(userSig) {
|
||||
if (!chat.value) {
|
||||
return Promise.reject(new Error("IM 实例不存在"));
|
||||
}
|
||||
if (loginPromise) {
|
||||
return loginPromise;
|
||||
}
|
||||
|
||||
loginPromise = chat.value
|
||||
.login({
|
||||
userID: ADMIN_IM_USER_ID,
|
||||
userSig,
|
||||
})
|
||||
.then((imResponse) => {
|
||||
if (imResponse.data.repeatLogin === true) {
|
||||
imReady.value = true;
|
||||
}
|
||||
return imResponse;
|
||||
})
|
||||
.catch((imError) => {
|
||||
const message = imError?.message || "IM 登录失败";
|
||||
initError.value = message;
|
||||
throw imError;
|
||||
})
|
||||
.finally(() => {
|
||||
loginPromise = null;
|
||||
});
|
||||
|
||||
return loginPromise;
|
||||
}
|
||||
|
||||
function onSdkNotReady() {
|
||||
console.log("[SDK Not Ready]");
|
||||
imReady.value = false;
|
||||
}
|
||||
|
||||
function onSdkReady() {
|
||||
console.log("[SDK Ready]");
|
||||
imReady.value = true;
|
||||
updateUserInfo();
|
||||
}
|
||||
|
||||
function onKickedOut() {
|
||||
console.log("[用户被踢下线]");
|
||||
imReady.value = false;
|
||||
initError.value = "IM 已下线,请刷新页面";
|
||||
}
|
||||
|
||||
async function joinGroupAndLoadHistory() {
|
||||
if (!chat.value || !imReady.value || !groupID.value) {
|
||||
return;
|
||||
}
|
||||
await joinGroup();
|
||||
await getHistoryMessageList("");
|
||||
}
|
||||
|
||||
function updateUserInfo() {
|
||||
if (!chat.value || !userInfo) {
|
||||
return;
|
||||
}
|
||||
|
||||
chat.value.updateMyProfile({
|
||||
nick: userInfo.nickName || userInfo.username || "管理员",
|
||||
avatar: userInfo.face || "",
|
||||
gender: TencentCloudChat.TYPES.GENDER_UNKNOWN,
|
||||
allowType: TencentCloudChat.TYPES.ALLOW_TYPE_ALLOW_ANY,
|
||||
});
|
||||
}
|
||||
|
||||
async function joinGroup() {
|
||||
if (!chat.value || !imReady.value || !groupID.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const imResponse = await chat.value.joinGroup({
|
||||
groupID: groupID.value,
|
||||
type: TencentCloudChat.TYPES.GRP_AVCHATROOM,
|
||||
});
|
||||
console.log("[加群成功]", imResponse);
|
||||
} catch (imError) {
|
||||
console.warn("joinGroup error:", imError);
|
||||
throw imError;
|
||||
}
|
||||
}
|
||||
|
||||
async function getHistoryMessageList(nextReqId) {
|
||||
if (!chat.value || !imReady.value || !groupID.value) {
|
||||
return;
|
||||
}
|
||||
if (isLoadingHistory.value || !hasMoreHistory.value) {
|
||||
return;
|
||||
}
|
||||
if (!nextReqId && historyLoaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
isLoadingHistory.value = true;
|
||||
|
||||
const requestParams = {
|
||||
conversationID: `GROUP${groupID.value}`,
|
||||
direction: 0,
|
||||
};
|
||||
|
||||
if (nextReqId) {
|
||||
requestParams.nextReqMessageID = nextReqId;
|
||||
}
|
||||
|
||||
try {
|
||||
const imResponse = await chat.value.getMessageList(requestParams);
|
||||
const msgList = imResponse.data.messageList;
|
||||
const nextId = imResponse.data.nextReqMessageID;
|
||||
const isCompleted = imResponse.data.isCompleted;
|
||||
|
||||
const formattedMessages = msgList.map((msg) => formatReceivedMessage(msg));
|
||||
formattedMessages.forEach((msg) => {
|
||||
addMessageToList(msg, "append");
|
||||
});
|
||||
|
||||
scrollToBottom(true);
|
||||
|
||||
nextReqMessageID.value = nextId;
|
||||
hasMoreHistory.value = !isCompleted;
|
||||
historyLoaded = true;
|
||||
} catch (imError) {
|
||||
console.warn("getMessageList error:", imError);
|
||||
throw imError;
|
||||
} finally {
|
||||
isLoadingHistory.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function formatReceivedMessage(message) {
|
||||
let messageText = "";
|
||||
let username = "";
|
||||
let isSystem = false;
|
||||
|
||||
if (message.from === "@TIM#SYSTEM") {
|
||||
username = "系统消息";
|
||||
isSystem = true;
|
||||
} else {
|
||||
username = message.nick || message.from || "用户";
|
||||
}
|
||||
|
||||
const avatar = message.avatar || null;
|
||||
const textType = TencentCloudChat.TYPES.MSG_TEXT;
|
||||
const customType = TencentCloudChat.TYPES.MSG_CUSTOM;
|
||||
|
||||
if (message.type === textType || message.type === "TIMTextElem") {
|
||||
messageText = message.payload?.text || "";
|
||||
} else if (message.type === customType || message.type === "TIMCustomElem") {
|
||||
try {
|
||||
const customData = JSON.parse(message.payload.data);
|
||||
messageText = customData.content || "系统消息";
|
||||
username = "系统消息";
|
||||
isSystem = true;
|
||||
} catch {
|
||||
messageText = "系统消息";
|
||||
username = "系统消息";
|
||||
isSystem = true;
|
||||
}
|
||||
} else {
|
||||
messageText = "欢迎加入直播间";
|
||||
}
|
||||
|
||||
return {
|
||||
username,
|
||||
message: messageText,
|
||||
avatar: isSystem ? null : avatar,
|
||||
messageId: message.ID,
|
||||
time: message.time,
|
||||
type: message.type,
|
||||
isSystem,
|
||||
};
|
||||
}
|
||||
|
||||
function onMessageReceived(event) {
|
||||
const msgList = event.data;
|
||||
|
||||
msgList.forEach((message) => {
|
||||
const formattedMessage = formatReceivedMessage(message);
|
||||
if (!formattedMessage.message?.trim() && !formattedMessage.isSystem) {
|
||||
return;
|
||||
}
|
||||
|
||||
addMessageToList(formattedMessage, "append");
|
||||
isAtBottom.value = true;
|
||||
unreadCount.value = 0;
|
||||
scrollToBottom(true);
|
||||
});
|
||||
}
|
||||
|
||||
function addMessageToList(message, mode = "append") {
|
||||
const exists = messageList.value.some((item) => item.messageId === message.messageId);
|
||||
if (exists) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode === "append") {
|
||||
messageList.value.push(message);
|
||||
if (messageList.value.length > MAX_MESSAGE_COUNT) {
|
||||
const removeCount = messageList.value.length - MAX_MESSAGE_COUNT;
|
||||
messageList.value.splice(0, removeCount);
|
||||
}
|
||||
} else {
|
||||
messageList.value.unshift(message);
|
||||
if (messageList.value.length > MAX_MESSAGE_COUNT) {
|
||||
const removeCount = messageList.value.length - MAX_MESSAGE_COUNT;
|
||||
messageList.value.splice(-removeCount, removeCount);
|
||||
}
|
||||
}
|
||||
|
||||
messageList.value.sort((a, b) => a.time - b.time);
|
||||
}
|
||||
|
||||
async function createTextMessageByInput() {
|
||||
const content = messageContent.value.trim();
|
||||
if (!content) {
|
||||
return;
|
||||
}
|
||||
if (!imReady.value) {
|
||||
Message.error("IM 未就绪,请稍后再试");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await postSendMessage({
|
||||
liveRoomId: unref(liveId),
|
||||
message: content,
|
||||
});
|
||||
|
||||
if (res?.success) {
|
||||
messageContent.value = "";
|
||||
isAtBottom.value = true;
|
||||
unreadCount.value = 0;
|
||||
scrollToBottom(true);
|
||||
}
|
||||
} catch {
|
||||
Message.error("发送失败");
|
||||
}
|
||||
}
|
||||
|
||||
function scrollToBottom(force = false) {
|
||||
if (!force && !isAtBottom.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
nextTick(() => {
|
||||
const run = () => {
|
||||
const anchor = bottomAnchorRef.value;
|
||||
if (anchor?.scrollIntoView) {
|
||||
anchor.scrollIntoView({ block: "end" });
|
||||
}
|
||||
const el = chatListRef.value;
|
||||
if (el) {
|
||||
el.scrollTop = el.scrollHeight;
|
||||
}
|
||||
};
|
||||
|
||||
run();
|
||||
requestAnimationFrame(run);
|
||||
setTimeout(run, 50);
|
||||
setTimeout(run, 150);
|
||||
});
|
||||
}
|
||||
|
||||
watch(
|
||||
() => messageList.value.length,
|
||||
() => {
|
||||
if (isAtBottom.value) {
|
||||
scrollToBottom(true);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
function checkIfAtBottom(scrollDetail) {
|
||||
const { scrollTop, scrollHeight, clientHeight } = scrollDetail;
|
||||
const isNearBottom = scrollTop + clientHeight >= scrollHeight - 10;
|
||||
|
||||
if (isNearBottom && !isAtBottom.value) {
|
||||
isAtBottom.value = true;
|
||||
unreadCount.value = 0;
|
||||
} else if (!isNearBottom && isAtBottom.value) {
|
||||
isAtBottom.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function onScroll() {
|
||||
const el = chatListRef.value;
|
||||
if (!el) {
|
||||
return;
|
||||
}
|
||||
|
||||
checkIfAtBottom({
|
||||
scrollTop: el.scrollTop,
|
||||
scrollHeight: el.scrollHeight,
|
||||
clientHeight: el.clientHeight,
|
||||
});
|
||||
}
|
||||
|
||||
function scrollToBottomAndClearUnread() {
|
||||
unreadCount.value = 0;
|
||||
isAtBottom.value = true;
|
||||
scrollToBottom(true);
|
||||
}
|
||||
|
||||
function setGroupID(id) {
|
||||
groupID.value = id;
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
resetSessionState();
|
||||
if (chat.value) {
|
||||
detachChatEvents(chat.value);
|
||||
try {
|
||||
chat.value.logout?.();
|
||||
} catch (error) {
|
||||
console.error("清理腾讯云 IM 失败:", error);
|
||||
}
|
||||
chat.value = null;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
chat,
|
||||
groupID,
|
||||
messageList,
|
||||
messageContent,
|
||||
chatListRef,
|
||||
bottomAnchorRef,
|
||||
isAtBottom,
|
||||
unreadCount,
|
||||
isLoadingHistory,
|
||||
hasMoreHistory,
|
||||
imReady,
|
||||
initError,
|
||||
initTencentIm,
|
||||
createTextMessageByInput,
|
||||
scrollToBottom,
|
||||
scrollToBottomAndClearUnread,
|
||||
onScroll,
|
||||
setGroupID,
|
||||
cleanup,
|
||||
};
|
||||
}
|
||||
44
manager/src/views/live/composables/useLiveSetting.js
Normal file
44
manager/src/views/live/composables/useLiveSetting.js
Normal file
@@ -0,0 +1,44 @@
|
||||
import { getSetting } from "@/api/index";
|
||||
|
||||
/** @type {Record<string, any> | null} */
|
||||
let cachedSetting = null;
|
||||
/** @type {Promise<Record<string, any> | null> | null} */
|
||||
let fetchingPromise = null;
|
||||
|
||||
/** 获取直播配置(带缓存) */
|
||||
export async function fetchLiveSetting(force = false) {
|
||||
if (!force && cachedSetting) {
|
||||
return cachedSetting;
|
||||
}
|
||||
if (!force && fetchingPromise) {
|
||||
return fetchingPromise;
|
||||
}
|
||||
|
||||
fetchingPromise = (async () => {
|
||||
try {
|
||||
const res = await getSetting("LIVE_SETTING");
|
||||
if (res?.success && res?.result) {
|
||||
cachedSetting = res.result;
|
||||
return cachedSetting;
|
||||
}
|
||||
console.warn("获取直播配置失败", res);
|
||||
return null;
|
||||
} catch (error) {
|
||||
console.error("获取直播配置异常:", error);
|
||||
return null;
|
||||
} finally {
|
||||
fetchingPromise = null;
|
||||
}
|
||||
})();
|
||||
|
||||
return fetchingPromise;
|
||||
}
|
||||
|
||||
/** 解析 IM SDK AppID */
|
||||
export function resolveSdkAppId(setting) {
|
||||
if (!setting?.imSdkAppid) {
|
||||
return 0;
|
||||
}
|
||||
const id = Number(setting.imSdkAppid);
|
||||
return Number.isNaN(id) ? 0 : id;
|
||||
}
|
||||
@@ -27,30 +27,28 @@
|
||||
<div class="panel-head">
|
||||
<span class="panel-title">直播预览</span>
|
||||
<div class="ratio-switch">
|
||||
<button
|
||||
type="button"
|
||||
class="ratio-btn"
|
||||
:class="{ active: aspectRatio === '16:9' }"
|
||||
@click="aspectRatio = '16:9'"
|
||||
>
|
||||
16:9
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="ratio-btn"
|
||||
:class="{ active: aspectRatio === '4:3' }"
|
||||
@click="aspectRatio = '4:3'"
|
||||
>
|
||||
4:3
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="player-box" :class="aspectRatio === '16:9' ? 'ratio-169' : 'ratio-43'">
|
||||
<div v-if="videoUrl" id="live-dplayer" class="player-inner" />
|
||||
<div v-else class="player-empty">
|
||||
<el-icon class="is-loading" :size="32"><Loading /></el-icon>
|
||||
<span>暂无拉流地址</span>
|
||||
<div v-if="showPlayerCover" class="player-cover">
|
||||
<img
|
||||
v-if="liveDetail.coverImg"
|
||||
class="cover-img"
|
||||
:src="liveDetail.coverImg"
|
||||
alt="直播封面"
|
||||
/>
|
||||
<div class="cover-mask">
|
||||
<el-tag :type="liveStatusTagType(liveStatus)" size="small">{{ liveStatusText(liveStatus) }}</el-tag>
|
||||
<span v-if="liveStatus === 'NEW' && liveDetail.startTime" class="cover-tip">
|
||||
开播:{{ formatTime(liveDetail.startTime) }}
|
||||
</span>
|
||||
<span v-else-if="liveStatus === 'PAUSED'" class="cover-tip">主播暂时离开,请稍候</span>
|
||||
<span v-else-if="liveStatus === 'ENDED'" class="cover-tip">直播已结束</span>
|
||||
<span v-else-if="liveStatus === 'LIVING' && !videoUrl" class="cover-tip">等待拉流地址...</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="shouldPlayStream" ref="hlsContainer" class="player-inner" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -112,8 +110,12 @@
|
||||
<div class="area-chat panel-box">
|
||||
<el-tabs v-model="chatTab" class="panel-tabs fill-tabs">
|
||||
<el-tab-pane label="互动聊天" name="chat">
|
||||
<div class="tab-body chat-placeholder">
|
||||
<el-empty :image-size="64" description="暂无聊天消息" />
|
||||
<div class="tab-body chat-tab-body">
|
||||
<LiveChatPanel
|
||||
:live-id="liveId"
|
||||
:live-detail="liveDetail"
|
||||
:active="chatTab === 'chat'"
|
||||
/>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="在线用户" name="online">
|
||||
@@ -237,8 +239,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DPlayer from "dplayer";
|
||||
import { DocumentCopy, Loading, Refresh } from "@element-plus/icons-vue";
|
||||
import { getSetting } from "@/api/index";
|
||||
import {
|
||||
endLive,
|
||||
getLiveInfo,
|
||||
@@ -246,16 +247,17 @@ import {
|
||||
liveUserList,
|
||||
startLive,
|
||||
} from "@/api/live";
|
||||
import { getSetting } from "@/api/index";
|
||||
import config from "@/config";
|
||||
import { DocumentCopy, Refresh } from "@element-plus/icons-vue";
|
||||
import CommentReview from "./components/CommentReview.vue";
|
||||
import Coupon from "./components/Coupon.vue";
|
||||
import LiveChatPanel from "./components/LiveChatPanel.vue";
|
||||
import LiveGoods from "./components/LiveGoods.vue";
|
||||
import LivePurchaseRecords from "./components/LivePurchaseRecords.vue";
|
||||
|
||||
export default {
|
||||
name: "live-control-panel",
|
||||
components: { CommentReview, Coupon, LiveGoods, LivePurchaseRecords, DocumentCopy, Loading, Refresh },
|
||||
components: { CommentReview, Coupon, LiveChatPanel, LiveGoods, LivePurchaseRecords, DocumentCopy, Refresh },
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
@@ -275,15 +277,31 @@ export default {
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
},
|
||||
player: null,
|
||||
nowTick: Date.now(),
|
||||
durationTimer: null,
|
||||
pollTimer: null,
|
||||
hlsHttpFallbackUsed: false,
|
||||
lastHlsPullUrl: "",
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.hlsInstance = null;
|
||||
this.hlsVideoElement = null;
|
||||
this._hlsVideoClickHandler = null;
|
||||
},
|
||||
computed: {
|
||||
liveStatus() {
|
||||
return this.liveDetail.liveStatus || this.liveDetail.status || "";
|
||||
},
|
||||
isLiving() {
|
||||
return this.liveStatus === "LIVING";
|
||||
},
|
||||
shouldPlayStream() {
|
||||
return this.isLiving && !!this.videoUrl;
|
||||
},
|
||||
showPlayerCover() {
|
||||
return !this.shouldPlayStream;
|
||||
},
|
||||
cumulativeViewers() {
|
||||
return Number(this.liveDetail.actualViewNumber ?? 0);
|
||||
},
|
||||
@@ -318,10 +336,19 @@ export default {
|
||||
},
|
||||
watch: {
|
||||
videoUrl() {
|
||||
this.initPlayer();
|
||||
this.syncH5Player();
|
||||
},
|
||||
isLiving() {
|
||||
this.syncH5Player();
|
||||
if (this.isLiving) {
|
||||
this.startPolling();
|
||||
} else {
|
||||
this.stopPolling();
|
||||
}
|
||||
},
|
||||
aspectRatio() {
|
||||
this.$nextTick(() => this.initPlayer());
|
||||
this.lastHlsPullUrl = "";
|
||||
this.$nextTick(() => this.syncH5Player());
|
||||
},
|
||||
chatTab(tab) {
|
||||
if (tab === "online") this.loadOnlineUsers();
|
||||
@@ -341,7 +368,8 @@ export default {
|
||||
this.startDurationTimer();
|
||||
},
|
||||
beforeUnmount() {
|
||||
this.destroyPlayer();
|
||||
this.destroyH5HlsPlayer();
|
||||
this.stopPolling();
|
||||
this.stopDurationTimer();
|
||||
},
|
||||
methods: {
|
||||
@@ -385,55 +413,208 @@ export default {
|
||||
return Number(val || 0).toFixed(2);
|
||||
},
|
||||
liveStatusText(status) {
|
||||
const map = { NEW: "未开始", LIVING: "直播中", ENDED: "已结束" };
|
||||
const map = { NEW: "未开始", LIVING: "直播中", PAUSED: "已暂停", ENDED: "已结束" };
|
||||
return map[status] || "未知";
|
||||
},
|
||||
liveStatusTagType(status) {
|
||||
const map = { NEW: "info", LIVING: "success", ENDED: "warning" };
|
||||
const map = { NEW: "info", LIVING: "success", PAUSED: "warning", ENDED: "warning" };
|
||||
return map[status] || "info";
|
||||
},
|
||||
startPolling() {
|
||||
this.stopPolling();
|
||||
if (!this.isLiving) return;
|
||||
this.pollTimer = setInterval(() => {
|
||||
this.loadDetail(false);
|
||||
}, 5000);
|
||||
},
|
||||
stopPolling() {
|
||||
if (this.pollTimer) {
|
||||
clearInterval(this.pollTimer);
|
||||
this.pollTimer = null;
|
||||
}
|
||||
},
|
||||
refreshAll() {
|
||||
this.loadDetail();
|
||||
this.loadOrderStats();
|
||||
this.$refs.purchaseRecords?.refresh();
|
||||
if (this.chatTab === "online") this.loadOnlineUsers();
|
||||
},
|
||||
destroyPlayer() {
|
||||
if (this.player) {
|
||||
this.player.destroy();
|
||||
this.player = null;
|
||||
}
|
||||
buildHlsPlayUrl(url, useHttpFallback = false) {
|
||||
if (!url) return "";
|
||||
const httpUrl =
|
||||
useHttpFallback && url.startsWith("https://")
|
||||
? url.replace("https://", "http://")
|
||||
: url;
|
||||
return httpUrl.replace(".flv", ".m3u8");
|
||||
},
|
||||
initPlayer() {
|
||||
this.destroyPlayer();
|
||||
if (!this.videoUrl) return;
|
||||
syncH5Player(retry = 0) {
|
||||
const shouldPlay = this.shouldPlayStream;
|
||||
if (!shouldPlay) {
|
||||
this.destroyH5HlsPlayer();
|
||||
this.lastHlsPullUrl = "";
|
||||
return;
|
||||
}
|
||||
if (
|
||||
this.videoUrl === this.lastHlsPullUrl &&
|
||||
this.hlsInstance &&
|
||||
this.hlsVideoElement &&
|
||||
!this.hlsVideoElement.paused
|
||||
) {
|
||||
return;
|
||||
}
|
||||
if (this.videoUrl === this.lastHlsPullUrl && this.hlsInstance) {
|
||||
this.ensureH5VideoPlaying(this.hlsVideoElement);
|
||||
return;
|
||||
}
|
||||
this.lastHlsPullUrl = this.videoUrl;
|
||||
this.hlsHttpFallbackUsed = false;
|
||||
this.$nextTick(() => {
|
||||
const container = document.getElementById("live-dplayer");
|
||||
if (!container) return;
|
||||
this.player = new DPlayer({
|
||||
container,
|
||||
live: this.liveStatus === "LIVING",
|
||||
autoplay: true,
|
||||
video: {
|
||||
url: this.videoUrl,
|
||||
type: "auto",
|
||||
},
|
||||
});
|
||||
const container = this.$refs.hlsContainer;
|
||||
if (!container) {
|
||||
if (retry < 8) {
|
||||
setTimeout(() => this.syncH5Player(retry + 1), 80);
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.initH5HlsPlayer();
|
||||
});
|
||||
},
|
||||
loadDetail() {
|
||||
this.loading = true;
|
||||
ensureH5VideoPlaying(video) {
|
||||
if (!video) return Promise.resolve();
|
||||
const tryPlay = (muted) => {
|
||||
video.muted = muted;
|
||||
return video.play().catch(() => Promise.reject());
|
||||
};
|
||||
return tryPlay(false)
|
||||
.catch(() => tryPlay(true))
|
||||
.catch(() => {
|
||||
console.warn("[HLS] 自动播放被阻止,请点击画面播放");
|
||||
});
|
||||
},
|
||||
async initH5HlsPlayer(useHttpFallback = false) {
|
||||
const originalUrl = this.videoUrl;
|
||||
const container = this.$refs.hlsContainer;
|
||||
if (!originalUrl || !container) return;
|
||||
|
||||
const url = this.buildHlsPlayUrl(originalUrl, useHttpFallback);
|
||||
this.destroyH5HlsPlayer();
|
||||
|
||||
const video = document.createElement("video");
|
||||
video.style.cssText = "width:100%;height:100%;object-fit:cover;background:#000;";
|
||||
video.autoplay = true;
|
||||
video.muted = true;
|
||||
video.defaultMuted = true;
|
||||
video.playsInline = true;
|
||||
video.setAttribute("autoplay", "");
|
||||
video.setAttribute("muted", "");
|
||||
video.setAttribute("playsinline", "");
|
||||
video.setAttribute("webkit-playsinline", "");
|
||||
video.controls = false;
|
||||
|
||||
const onVideoClick = () => {
|
||||
if (video.muted) {
|
||||
video.muted = false;
|
||||
}
|
||||
video.play().catch(() => {});
|
||||
};
|
||||
video.addEventListener("click", onVideoClick);
|
||||
container.appendChild(video);
|
||||
this.hlsVideoElement = video;
|
||||
this._hlsVideoClickHandler = onVideoClick;
|
||||
|
||||
const onReadyPlay = () => {
|
||||
this.ensureH5VideoPlaying(video);
|
||||
};
|
||||
|
||||
let Hls = null;
|
||||
try {
|
||||
const hlsModule = await import("hls.js");
|
||||
Hls = hlsModule.default;
|
||||
} catch (error) {
|
||||
console.error("[HLS] 加载播放器失败:", error);
|
||||
this.$Message.error("直播播放器加载失败,请刷新页面重试");
|
||||
return;
|
||||
}
|
||||
|
||||
if (Hls.isSupported()) {
|
||||
const hls = new Hls({
|
||||
enableWorker: true,
|
||||
lowLatencyMode: true,
|
||||
liveSyncDurationCount: 3,
|
||||
liveMaxLatencyDurationCount: 6,
|
||||
maxBufferLength: 10,
|
||||
maxMaxBufferLength: 30,
|
||||
});
|
||||
this.hlsInstance = hls;
|
||||
hls.on(Hls.Events.MEDIA_ATTACHED, onReadyPlay);
|
||||
hls.on(Hls.Events.MANIFEST_PARSED, onReadyPlay);
|
||||
hls.attachMedia(video);
|
||||
hls.loadSource(url);
|
||||
hls.on(Hls.Events.ERROR, (_event, data) => {
|
||||
if (!data.fatal) return;
|
||||
switch (data.type) {
|
||||
case Hls.ErrorTypes.NETWORK_ERROR:
|
||||
if (!this.hlsHttpFallbackUsed && originalUrl.startsWith("https://")) {
|
||||
console.warn("[HLS] HTTPS 加载失败,尝试 HTTP 降级...");
|
||||
this.hlsHttpFallbackUsed = true;
|
||||
this.destroyH5HlsPlayer();
|
||||
this.$nextTick(() => this.initH5HlsPlayer(true));
|
||||
} else {
|
||||
console.error("[HLS] 网络错误,尝试重连...");
|
||||
hls.startLoad();
|
||||
}
|
||||
break;
|
||||
case Hls.ErrorTypes.MEDIA_ERROR:
|
||||
console.error("[HLS] 媒体错误,尝试恢复...");
|
||||
hls.recoverMediaError();
|
||||
break;
|
||||
default:
|
||||
console.error("[HLS] 致命错误:", data);
|
||||
this.destroyH5HlsPlayer();
|
||||
this.$Message.error("直播加载失败");
|
||||
break;
|
||||
}
|
||||
});
|
||||
} else if (video.canPlayType("application/vnd.apple.mpegurl")) {
|
||||
video.src = url;
|
||||
video.addEventListener("loadedmetadata", onReadyPlay);
|
||||
video.addEventListener("canplay", onReadyPlay);
|
||||
} else {
|
||||
this.$Message.error("当前浏览器不支持 HLS 播放");
|
||||
}
|
||||
},
|
||||
destroyH5HlsPlayer() {
|
||||
if (this.hlsInstance) {
|
||||
this.hlsInstance.destroy();
|
||||
this.hlsInstance = null;
|
||||
}
|
||||
if (this.hlsVideoElement) {
|
||||
if (this._hlsVideoClickHandler) {
|
||||
this.hlsVideoElement.removeEventListener("click", this._hlsVideoClickHandler);
|
||||
this._hlsVideoClickHandler = null;
|
||||
}
|
||||
this.hlsVideoElement.remove();
|
||||
this.hlsVideoElement = null;
|
||||
}
|
||||
const container = this.$refs.hlsContainer;
|
||||
if (container) {
|
||||
container.innerHTML = "";
|
||||
}
|
||||
},
|
||||
loadDetail(showLoading = true) {
|
||||
if (showLoading) this.loading = true;
|
||||
getLiveInfo(this.liveId)
|
||||
.then((res) => {
|
||||
this.loading = false;
|
||||
if (showLoading) this.loading = false;
|
||||
if (res.success) {
|
||||
const data = res.result || {};
|
||||
this.liveDetail = data;
|
||||
this.videoUrl = data.pullStreamUrl || data.streamUrl || "";
|
||||
this.syncH5Player();
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.loading = false;
|
||||
if (showLoading) this.loading = false;
|
||||
});
|
||||
},
|
||||
loadOrderStats() {
|
||||
@@ -503,7 +684,8 @@ export default {
|
||||
return endLive(this.liveId).then((res) => {
|
||||
if (res.success) {
|
||||
this.$Message.success("直播已结束");
|
||||
this.destroyPlayer();
|
||||
this.destroyH5HlsPlayer();
|
||||
this.stopPolling();
|
||||
this.refreshAll();
|
||||
}
|
||||
});
|
||||
@@ -611,6 +793,13 @@ export default {
|
||||
.area-chat,
|
||||
.area-stats {
|
||||
min-height: 0;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.area-chat {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.area-manage {
|
||||
@@ -687,17 +876,37 @@ export default {
|
||||
.player-inner {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.player-empty {
|
||||
.player-cover {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
z-index: 2;
|
||||
background: #000;
|
||||
|
||||
.cover-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.cover-mask {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
color: #909399;
|
||||
gap: 10px;
|
||||
background: rgba(0, 0, 0, 0.45);
|
||||
}
|
||||
|
||||
.cover-tip {
|
||||
color: #fff;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
@@ -874,12 +1083,14 @@ export default {
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
.chat-placeholder {
|
||||
.chat-tab-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
padding: 12px 16px 12px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
|
||||
38
manager/src/views/live/utils/GenerateTestUserSig.js
Normal file
38
manager/src/views/live/utils/GenerateTestUserSig.js
Normal file
@@ -0,0 +1,38 @@
|
||||
import LibGenerateTestUserSig from './lib-generate-test-usersig-es.min.js';
|
||||
/**
|
||||
* Signature expiration time, which should not be too short
|
||||
* Time unit: second
|
||||
* Default time: 7 * 24 * 60 * 60 = 604800 = 7days
|
||||
*/
|
||||
const EXPIRETIME = 604800;
|
||||
|
||||
/**
|
||||
* Module: GenerateTestUserSig
|
||||
*
|
||||
* Description: Generates UserSig for testing. UserSig is a security signature designed by Tencent Cloud for its cloud services.
|
||||
* It is calculated based on `SDKAppID`, `UserID`, and `EXPIRETIME` using the HMAC-SHA256 encryption algorithm.
|
||||
*
|
||||
* Attention: For the following reasons, do not use the code below in your commercial application.
|
||||
*
|
||||
* The code may be able to calculate UserSig correctly, but it is only for quick testing of the SDK’s basic features, not for commercial applications.
|
||||
* `SECRETKEY` in client code can be easily decompiled and reversed, especially on web.
|
||||
* Once your key is disclosed, attackers will be able to steal your Tencent Cloud traffic.
|
||||
*
|
||||
* The correct method is to deploy the `UserSig` calculation code and encryption key on your project server so that your application can request from your server a `UserSig` that is calculated whenever one is needed.
|
||||
* Given that it is more difficult to hack a server than a client application, server-end calculation can better protect your key.
|
||||
*
|
||||
* Reference: https://cloud.tencent.com/document/product/647/17275#Server
|
||||
*/
|
||||
|
||||
function genTestUserSig(options) {
|
||||
const { SDKAppID, secretKey, userID } = options;
|
||||
const sdkAppId = Number(SDKAppID);
|
||||
const generator = new LibGenerateTestUserSig(sdkAppId, secretKey, EXPIRETIME);
|
||||
const userSig = generator.genTestUserSig(userID);
|
||||
return {
|
||||
SDKAppID: sdkAppId,
|
||||
userSig,
|
||||
};
|
||||
}
|
||||
|
||||
export { genTestUserSig, EXPIRETIME };
|
||||
2
manager/src/views/live/utils/lib-generate-test-usersig-es.min.js
vendored
Normal file
2
manager/src/views/live/utils/lib-generate-test-usersig-es.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -7,6 +7,7 @@
|
||||
<script>
|
||||
import Cookies from "js-cookie";
|
||||
import util from "@/libs/util";
|
||||
import { getCategoryTree } from "@/api/goods.js";
|
||||
|
||||
export default {
|
||||
name: "App",
|
||||
@@ -18,6 +19,13 @@ export default {
|
||||
util.initRouter(this);
|
||||
this.$store.commit("setOpenedList");
|
||||
this.$store.commit("initCachepage");
|
||||
if (!localStorage.getItem("category")) {
|
||||
getCategoryTree().then((res) => {
|
||||
if (res.success && Array.isArray(res.result)) {
|
||||
localStorage.setItem("category", JSON.stringify(res.result));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -2,8 +2,7 @@ import { getCurrentPermissionList } from "@/api/index";
|
||||
import lazyLoading from "./lazyLoading.js";
|
||||
import { router } from "@/router/index";
|
||||
import Cookies from "js-cookie";
|
||||
|
||||
const config = require("@/config/index");
|
||||
import config from "@/config/index";
|
||||
|
||||
let util = {};
|
||||
|
||||
|
||||
@@ -22,8 +22,11 @@ import { setStore, getStore, removeStore } from "@/libs/storage";
|
||||
import util from "@/libs/util";
|
||||
import { md5 } from "@/utils/md5.js";
|
||||
import * as filters from "@/utils/filters";
|
||||
import config from "@/config/index";
|
||||
import imgError from "./assets/img-error.png";
|
||||
import loadingGif from "./assets/loading2.gif";
|
||||
|
||||
const { aMapSecurityJsCode, mainColor } = require("@/config");
|
||||
const { aMapSecurityJsCode, mainColor } = config;
|
||||
|
||||
if (aMapSecurityJsCode) {
|
||||
window._AMapSecurityConfig = {
|
||||
@@ -43,8 +46,8 @@ setupLegacyMessage(app);
|
||||
installVueQr(app);
|
||||
|
||||
app.use(VueLazyload, {
|
||||
error: require("./assets/img-error.png"),
|
||||
loading: require("./assets/loading2.gif"),
|
||||
error: imgError,
|
||||
loading: loadingGif,
|
||||
});
|
||||
|
||||
app.use(router);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import Main from "@/views/Main.vue";
|
||||
|
||||
const config = require('@/config/index')
|
||||
import config from "@/config/index";
|
||||
// 不作为Main组件的子页面展示的页面单独写,如下
|
||||
export const loginRouter = {
|
||||
path: "/login",
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
const { setting } = require("@/config");
|
||||
import config from "@/config/index";
|
||||
|
||||
const { setting } = config;
|
||||
|
||||
const localSetting = window.localStorage.getItem('setting')
|
||||
const settingData = {
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
border-radius: 0.4em;
|
||||
flex-wrap: wrap;
|
||||
|
||||
> .ivu-form-item,
|
||||
> .el-form-item {
|
||||
margin: 8px 10px !important;
|
||||
}
|
||||
@@ -44,8 +43,3 @@
|
||||
.search > .el-card + .el-card {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
// 兼容遗留 iView
|
||||
.ivu-card + .ivu-card {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
@@ -120,6 +120,7 @@ import { Iphone, Message, Lock } from "@element-plus/icons-vue";
|
||||
import * as RegExp from "@/utils/regular.js";
|
||||
import * as apiLogin from "@/api/index.js";
|
||||
import { sendSms } from "@/api/common.js";
|
||||
import config from "@/config/index";
|
||||
import verify from "@/views/my-components/verify";
|
||||
|
||||
export default {
|
||||
@@ -127,7 +128,7 @@ export default {
|
||||
components: { verify, Iphone, Message, Lock },
|
||||
data() {
|
||||
return {
|
||||
config: require("@/config"),
|
||||
config,
|
||||
loading: false,
|
||||
loading1: false,
|
||||
formFirst: {
|
||||
@@ -207,7 +208,7 @@ export default {
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.loading = false;
|
||||
this.loading1 = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
<div></div>
|
||||
<div class="user-dropdown-menu-con">
|
||||
<el-row
|
||||
type="flex"
|
||||
justify="end"
|
||||
align="middle"
|
||||
class="user-dropdown-innercon"
|
||||
@@ -90,8 +89,7 @@ import util from "@/libs/util.js";
|
||||
import { logout } from "@/api/index";
|
||||
import { getIMDetail } from "@/api/common";
|
||||
import { userMsg } from "@/api/index";
|
||||
|
||||
const config = require("@/config/index.js");
|
||||
import config from "@/config/index.js";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
.change-pass {
|
||||
&-btn-box {
|
||||
margin-bottom: 10px;
|
||||
|
||||
button {
|
||||
padding-left: 0;
|
||||
|
||||
span {
|
||||
color: #2D8CF0;
|
||||
transition: all .2s;
|
||||
}
|
||||
|
||||
span:hover {
|
||||
color: #0C25F1;
|
||||
transition: all .2s;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -93,19 +93,21 @@ export default {
|
||||
this.$refs.editPasswordForm.validate((valid) => {
|
||||
if (!valid) return;
|
||||
this.savePassLoading = true;
|
||||
changePass(params).then((res) => {
|
||||
this.savePassLoading = false;
|
||||
if (res.success) {
|
||||
ElMessageBox.alert("修改密码成功,需重新登录", "修改密码成功", {
|
||||
confirmButtonText: "确定",
|
||||
callback: () => {
|
||||
changePass(params)
|
||||
.then((res) => {
|
||||
if (res?.success) {
|
||||
ElMessageBox.alert("修改密码成功,需重新登录", "修改密码成功", {
|
||||
confirmButtonText: "确定",
|
||||
}).then(() => {
|
||||
this.$store.commit("logout", this);
|
||||
this.$store.commit("clearOpenedSubmenu");
|
||||
this.$router.push({ name: "login" });
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
this.savePassLoading = false;
|
||||
});
|
||||
});
|
||||
},
|
||||
cancelEditPass() {
|
||||
@@ -120,25 +122,3 @@ export default {
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.change-pass {
|
||||
&-btn-box {
|
||||
margin-bottom: 10px;
|
||||
|
||||
button {
|
||||
padding-left: 0;
|
||||
|
||||
span {
|
||||
color: #2d8cf0;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
span:hover {
|
||||
color: #0c25f1;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -94,7 +94,7 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
>.ivu-form {
|
||||
>.el-form {
|
||||
flex-wrap: wrap !important;
|
||||
}
|
||||
|
||||
@@ -175,11 +175,11 @@ div.base-info-item {
|
||||
justify-content: flex-start;
|
||||
width: 100%;
|
||||
|
||||
>.ivu-card-body {
|
||||
>.el-card__body {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.ivu-card-body {
|
||||
.el-card__body {
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
@@ -344,7 +344,7 @@ div.base-info-item {
|
||||
text-align: center;
|
||||
z-index: 999;
|
||||
|
||||
>.ivu-btn {
|
||||
>.el-button {
|
||||
margin: 0 10px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,6 +78,8 @@
|
||||
</template>
|
||||
<script>
|
||||
import * as API_GOODS from "@/api/goods";
|
||||
import goodsType1Img from "@/assets/goodsType1.png";
|
||||
import goodsType2Img from "@/assets/goodsType2.png";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
@@ -85,14 +87,14 @@ export default {
|
||||
goodsTypeWay: [
|
||||
{
|
||||
title: "实物商品",
|
||||
img: require("@/assets/goodsType1.png"),
|
||||
img: goodsType1Img,
|
||||
desc: "零售批发,物流配送",
|
||||
type: "PHYSICAL_GOODS",
|
||||
check: false,
|
||||
},
|
||||
{
|
||||
title: "虚拟商品",
|
||||
img: require("@/assets/goodsType2.png"),
|
||||
img: goodsType2Img,
|
||||
desc: "虚拟核验,无需物流",
|
||||
type: "VIRTUAL_GOODS",
|
||||
check: false,
|
||||
|
||||
@@ -10,10 +10,10 @@
|
||||
<div class="form-item-view">
|
||||
<el-form-item label="商品分类">
|
||||
<span class="goods-category-name">{{
|
||||
this.baseInfoForm.categoryName[0]
|
||||
baseInfoForm.categoryName[0]
|
||||
}}</span>
|
||||
<span> > {{ this.baseInfoForm.categoryName[1] }}</span>
|
||||
<span> > {{ this.baseInfoForm.categoryName[2] }}</span>
|
||||
<span> > {{ baseInfoForm.categoryName[1] }}</span>
|
||||
<span> > {{ baseInfoForm.categoryName[2] }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="商品名称" prop="goodsName">
|
||||
<el-input v-model="baseInfoForm.goodsName" clearable placeholder="商品名称" style="width: 260px" type="text" />
|
||||
@@ -190,7 +190,7 @@
|
||||
<el-collapse-item title="自定义规格项" name="1">
|
||||
<div>
|
||||
<div v-for="(item, $index) in skuInfo" :key="$index" class="sku-item-content">
|
||||
<el-card class="ivu-card-body">
|
||||
<el-card>
|
||||
<template #header>
|
||||
<el-button link type="danger" @click="handleCloseSkuItem($index, item)">删除规格项</el-button>
|
||||
</template>
|
||||
@@ -478,7 +478,7 @@
|
||||
<div class="footer-btns">
|
||||
<el-button type="primary" @click="pre">上一步</el-button>
|
||||
<el-button :loading="submitLoading" type="primary" @click="save">
|
||||
{{ this.$route.query.id ? "保存" : "保存商品" }}
|
||||
{{ $route.query.id ? "保存" : "保存商品" }}
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1310,7 +1310,12 @@ export default {
|
||||
this.params_panel = [];
|
||||
API_GOODS.getCategoryParamsListDataSeller(this.categoryId).then(
|
||||
(response) => {
|
||||
if (!response || response.length <= 0) {
|
||||
const list = Array.isArray(response)
|
||||
? response
|
||||
: Array.isArray(response?.result)
|
||||
? response.result
|
||||
: [];
|
||||
if (!list.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1355,15 +1360,15 @@ export default {
|
||||
return undefined;
|
||||
};
|
||||
|
||||
const isGrouped = response[0] && Array.isArray(response[0].params);
|
||||
const isGrouped = list[0] && Array.isArray(list[0].params);
|
||||
const flatParams = isGrouped
|
||||
? response.reduce((acc, g) => {
|
||||
? list.reduce((acc, g) => {
|
||||
if (g && Array.isArray(g.params)) {
|
||||
acc.push(...g.params);
|
||||
}
|
||||
return acc;
|
||||
}, [])
|
||||
: response;
|
||||
: list;
|
||||
|
||||
this.goodsParams = flatParams
|
||||
.map((p) => {
|
||||
@@ -1547,7 +1552,7 @@ export default {
|
||||
}
|
||||
} else if (val._error) {
|
||||
// 清除错误
|
||||
this.$delete(val, '_error');
|
||||
delete val._error;
|
||||
if (this.skuInfo[groupIndex]) {
|
||||
this.skuInfo[groupIndex].spec_values = this.skuInfo[groupIndex].spec_values.filter((i) => i.value !== "");
|
||||
}
|
||||
@@ -2316,7 +2321,7 @@ export default {
|
||||
</style>
|
||||
|
||||
<style scoped>
|
||||
.ivu-select .ivu-select-dropdown {
|
||||
.el-select .el-select-dropdown {
|
||||
overflow: hidden !important;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<h4>Hi,<span style="margin-left: 5px">{{ userData.nickName }}</span></h4>
|
||||
<img
|
||||
class="shop-logo"
|
||||
:src="userData.storeLogo || require('@/assets/logo1.png')"
|
||||
:src="userData.storeLogo || defaultLogo"
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
@@ -199,6 +199,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import defaultLogo from "@/assets/logo1.png";
|
||||
import { Picture, CreditCard, List, User } from "@element-plus/icons-vue";
|
||||
import { getSellerHomeData, getHomeNotice } from "@/api/index";
|
||||
import { getIMDetail } from "@/api/common";
|
||||
@@ -216,6 +217,7 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
defaultLogo,
|
||||
noticeFlage: false,
|
||||
homeData: {},
|
||||
userData: "",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const plugins = [
|
||||
'advlist', 'anchor', 'autolink', 'autosave', 'code', 'codesample', 'directionality', 'emoticons', 'fullscreen', 'image', 'importcss', 'insertdatetime', 'link', 'lists', 'media', 'nonbreaking', 'pagebreak', 'preview', 'save', 'searchreplace', 'table', 'template', 'visualblocks', 'visualchars', 'wordcount'
|
||||
'advlist', 'anchor', 'autolink', 'autosave', 'charmap', 'code', 'codesample', 'directionality', 'emoticons', 'fullscreen', 'image', 'importcss', 'insertdatetime', 'link', 'lists', 'media', 'nonbreaking', 'pagebreak', 'preview', 'save', 'searchreplace', 'table', 'template', 'visualblocks', 'visualchars', 'wordcount'
|
||||
]
|
||||
export default plugins
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
</template>
|
||||
<script>
|
||||
import { getCategoryTree } from "@/api/goods.js";
|
||||
|
||||
export default {
|
||||
data() {
|
||||
@@ -40,10 +41,32 @@ export default {
|
||||
this.init();
|
||||
},
|
||||
methods: {
|
||||
loadCategoryFromCache() {
|
||||
try {
|
||||
const raw = localStorage.getItem("category");
|
||||
if (!raw) {
|
||||
return null;
|
||||
}
|
||||
const parsed = JSON.parse(raw);
|
||||
return Array.isArray(parsed) ? parsed : null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
applyCategoryList(category) {
|
||||
if (!Array.isArray(category)) {
|
||||
this.categoryList = [];
|
||||
return;
|
||||
}
|
||||
category.forEach((item) => {
|
||||
item.___type = "category";
|
||||
});
|
||||
this.categoryList = category;
|
||||
},
|
||||
// 点击一级
|
||||
handleClickChild(item, index) {
|
||||
this.parentIndex = index;
|
||||
this.secondLevel = item.children;
|
||||
this.secondLevel = item.children || [];
|
||||
item.___type = "category";
|
||||
item.allId = item.id;
|
||||
|
||||
@@ -51,8 +74,6 @@ export default {
|
||||
this.thirdIndex = '';
|
||||
this.thirdLevel = []
|
||||
this.$emit("selected", [item]);
|
||||
// 点击第一级的时候默认显示第二级第一个
|
||||
// this.handleClickSecondChild(item.children, 0);
|
||||
},
|
||||
// 点击二级
|
||||
handleClickSecondChild(second, index) {
|
||||
@@ -60,10 +81,9 @@ export default {
|
||||
second.allId = `${second.parentId},${second.id}`
|
||||
|
||||
this.secondIndex = index;
|
||||
this.thirdLevel = second.children;
|
||||
this.thirdLevel = second.children || [];
|
||||
this.thirdIndex = '';
|
||||
this.$emit("selected", [second]);
|
||||
// this.handleClickthirdChild(second.children[0], 0);
|
||||
},
|
||||
// 点击三级
|
||||
handleClickthirdChild(item, index) {
|
||||
@@ -73,21 +93,17 @@ export default {
|
||||
this.thirdIndex = index;
|
||||
},
|
||||
init() {
|
||||
const loadCategory = () => {
|
||||
const category = JSON.parse(localStorage.getItem("category"));
|
||||
if (!Array.isArray(category)) {
|
||||
return;
|
||||
}
|
||||
category.forEach((item) => {
|
||||
item.___type = "category";
|
||||
});
|
||||
this.categoryList = category;
|
||||
};
|
||||
|
||||
loadCategory();
|
||||
if (!this.categoryList.length) {
|
||||
setTimeout(loadCategory, 3000);
|
||||
const cached = this.loadCategoryFromCache();
|
||||
if (cached) {
|
||||
this.applyCategoryList(cached);
|
||||
return;
|
||||
}
|
||||
getCategoryTree().then((res) => {
|
||||
if (res.success && Array.isArray(res.result)) {
|
||||
localStorage.setItem("category", JSON.stringify(res.result));
|
||||
this.applyCategoryList(res.result);
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -3,10 +3,12 @@ import category from "./category.vue";
|
||||
import pages from "./pages.vue";
|
||||
import goods from "../goods-dialog.vue";
|
||||
import other from "./other.vue";
|
||||
import shops from "./shops.vue";
|
||||
|
||||
export default {
|
||||
category: markRaw(category),
|
||||
goods: markRaw(goods),
|
||||
other: markRaw(other),
|
||||
pages: markRaw(pages),
|
||||
shops: markRaw(shops),
|
||||
};
|
||||
|
||||
@@ -44,12 +44,12 @@
|
||||
</div>
|
||||
</div>
|
||||
<el-pagination
|
||||
v-model:current-page="params.pageNumber"
|
||||
class="pageration"
|
||||
size="small"
|
||||
layout="total, prev, pager, next, jumper"
|
||||
:total="total"
|
||||
:page-size="params.pageSize"
|
||||
:current-page="params.pageNumber"
|
||||
@current-change="changePageSize"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import defaultLogo from "@/assets/logo.png";
|
||||
import { getBaseSite } from "@/api/common.js";
|
||||
|
||||
export default {
|
||||
|
||||
@@ -157,17 +157,6 @@
|
||||
height: 100%;
|
||||
|
||||
|
||||
.options {
|
||||
.ivu-select-dropdown {
|
||||
transform-origin: center top 0px;
|
||||
position: absolute;
|
||||
top: 45px !important;
|
||||
left: -2px;
|
||||
will-change: top, left;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.message-con {
|
||||
display: inline-block;
|
||||
|
||||
|
||||
@@ -20,8 +20,7 @@
|
||||
<script>
|
||||
import AMapLoader from "@amap/amap-jsapi-loader";
|
||||
import { getRegion } from "@/api/common.js";
|
||||
|
||||
const config = require("@/config/index");
|
||||
import config from "@/config/index";
|
||||
export default {
|
||||
name: "map",
|
||||
data() {
|
||||
|
||||
@@ -214,11 +214,8 @@ export default {
|
||||
default: () => []
|
||||
},
|
||||
size: {
|
||||
default() {
|
||||
return !this.$IVIEW || this.$IVIEW.size === ""
|
||||
? "default"
|
||||
: this.$IVIEW.size;
|
||||
}
|
||||
type: String,
|
||||
default: "default",
|
||||
},
|
||||
loading: {
|
||||
type: Boolean,
|
||||
|
||||
@@ -350,12 +350,8 @@
|
||||
|
||||
<script>
|
||||
import * as API_Order from "@/api/order";
|
||||
import vueQr from "vue-qr";
|
||||
export default {
|
||||
components: {
|
||||
"vue-qr": vueQr,
|
||||
},
|
||||
name: "orderDetail",
|
||||
name: "returnGoodsOrderDetail",
|
||||
data() {
|
||||
return {
|
||||
sn: "", // 订单号
|
||||
@@ -624,9 +620,6 @@ export default {
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.ivu-col {
|
||||
width: 100% !important;
|
||||
}
|
||||
.main-content {
|
||||
min-height: 600px;
|
||||
padding: 10px;
|
||||
|
||||
@@ -49,6 +49,9 @@
|
||||
import { UploadFilled } from "@element-plus/icons-vue";
|
||||
import { downLoadDeliverExcel, uploadDeliverExcel } from "@/api/order.js";
|
||||
import { baseUrl } from "@/libs/axios.js";
|
||||
import downloadImg from "@/assets/download.png";
|
||||
import uploadImg from "@/assets/upload.png";
|
||||
import successImg from "@/assets/success.png";
|
||||
|
||||
export default {
|
||||
components: { UploadFilled },
|
||||
@@ -59,17 +62,17 @@ export default {
|
||||
accessToken: {},
|
||||
stepList: [
|
||||
{
|
||||
img: require("@/assets/download.png"),
|
||||
img: downloadImg,
|
||||
title: "1.下载批量发货导入模板",
|
||||
checked: true,
|
||||
},
|
||||
{
|
||||
img: require("@/assets/upload.png"),
|
||||
img: uploadImg,
|
||||
title: "2.上传数据",
|
||||
checked: false,
|
||||
},
|
||||
{
|
||||
img: require("@/assets/success.png"),
|
||||
img: successImg,
|
||||
title: "3.完成",
|
||||
checked: false,
|
||||
},
|
||||
|
||||
@@ -578,7 +578,7 @@ export default {
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scpoed>
|
||||
<style lang="scss" scoped>
|
||||
h4 {
|
||||
margin-bottom: 10px;
|
||||
padding: 0 10px;
|
||||
|
||||
@@ -116,7 +116,7 @@
|
||||
<img v-if="imageVisible" :src="imageSrc" style="width: 100%" alt="" />
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog v-model="liveGoodsVisible" width="800px" :show-footer="false">
|
||||
<el-dialog v-model="liveGoodsVisible" width="800px">
|
||||
<liveGoods reviewed @selectedGoods="callBackData" />
|
||||
</el-dialog>
|
||||
</div>
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
<!-- 选择商品。链接 -->
|
||||
<liliDialog ref="liliDialog" @selectedLink="selectedLink"></liliDialog>
|
||||
<!-- 选择图片 -->
|
||||
<el-dialog width="1200px" v-model="picModelFlag" :show-footer="false">
|
||||
<el-dialog width="1200px" v-model="picModelFlag">
|
||||
<ossManage @callback="callbackSelected" :isComponent="true" :initialize="picModelFlag" ref="ossManage"/>
|
||||
</el-dialog>
|
||||
</li>
|
||||
|
||||
@@ -1,7 +1 @@
|
||||
import hotzone from './index.vue'
|
||||
|
||||
hotzone.install = (Vue) => {
|
||||
Vue.component(hotzone.name, hotzone)
|
||||
}
|
||||
|
||||
export default hotzone
|
||||
export { default } from "./index.vue";
|
||||
|
||||
@@ -1,3 +1,20 @@
|
||||
import nav1 from '@/assets/nav/1.jpg';
|
||||
import nav2 from '@/assets/nav/2.jpg';
|
||||
import nav3 from '@/assets/nav/3.jpg';
|
||||
import nav4 from '@/assets/nav/4.jpg';
|
||||
import nav5 from '@/assets/nav/5.jpg';
|
||||
import navDecorate from '@/assets/nav/decorate.png';
|
||||
import navDecorate1 from '@/assets/nav/decorate1.png';
|
||||
import navDecorate2 from '@/assets/nav/decorate2.jpeg';
|
||||
import navDecorate3 from '@/assets/nav/decorate3.jpeg';
|
||||
import navDecorate4 from '@/assets/nav/decorate4.jpeg';
|
||||
import navDecorate5 from '@/assets/nav/decorate5.jpeg';
|
||||
import navDecorate6 from '@/assets/nav/decorate6.jpeg';
|
||||
import navDecorate7 from '@/assets/nav/decorate7.jpeg';
|
||||
import navDecorate8 from '@/assets/nav/decorate8.png';
|
||||
import navDecorate9 from '@/assets/nav/decorate9.png';
|
||||
import navDecorate10 from '@/assets/nav/decorate10.jpeg';
|
||||
import navDecorate11 from '@/assets/nav/decorate11.jpeg';
|
||||
|
||||
export const modelData = [
|
||||
{
|
||||
@@ -7,32 +24,32 @@ export const modelData = [
|
||||
showName: '',
|
||||
options: {
|
||||
list: [{
|
||||
img: require('@/assets/nav/decorate1.png'),
|
||||
img: navDecorate1,
|
||||
url: '',
|
||||
size: '1200*自定义'
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/1.jpg'),
|
||||
img: nav1,
|
||||
url: '',
|
||||
size: '230*190'
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/1.jpg'),
|
||||
img: nav1,
|
||||
url: '',
|
||||
size: '230*190'
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/1.jpg'),
|
||||
img: nav1,
|
||||
url: '',
|
||||
size: '230*190'
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/1.jpg'),
|
||||
img: nav1,
|
||||
url: '',
|
||||
size: '230*190'
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/1.jpg'),
|
||||
img: nav1,
|
||||
url: '',
|
||||
size: '230*190'
|
||||
}
|
||||
@@ -48,70 +65,70 @@ export const modelData = [
|
||||
list: [{
|
||||
time: 6,
|
||||
goodsList: [{
|
||||
img: require('@/assets/nav/1.jpg'),
|
||||
img: nav1,
|
||||
price: 20,
|
||||
originalPrice: 30,
|
||||
name: '阿迪达斯三叶草asdasdafads123213a',
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/2.jpg'),
|
||||
img: nav2,
|
||||
price: 20,
|
||||
originalPrice: 30,
|
||||
name: '阿迪达斯三叶草asdasdafadsa',
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/3.jpg'),
|
||||
img: nav3,
|
||||
price: 20,
|
||||
originalPrice: 30,
|
||||
name: '阿迪达斯三叶草asdasdafadsa',
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/4.jpg'),
|
||||
img: nav4,
|
||||
price: 20,
|
||||
originalPrice: 30,
|
||||
name: '阿迪达斯三叶草asdasdafadsa',
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/5.jpg'),
|
||||
img: nav5,
|
||||
price: 20,
|
||||
originalPrice: 30,
|
||||
name: '阿迪达斯三叶草asdasdafadsa',
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/1.jpg'),
|
||||
img: nav1,
|
||||
price: 20,
|
||||
originalPrice: 30,
|
||||
name: '阿迪达斯三叶草asdasdafadsa',
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/2.jpg'),
|
||||
img: nav2,
|
||||
price: 20,
|
||||
originalPrice: 30,
|
||||
name: '阿迪达斯三叶草asdasdafadsa',
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/3.jpg'),
|
||||
img: nav3,
|
||||
price: 20,
|
||||
originalPrice: 30,
|
||||
name: '阿迪达斯三叶草asdasdafadsa',
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/4.jpg'),
|
||||
img: nav4,
|
||||
price: 20,
|
||||
originalPrice: 30,
|
||||
name: '阿迪达斯三叶草asdasdafadsa',
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/5.jpg'),
|
||||
img: nav5,
|
||||
price: 20,
|
||||
originalPrice: 30,
|
||||
name: '阿迪达斯三叶草asdasdafadsa',
|
||||
@@ -122,23 +139,23 @@ export const modelData = [
|
||||
{
|
||||
time: 8,
|
||||
goodsList: [{
|
||||
img: require('@/assets/nav/1.jpg'),
|
||||
img: nav1,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/2.jpg'),
|
||||
img: nav2,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/3.jpg'),
|
||||
img: nav3,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/4.jpg'),
|
||||
img: nav4,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/5.jpg'),
|
||||
img: nav5,
|
||||
url: ''
|
||||
},
|
||||
]
|
||||
@@ -146,23 +163,23 @@ export const modelData = [
|
||||
{
|
||||
time: 10,
|
||||
goodsList: [{
|
||||
img: require('@/assets/nav/1.jpg'),
|
||||
img: nav1,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/2.jpg'),
|
||||
img: nav2,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/3.jpg'),
|
||||
img: nav3,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/4.jpg'),
|
||||
img: nav4,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/5.jpg'),
|
||||
img: nav5,
|
||||
url: ''
|
||||
},
|
||||
]
|
||||
@@ -170,23 +187,23 @@ export const modelData = [
|
||||
{
|
||||
time: 12,
|
||||
goodsList: [{
|
||||
img: require('@/assets/nav/1.jpg'),
|
||||
img: nav1,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/2.jpg'),
|
||||
img: nav2,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/3.jpg'),
|
||||
img: nav3,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/4.jpg'),
|
||||
img: nav4,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/5.jpg'),
|
||||
img: nav5,
|
||||
url: ''
|
||||
},
|
||||
]
|
||||
@@ -213,65 +230,65 @@ export const modelData = [
|
||||
icon: 'md-image',
|
||||
options: {
|
||||
bgImg: {
|
||||
img: require('@/assets/nav/decorate.png'),
|
||||
img: navDecorate,
|
||||
url: '',
|
||||
size: "1300*585"
|
||||
},
|
||||
classification: [{
|
||||
img: require('@/assets/nav/decorate2.jpeg'),
|
||||
img: navDecorate2,
|
||||
url: '',
|
||||
size: '190*210'
|
||||
}, {
|
||||
img: require('@/assets/nav/decorate2.jpeg'),
|
||||
img: navDecorate2,
|
||||
url: '',
|
||||
size: '190*210'
|
||||
}, {
|
||||
img: require('@/assets/nav/decorate2.jpeg'),
|
||||
img: navDecorate2,
|
||||
url: '',
|
||||
size: '190*210'
|
||||
}, {
|
||||
img: require('@/assets/nav/decorate2.jpeg'),
|
||||
img: navDecorate2,
|
||||
url: '',
|
||||
size: '190*210'
|
||||
}, {
|
||||
img: require('@/assets/nav/decorate2.jpeg'),
|
||||
img: navDecorate2,
|
||||
url: '',
|
||||
size: '190*210'
|
||||
}, {
|
||||
img: require('@/assets/nav/decorate2.jpeg'),
|
||||
img: navDecorate2,
|
||||
url: '',
|
||||
size: '190*210'
|
||||
}, {
|
||||
img: require('@/assets/nav/decorate2.jpeg'),
|
||||
img: navDecorate2,
|
||||
url: '',
|
||||
size: '190*210'
|
||||
}, {
|
||||
img: require('@/assets/nav/decorate2.jpeg'),
|
||||
img: navDecorate2,
|
||||
url: '',
|
||||
size: '190*210'
|
||||
}, {
|
||||
img: require('@/assets/nav/decorate2.jpeg'),
|
||||
img: navDecorate2,
|
||||
url: '',
|
||||
size: '190*210'
|
||||
}, {
|
||||
img: require('@/assets/nav/decorate2.jpeg'),
|
||||
img: navDecorate2,
|
||||
url: '',
|
||||
size: '190*210'
|
||||
}, ],
|
||||
brandList: [{
|
||||
img: require('@/assets/nav/decorate11.jpeg'),
|
||||
img: navDecorate11,
|
||||
url: '',
|
||||
size: '240*105'
|
||||
}, {
|
||||
img: require('@/assets/nav/decorate11.jpeg'),
|
||||
img: navDecorate11,
|
||||
url: '',
|
||||
size: '240*105'
|
||||
}, {
|
||||
img: require('@/assets/nav/decorate11.jpeg'),
|
||||
img: navDecorate11,
|
||||
url: '',
|
||||
size: '240*105'
|
||||
}, {
|
||||
img: require('@/assets/nav/decorate11.jpeg'),
|
||||
img: navDecorate11,
|
||||
url: '',
|
||||
size: '240*105'
|
||||
}, ]
|
||||
@@ -288,49 +305,49 @@ export const modelData = [
|
||||
bgColor: '#449dae',
|
||||
url: '',
|
||||
list: [{
|
||||
img: require('@/assets/nav/decorate3.jpeg'),
|
||||
img: navDecorate3,
|
||||
name: '阿迪达斯三叶草',
|
||||
describe: '也许是每一款经典系列都应该有一个独特的故事吧',
|
||||
url: '',
|
||||
size: '160*160'
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate4.jpeg'),
|
||||
img: navDecorate4,
|
||||
name: '360行车记录',
|
||||
describe: '夜行 监控 电子狗 蓝牙',
|
||||
url: '',
|
||||
size: '80*80'
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate4.jpeg'),
|
||||
img: navDecorate4,
|
||||
name: '360行车记录',
|
||||
describe: '夜行 监控 电子狗 蓝牙',
|
||||
url: '',
|
||||
size: '80*80'
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate4.jpeg'),
|
||||
img: navDecorate4,
|
||||
name: '360行车记录',
|
||||
describe: '夜行 监控 电子狗 蓝牙',
|
||||
url: '',
|
||||
size: '80*80'
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate4.jpeg'),
|
||||
img: navDecorate4,
|
||||
name: '360行车记录',
|
||||
describe: '夜行 监控 电子狗 蓝牙',
|
||||
url: '',
|
||||
size: '80*80'
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate4.jpeg'),
|
||||
img: navDecorate4,
|
||||
name: '360行车记录',
|
||||
describe: '夜行 监控 电子狗 蓝牙',
|
||||
url: '',
|
||||
size: '80*80'
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate4.jpeg'),
|
||||
img: navDecorate4,
|
||||
name: '360行车记录',
|
||||
describe: '夜行 监控 电子狗 蓝牙',
|
||||
url: '',
|
||||
@@ -344,28 +361,28 @@ export const modelData = [
|
||||
bgColor: '#a25684',
|
||||
url: '',
|
||||
list: [{
|
||||
img: require('@/assets/nav/decorate5.jpeg'),
|
||||
img: navDecorate5,
|
||||
name: '好心情喝出来',
|
||||
describe: '遇见懂你的饮品',
|
||||
url: '',
|
||||
size: '100*100'
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate5.jpeg'),
|
||||
img: navDecorate5,
|
||||
name: '好心情喝出来',
|
||||
describe: '遇见懂你的饮品',
|
||||
url: '',
|
||||
size: '100*100'
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate5.jpeg'),
|
||||
img: navDecorate5,
|
||||
name: '好心情喝出来',
|
||||
describe: '遇见懂你的饮品',
|
||||
url: '',
|
||||
size: '100*100'
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate5.jpeg'),
|
||||
img: navDecorate5,
|
||||
name: '好心情喝出来',
|
||||
describe: '遇见懂你的饮品',
|
||||
url: '',
|
||||
@@ -388,35 +405,35 @@ export const modelData = [
|
||||
list: [{
|
||||
name: '新年心愿单',
|
||||
describe: '满269减50,满999减100',
|
||||
img: require('@/assets/nav/decorate6.jpeg'),
|
||||
img: navDecorate6,
|
||||
url: '',
|
||||
size: "160*160"
|
||||
},
|
||||
{
|
||||
name: 'Ms.Maggie 冬季时尚',
|
||||
describe: '满269减50',
|
||||
img: require('@/assets/nav/decorate6.jpeg'),
|
||||
img: navDecorate6,
|
||||
url: '',
|
||||
size: "90*90"
|
||||
},
|
||||
{
|
||||
name: 'Ms.Maggie 冬季时尚',
|
||||
describe: '满269减50',
|
||||
img: require('@/assets/nav/decorate6.jpeg'),
|
||||
img: navDecorate6,
|
||||
url: '',
|
||||
size: "90*90"
|
||||
},
|
||||
{
|
||||
name: 'Ms.Maggie 冬季时尚',
|
||||
describe: '满269减50',
|
||||
img: require('@/assets/nav/decorate6.jpeg'),
|
||||
img: navDecorate6,
|
||||
url: '',
|
||||
size: "90*90"
|
||||
},
|
||||
{
|
||||
name: '阿迪达斯 领跑时尚',
|
||||
describe: '满269减50',
|
||||
img: require('@/assets/nav/decorate6.jpeg'),
|
||||
img: navDecorate6,
|
||||
url: '',
|
||||
size: "90*90"
|
||||
},
|
||||
@@ -430,42 +447,42 @@ export const modelData = [
|
||||
list: [{
|
||||
name: '阿迪达斯 领跑时尚',
|
||||
describe: '满269减50',
|
||||
img: require('@/assets/nav/decorate6.jpeg'),
|
||||
img: navDecorate6,
|
||||
url: '',
|
||||
size: "90*90"
|
||||
},
|
||||
{
|
||||
name: '阿迪达斯 领跑时尚',
|
||||
describe: '满269减50',
|
||||
img: require('@/assets/nav/decorate6.jpeg'),
|
||||
img: navDecorate6,
|
||||
url: '',
|
||||
size: "90*90"
|
||||
},
|
||||
{
|
||||
name: '阿迪达斯 领跑时尚',
|
||||
describe: '满269减50',
|
||||
img: require('@/assets/nav/decorate6.jpeg'),
|
||||
img: navDecorate6,
|
||||
url: '',
|
||||
size: "90*90"
|
||||
},
|
||||
{
|
||||
name: '阿迪达斯 领跑时尚',
|
||||
describe: '满269减50',
|
||||
img: require('@/assets/nav/decorate6.jpeg'),
|
||||
img: navDecorate6,
|
||||
url: '',
|
||||
size: "90*90"
|
||||
},
|
||||
{
|
||||
name: '阿迪达斯 领跑时尚',
|
||||
describe: '满269减50',
|
||||
img: require('@/assets/nav/decorate6.jpeg'),
|
||||
img: navDecorate6,
|
||||
url: '',
|
||||
size: "90*90"
|
||||
},
|
||||
{
|
||||
name: '阿迪达斯 领跑时尚',
|
||||
describe: '满269减50',
|
||||
img: require('@/assets/nav/decorate6.jpeg'),
|
||||
img: navDecorate6,
|
||||
url: '',
|
||||
size: "90*90"
|
||||
},
|
||||
@@ -479,37 +496,37 @@ export const modelData = [
|
||||
list: [{
|
||||
name: '小米红米3s手机壳保护套红米3高配版指纹男女款潮版磨砂硬壳防摔 收藏截图 送大礼包',
|
||||
price: 14.9,
|
||||
img: require('@/assets/nav/decorate7.jpeg'),
|
||||
img: navDecorate7,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
name: '小米红米3s手机壳保护套红米3高配版指纹男女款潮版磨砂硬壳防摔 收藏截图 送大礼包',
|
||||
price: 14.9,
|
||||
img: require('@/assets/nav/decorate7.jpeg'),
|
||||
img: navDecorate7,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
name: '小米红米3s手机壳保护套红米3高配版指纹男女款潮版磨砂硬壳防摔 收藏截图 送大礼包',
|
||||
price: 14.9,
|
||||
img: require('@/assets/nav/decorate7.jpeg'),
|
||||
img: navDecorate7,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
name: '小米红米3s手机壳保护套红米3高配版指纹男女款潮版磨砂硬壳防摔 收藏截图 送大礼包',
|
||||
price: 14.9,
|
||||
img: require('@/assets/nav/decorate7.jpeg'),
|
||||
img: navDecorate7,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
name: '小米红米3s手机壳保护套红米3高配版指纹男女款潮版磨砂硬壳防摔 收藏截图 送大礼包',
|
||||
price: 14.9,
|
||||
img: require('@/assets/nav/decorate7.jpeg'),
|
||||
img: navDecorate7,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
name: '小米红米3s手机壳保护套红米3高配版指纹男女款潮版磨砂硬壳防摔 收藏截图 送大礼包',
|
||||
price: 14.9,
|
||||
img: require('@/assets/nav/decorate7.jpeg'),
|
||||
img: navDecorate7,
|
||||
url: ''
|
||||
},
|
||||
]
|
||||
@@ -524,7 +541,7 @@ export const modelData = [
|
||||
list: [{
|
||||
name: '生鲜',
|
||||
describe: "年货带回家 满199减60",
|
||||
img: require('@/assets/nav/decorate8.png'),
|
||||
img: navDecorate8,
|
||||
url: '',
|
||||
fromColor: '#e89621',
|
||||
toColor: "#f5c568",
|
||||
@@ -533,7 +550,7 @@ export const modelData = [
|
||||
{
|
||||
name: '众筹',
|
||||
describe: "年货带回家",
|
||||
img: require('@/assets/nav/decorate9.png'),
|
||||
img: navDecorate9,
|
||||
url: '',
|
||||
fromColor: "#325bb4",
|
||||
toColor: '#4c9afe',
|
||||
@@ -542,7 +559,7 @@ export const modelData = [
|
||||
{
|
||||
name: '生鲜',
|
||||
describe: "年货带回家 满199减60",
|
||||
img: require('@/assets/nav/decorate8.png'),
|
||||
img: navDecorate8,
|
||||
url: '',
|
||||
fromColor: "#1c9daf",
|
||||
toColor: '#40cda7',
|
||||
@@ -551,7 +568,7 @@ export const modelData = [
|
||||
{
|
||||
name: '众筹',
|
||||
describe: "备孕有孕检测仪",
|
||||
img: require('@/assets/nav/decorate9.png'),
|
||||
img: navDecorate9,
|
||||
url: '',
|
||||
fromColor: "#d13837",
|
||||
toColor: '#df6d4f',
|
||||
@@ -560,7 +577,7 @@ export const modelData = [
|
||||
{
|
||||
name: '生鲜',
|
||||
describe: "年货带回家 满199减60",
|
||||
img: require('@/assets/nav/decorate8.png'),
|
||||
img: navDecorate8,
|
||||
url: '',
|
||||
fromColor: "#ca4283",
|
||||
toColor: '#eb75cf',
|
||||
@@ -569,7 +586,7 @@ export const modelData = [
|
||||
{
|
||||
name: '众筹',
|
||||
describe: "备孕有孕检测仪",
|
||||
img: require('@/assets/nav/decorate9.png'),
|
||||
img: navDecorate9,
|
||||
url: '',
|
||||
fromColor: "#5d40c1",
|
||||
toColor: '#8c5fdb',
|
||||
@@ -595,244 +612,244 @@ export const modelData = [
|
||||
options: {
|
||||
list: [
|
||||
[{
|
||||
img: require('@/assets/nav/decorate10.jpeg'),
|
||||
img: navDecorate10,
|
||||
name: 'Apple/苹果 13 英寸:MacBook Pro Multi-Touch Bar 和 Touch ID 2.9GHz 处理器 512GB 存储容量',
|
||||
price: 6666,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate10.jpeg'),
|
||||
img: navDecorate10,
|
||||
name: 'Apple/苹果 13 英寸:MacBook Pro Multi-Touch Bar 和 Touch ID 2.9GHz 处理器 512GB 存储容量',
|
||||
price: 6666,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate10.jpeg'),
|
||||
img: navDecorate10,
|
||||
name: 'Apple/苹果 13 英寸:MacBook Pro Multi-Touch Bar 和 Touch ID 2.9GHz 处理器 512GB 存储容量',
|
||||
price: 6666,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate10.jpeg'),
|
||||
img: navDecorate10,
|
||||
name: 'Apple/苹果 13 英寸:MacBook Pro Multi-Touch Bar 和 Touch ID 2.9GHz 处理器 512GB 存储容量',
|
||||
price: 6666,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate10.jpeg'),
|
||||
img: navDecorate10,
|
||||
name: 'Apple/苹果 13 英寸:MacBook Pro Multi-Touch Bar 和 Touch ID 2.9GHz 处理器 512GB 存储容量',
|
||||
price: 6666,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate10.jpeg'),
|
||||
img: navDecorate10,
|
||||
name: 'Apple/苹果 13 英寸:MacBook Pro Multi-Touch Bar 和 Touch ID 2.9GHz 处理器 512GB 存储容量',
|
||||
price: 6666,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate10.jpeg'),
|
||||
img: navDecorate10,
|
||||
name: 'Apple/苹果 13 英寸:MacBook Pro Multi-Touch Bar 和 Touch ID 2.9GHz 处理器 512GB 存储容量',
|
||||
price: 6666,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate10.jpeg'),
|
||||
img: navDecorate10,
|
||||
name: 'Apple/苹果 13 英寸:MacBook Pro Multi-Touch Bar 和 Touch ID 2.9GHz 处理器 512GB 存储容量',
|
||||
price: 6666,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate10.jpeg'),
|
||||
img: navDecorate10,
|
||||
name: 'Apple/苹果 13 英寸:MacBook Pro Multi-Touch Bar 和 Touch ID 2.9GHz 处理器 512GB 存储容量',
|
||||
price: 6666,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate10.jpeg'),
|
||||
img: navDecorate10,
|
||||
name: 'Apple/苹果 13 英寸:MacBook Pro Multi-Touch Bar 和 Touch ID 2.9GHz 处理器 512GB 存储容量',
|
||||
price: 6666,
|
||||
url: ''
|
||||
},
|
||||
],
|
||||
[{
|
||||
img: require('@/assets/nav/decorate10.jpeg'),
|
||||
img: navDecorate10,
|
||||
name: 'Apple/苹果 13 英寸:MacBook Pro Multi-Touch Bar 和 Touch ID 2.9GHz 处理器 512GB 存储容量',
|
||||
price: 6666,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate10.jpeg'),
|
||||
img: navDecorate10,
|
||||
name: 'Apple/苹果 13 英寸:MacBook Pro Multi-Touch Bar 和 Touch ID 2.9GHz 处理器 512GB 存储容量',
|
||||
price: 6666,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate10.jpeg'),
|
||||
img: navDecorate10,
|
||||
name: 'Apple/苹果 13 英寸:MacBook Pro Multi-Touch Bar 和 Touch ID 2.9GHz 处理器 512GB 存储容量',
|
||||
price: 6666,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate10.jpeg'),
|
||||
img: navDecorate10,
|
||||
name: 'Apple/苹果 13 英寸:MacBook Pro Multi-Touch Bar 和 Touch ID 2.9GHz 处理器 512GB 存储容量',
|
||||
price: 6666,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate10.jpeg'),
|
||||
img: navDecorate10,
|
||||
name: 'Apple/苹果 13 英寸:MacBook Pro Multi-Touch Bar 和 Touch ID 2.9GHz 处理器 512GB 存储容量',
|
||||
price: 6666,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate10.jpeg'),
|
||||
img: navDecorate10,
|
||||
name: 'Apple/苹果 13 英寸:MacBook Pro Multi-Touch Bar 和 Touch ID 2.9GHz 处理器 512GB 存储容量',
|
||||
price: 6666,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate10.jpeg'),
|
||||
img: navDecorate10,
|
||||
name: 'Apple/苹果 13 英寸:MacBook Pro Multi-Touch Bar 和 Touch ID 2.9GHz 处理器 512GB 存储容量',
|
||||
price: 6666,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate10.jpeg'),
|
||||
img: navDecorate10,
|
||||
name: 'Apple/苹果 13 英寸:MacBook Pro Multi-Touch Bar 和 Touch ID 2.9GHz 处理器 512GB 存储容量',
|
||||
price: 6666,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate10.jpeg'),
|
||||
img: navDecorate10,
|
||||
name: 'Apple/苹果 13 英寸:MacBook Pro Multi-Touch Bar 和 Touch ID 2.9GHz 处理器 512GB 存储容量',
|
||||
price: 6666,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate10.jpeg'),
|
||||
img: navDecorate10,
|
||||
name: 'Apple/苹果 13 英寸:MacBook Pro Multi-Touch Bar 和 Touch ID 2.9GHz 处理器 512GB 存储容量',
|
||||
price: 6666,
|
||||
url: ''
|
||||
},
|
||||
],
|
||||
[{
|
||||
img: require('@/assets/nav/decorate10.jpeg'),
|
||||
img: navDecorate10,
|
||||
name: 'Apple/苹果 13 英寸:MacBook Pro Multi-Touch Bar 和 Touch ID 2.9GHz 处理器 512GB 存储容量',
|
||||
price: 6666,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate10.jpeg'),
|
||||
img: navDecorate10,
|
||||
name: 'Apple/苹果 13 英寸:MacBook Pro Multi-Touch Bar 和 Touch ID 2.9GHz 处理器 512GB 存储容量',
|
||||
price: 6666,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate10.jpeg'),
|
||||
img: navDecorate10,
|
||||
name: 'Apple/苹果 13 英寸:MacBook Pro Multi-Touch Bar 和 Touch ID 2.9GHz 处理器 512GB 存储容量',
|
||||
price: 6666,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate10.jpeg'),
|
||||
img: navDecorate10,
|
||||
name: 'Apple/苹果 13 英寸:MacBook Pro Multi-Touch Bar 和 Touch ID 2.9GHz 处理器 512GB 存储容量',
|
||||
price: 6666,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate10.jpeg'),
|
||||
img: navDecorate10,
|
||||
name: 'Apple/苹果 13 英寸:MacBook Pro Multi-Touch Bar 和 Touch ID 2.9GHz 处理器 512GB 存储容量',
|
||||
price: 6666,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate10.jpeg'),
|
||||
img: navDecorate10,
|
||||
name: 'Apple/苹果 13 英寸:MacBook Pro Multi-Touch Bar 和 Touch ID 2.9GHz 处理器 512GB 存储容量',
|
||||
price: 6666,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate10.jpeg'),
|
||||
img: navDecorate10,
|
||||
name: 'Apple/苹果 13 英寸:MacBook Pro Multi-Touch Bar 和 Touch ID 2.9GHz 处理器 512GB 存储容量',
|
||||
price: 6666,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate10.jpeg'),
|
||||
img: navDecorate10,
|
||||
name: 'Apple/苹果 13 英寸:MacBook Pro Multi-Touch Bar 和 Touch ID 2.9GHz 处理器 512GB 存储容量',
|
||||
price: 6666,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate10.jpeg'),
|
||||
img: navDecorate10,
|
||||
name: 'Apple/苹果 13 英寸:MacBook Pro Multi-Touch Bar 和 Touch ID 2.9GHz 处理器 512GB 存储容量',
|
||||
price: 6666,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate10.jpeg'),
|
||||
img: navDecorate10,
|
||||
name: 'Apple/苹果 13 英寸:MacBook Pro Multi-Touch Bar 和 Touch ID 2.9GHz 处理器 512GB 存储容量',
|
||||
price: 6666,
|
||||
url: ''
|
||||
},
|
||||
],
|
||||
[{
|
||||
img: require('@/assets/nav/decorate10.jpeg'),
|
||||
img: navDecorate10,
|
||||
name: 'Apple/苹果 13 英寸:MacBook Pro Multi-Touch Bar 和 Touch ID 2.9GHz 处理器 512GB 存储容量',
|
||||
price: 6666,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate10.jpeg'),
|
||||
img: navDecorate10,
|
||||
name: 'Apple/苹果 13 英寸:MacBook Pro Multi-Touch Bar 和 Touch ID 2.9GHz 处理器 512GB 存储容量',
|
||||
price: 6666,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate10.jpeg'),
|
||||
img: navDecorate10,
|
||||
name: 'Apple/苹果 13 英寸:MacBook Pro Multi-Touch Bar 和 Touch ID 2.9GHz 处理器 512GB 存储容量',
|
||||
price: 6666,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate10.jpeg'),
|
||||
img: navDecorate10,
|
||||
name: 'Apple/苹果 13 英寸:MacBook Pro Multi-Touch Bar 和 Touch ID 2.9GHz 处理器 512GB 存储容量',
|
||||
price: 6666,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate10.jpeg'),
|
||||
img: navDecorate10,
|
||||
name: 'Apple/苹果 13 英寸:MacBook Pro Multi-Touch Bar 和 Touch ID 2.9GHz 处理器 512GB 存储容量',
|
||||
price: 6666,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate10.jpeg'),
|
||||
img: navDecorate10,
|
||||
name: 'Apple/苹果 13 英寸:MacBook Pro Multi-Touch Bar 和 Touch ID 2.9GHz 处理器 512GB 存储容量',
|
||||
price: 6666,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate10.jpeg'),
|
||||
img: navDecorate10,
|
||||
name: 'Apple/苹果 13 英寸:MacBook Pro Multi-Touch Bar 和 Touch ID 2.9GHz 处理器 512GB 存储容量',
|
||||
price: 6666,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate10.jpeg'),
|
||||
img: navDecorate10,
|
||||
name: 'Apple/苹果 13 英寸:MacBook Pro Multi-Touch Bar 和 Touch ID 2.9GHz 处理器 512GB 存储容量',
|
||||
price: 6666,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate10.jpeg'),
|
||||
img: navDecorate10,
|
||||
name: 'Apple/苹果 13 英寸:MacBook Pro Multi-Touch Bar 和 Touch ID 2.9GHz 处理器 512GB 存储容量',
|
||||
price: 6666,
|
||||
url: ''
|
||||
},
|
||||
{
|
||||
img: require('@/assets/nav/decorate10.jpeg'),
|
||||
img: navDecorate10,
|
||||
name: 'Apple/苹果 13 英寸:MacBook Pro Multi-Touch Bar 和 Touch ID 2.9GHz 处理器 512GB 存储容量',
|
||||
price: 6666,
|
||||
url: ''
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
</ul>
|
||||
</div>
|
||||
<div class="search-con">
|
||||
<img :src="require('@/assets/logo.png')" class="logo" alt="" />
|
||||
<img :src="logoImg" class="logo" alt="" />
|
||||
<div class="search">
|
||||
<el-input size="large" placeholder="输入你想查找的商品">
|
||||
<template #append>
|
||||
@@ -144,6 +144,7 @@
|
||||
</template>
|
||||
<script>
|
||||
import { ShoppingCart } from "@element-plus/icons-vue";
|
||||
import logoImg from "@/assets/logo.png";
|
||||
import Draggable from "vuedraggable";
|
||||
import ModelFormItem from "./modelFormItem.vue";
|
||||
import ossManage from "@/views/sys/oss-manage/ossManage";
|
||||
@@ -158,6 +159,7 @@ export default {
|
||||
props: ["data"],
|
||||
data() {
|
||||
return {
|
||||
logoImg,
|
||||
picModelFlag: false,
|
||||
showModal: false,
|
||||
showModalNav: false,
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
class="discountAdvert"
|
||||
:style="{
|
||||
'background-image':
|
||||
'url(' + require('@/assets/nav/decorate.png') + ')',
|
||||
'url(' + decorateImg + ')',
|
||||
}"
|
||||
>
|
||||
<div>
|
||||
@@ -280,6 +280,7 @@ import onlyGoodsModel from "./modelList/onlyGoodsModel.vue";
|
||||
|
||||
import oneRowThreeColumns from "./modelList/oneRowThreeColumns.vue";
|
||||
import seckillOnlyAlbum from "./modelList/seckill-only-album.vue";
|
||||
import decorateImg from "@/assets/nav/decorate.png";
|
||||
export default {
|
||||
name: "modelFormItem",
|
||||
props: ["element", "select", "index", "data"],
|
||||
@@ -302,6 +303,7 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
decorateImg,
|
||||
showModal: false, // modal显隐
|
||||
selected: {}, // 弹窗编辑草稿
|
||||
editTarget: null, // 确定后写回的原数据
|
||||
|
||||
@@ -36,7 +36,6 @@ export default {
|
||||
default: {}
|
||||
}
|
||||
},
|
||||
components: {},
|
||||
mounted() {
|
||||
|
||||
},
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
z-index: 99;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.ivu-btn,
|
||||
.el-button{
|
||||
float: right;
|
||||
margin-right: 5px;
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
.ivu-card-body {
|
||||
.el-card__body {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
@@ -243,7 +243,7 @@
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
.demo-tree-render .ivu-tree-title{
|
||||
.demo-tree-render .el-tree-node__content{
|
||||
width: 94%;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,166 +222,8 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
|
||||
<!--<div class="oss-operation padding-row">-->
|
||||
<!--<div>-->
|
||||
<!--<Upload-->
|
||||
<!--ref="up"-->
|
||||
<!--:action="commonUrl + '/common/common/upload/file'"-->
|
||||
<!--:data="{-->
|
||||
<!--directoryPath: searchForm.fileDirectoryId,-->
|
||||
<!--}"-->
|
||||
<!--:headers="accessToken"-->
|
||||
<!--:max-size="20480"-->
|
||||
<!--:on-error="handleError"-->
|
||||
<!--:on-exceeded-size="handleMaxSize"-->
|
||||
<!--:on-success="handleSuccess"-->
|
||||
<!--:show-upload-list="false"-->
|
||||
<!--multiple-->
|
||||
<!--style="display: inline-block"-->
|
||||
<!-->-->
|
||||
<!--<Button>上传图片</Button>-->
|
||||
<!--</Upload>-->
|
||||
<!--<Dropdown @on-click="handleDropdown" v-if="!isComponent">-->
|
||||
<!--<Button>-->
|
||||
<!--更多操作-->
|
||||
<!--<Icon type="md-arrow-dropdown"/>-->
|
||||
<!--</Button>-->
|
||||
<!--<DropdownMenu slot="list">-->
|
||||
<!--<DropdownItem name="refresh">刷新</DropdownItem>-->
|
||||
<!--<DropdownItem v-show="showType == 'list'" name="removeAll"-->
|
||||
<!-->批量删除-->
|
||||
<!--</DropdownItem>-->
|
||||
<!--</DropdownMenu>-->
|
||||
<!--</Dropdown>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
</div>
|
||||
|
||||
<!--<Alert show-icon v-if="!isComponent">-->
|
||||
<!--已选择-->
|
||||
<!--<span>{{ selectCount }}</span> 项-->
|
||||
<!--<a class="select-clear" @click="clearSelectAll">清空</a>-->
|
||||
<!--<span v-if="selectCount > 0" style="margin-left: 15px"-->
|
||||
<!-->共计 {{ totalSize }} 存储量</span-->
|
||||
<!-->-->
|
||||
<!--</Alert>-->
|
||||
|
||||
<!--<div v-show="showType === 'list'" >-->
|
||||
<!--<div class="flex">-->
|
||||
<!--<div class="article-category mr_10">-->
|
||||
<!--<Tree-->
|
||||
<!--:data="treeData"-->
|
||||
<!--@on-contextmenu="handleContextMenu"-->
|
||||
<!--@on-select-change="handleCateChange"-->
|
||||
<!-->-->
|
||||
<!--<template slot="contextMenu" v-if="!isComponent">-->
|
||||
<!--<DropdownItem @click.native="handleContextMenuEdit"-->
|
||||
<!-->编辑-->
|
||||
<!--</DropdownItem-->
|
||||
<!-->-->
|
||||
<!--<DropdownItem-->
|
||||
<!--style="color: #ed4014"-->
|
||||
<!--@click.native="handleContextMenuDelete"-->
|
||||
<!-->删除-->
|
||||
<!--</DropdownItem-->
|
||||
<!-->-->
|
||||
<!--</template>-->
|
||||
<!--</Tree>-->
|
||||
<!--<Alert v-if="!isComponent">鼠标右键编辑/删除分组</Alert>-->
|
||||
<!--<div class="group-row flex" v-if="!isComponent">-->
|
||||
<!--<Button @click="handleClickAddGroup">添加分组</Button>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
|
||||
<!--<Table-->
|
||||
<!--ref="table"-->
|
||||
<!--:columns="isComponent ? viewColumns : columns"-->
|
||||
<!--:data="data"-->
|
||||
<!--:loading="loading"-->
|
||||
<!--border-->
|
||||
<!--class="table"-->
|
||||
<!--sortable="custom"-->
|
||||
<!--@on-sort-change="changeSort"-->
|
||||
<!--@on-selection-change="changeSelect"-->
|
||||
<!-->-->
|
||||
<!--<template slot="fileKey" slot-scope="{ row }">-->
|
||||
<!--<a @click="copyFileUrl(row)">{{ row.fileKey }}</a>-->
|
||||
<!--</template>-->
|
||||
<!--</Table>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
|
||||
<!--<div v-show="showType === 'thumb'">-->
|
||||
<!--<div class="oss-wrapper">-->
|
||||
<!--<Card v-for="(item, i) in data" :key="i" class="oss-card">-->
|
||||
<!--<div class="content">-->
|
||||
<!--<img-->
|
||||
<!--v-if="item.fileType.indexOf('image') >= 0"-->
|
||||
<!--:src="item.url"-->
|
||||
<!--class="img"-->
|
||||
<!--@click="showPic(item)"-->
|
||||
<!--/>-->
|
||||
<!--<div-->
|
||||
<!--v-else-if="item.fileType.indexOf('video') >= 0"-->
|
||||
<!--class="video"-->
|
||||
<!--@click="showVideo(item)"-->
|
||||
<!-->-->
|
||||
<!--<!– 文件小于5MB显示video –>-->
|
||||
<!--<video v-if="item.fileSize < 1024 * 1024 * 5" class="cover">-->
|
||||
<!--<source :src="item.url"/>-->
|
||||
<!--</video>-->
|
||||
<!--<img class="play" src="@/assets/play.png"/>-->
|
||||
<!--</div>-->
|
||||
<!--<div v-else class="other">-->
|
||||
<!--<div class="name">{{ item.name }}</div>-->
|
||||
<!--<div class="key">{{ item.fileKey }}</div>-->
|
||||
<!--<div class="info">-->
|
||||
<!--文件类型:{{ item.fileType }} 文件大小:{{-->
|
||||
<!--((item.fileSize * 1.0) / (1024 * 1024)).toFixed(2)-->
|
||||
<!--}}-->
|
||||
<!--MB 创建时间:{{ item.createTime }}-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
<!--<div class="actions">-->
|
||||
<!--<div class="btn">-->
|
||||
<!--<Tooltip content="下载" placement="top">-->
|
||||
<!--<Icon-->
|
||||
<!--size="16"-->
|
||||
<!--type="md-download"-->
|
||||
<!--@click="download(item)"-->
|
||||
<!--/>-->
|
||||
<!--</Tooltip>-->
|
||||
<!--</div>-->
|
||||
<!--<div class="btn">-->
|
||||
<!--<Tooltip content="重命名" placement="top">-->
|
||||
<!--<Icon size="16" type="md-create" @click="rename(item)"/>-->
|
||||
<!--</Tooltip>-->
|
||||
<!--</div>-->
|
||||
<!--<div class="btn-no">-->
|
||||
<!--<Tooltip content="删除" placement="top">-->
|
||||
<!--<Icon size="16" type="md-trash" @click="remove(item)"/>-->
|
||||
<!--</Tooltip>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
<!--</Card>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
<!--<Row class="mt_10" justify="end" type="flex">-->
|
||||
<!--<Page-->
|
||||
<!--:current="searchForm.pageNumber"-->
|
||||
<!--:page-size="searchForm.pageSize"-->
|
||||
<!--:page-size-opts="pageSizeOpts"-->
|
||||
<!--:total="total"-->
|
||||
<!--show-elevator-->
|
||||
<!--show-sizer-->
|
||||
<!--show-total-->
|
||||
<!--size="small"-->
|
||||
<!--@on-change="changePage"-->
|
||||
<!--@on-page-size-change="changePageSize"-->
|
||||
<!--></Page>-->
|
||||
<!--</Row>-->
|
||||
</el-card>
|
||||
</el-row>
|
||||
<el-dialog
|
||||
@@ -477,7 +319,8 @@ import {
|
||||
import DPlayer from "dplayer";
|
||||
import {commonUrl} from "@/libs/axios";
|
||||
|
||||
const config = require("@/config/index");
|
||||
import config from "@/config/index";
|
||||
import playImg from "@/assets/play.png";
|
||||
|
||||
let dp;
|
||||
export default {
|
||||
@@ -631,7 +474,7 @@ export default {
|
||||
} else {
|
||||
return h("img", {
|
||||
attrs: {
|
||||
src: require("@/assets/play.png"),
|
||||
src: playImg,
|
||||
},
|
||||
style: {
|
||||
cursor: "pointer",
|
||||
@@ -832,7 +675,7 @@ export default {
|
||||
} else {
|
||||
return h("img", {
|
||||
attrs: {
|
||||
src: require("@/assets/play.png"),
|
||||
src: playImg,
|
||||
},
|
||||
style: {
|
||||
cursor: "pointer",
|
||||
@@ -917,41 +760,6 @@ export default {
|
||||
groupLoading: false,
|
||||
// 图片列表
|
||||
selectedOss: [],
|
||||
myData: [
|
||||
{
|
||||
title: 'parent 1',
|
||||
expand: true,
|
||||
render: (h, {root, node, data}) => {
|
||||
return h('span', {style: {display: 'inline-block', width: '100%'}}, [
|
||||
h('span', [h("Icon", {type: 'ios-folder-outline', style: {marginRight: '8px'}}), h('span', data.title)]),
|
||||
h('span', {style: {display: 'inline-block', float: 'right', marginRight: '32px'}},
|
||||
[h("Button", {
|
||||
...this.buttonProps,
|
||||
icon: 'ios-add',
|
||||
type: 'primary',
|
||||
style: {width: '64px'},
|
||||
onClick: () => {
|
||||
this.append(data)
|
||||
}
|
||||
})
|
||||
])
|
||||
]);
|
||||
},
|
||||
children: [
|
||||
{
|
||||
title: 'child 1-1',
|
||||
expand: true,
|
||||
children: [{title: 'leaf 1-1-1', expand: true}, {title: 'leaf 1-1-2', expand: true}]
|
||||
},
|
||||
{
|
||||
title: 'child 1-2',
|
||||
expand: true,
|
||||
children: [{title: 'leaf 1-2-1', expand: true}, {title: 'leaf 1-2-1', expand: true}]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
buttonProps: {type: 'default', size: 'small',},
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
@@ -1099,57 +907,6 @@ export default {
|
||||
this.searchForm.pageNumber = value;
|
||||
this.getDataList();
|
||||
},
|
||||
// 自定义tree节点显示内容和交互
|
||||
renderContent(h, {root, node, data}) {
|
||||
if (data.value === '0') {
|
||||
return h('span', {style: {display: 'inline-block', width: '100%'}},
|
||||
[
|
||||
h('span', [h("Icon", {type: 'ios-paper-outline', style: {marginRight: '8px'}}), h('span', data.title)]),
|
||||
h('span', {style: {display: 'inline-block', float: 'right', marginRight: '10px'}}, [])
|
||||
]
|
||||
);
|
||||
} else {
|
||||
return h('span', {style: {display: 'inline-block', width: '100%'}},
|
||||
[
|
||||
h('span', [h("Icon", {type: 'ios-paper-outline', style: {marginRight: '8px'}}), h('span', data.title)]),
|
||||
h('span', {style: {display: 'inline-block', float: 'right', marginRight: '10px'}},
|
||||
[
|
||||
h("Dropdown", {style: {marginLeft: "4px"}},
|
||||
[
|
||||
h("Icon", {
|
||||
props: {type: 'ios-more', size: "20",},
|
||||
style: {display: 'inline-block'},
|
||||
on: {
|
||||
click: () => {
|
||||
}
|
||||
}
|
||||
}),
|
||||
h("DropdownMenu", {
|
||||
slot: "list"
|
||||
}, [
|
||||
h("DropdownItem", {
|
||||
nativeOn: {
|
||||
click: () => {
|
||||
this.handleContextMenuEdit(root, node, data)
|
||||
}
|
||||
}
|
||||
}, "编辑"),
|
||||
h("DropdownItem", {
|
||||
nativeOn: {
|
||||
click: () => {
|
||||
this.handleContextMenuDelete()
|
||||
}
|
||||
}
|
||||
}, "删除"),
|
||||
])
|
||||
]),
|
||||
])
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
|
||||
handleContextMenu(val) {
|
||||
console.log('handleContextMenu', val);
|
||||
|
||||
@@ -218,166 +218,8 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
|
||||
<!--<div class="oss-operation padding-row">-->
|
||||
<!--<div>-->
|
||||
<!--<Upload-->
|
||||
<!--ref="up"-->
|
||||
<!--:action="commonUrl + '/common/common/upload/file'"-->
|
||||
<!--:data="{-->
|
||||
<!--directoryPath: searchForm.fileDirectoryId,-->
|
||||
<!--}"-->
|
||||
<!--:headers="accessToken"-->
|
||||
<!--:max-size="20480"-->
|
||||
<!--:on-error="handleError"-->
|
||||
<!--:on-exceeded-size="handleMaxSize"-->
|
||||
<!--:on-success="handleSuccess"-->
|
||||
<!--:show-upload-list="false"-->
|
||||
<!--multiple-->
|
||||
<!--style="display: inline-block"-->
|
||||
<!-->-->
|
||||
<!--<el-button>上传图片</el-button>-->
|
||||
<!--</Upload>-->
|
||||
<!--<Dropdown @click="handleDropdown" v-if="!isComponent">-->
|
||||
<!--<el-button>-->
|
||||
<!--更多操作-->
|
||||
<!--<Icon type="md-arrow-dropdown"/>-->
|
||||
<!--</el-button>-->
|
||||
<!--<DropdownMenu #list>-->
|
||||
<!--<DropdownItem name="refresh">刷新</DropdownItem>-->
|
||||
<!--<DropdownItem v-show="showType == 'list'" name="removeAll"-->
|
||||
<!-->批量删除-->
|
||||
<!--</DropdownItem>-->
|
||||
<!--</DropdownMenu>-->
|
||||
<!--</Dropdown>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
</div>
|
||||
|
||||
<!--<Alert show-icon v-if="!isComponent">-->
|
||||
<!--已选择-->
|
||||
<!--<span>{{ selectCount }}</span> 项-->
|
||||
<!--<a class="select-clear" @click="clearSelectAll">清空</a>-->
|
||||
<!--<span v-if="selectCount > 0" style="margin-left: 15px"-->
|
||||
<!-->共计 {{ totalSize }} 存储量</span-->
|
||||
<!-->-->
|
||||
<!--</Alert>-->
|
||||
|
||||
<!--<div v-show="showType === 'list'" >-->
|
||||
<!--<div class="flex">-->
|
||||
<!--<div class="article-category mr_10">-->
|
||||
<!--<Tree-->
|
||||
<!--:data="treeData"-->
|
||||
<!--@on-contextmenu="handleContextMenu"-->
|
||||
<!--@on-select-change="handleCateChange"-->
|
||||
<!-->-->
|
||||
<!--<template #contextMenu v-if="!isComponent">-->
|
||||
<!--<DropdownItem @click.native="handleContextMenuEdit"-->
|
||||
<!-->编辑-->
|
||||
<!--</DropdownItem-->
|
||||
<!-->-->
|
||||
<!--<DropdownItem-->
|
||||
<!--style="color: #ed4014"-->
|
||||
<!--@click.native="handleContextMenuDelete"-->
|
||||
<!-->删除-->
|
||||
<!--</DropdownItem-->
|
||||
<!-->-->
|
||||
<!--</template>-->
|
||||
<!--</Tree>-->
|
||||
<!--<Alert v-if="!isComponent">鼠标右键编辑/删除分组</Alert>-->
|
||||
<!--<div class="group-row flex" v-if="!isComponent">-->
|
||||
<!--<el-button @click="handleClickAddGroup">添加分组</el-button>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
|
||||
<!--<Table-->
|
||||
<!--ref="table"-->
|
||||
<!--:columns="isComponent ? viewColumns : columns"-->
|
||||
<!--:data="data"-->
|
||||
<!--:loading="loading"-->
|
||||
<!--border-->
|
||||
<!--class="table"-->
|
||||
<!--sortable="custom"-->
|
||||
<!--@on-sort-change="changeSort"-->
|
||||
<!--@on-selection-change="changeSelect"-->
|
||||
<!-->-->
|
||||
<!--<template #fileKey #default="{ row }">-->
|
||||
<!--<a @click="copyFileUrl(row)">{{ row.fileKey }}</a>-->
|
||||
<!--</template>-->
|
||||
<!--</Table>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
|
||||
<!--<div v-show="showType === 'thumb'">-->
|
||||
<!--<div class="oss-wrapper">-->
|
||||
<!--<Card v-for="(item, i) in data" :key="i" class="oss-card">-->
|
||||
<!--<div class="content">-->
|
||||
<!--<img-->
|
||||
<!--v-if="item.fileType.indexOf('image') >= 0"-->
|
||||
<!--:src="item.url"-->
|
||||
<!--class="img"-->
|
||||
<!--@click="showPic(item)"-->
|
||||
<!--/>-->
|
||||
<!--<div-->
|
||||
<!--v-else-if="item.fileType.indexOf('video') >= 0"-->
|
||||
<!--class="video"-->
|
||||
<!--@click="showVideo(item)"-->
|
||||
<!-->-->
|
||||
<!--<!– 文件小于5MB显示video –>-->
|
||||
<!--<video v-if="item.fileSize < 1024 * 1024 * 5" class="cover">-->
|
||||
<!--<source :src="item.url"/>-->
|
||||
<!--</video>-->
|
||||
<!--<img class="play" src="@/assets/play.png"/>-->
|
||||
<!--</div>-->
|
||||
<!--<div v-else class="other">-->
|
||||
<!--<div class="name">{{ item.name }}</div>-->
|
||||
<!--<div class="key">{{ item.fileKey }}</div>-->
|
||||
<!--<div class="info">-->
|
||||
<!--文件类型:{{ item.fileType }} 文件大小:{{-->
|
||||
<!--((item.fileSize * 1.0) / (1024 * 1024)).toFixed(2)-->
|
||||
<!--}}-->
|
||||
<!--MB 创建时间:{{ item.createTime }}-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
<!--<div class="actions">-->
|
||||
<!--<div class="btn">-->
|
||||
<!--<el-tooltip content="下载" placement="top">-->
|
||||
<!--<Icon-->
|
||||
<!--size="16"-->
|
||||
<!--type="md-download"-->
|
||||
<!--@click="download(item)"-->
|
||||
<!--/>-->
|
||||
<!--</el-tooltip>-->
|
||||
<!--</div>-->
|
||||
<!--<div class="btn">-->
|
||||
<!--<el-tooltip content="重命名" placement="top">-->
|
||||
<!--<Icon size="16" type="md-create" @click="rename(item)"/>-->
|
||||
<!--</el-tooltip>-->
|
||||
<!--</div>-->
|
||||
<!--<div class="btn-no">-->
|
||||
<!--<el-tooltip content="删除" placement="top">-->
|
||||
<!--<Icon size="16" type="md-trash" @click="remove(item)"/>-->
|
||||
<!--</el-tooltip>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
<!--</el-card>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
<!--<div class="mt_10" justify="end" type="flex">-->
|
||||
<!--<Page-->
|
||||
<!--:current="searchForm.pageNumber"-->
|
||||
<!--:page-size="searchForm.pageSize"-->
|
||||
<!--:page-size-opts="pageSizeOpts"-->
|
||||
<!--:total="total"-->
|
||||
<!--show-elevator-->
|
||||
<!--show-sizer-->
|
||||
<!--show-total-->
|
||||
<!--size="small"-->
|
||||
<!--@change="changePage"-->
|
||||
<!--@size-change="changePageSize"-->
|
||||
<!--></el-pagination>-->
|
||||
<!--</div>-->
|
||||
</el-card>
|
||||
</el-row>
|
||||
<el-dialog
|
||||
@@ -473,7 +315,8 @@ import {
|
||||
import DPlayer from "dplayer";
|
||||
import {commonUrl} from "@/libs/axios";
|
||||
|
||||
const config = require("@/config/index");
|
||||
import config from "@/config/index";
|
||||
import playImg from "@/assets/play.png";
|
||||
|
||||
let dp;
|
||||
export default {
|
||||
@@ -632,7 +475,7 @@ export default {
|
||||
} else {
|
||||
return h("img", {
|
||||
attrs: {
|
||||
src: require("@/assets/play.png"),
|
||||
src: playImg,
|
||||
},
|
||||
style: {
|
||||
cursor: "pointer",
|
||||
@@ -833,7 +676,7 @@ export default {
|
||||
} else {
|
||||
return h("img", {
|
||||
attrs: {
|
||||
src: require("@/assets/play.png"),
|
||||
src: playImg,
|
||||
},
|
||||
style: {
|
||||
cursor: "pointer",
|
||||
@@ -918,41 +761,6 @@ export default {
|
||||
groupLoading: false,
|
||||
// 图片列表
|
||||
selectedOss: [],
|
||||
myData: [
|
||||
{
|
||||
title: 'parent 1',
|
||||
expand: true,
|
||||
render: (h, {root, node, data}) => {
|
||||
return h('span', {style: {display: 'inline-block', width: '100%'}}, [
|
||||
h('span', [h("Icon", {type: 'ios-folder-outline', style: {marginRight: '8px'}}), h('span', data.title)]),
|
||||
h('span', {style: {display: 'inline-block', float: 'right', marginRight: '32px'}},
|
||||
[h("Button", {
|
||||
...this.buttonProps,
|
||||
icon: 'ios-add',
|
||||
type: 'primary',
|
||||
style: {width: '64px'},
|
||||
onClick: () => {
|
||||
this.append(data)
|
||||
}
|
||||
})
|
||||
])
|
||||
]);
|
||||
},
|
||||
children: [
|
||||
{
|
||||
title: 'child 1-1',
|
||||
expand: true,
|
||||
children: [{title: 'leaf 1-1-1', expand: true}, {title: 'leaf 1-1-2', expand: true}]
|
||||
},
|
||||
{
|
||||
title: 'child 1-2',
|
||||
expand: true,
|
||||
children: [{title: 'leaf 1-2-1', expand: true}, {title: 'leaf 1-2-1', expand: true}]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
buttonProps: {type: 'default', size: 'small',},
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
@@ -1104,57 +912,6 @@ export default {
|
||||
this.searchForm.pageNumber = value;
|
||||
this.getDataList();
|
||||
},
|
||||
// 自定义tree节点显示内容和交互
|
||||
renderContent(h, {root, node, data}) {
|
||||
if (data.value === '0') {
|
||||
return h('span', {style: {display: 'inline-block', width: '100%'}},
|
||||
[
|
||||
h('span', [h("Icon", {type: 'ios-paper-outline', style: {marginRight: '8px'}}), h('span', data.title)]),
|
||||
h('span', {style: {display: 'inline-block', float: 'right', marginRight: '10px'}}, [])
|
||||
]
|
||||
);
|
||||
} else {
|
||||
return h('span', {style: {display: 'inline-block', width: '100%'}},
|
||||
[
|
||||
h('span', [h("Icon", {type: 'ios-paper-outline', style: {marginRight: '8px'}}), h('span', data.title)]),
|
||||
h('span', {style: {display: 'inline-block', float: 'right', marginRight: '10px'}},
|
||||
[
|
||||
h("Dropdown", {style: {marginLeft: "4px"}},
|
||||
[
|
||||
h("Icon", {
|
||||
props: {type: 'ios-more', size: "20",},
|
||||
style: {display: 'inline-block'},
|
||||
on: {
|
||||
click: () => {
|
||||
}
|
||||
}
|
||||
}),
|
||||
h("DropdownMenu", {
|
||||
slot: "list"
|
||||
}, [
|
||||
h("DropdownItem", {
|
||||
nativeOn: {
|
||||
click: () => {
|
||||
this.handleContextMenuEdit(root, node, data)
|
||||
}
|
||||
}
|
||||
}, "编辑"),
|
||||
h("DropdownItem", {
|
||||
nativeOn: {
|
||||
click: () => {
|
||||
this.handleContextMenuDelete()
|
||||
}
|
||||
}
|
||||
}, "删除"),
|
||||
])
|
||||
]),
|
||||
])
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
|
||||
handleContextMenu(val) {
|
||||
console.log('handleContextMenu', val);
|
||||
|
||||
@@ -247,7 +247,7 @@
|
||||
@click="changeTextAlign('left')"
|
||||
>
|
||||
<img
|
||||
:src="require('@/assets/align-text-left.png')"
|
||||
:src="alignTextLeftImg"
|
||||
class="align-text"
|
||||
alt=""
|
||||
/>
|
||||
@@ -258,7 +258,7 @@
|
||||
@click="changeTextAlign('center')"
|
||||
>
|
||||
<img
|
||||
:src="require('@/assets/align-text-center.png')"
|
||||
:src="alignTextCenterImg"
|
||||
class="align-text"
|
||||
alt=""
|
||||
/>
|
||||
@@ -269,7 +269,7 @@
|
||||
@click="changeTextAlign('right')"
|
||||
>
|
||||
<img
|
||||
:src="require('@/assets/align-text-right.png')"
|
||||
:src="alignTextRightImg"
|
||||
class="align-text"
|
||||
alt=""
|
||||
/>
|
||||
@@ -526,6 +526,9 @@
|
||||
</template>
|
||||
<script>
|
||||
import { CircleClose } from "@element-plus/icons-vue";
|
||||
import alignTextLeftImg from "@/assets/align-text-left.png";
|
||||
import alignTextCenterImg from "@/assets/align-text-center.png";
|
||||
import alignTextRightImg from "@/assets/align-text-right.png";
|
||||
import ossManage from "@/views/sys/oss-manage/ossManage";
|
||||
import { modelData } from "./config";
|
||||
import hotzone from "@/views/shop/hotzone";
|
||||
@@ -540,6 +543,9 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
alignTextLeftImg,
|
||||
alignTextCenterImg,
|
||||
alignTextRightImg,
|
||||
ways, // 选择链接的类型
|
||||
picModelFlag: false, //图片选择器
|
||||
linkType: "goods", // dialog弹窗口类型
|
||||
|
||||
@@ -99,10 +99,14 @@ export default {
|
||||
},
|
||||
props: ["res"],
|
||||
methods: {
|
||||
handleClickGoods(id) {
|
||||
this.$router.push({
|
||||
query: { id },
|
||||
path: "/goods/goods-info/goodsDetail",
|
||||
handleClickGoods(goodsId) {
|
||||
if (!goodsId) {
|
||||
this.$Message.warning("商品信息不存在");
|
||||
return;
|
||||
}
|
||||
this.$filters.customRouterPush({
|
||||
name: "goods-operation-edit",
|
||||
query: { id: goodsId },
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
@@ -112,10 +112,14 @@ export default {
|
||||
},
|
||||
props: ["res"],
|
||||
methods: {
|
||||
handleClickGoods(id) {
|
||||
this.$router.push({
|
||||
query: { id },
|
||||
path: "/goods/goods-info/goodsDetail",
|
||||
handleClickGoods(goodsId) {
|
||||
if (!goodsId) {
|
||||
this.$Message.warning("商品信息不存在");
|
||||
return;
|
||||
}
|
||||
this.$filters.customRouterPush({
|
||||
name: "goods-operation-edit",
|
||||
query: { id: goodsId },
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
.ivu-card-body {
|
||||
.el-card__body {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
@@ -240,7 +240,7 @@
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
.demo-tree-render .ivu-tree-title{
|
||||
.demo-tree-render .el-tree-node__content {
|
||||
width: 94%;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,10 +73,7 @@
|
||||
<div class="search">
|
||||
<el-card class="tabs-card">
|
||||
<el-tabs v-model="activeRoleTab" @tab-change="handleRoleTabChange">
|
||||
<el-tab-pane label="管理员" name="MANAGER" />
|
||||
<el-tab-pane label="商家" name="STORE" />
|
||||
<el-tab-pane label="用户" name="MEMBER" />
|
||||
<el-tab-pane label="客服" name="CUSTOMER" />
|
||||
</el-tabs>
|
||||
</el-card>
|
||||
<el-row>
|
||||
@@ -232,167 +229,7 @@
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
|
||||
<!--<div class="oss-operation padding-row">-->
|
||||
<!--<div>-->
|
||||
<!--<Upload-->
|
||||
<!--ref="up"-->
|
||||
<!--:action="commonUrl + '/common/common/upload/file'"-->
|
||||
<!--:data="{-->
|
||||
<!--directoryPath: searchForm.fileDirectoryId,-->
|
||||
<!--}"-->
|
||||
<!--:headers="accessToken"-->
|
||||
<!--:max-size="20480"-->
|
||||
<!--:on-error="handleError"-->
|
||||
<!--:on-exceeded-size="handleMaxSize"-->
|
||||
<!--:on-success="handleSuccess"-->
|
||||
<!--:show-upload-list="false"-->
|
||||
<!--multiple-->
|
||||
<!--style="display: inline-block"-->
|
||||
<!-->-->
|
||||
<!--<Button>上传图片</Button>-->
|
||||
<!--</Upload>-->
|
||||
<!--<Dropdown @on-click="handleDropdown" v-if="!isComponent">-->
|
||||
<!--<Button>-->
|
||||
<!--更多操作-->
|
||||
<!--<Icon type="md-arrow-dropdown"/>-->
|
||||
<!--</Button>-->
|
||||
<!--<DropdownMenu slot="list">-->
|
||||
<!--<DropdownItem name="refresh">刷新</DropdownItem>-->
|
||||
<!--<DropdownItem v-show="showType == 'list'" name="removeAll"-->
|
||||
<!-->批量删除-->
|
||||
<!--</DropdownItem>-->
|
||||
<!--</DropdownMenu>-->
|
||||
<!--</Dropdown>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
</div>
|
||||
|
||||
<!--<Alert show-icon v-if="!isComponent">-->
|
||||
<!--已选择-->
|
||||
<!--<span>{{ selectCount }}</span> 项-->
|
||||
<!--<a class="select-clear" @click="clearSelectAll">清空</a>-->
|
||||
<!--<span v-if="selectCount > 0" style="margin-left: 15px"-->
|
||||
<!-->共计 {{ totalSize }} 存储量</span-->
|
||||
<!-->-->
|
||||
<!--</Alert>-->
|
||||
|
||||
<!--<div v-show="showType === 'list'" >-->
|
||||
<!--<div class="flex">-->
|
||||
<!--<div class="article-category mr_10">-->
|
||||
<!--<Tree-->
|
||||
<!--:data="treeData"-->
|
||||
<!--@on-contextmenu="handleContextMenu"-->
|
||||
<!--@on-select-change="handleCateChange"-->
|
||||
<!-->-->
|
||||
<!--<template slot="contextMenu" v-if="!isComponent">-->
|
||||
<!--<DropdownItem @click.native="handleContextMenuEdit"-->
|
||||
<!-->编辑-->
|
||||
<!--</DropdownItem-->
|
||||
<!-->-->
|
||||
<!--<DropdownItem-->
|
||||
<!--style="color: #ed4014"-->
|
||||
<!--@click.native="handleContextMenuDelete"-->
|
||||
<!-->删除-->
|
||||
<!--</DropdownItem-->
|
||||
<!-->-->
|
||||
<!--</template>-->
|
||||
<!--</Tree>-->
|
||||
<!--<Alert v-if="!isComponent">鼠标右键编辑/删除分组</Alert>-->
|
||||
<!--<div class="group-row flex" v-if="!isComponent">-->
|
||||
<!--<Button @click="handleClickAddGroup">添加分组</Button>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
|
||||
<!--<Table-->
|
||||
<!--ref="table"-->
|
||||
<!--:columns="isComponent ? viewColumns : columns"-->
|
||||
<!--:data="data"-->
|
||||
<!--:loading="loading"-->
|
||||
<!--border-->
|
||||
<!--class="table"-->
|
||||
<!--sortable="custom"-->
|
||||
<!--@on-sort-change="changeSort"-->
|
||||
<!--@on-selection-change="changeSelect"-->
|
||||
<!-->-->
|
||||
<!--<template slot="fileKey" slot-scope="{ row }">-->
|
||||
<!--<a @click="copyFileUrl(row)">{{ row.fileKey }}</a>-->
|
||||
<!--</template>-->
|
||||
<!--</Table>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
|
||||
<!--<div v-show="showType === 'thumb'">-->
|
||||
<!--<div class="oss-wrapper">-->
|
||||
<!--<Card v-for="(item, i) in data" :key="i" class="oss-card">-->
|
||||
<!--<div class="content">-->
|
||||
<!--<img-->
|
||||
<!--v-if="item.fileType.indexOf('image') >= 0"-->
|
||||
<!--:src="item.url"-->
|
||||
<!--class="img"-->
|
||||
<!--@click="showPic(item)"-->
|
||||
<!--/>-->
|
||||
<!--<div-->
|
||||
<!--v-else-if="item.fileType.indexOf('video') >= 0"-->
|
||||
<!--class="video"-->
|
||||
<!--@click="showVideo(item)"-->
|
||||
<!-->-->
|
||||
<!--<!– 文件小于5MB显示video –>-->
|
||||
<!--<video v-if="item.fileSize < 1024 * 1024 * 5" class="cover">-->
|
||||
<!--<source :src="item.url"/>-->
|
||||
<!--</video>-->
|
||||
<!--<img class="play" src="@/assets/play.png"/>-->
|
||||
<!--</div>-->
|
||||
<!--<div v-else class="other">-->
|
||||
<!--<div class="name">{{ item.name }}</div>-->
|
||||
<!--<div class="key">{{ item.fileKey }}</div>-->
|
||||
<!--<div class="info">-->
|
||||
<!--文件类型:{{ item.fileType }} 文件大小:{{-->
|
||||
<!--((item.fileSize * 1.0) / (1024 * 1024)).toFixed(2)-->
|
||||
<!--}}-->
|
||||
<!--MB 创建时间:{{ item.createTime }}-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
<!--<div class="actions">-->
|
||||
<!--<div class="btn">-->
|
||||
<!--<Tooltip content="下载" placement="top">-->
|
||||
<!--<Icon-->
|
||||
<!--size="16"-->
|
||||
<!--type="md-download"-->
|
||||
<!--@click="download(item)"-->
|
||||
<!--/>-->
|
||||
<!--</Tooltip>-->
|
||||
<!--</div>-->
|
||||
<!--<div class="btn">-->
|
||||
<!--<Tooltip content="重命名" placement="top">-->
|
||||
<!--<Icon size="16" type="md-create" @click="rename(item)"/>-->
|
||||
<!--</Tooltip>-->
|
||||
<!--</div>-->
|
||||
<!--<div class="btn-no">-->
|
||||
<!--<Tooltip content="删除" placement="top">-->
|
||||
<!--<Icon size="16" type="md-trash" @click="remove(item)"/>-->
|
||||
<!--</Tooltip>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
<!--</Card>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
<!--<Row class="mt_10" justify="end" type="flex">-->
|
||||
<!--<Page-->
|
||||
<!--:current="searchForm.pageNumber"-->
|
||||
<!--:page-size="searchForm.pageSize"-->
|
||||
<!--:page-size-opts="pageSizeOpts"-->
|
||||
<!--:total="total"-->
|
||||
<!--show-elevator-->
|
||||
<!--show-sizer-->
|
||||
<!--show-total-->
|
||||
<!--size="small"-->
|
||||
<!--@on-change="changePage"-->
|
||||
<!--@on-page-size-change="changePageSize"-->
|
||||
<!--></Page>-->
|
||||
<!--</Row>-->
|
||||
</el-card>
|
||||
</el-row>
|
||||
<el-dialog
|
||||
@@ -488,7 +325,7 @@ import {
|
||||
import DPlayer from "dplayer";
|
||||
import {commonUrl} from "@/libs/axios";
|
||||
|
||||
const config = require("@/config/index");
|
||||
import config from "@/config/index";
|
||||
|
||||
let dp;
|
||||
export default {
|
||||
@@ -553,14 +390,14 @@ export default {
|
||||
picTitle: "", // 图片title
|
||||
videoTitle: "", // 视频title
|
||||
modalTitle: "", // 添加或编辑标题
|
||||
activeRoleTab: "MANAGER",
|
||||
activeRoleTab: "STORE",
|
||||
searchForm: {
|
||||
// 搜索框对应data对象
|
||||
name: "",
|
||||
fileKey: "",
|
||||
fileType: "",
|
||||
fileCategory: "",
|
||||
userEnums: "MANAGER",
|
||||
userEnums: "STORE",
|
||||
pageNumber: 1, // 当前页数
|
||||
pageSize: 20, // 页面大小
|
||||
sort: "createTime", // 默认排序字段
|
||||
@@ -585,342 +422,6 @@ export default {
|
||||
selectList: [], // 多选数据
|
||||
selectCount: 0, // 多选计数
|
||||
totalSize: "", // 文件大小统计
|
||||
columns: [
|
||||
// 表头
|
||||
{
|
||||
type: "selection",
|
||||
width: 60,
|
||||
align: "center",
|
||||
},
|
||||
{
|
||||
title: "缩略图(点击预览)",
|
||||
key: "url",
|
||||
width: 300,
|
||||
align: "center",
|
||||
render: (h, params) => {
|
||||
if (this.isImageFile(params.row)) {
|
||||
return h("img", {
|
||||
attrs: {
|
||||
src: params.row.url || "",
|
||||
alt: "加载图片失败",
|
||||
},
|
||||
style: {
|
||||
cursor: "pointer",
|
||||
width: "80px",
|
||||
height: "60px",
|
||||
margin: "10px 0",
|
||||
"object-fit": "contain",
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
this.showPic(params.row);
|
||||
},
|
||||
},
|
||||
});
|
||||
} else if (this.isVideoFile(params.row)) {
|
||||
// 如果视频文件大小超过5MB不予加载video
|
||||
if (params.row.fileSize < 1024 * 1024 * 5) {
|
||||
return h(
|
||||
"video",
|
||||
{
|
||||
style: {
|
||||
cursor: "pointer",
|
||||
width: "80px",
|
||||
height: "60px",
|
||||
margin: "10px 0",
|
||||
"object-fit": "contain",
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
this.showVideo(params.row);
|
||||
},
|
||||
},
|
||||
},
|
||||
[
|
||||
h("source", {
|
||||
attrs: {
|
||||
src: params.row.url,
|
||||
},
|
||||
}),
|
||||
]
|
||||
);
|
||||
} else {
|
||||
return h("img", {
|
||||
attrs: {
|
||||
src: require("@/assets/play.png"),
|
||||
},
|
||||
style: {
|
||||
cursor: "pointer",
|
||||
width: "80px",
|
||||
height: "60px",
|
||||
margin: "10px 0",
|
||||
"object-fit": "contain",
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
this.showVideo(params.row);
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
} else {
|
||||
return h("span", "非多媒体类型");
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "文件类型",
|
||||
key: "fileType",
|
||||
width: 115,
|
||||
className: this.selectImage == true ? "none" : "",
|
||||
},
|
||||
{
|
||||
title: "文件大小",
|
||||
key: "fileSize",
|
||||
width: 115,
|
||||
sortable: true,
|
||||
className: this.selectImage == true ? "none" : "",
|
||||
render: (h, params) => {
|
||||
let m =
|
||||
((params.row.fileSize * 1.0) / (1024 * 1024)).toFixed(2) + " MB";
|
||||
return h("span", m);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "上传者",
|
||||
key: "createBy",
|
||||
width: 200,
|
||||
render: (h, params) => {
|
||||
let m = "";
|
||||
if (params.row.userEnums == "MANAGER") {
|
||||
m = "[管理员]";
|
||||
} else if (params.row.userEnums == "STORE") {
|
||||
m = "[商家]";
|
||||
} else if (params.row.userEnums == "CUSTOMER") {
|
||||
m = "[客服]";
|
||||
} else {
|
||||
m = "[用户]";
|
||||
}
|
||||
m += params.row.createBy;
|
||||
return h("span", m);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
key: "action",
|
||||
align: "center",
|
||||
fixed: "right",
|
||||
// width: 300,
|
||||
render: (h, params) => {
|
||||
return h("div", [
|
||||
h(
|
||||
"a",
|
||||
{
|
||||
style: {
|
||||
color: "#2d8cf0",
|
||||
cursor: "pointer",
|
||||
textDecoration: "none",
|
||||
marginRight: "5px",
|
||||
display: this.selectImage === true ? "inline-block" : "none",
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
this.selectedParams(params.row);
|
||||
},
|
||||
},
|
||||
},
|
||||
"选择"
|
||||
),
|
||||
h(
|
||||
"span",
|
||||
{
|
||||
style: {
|
||||
margin: "0 8px",
|
||||
color: "#dcdee2",
|
||||
display: this.selectImage === true ? "inline-block" : "none",
|
||||
},
|
||||
},
|
||||
"|"
|
||||
),
|
||||
h(
|
||||
"a",
|
||||
{
|
||||
style: {
|
||||
color: "#2d8cf0",
|
||||
cursor: "pointer",
|
||||
textDecoration: "none",
|
||||
marginRight: "5px",
|
||||
display: this.selectImage == true ? "none" : "inline-block",
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
this.download(params.row);
|
||||
},
|
||||
},
|
||||
},
|
||||
"下载"
|
||||
),
|
||||
h(
|
||||
"span",
|
||||
{
|
||||
style: {
|
||||
margin: "0 8px",
|
||||
color: "#dcdee2",
|
||||
display: this.selectImage == true ? "none" : "inline-block",
|
||||
},
|
||||
},
|
||||
"|"
|
||||
),
|
||||
h(
|
||||
"a",
|
||||
{
|
||||
style: {
|
||||
color: "#2d8cf0",
|
||||
cursor: "pointer",
|
||||
textDecoration: "none",
|
||||
display: this.selectImage == true ? "none" : "inline-block",
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
this.remove(params.row);
|
||||
},
|
||||
},
|
||||
},
|
||||
"删除"
|
||||
),
|
||||
]);
|
||||
},
|
||||
},
|
||||
],
|
||||
viewColumns: [
|
||||
{
|
||||
title: "缩略图(点击预览)",
|
||||
key: "url",
|
||||
// width: 150,
|
||||
align: "center",
|
||||
render: (h, params) => {
|
||||
if (this.isImageFile(params.row)) {
|
||||
return h("img", {
|
||||
attrs: {
|
||||
src: params.row.url || "",
|
||||
alt: "加载图片失败",
|
||||
},
|
||||
style: {
|
||||
cursor: "pointer",
|
||||
width: "80px",
|
||||
height: "60px",
|
||||
margin: "10px 0",
|
||||
"object-fit": "contain",
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
this.showPic(params.row);
|
||||
},
|
||||
},
|
||||
});
|
||||
} else if (this.isVideoFile(params.row)) {
|
||||
// 如果视频文件大小超过5MB不予加载video
|
||||
if (params.row.fileSize < 1024 * 1024 * 5) {
|
||||
return h(
|
||||
"video",
|
||||
{
|
||||
style: {
|
||||
cursor: "pointer",
|
||||
width: "80px",
|
||||
height: "60px",
|
||||
margin: "10px 0",
|
||||
"object-fit": "contain",
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
this.showVideo(params.row);
|
||||
},
|
||||
},
|
||||
},
|
||||
[
|
||||
h("source", {
|
||||
attrs: {
|
||||
src: params.row.url,
|
||||
},
|
||||
}),
|
||||
]
|
||||
);
|
||||
} else {
|
||||
return h("img", {
|
||||
attrs: {
|
||||
src: require("@/assets/play.png"),
|
||||
},
|
||||
style: {
|
||||
cursor: "pointer",
|
||||
width: "80px",
|
||||
height: "60px",
|
||||
margin: "10px 0",
|
||||
"object-fit": "contain",
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
this.showVideo(params.row);
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
} else {
|
||||
return h("span", "非多媒体类型");
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "上传者",
|
||||
key: "createBy",
|
||||
width: 120,
|
||||
sortable: true,
|
||||
render: (h, params) => {
|
||||
let m = "";
|
||||
if (params.row.userEnums == "MANAGER") {
|
||||
m = "[管理员]";
|
||||
} else if (params.row.userEnums == "STORE") {
|
||||
m = "[商家]";
|
||||
} else if (params.row.userEnums == "CUSTOMER") {
|
||||
m = "[客服]";
|
||||
} else {
|
||||
m = "[用户]";
|
||||
}
|
||||
m += params.row.createBy;
|
||||
return h("span", m);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
key: "action",
|
||||
align: "center",
|
||||
fixed: "right",
|
||||
width: 300,
|
||||
render: (h, params) => {
|
||||
return h("div", [
|
||||
h(
|
||||
"Button",
|
||||
{
|
||||
props: {
|
||||
type: "default",
|
||||
size: "small",
|
||||
},
|
||||
style: {
|
||||
marginRight: "5px",
|
||||
display:
|
||||
this.selectImage === true ? "inline-block" : "none",
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
this.selectedParams(params.row);
|
||||
},
|
||||
},
|
||||
},
|
||||
"选择"
|
||||
)
|
||||
]);
|
||||
},
|
||||
},
|
||||
],
|
||||
data: [], // 表单数据
|
||||
total: 0, // 表单数据总数
|
||||
pageSizeOpts: [5, 10, 20], // 页码展示项
|
||||
@@ -933,41 +434,6 @@ export default {
|
||||
groupLoading: false,
|
||||
// 图片列表
|
||||
selectedOss: [],
|
||||
myData: [
|
||||
{
|
||||
title: 'parent 1',
|
||||
expand: true,
|
||||
render: (h, {root, node, data}) => {
|
||||
return h('span', {style: {display: 'inline-block', width: '100%'}}, [
|
||||
h('span', [h("Icon", {type: 'ios-folder-outline', style: {marginRight: '8px'}}), h('span', data.title)]),
|
||||
h('span', {style: {display: 'inline-block', float: 'right', marginRight: '32px'}},
|
||||
[h("Button", {
|
||||
...this.buttonProps,
|
||||
icon: 'ios-add',
|
||||
type: 'primary',
|
||||
style: {width: '64px'},
|
||||
onClick: () => {
|
||||
this.append(data)
|
||||
}
|
||||
})
|
||||
])
|
||||
]);
|
||||
},
|
||||
children: [
|
||||
{
|
||||
title: 'child 1-1',
|
||||
expand: true,
|
||||
children: [{title: 'leaf 1-1-1', expand: true}, {title: 'leaf 1-1-2', expand: true}]
|
||||
},
|
||||
{
|
||||
title: 'child 1-2',
|
||||
expand: true,
|
||||
children: [{title: 'leaf 1-2-1', expand: true}, {title: 'leaf 1-2-1', expand: true}]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
buttonProps: {type: 'default', size: 'small',},
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
@@ -999,7 +465,7 @@ export default {
|
||||
return this.activeRoleTab === "MANAGER";
|
||||
},
|
||||
canUploadImages() {
|
||||
return this.activeRoleTab === "MANAGER";
|
||||
return this.activeRoleTab === "MANAGER" || this.activeRoleTab === "STORE";
|
||||
},
|
||||
uploadData() {
|
||||
return {
|
||||
@@ -1125,61 +591,8 @@ export default {
|
||||
this.searchForm.pageNumber = value;
|
||||
this.getDataList();
|
||||
},
|
||||
// 自定义tree节点显示内容和交互
|
||||
renderContent(h, {root, node, data}) {
|
||||
if (data.value === '0') {
|
||||
return h('span', {style: {display: 'inline-block', width: '100%'}},
|
||||
[
|
||||
h('span', [h("Icon", {type: 'ios-paper-outline', style: {marginRight: '8px'}}), h('span', data.title)]),
|
||||
h('span', {style: {display: 'inline-block', float: 'right', marginRight: '10px'}}, [])
|
||||
]
|
||||
);
|
||||
} else {
|
||||
return h('span', {style: {display: 'inline-block', width: '100%'}},
|
||||
[
|
||||
h('span', [h("Icon", {type: 'ios-paper-outline', style: {marginRight: '8px'}}), h('span', data.title)]),
|
||||
h('span', {style: {display: 'inline-block', float: 'right', marginRight: '10px'}},
|
||||
[
|
||||
h("Dropdown", {style: {marginLeft: "4px"}},
|
||||
[
|
||||
h("Icon", {
|
||||
props: {type: 'ios-more', size: "20",},
|
||||
style: {display: 'inline-block'},
|
||||
on: {
|
||||
click: () => {
|
||||
}
|
||||
}
|
||||
}),
|
||||
h("DropdownMenu", {
|
||||
slot: "list"
|
||||
}, [
|
||||
h("DropdownItem", {
|
||||
nativeOn: {
|
||||
click: () => {
|
||||
this.handleContextMenuEdit(root, node, data)
|
||||
}
|
||||
}
|
||||
}, "编辑"),
|
||||
h("DropdownItem", {
|
||||
nativeOn: {
|
||||
click: () => {
|
||||
this.handleContextMenuDelete()
|
||||
}
|
||||
}
|
||||
}, "删除"),
|
||||
])
|
||||
]),
|
||||
])
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
|
||||
handleContextMenu(val) {
|
||||
console.log('handleContextMenu', val);
|
||||
this.selectedGroupData = val;
|
||||
this.selectedGroupData = val;
|
||||
},
|
||||
// 编辑分组
|
||||
handleContextMenuEdit(root, node, data) {
|
||||
|
||||
Reference in New Issue
Block a user