全栈小学生 bf224633d5 update
2024-08-17 09:35:06 +08:00

476 lines
18 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { defineStore } from 'pinia'
import { t } from '@/lang'
import { toRaw } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { cloneDeep } from 'lodash-es'
const useDiyStore = defineStore('diy', {
state: () => {
return {
id: 0,
load: false, // 加载状态
currentIndex: -99, // 当前正在编辑的组件下标
currentComponent: 'edit-page', // 当前正在编辑的组件名称
pageMode: 'diy',
editTab: 'content',// 编辑页面
pageTitle: '', // 页面名称(用于后台展示)
name: '', // 页面标识
type: '', // 页面模板
typeName: '', // 页面模板名称
templateName: '', // 页面模板标识
isDefault: 0, // 是否默认页面
predefineColors: [
'#F4391c',
'#ff4500',
'#ff8c00',
'#FFD009',
'#ffd700',
'#19C650',
'#90ee90',
'#00ced1',
'#1e90ff',
'#c71585',
'#FF407E',
'#CFAF70',
'#A253FF',
'rgba(255, 69, 0, 0.68)',
'rgb(255, 120, 0)',
'hsl(181, 100%, 37%)',
'hsla(209, 100%, 56%, 0.73)',
'#c7158577'
],
components: <any>[], // 组件集合
position: ['top_fixed', 'right_fixed', 'bottom_fixed', 'left_fixed', 'fixed'],
global: {
title: "页面", // 页面标题(用于前台展示)
pageStartBgColor: "", // 页面背景颜色(开始)
pageEndBgColor: "", // 页面背景颜色(结束)
pageGradientAngle: 'to bottom', // 渐变角度从上到下to bottom、从左到右to right
bgUrl: '', // 页面背景图片
bgHeightScale: 0, // 页面背景高度比例,单位%0为高度自适应
imgWidth: '', // 页面背景图片宽度
imgHeight: '', // 页面背景图片高度
// 顶部导航栏
topStatusBar: {
isShow: true, // 是否显示
bgColor: "#ffffff", // 头部背景颜色
rollBgColor: "#ffffff", // 滚动时,头部背景颜色
style: 'style-1', // 导航栏风格样式style-1文字style-2图片+文字style-3图片+搜索style-4定位
styleName: '风格1',
textColor: "#333333", // 文字颜色
rollTextColor: "#333333", // 滚动时,头部文字颜色
textAlign: 'center', // 文字对齐方式
inputPlaceholder: '请输入搜索关键词',
imgUrl: '', // 图片
link: { // 跳转链接
name: ""
}
},
bottomTabBarSwitch: true, // 底部导航开关
// 弹框 count不弹出 -1首次弹出 1每次弹出 0
popWindow: {
imgUrl: "",
imgWidth: '',
imgHeight: '',
count: -1,
show: 0,
link: {
name: ""
},
},
// 公共模板属性,所有组件都继承,无需重复定义,组件内部根据业务自行调用
template: {
textColor: "#303133", // 文字颜色
pageStartBgColor: "", // 组件底部背景颜色(开始)
pageEndBgColor: "", // 组件底部背景颜色(结束)
pageGradientAngle: 'to bottom', // 渐变角度从上到下to bottom、从左到右to right
componentBgUrl: '', // 组件背景图片
componentBgAlpha: 2, // 组件背景图片的透明度0~10
componentStartBgColor: '', // 组件背景颜色(开始)
componentEndBgColor: '', // 组件背景颜色(结束)
componentGradientAngle: 'to bottom', // 渐变角度从上到下to bottom、从左到右to right
topRounded: 0, // 组件上圆角
bottomRounded: 0, // 组件下圆角
elementBgColor: '', // 元素背景颜色
topElementRounded: 0, // 元素上圆角
bottomElementRounded: 0, // 元素下圆角
margin: {
top: 0, // 上边距
bottom: 0, // 下边距
both: 0, // 左右边距
}
}
},
// 组件集合
value: <any>[]
}
},
getters: {
editComponent: (state) => {
if (state.currentIndex == -99) {
return state.global;
} else {
return state.value[state.currentIndex];
}
},
},
actions: {
// 初始化数据
init() {
this.global = {
title: "页面", // 页面标题
pageStartBgColor: "", // 页面背景颜色(开始)
pageEndBgColor: "", // 页面背景颜色(结束)
pageGradientAngle: 'to bottom', // 渐变角度从上到下to bottom、从左到右to right
bgUrl: '', // 页面背景图片
bgHeightScale: 100, // 页面背景高度比例,单位%
imgWidth: '', // 页面背景图片宽度
imgHeight: '', // 页面背景图片高度
// 顶部导航栏
topStatusBar: {
isShow: true, // 是否显示
bgColor: "#ffffff", // 头部背景颜色
rollBgColor: "#ffffff", // 滚动时,头部背景颜色
style: 'style-1', // 导航栏风格样式style-1文字style-2图片+文字style-3图片+搜索style-4定位
styleName: '风格1',
textColor: "#333333", // 文字颜色
rollTextColor: "#333333", // 滚动时,头部文字颜色
textAlign: 'center', // 文字对齐方式
inputPlaceholder: '请输入搜索关键词',
imgUrl: '', // 图片
link: { // 跳转链接
name: ""
}
},
bottomTabBarSwitch: true, // 底部导航开关
// 弹框 count不弹出 -1首次弹出 1每次弹出 0
popWindow: {
imgUrl: "",
imgWidth: '',
imgHeight: '',
count: -1,
show: 0,
link: {
name: ""
},
},
// 公共模板属性,所有组件都继承,无需重复定义,组件内部根据业务自行调用
template: {
textColor: "#303133", // 文字颜色
pageStartBgColor: "", // 组件底部背景颜色(开始)
pageEndBgColor: "", // 组件底部背景颜色(结束)
pageGradientAngle: 'to bottom', // 渐变角度从上到下to bottom、从左到右to right
componentBgUrl: '', // 组件背景图片
componentBgAlpha: 2, // 组件背景图片的透明度
componentStartBgColor: '', // 组件背景颜色(开始)
componentEndBgColor: '', // 组件背景颜色(结束)
componentGradientAngle: 'to bottom', // 渐变角度从上到下to bottom、从左到右to right
topRounded: 0, // 组件上圆角
bottomRounded: 0, // 组件下圆角
elementBgColor: '', // 元素背景颜色
topElementRounded: 0, // 元素上圆角
bottomElementRounded: 0, // 元素下圆角
margin: {
top: 0, // 上边距
bottom: 0, // 下边距
both: 0, // 左右边距
}
}
};
this.value = [];
},
// 添加组件
addComponent(key: string, data: any) {
// 加载完才能添加组件
if (!this.load) return;
// 删除不用的字段
let component = cloneDeep(data);
component.id = this.generateRandom();
component.componentName = key;
component.componentTitle = component.title;
component.ignore = []; // 忽略公共属性
Object.assign(component, component.value);
delete component.title;
delete component.value;
delete component.type;
delete component.icon;
// 默认继承全局属性
let template = cloneDeep(this.global.template);
Object.assign(component, template);
if (component.template) {
// 按照组件初始的属性覆盖默认值
Object.assign(component, component.template);
delete component.template;
}
if (!this.checkComponentIsAdd(component)) {
// 组件最多只能添加n个
ElMessage({
type: 'warning',
message: `${ component.componentTitle }${ t('componentCanOnlyAdd') }${ component.uses }${ t('piece') }`,
});
return;
}
// 置顶组件,只能在第一个位置中添加
if (component.position && this.position.indexOf(component.position) != -1) {
this.currentIndex = 0;
// 指定位置添加组件
this.value.splice(0, 0, component);
} else if (this.currentIndex === -99) {
this.value.push(component);
// 添加组件后(不是编辑调用的),选择最后一个
this.currentIndex = this.value.length - 1;
} else {
// 指定位置添加组件
this.value.splice(++this.currentIndex, 0, component);
}
this.currentComponent = component.path;
},
generateRandom(len: number = 5) {
return Number(Math.random().toString().substr(3, len) + Date.now()).toString(36);
},
// 将数据发送到uniapp
postMessage() {
var diyData = JSON.stringify({
pageMode: this.pageMode,
currentIndex: this.currentIndex,
global: toRaw(this.global),
value: toRaw(this.value)
});
window.previewIframe.contentWindow.postMessage(diyData, '*');
},
// 选中正在编辑的组件
changeCurrentIndex(index: number, component: any = null) {
this.currentIndex = index;
if (this.currentIndex == -99) {
this.currentComponent = 'edit-page';
} else if (component) {
this.currentComponent = component.path;
}
},
// 删除组件
delComponent() {
if (this.currentIndex == -99) return;
ElMessageBox.confirm(
t('delComponentTips'),
t('warning'),
{
confirmButtonText: t('confirm'),
cancelButtonText: t('cancel'),
type: 'warning',
autofocus: false
}
).then(() => {
this.value.splice(this.currentIndex, 1);
// 如果组件全部删除,则选中页面设置
if (this.value.length === 0) {
this.currentIndex = -99;
}
// 如果当前选中的组件不存在,则选择上一个
if (this.currentIndex === this.value.length) {
this.currentIndex--;
}
let component = cloneDeep(this.value[this.currentIndex]);
this.changeCurrentIndex(this.currentIndex, component)
}).catch(() => {
})
},
// 上移组件
moveUpComponent() {
var temp = cloneDeep(this.value[this.currentIndex]); // 当前选中组件
let prevIndex = this.currentIndex - 1;
var temp2 = cloneDeep(this.value[prevIndex]); // 上个组件
if ((this.currentIndex - 1) < 0 || temp2.position && this.position.indexOf(temp2.position) != -1) return; // 从0开始
temp.id = this.generateRandom(); // 更新id刷新组件数据
temp2.id = this.generateRandom(); // 更新id刷新组件数据
if (temp.position && this.position.indexOf(temp.position) != -1) {
ElMessage({
type: 'warning',
message: `${ t('componentNotMoved') }`,
});
return;
}
this.value[this.currentIndex] = temp2;
this.value[prevIndex] = temp;
this.changeCurrentIndex(prevIndex, temp);
},
// 下移组件
moveDownComponent() {
if (this.currentIndex < -1 || (this.currentIndex + 1) >= this.value.length) return; // 最后一个不能下移
var nextIndex = this.currentIndex + 1;
var temp = cloneDeep(this.value[this.currentIndex]); // 当前选中组件
temp.id = this.generateRandom(); // 更新id刷新组件数据
var temp2 = cloneDeep(this.value[nextIndex]); // 下个组件
temp2.id = this.generateRandom(); // 更新id刷新组件数据
if (temp.position && this.position.indexOf(temp.position) != -1) {
ElMessage({
type: 'warning',
message: `${ t('componentNotMoved') }`,
});
return;
}
this.value[this.currentIndex] = temp2;
this.value[nextIndex] = temp;
this.changeCurrentIndex(nextIndex, temp);
},
// 复制组件
copyComponent() {
if (this.currentIndex < 0) return; // 从0开始
let component = cloneDeep(this.value[this.currentIndex]); // 当前选中组件
component.id = this.generateRandom(); // 更新id刷新组件数据
if (!this.checkComponentIsAdd(component)) {
ElMessage({
type: 'warning',
message: `${ t('notCopy') }${ component.componentTitle }${ t('componentCanOnlyAdd') }${ component.uses }${ t('piece') }`,
});
return;
}
if (component.position && this.position.indexOf(component.position) != -1) {
ElMessage({
type: 'warning',
message: `${ t('notCopy') }${ component.componentTitle }${ t('componentCanOnlyAdd') }1${ t('piece') }`,
});
return;
}
var index = this.currentIndex + 1;
this.value.splice(index, 0, component);
this.changeCurrentIndex(index, component);
},
// 检测组件是否允许添加true允许 false不允许
checkComponentIsAdd(component: any) {
//为0时不处理
if (component.uses === 0) return true;
var count = 0;
//遍历已添加的自定义组件,检测是否超出数量
for (var i in this.value) if (this.value[i].componentName === component.componentName) count++;
if (count >= component.uses) return false;
else return true;
},
// 重置当前组件数据
resetComponent() {
if (this.currentIndex < 0) return; // 从0开始
ElMessageBox.confirm(
t('resetComponentTips'),
t('warning'),
{
confirmButtonText: t('confirm'),
cancelButtonText: t('cancel'),
type: 'warning',
autofocus: false
}
).then(() => {
// 重置当前选中的组件数据
for (let i = 0; i < this.components.length; i++) {
if (this.components[i].componentName == this.editComponent.componentName) {
Object.assign(this.editComponent, this.components[i]);
break;
}
}
}).catch(() => {
})
},
// 组件验证
verify() {
if (this.pageTitle === "") {
ElMessage({
message: t('diyPageTitlePlaceholder'),
type: 'warning'
})
this.changeCurrentIndex(-99);
return false;
}
// if (this.global.title === "") {
// ElMessage({
// message: t('diyTitlePlaceholder'),
// type: 'warning'
// })
// this.changeCurrentIndex(-99);
// return false;
// }
for (var i = 0; i < this.value.length; i++) {
try {
if (this.value[i].verify) {
var res = this.value[i].verify(i);
if (!res.code) {
this.changeCurrentIndex(i, this.value[i])
ElMessage({
message: res.message,
type: 'warning'
})
return false;
}
}
} catch (e) {
console.log("verify Error:", e, i, this.value[i]);
}
}
return true;
}
}
})
export default useDiyStore