mirror of
https://gitee.com/zongzhige/shopxo-diy.git
synced 2026-06-05 18:25:52 +08:00
Merge branch 'dev-yxl' of gitee.com:zongzhige/shopxo-diy into dev
This commit is contained in:
@ -1,20 +1,20 @@
|
||||
import { get_type } from '@/utils/common';
|
||||
import request from '@/utils/request';
|
||||
import index_request from '@/utils/index-request';
|
||||
import { isEmpty } from 'lodash';
|
||||
|
||||
class CommonAPI {
|
||||
/** 链接初始化接口 */
|
||||
static getInit() {
|
||||
const new_type = get_type();
|
||||
if (isEmpty(new_type)) {
|
||||
const location_host = document.location.host;
|
||||
if (isEmpty(new_type) || location_host.indexOf('#/tabbar') !== -1) {
|
||||
return request({
|
||||
url: `diyapi/init`,
|
||||
method: 'post',
|
||||
});
|
||||
} else {
|
||||
return index_request({
|
||||
url: `?s=plugins/index/pluginsname/${ new_type }/pluginscontrol/diyapi/pluginsaction/init.html`,
|
||||
return request({
|
||||
url: `plugins/index/pluginsname/${ new_type }/pluginscontrol/diyapi/pluginsaction/init.html`,
|
||||
method: 'post',
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,22 +0,0 @@
|
||||
import request from '@/utils/request';
|
||||
|
||||
class ShopAPI {
|
||||
/** 获取tabbar列表 */
|
||||
static getTabbar(data: any) {
|
||||
return request({
|
||||
url: `diyapi/apptabbardata`,
|
||||
method: 'post',
|
||||
data,
|
||||
});
|
||||
}
|
||||
/** 保存tabbar */
|
||||
static saveTabbar(data: any) {
|
||||
return request({
|
||||
url: `diyapi/apptabbarsave`,
|
||||
method: 'post',
|
||||
data,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default ShopAPI;
|
||||
@ -46,6 +46,7 @@ export const commonStore = defineStore('common', () => {
|
||||
diy_upload_url: '' as string, //diy导入
|
||||
attachment_category_operate: {} as any, // 附件分类权限
|
||||
attachment_operate: {} as any, // 附件权限
|
||||
diy_config_operate: {} as any, //---- diy配置权限
|
||||
} as any, // 基础数据配置参数
|
||||
preview_url: '',
|
||||
});
|
||||
|
||||
@ -15,46 +15,89 @@ export const font_weight = [
|
||||
{ name: '正常', value: '400' },
|
||||
];
|
||||
|
||||
/**
|
||||
* 从URL中提取指定前缀后的ID值
|
||||
* @param prefix 前缀字符串
|
||||
* @returns 提取的ID值
|
||||
*/
|
||||
const extractIdFromUrl = (prefix: string): string => {
|
||||
const url = document.location.href;
|
||||
const startIndex = url.indexOf(prefix);
|
||||
if (startIndex === -1) return '';
|
||||
|
||||
// 计算起始位置(包含前缀)
|
||||
const start = startIndex + prefix.length;
|
||||
let result = url.substring(start);
|
||||
|
||||
// 移除.html后缀
|
||||
const dotIndex = result.indexOf('.');
|
||||
if (dotIndex !== -1) {
|
||||
result = result.substring(0, dotIndex);
|
||||
}
|
||||
|
||||
// 移除查询参数
|
||||
const andIndex = result.indexOf('&');
|
||||
if (andIndex !== -1) {
|
||||
result = result.substring(0, andIndex);
|
||||
}
|
||||
|
||||
// 移除路径分隔符后的部分
|
||||
const slashIndex = result.indexOf('/');
|
||||
if (slashIndex !== -1) {
|
||||
result = result.substring(0, slashIndex);
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
// 截取document.location.search字符串内id/后面的所有字段
|
||||
export const get_id = () => {
|
||||
let new_id = '';
|
||||
// 去除origin的数据
|
||||
// 先尝试匹配 id/ 模式
|
||||
const url = document.location.href;
|
||||
if (url.indexOf('id/') != -1) {
|
||||
new_id = url.substring(url.indexOf('id/') + 3);
|
||||
// 去除字符串的.html
|
||||
let html_index = new_id.indexOf('.html');
|
||||
if (html_index != -1) {
|
||||
new_id = new_id.substring(0, html_index);
|
||||
const idIndex = url.indexOf('id/');
|
||||
if (idIndex !== -1) {
|
||||
const result = url.substring(idIndex + 3);
|
||||
const htmlIndex = result.indexOf('.html');
|
||||
if (htmlIndex !== -1) {
|
||||
return result.substring(0, htmlIndex);
|
||||
}
|
||||
return new_id;
|
||||
} else if (url.indexOf('-saveinfo') != -1) {
|
||||
new_id = url.substring(url.indexOf('-saveinfo-') + 10);
|
||||
// 去除字符串的.html
|
||||
const dot_data = new_id.split('.')[0];
|
||||
if (dot_data != '') {
|
||||
new_id = dot_data.split('/')[0];
|
||||
}
|
||||
return new_id;
|
||||
} else {
|
||||
return new_id;
|
||||
return result.split('.')[0].split('/')[0];
|
||||
}
|
||||
|
||||
// 尝试匹配-saveinfo-模式
|
||||
const saveinfoResult = extractIdFromUrl('-saveinfo-');
|
||||
if (saveinfoResult) return saveinfoResult;
|
||||
|
||||
// 尝试匹配-forminputinfo-模式
|
||||
return extractIdFromUrl('-diyinfo-');
|
||||
};
|
||||
|
||||
// 获取当前业务类型
|
||||
export const get_type = () => {
|
||||
let new_type = '';
|
||||
return data_handle('type/', '');
|
||||
}
|
||||
// 获取类型
|
||||
export const get_business = () => {
|
||||
return data_handle('business/', '');
|
||||
}
|
||||
// 数据处理
|
||||
export const data_handle = (val: string, default_val: string): string => {
|
||||
let new_data = default_val;
|
||||
// 去除origin的数据
|
||||
const url = document.location.href;
|
||||
if (url.indexOf('type/') != -1) {
|
||||
new_type = url.substring(url.indexOf('type/') + 5);
|
||||
if (url.indexOf(val) != -1) {
|
||||
new_data = url.substring(url.indexOf(val) + val.length);
|
||||
// 去除字符串的.html
|
||||
const dot_data = new_type.split('.')[0];
|
||||
if (dot_data != '') {
|
||||
new_type = dot_data.split('/')[0];
|
||||
// 去除并且数据
|
||||
if (new_data.indexOf('&') != -1) {
|
||||
new_data = new_data.split('&')[0];
|
||||
}
|
||||
return new_type;
|
||||
const dot_data = new_data.split('.')[0];
|
||||
if (dot_data != '') {
|
||||
new_data = dot_data.split('/')[0];
|
||||
}
|
||||
return new_data;
|
||||
} else {
|
||||
return new_type;
|
||||
return new_data;
|
||||
}
|
||||
}
|
||||
@ -1,118 +0,0 @@
|
||||
import axios, { InternalAxiosRequestConfig, AxiosResponse } from 'axios';
|
||||
import { ElMessage, ElMessageBox, type MessageHandler } from 'element-plus';
|
||||
import { get_cookie } from './index';
|
||||
import { get_id, get_type } from './common';
|
||||
|
||||
// 提示拦截
|
||||
|
||||
let messageInstance: MessageHandler;
|
||||
const message_error = (info: string) => {
|
||||
if (messageInstance) {
|
||||
messageInstance.close();
|
||||
}
|
||||
messageInstance = ElMessage.error({
|
||||
type: 'error',
|
||||
message: info,
|
||||
duration: 30000,
|
||||
showClose: true,
|
||||
});
|
||||
};
|
||||
|
||||
// 创建一个状态变量来跟踪是否已经弹出了退出登录的弹窗
|
||||
const isLogoutModalShown = ref(true);
|
||||
|
||||
// 用于存储每个请求的CancelToken
|
||||
const pendingRequests = new Map();
|
||||
// 不需要认证的接口
|
||||
const release_url = ['attachmentapi/upload'];
|
||||
// 创建 axios 实例
|
||||
const index = window.location.href.lastIndexOf('?s=');
|
||||
const new_data = window.location.href.substring(0, index);
|
||||
const new_index = new_data.lastIndexOf('/');
|
||||
const pro_url = window.location.href.substring(0, new_index);
|
||||
const service = axios.create({
|
||||
baseURL: import.meta.env.VITE_APP_BASE_API_INDEX_PHP == '/dev-index' ? import.meta.env.VITE_APP_BASE_API_INDEX_PHP : pro_url + '/index.php',
|
||||
timeout: 60000,
|
||||
headers: { 'Content-Type': 'application/json;charset=utf-8', 'X-Requested-With': 'XMLHttpRequest' },
|
||||
});
|
||||
/** @ts-ignore */
|
||||
// 请求拦截器
|
||||
service.interceptors.request.use(
|
||||
async (config: InternalAxiosRequestConfig) => {
|
||||
// 如果是本地则使用静态tonken如果是线上则使用cookie的token
|
||||
const symbol = config.url?.includes('?') ? '&' : '?';
|
||||
if (import.meta.env.VITE_APP_BASE_API_INDEX_PHP == '/dev-index') {
|
||||
let temp_data = await import(import.meta.env.VITE_APP_BASE_API_INDEX_PHP == '/dev-index' ? '../../temp.d' : '../../temp_pro.d');
|
||||
config.url = config.url + symbol + 'token=' + temp_data.default.temp_token;
|
||||
} else {
|
||||
// 如果是shop认为是多商户插件使用user_info的cookie
|
||||
const cookie = get_type() == 'shop' ? get_cookie('user_info') : get_cookie('admin_info');
|
||||
if (cookie && cookie !== null && cookie !== 'null') {
|
||||
config.url = config.url + '&token=' + (JSON.parse(cookie) !== 'null' ? JSON.parse(cookie)?.token : '');
|
||||
}
|
||||
}
|
||||
// 添加diy_id和diy_type参数
|
||||
config.url = `${config.url}&diy_id=${ get_id() }&diy_type=${ get_type() }`;
|
||||
// 判断是否是包含不需要认证的接口
|
||||
const release_list = release_url.filter(item => config.url?.includes(item));
|
||||
if (release_list.length === 0) {
|
||||
// 检查是否有相同请求正在进行,如果有则取消, 防止重复请求导致返回数据有误
|
||||
if (pendingRequests.has(config.url)) {
|
||||
const cancelToken = pendingRequests.get(config.url);
|
||||
cancelToken.cancel('canceled');
|
||||
pendingRequests.delete(config.url);
|
||||
}
|
||||
// 创建一个新的 CancelToken
|
||||
const source = axios.CancelToken.source();
|
||||
config.cancelToken = source.token;
|
||||
pendingRequests.set(config.url, source);
|
||||
}
|
||||
return config;
|
||||
},
|
||||
(error: any) => {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
// 响应拦截器
|
||||
service.interceptors.response.use(
|
||||
(response: AxiosResponse) => {
|
||||
// 请求完成后,从pendingRequests中移除
|
||||
pendingRequests.delete(response.config.url);
|
||||
|
||||
const { code, msg, message, data } = response.data;
|
||||
if (code == 0) {
|
||||
return response.data;
|
||||
} else if (code == -400) {
|
||||
if (isLogoutModalShown.value) {
|
||||
isLogoutModalShown.value = false;
|
||||
ElMessageBox.alert(msg, '温馨提示', {
|
||||
confirmButtonText: '确定',
|
||||
showClose: false,
|
||||
type: 'warning',
|
||||
}).then(() => {
|
||||
localStorage.clear(); // @vueuse/core 自动导入
|
||||
window.location.href = data.logout;
|
||||
});
|
||||
}
|
||||
} else {
|
||||
message_error(msg || message || '系统出错');
|
||||
return Promise.reject('Error');
|
||||
// return Promise.reject(new Error(msg || 'Error'));
|
||||
}
|
||||
},
|
||||
(error: any) => {
|
||||
if (error.response && error.response.data) {
|
||||
const { msg, message } = error.response.data;
|
||||
message_error(msg || message || '系统出错');
|
||||
} else if (error.message == 'canceled') {
|
||||
console.log('请求已取消');
|
||||
} else {
|
||||
message_error(error.message);
|
||||
}
|
||||
|
||||
return Promise.reject(error.message);
|
||||
}
|
||||
);
|
||||
|
||||
// 导出 axios 实例
|
||||
export default service;
|
||||
@ -24,8 +24,11 @@ const pendingRequests = new Map();
|
||||
// 不需要认证的接口
|
||||
const release_url = ['attachmentapi/upload'];
|
||||
// 创建 axios 实例
|
||||
const index = window.location.href.lastIndexOf('?s=');
|
||||
const pro_url = window.location.href.substring(0, index);
|
||||
const index = window.location.href.lastIndexOf('.php');
|
||||
let pro_url = window.location.origin;
|
||||
if (index !== -1) {
|
||||
pro_url = window.location.href.substring(0, index) + '.php';
|
||||
}
|
||||
const service = axios.create({
|
||||
baseURL: import.meta.env.VITE_APP_BASE_API == '/dev-admin' ? import.meta.env.VITE_APP_BASE_API : pro_url + '?s=',
|
||||
timeout: 60000,
|
||||
|
||||
@ -5,19 +5,19 @@
|
||||
<!-- <icon name="arrow-left" color="f">返回</icon> -->
|
||||
<div class="flex-row align-c">
|
||||
<div class="name">
|
||||
<div class="flex-row align-c gap-10 c-pointer" @click="dialog_visible = true">
|
||||
<image-empty :src="modelValue.logo" class="round img" error-img-style="width: 2.2rem;height: 2.2rem;" />
|
||||
<div :class="[{'c-pointer': common_store_config?.diy_config_operate?.is_base_data == 1}, 'flex-row align-c gap-10']" @click="common_store_config?.diy_config_operate?.is_base_data == 1 ? dialog_visible = true : ''">
|
||||
<image-empty v-if="modelValue.logo" :src="modelValue.logo" class="round img" error-img-style="width: 2.2rem;height: 2.2rem;" />
|
||||
<div>{{ modelValue.name }}</div>
|
||||
<icon name="edit" color="#7DBEFF"></icon>
|
||||
<icon v-if="common_store_config?.diy_config_operate?.is_base_data == 1" name="edit" color="#7DBEFF"></icon>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="nav-right">
|
||||
<el-button class="btn-plain" @click="upload_manage">上传管理</el-button>
|
||||
<el-button class="btn-plain" :class="saveDisabled ? 'disabled' : ''" :disabled="saveDisabled" @click="preview_event">预览</el-button>
|
||||
<el-button class="btn-plain" :class="saveDisabled ? 'disabled' : ''" :disabled="saveDisabled" @click="save_event">仅保存</el-button>
|
||||
<el-button class="btn-white" :class="saveDisabled ? 'disabled' : ''" :disabled="saveDisabled" @click="save_close_event">保存关闭</el-button>
|
||||
<el-button v-if="common_store_config?.diy_config_operate?.is_upload_admin == 1" class="btn-plain" @click="upload_manage">上传管理</el-button>
|
||||
<el-button v-if="common_store_config.preview_url !== ''" class="btn-plain" :class="saveDisabled ? 'disabled' : ''" :disabled="saveDisabled" @click="preview_event">预览</el-button>
|
||||
<el-button v-if="common_store_config.diy_config_operate.is_save_button == 1" :class="[common_store_config.diy_config_operate.is_save_close_button == 1 ? 'btn-plain' : 'btn-white', saveDisabled ? 'disabled' : '']" :disabled="saveDisabled" @click="save_event">保存</el-button>
|
||||
<el-button v-if="common_store_config.diy_config_operate.is_save_close_button == 1" class="btn-white" :class="saveDisabled ? 'disabled' : ''" :disabled="saveDisabled" @click="save_close_event">保存关闭</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-dialog v-model="dialog_visible" class="radius-lg" width="650" draggable :close-on-click-modal="false" append-to-body>
|
||||
@ -53,6 +53,8 @@
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { FormInstance, FormRules } from 'element-plus';
|
||||
import { commonStore } from '@/store';
|
||||
const common_store = commonStore();
|
||||
const props = defineProps({
|
||||
saveDisabled: {
|
||||
type: Boolean,
|
||||
@ -60,6 +62,8 @@ const props = defineProps({
|
||||
},
|
||||
});
|
||||
const modelValue = defineModel({ type: Object, default: {} });
|
||||
// 公共配置项
|
||||
const common_store_config = computed(() => common_store.common.config);
|
||||
// #region 变量 --------------------start
|
||||
const is_custom_dialog = ref(false);
|
||||
const dialog_visible = ref(false);
|
||||
|
||||
@ -523,7 +523,9 @@ const save_formmat_form_data = (data: diy_data_item, close: boolean = false, is_
|
||||
preview_dialog.value = true;
|
||||
diy_id.value = String(res.data);
|
||||
}
|
||||
form.value.id = String(res.data);
|
||||
if (res.data != null && res.data != '') {
|
||||
form.value.id = String(res.data);
|
||||
}
|
||||
// 本地的时候会补id参数
|
||||
if (import.meta.env.VITE_APP_BASE_API == '/dev-admin') {
|
||||
history.pushState({}, '', '?s=diy/saveinfo/id/' + res.data + '.html');
|
||||
|
||||
@ -24,6 +24,7 @@ import defaultSettings from './components/main/index';
|
||||
import { cloneDeep } from 'lodash';
|
||||
import CommonAPI from '@/api/common';
|
||||
import { commonStore } from '@/store';
|
||||
import { get_business } from '@/utils/common';
|
||||
const common_store = commonStore();
|
||||
const temp_form = ref(defaultSettings.footer_nav);
|
||||
const form = ref<any>({});
|
||||
@ -37,7 +38,7 @@ onMounted(() => {
|
||||
});
|
||||
const is_empty = ref(false);
|
||||
const init = () => {
|
||||
CommonAPI.getDynamicApi(common_store.common.config.app_tabbar_data_url, { type: get_type() })
|
||||
CommonAPI.getDynamicApi(common_store.common.config.app_tabbar_data_url, { business: get_business() })
|
||||
.then((res: any) => {
|
||||
if (res.data) {
|
||||
let data = res.data;
|
||||
@ -77,8 +78,8 @@ const save_disabled = ref(false);
|
||||
const save_event = () => {
|
||||
const clone_form = cloneDeep(form.value);
|
||||
const new_data = {
|
||||
type: get_type(),
|
||||
config: clone_form,
|
||||
business: get_business(),
|
||||
};
|
||||
save_disabled.value = true;
|
||||
// 数据改造
|
||||
@ -93,18 +94,7 @@ const save_event = () => {
|
||||
save_disabled.value = false;
|
||||
});
|
||||
};
|
||||
const get_type = () => {
|
||||
let new_type = 'home';
|
||||
if (document.location.search.indexOf('/type/') != -1) {
|
||||
new_type = document.location.search.substring(document.location.search.indexOf('/type/') + 6);
|
||||
// 进行3次切割选择参数内容
|
||||
const result1 = splitAndGetFirst(new_type, '/');
|
||||
const result2 = splitAndGetFirst(result1, '&');
|
||||
return splitAndGetFirst(result2, '#');
|
||||
} else {
|
||||
return new_type;
|
||||
}
|
||||
};
|
||||
|
||||
function splitAndGetFirst(str: string, separator: string): string {
|
||||
const data = str.split(separator);
|
||||
if (data.length > 1) {
|
||||
|
||||
Reference in New Issue
Block a user