Commit e21a16bd authored by chenqikuai's avatar chenqikuai

性能优化

parent 1b350fd6
mv dist sy3
tar -czf sy3.tar sy3
scp sy3.tar root@183.134.99.140:/var/www/html/personal/sy3.tar
rm -rf sy3.tar
rm -rf sy3
ssh root@183.134.99.140 'cd /var/www/html/personal/ && rm -rf sy3 && tar -xzf sy3.tar && rm -rf sy3.tar'
echo 'done. 👉 http://183.134.99.140:8908'
This diff is collapsed.
......@@ -15,9 +15,10 @@
},
"dependencies": {
"@chenfengyuan/vue-countdown": "^2.0.0",
"@tinymce/tinymce-vue": "^5.0.0",
"axios": "^0.26.1",
"comlink": "^4.3.1",
"cqk-sy-ui": "^1.2.78",
"cqk-sy-ui": "^1.2.82",
"crypto-js": "^4.1.1",
"dom-to-image": "^2.6.0",
"element-plus": "^2.1.9",
......@@ -26,7 +27,7 @@
"pdfjs-dist": "^2.5.207",
"simple-components01": "^0.1.15",
"unplugin-element-plus": "^0.3.2",
"vue": "^3.2.37",
"vue": "^3.2.16",
"vue-cropper": "^1.0.2",
"vue-router": "^4.0.13",
"vuedraggable": "^4.1.0"
......
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="19" viewBox="0 0 18 19"><g fill="#3D475A" transform="translate(.25 .25)"><path d="M4.75 6 1.75 6C.783501688 6 0 6.78350169 0 7.75L0 10.75C0 11.7164983.783501688 12.5 1.75 12.5L4.75 12.5C5.71649831 12.5 6.5 11.7164983 6.5 10.75L6.5 7.75C6.5 6.78350169 5.71649831 6 4.75 6ZM1.75 7.5 4.75 7.5C4.88807119 7.5 5 7.61192881 5 7.75L5 10.75C5 10.8880712 4.88807119 11 4.75 11L1.75 11C1.61192881 11 1.5 10.8880712 1.5 10.75L1.5 7.75C1.5 7.61192881 1.61192881 7.5 1.75 7.5ZM15.75 0 12.75 0C11.7835017 0 11 .783501688 11 1.75L11 4.75C11 5.71649831 11.7835017 6.5 12.75 6.5L15.75 6.5C16.7164983 6.5 17.5 5.71649831 17.5 4.75L17.5 1.75C17.5.783501688 16.7164983 0 15.75 0ZM12.75 1.5 15.75 1.5C15.8880712 1.5 16 1.61192881 16 1.75L16 4.75C16 4.88807119 15.8880712 5 15.75 5L12.75 5C12.6119288 5 12.5 4.88807119 12.5 4.75L12.5 1.75C12.5 1.61192881 12.6119288 1.5 12.75 1.5Z"/><path d="M11.25,3 L11.25,4.5 L9.75,4.5 C9.63165327,4.5 9.53251318,4.58223341 9.50660268,4.69267729 L9.5,4.75 L9.5,13.75 C9.5,13.8683467 9.58223341,13.9674868 9.69267729,13.9933973 L9.75,14 L11.75,14 L11.75,15.5 L9.75,15.5 C8.8318266,15.5 8.07880766,14.7928897 8.0058012,13.8935272 L8,13.75 L8,4.75 C8,3.8318266 8.70711027,3.07880766 9.60647279,3.0058012 L9.75,3 L11.25,3 Z"/><path d="M15.75,12 L12.75,12 C11.7835017,12 11,12.7835017 11,13.75 L11,16.75 C11,17.7164983 11.7835017,18.5 12.75,18.5 L15.75,18.5 C16.7164983,18.5 17.5,17.7164983 17.5,16.75 L17.5,13.75 C17.5,12.7835017 16.7164983,12 15.75,12 Z M12.75,13.5 L15.75,13.5 C15.8880712,13.5 16,13.6119288 16,13.75 L16,16.75 C16,16.8880712 15.8880712,17 15.75,17 L12.75,17 C12.6119288,17 12.5,16.8880712 12.5,16.75 L12.5,13.75 C12.5,13.6119288 12.6119288,13.5 12.75,13.5 Z"/><polygon points="8.75 8.5 8.75 10 5.75 10 5.75 8.5"/></g></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20"><g fill="#3D475A" transform="translate(.25 .75)"><path d="M3 4.25 4.5 4.25 4.5 16.5C4.5 17.2830171 4.63321809 17.4779328 5.26247619 17.4981547L5.38636364 17.5 14.1136364 17.5C14.8063167 17.5 14.9802807 17.3511442 14.9983503 16.6400248L15 16.5 15 4.25 16.5 4.25 16.5 16.5C16.5 18.0605421 15.7787805 18.9288434 14.3021518 18.9958106L14.1136364 19 5.38636364 19C3.84672482 19 3.0639198 18.1941204 3.00375882 16.6914545L3 16.5 3 4.25ZM12.75 0C13.1642136 0 13.5.335786438 13.5.75 13.5 1.12969577 13.2178461 1.44349096 12.8517706 1.49315338L12.75 1.5 7.75 1.5C7.33578644 1.5 7 1.16421356 7 .75 7 .370304234 7.28215388.0565090391 7.64822944.006846616L7.75 0 12.75 0Z"/><path d="M11.75,10 C12.1642136,10 12.5,10.3357864 12.5,10.75 C12.5,11.1296958 12.2178461,11.443491 11.8517706,11.4931534 L11.75,11.5 L3.75,11.5 C3.33578644,11.5 3,11.1642136 3,10.75 C3,10.3703042 3.28215388,10.056509 3.64822944,10.0068466 L3.75,10 L11.75,10 Z" transform="rotate(-90 7.75 10.75)"/><path d="M15.75,10 C16.1642136,10 16.5,10.3357864 16.5,10.75 C16.5,11.1296958 16.2178461,11.443491 15.8517706,11.4931534 L15.75,11.5 L7.75,11.5 C7.33578644,11.5 7,11.1642136 7,10.75 C7,10.3703042 7.28215388,10.056509 7.64822944,10.0068466 L7.75,10 L15.75,10 Z" transform="rotate(-90 11.75 10.75)"/><path d="M18.75,3 C19.1642136,3 19.5,3.33578644 19.5,3.75 C19.5,4.12969577 19.2178461,4.44349096 18.8517706,4.49315338 L18.75,4.5 L0.75,4.5 C0.335786438,4.5 0,4.16421356 0,3.75 C0,3.37030423 0.282153882,3.05650904 0.648229443,3.00684662 L0.75,3 L18.75,3 Z"/></g></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" width="8" height="12" viewBox="0 0 8 12"><g fill="#959595"><path d="M2.84217094e-14 1C-.0000565096173 1.35724675.190530049 1.68738054.499954335 1.86602023.809378621 2.04465992 1.19062138 2.04465992 1.50004567 1.86602023 1.80946995 1.68738054 2.00005651 1.35724675 2 1 2.00005651.64275325 1.80946995.312619459 1.50004567.133979768 1.19062138-.0446599227.809378621-.0446599227.499954335.133979768.190530049.312619459-.0000565096173.64275325 2.84217094e-14 1ZM5 1C4.99994349 1.35724675 5.19053005 1.68738054 5.49995433 1.86602023 5.80937862 2.04465992 6.19062138 2.04465992 6.50004567 1.86602023 6.80946995 1.68738054 7.00005651 1.35724675 7 1 7.00005651.64275325 6.80946995.312619459 6.50004567.133979768 6.19062138-.0446599227 5.80937862-.0446599227 5.49995433.133979768 5.19053005.312619459 4.99994349.64275325 5 1ZM10 1C9.99994349 1.35724675 10.19053 1.68738054 10.4999543 1.86602023 10.8093786 2.04465992 11.1906214 2.04465992 11.5000457 1.86602023 11.80947 1.68738054 12.0000565 1.35724675 12 1 12.0000565.64275325 11.80947.312619459 11.5000457.133979768 11.1906214-.0446599227 10.8093786-.0446599227 10.4999543.133979768 10.19053.312619459 9.99994349.64275325 10 1Z" transform="matrix(0 -1 -1 0 2 12)"/><path d="M2.84217094e-14 1C-.0000565096173 1.35724675.190530049 1.68738054.499954335 1.86602023.809378621 2.04465992 1.19062138 2.04465992 1.50004567 1.86602023 1.80946995 1.68738054 2.00005651 1.35724675 2 1 2.00005651.64275325 1.80946995.312619459 1.50004567.133979768 1.19062138-.0446599227.809378621-.0446599227.499954335.133979768.190530049.312619459-.0000565096173.64275325 2.84217094e-14 1ZM5 1C4.99994349 1.35724675 5.19053005 1.68738054 5.49995433 1.86602023 5.80937862 2.04465992 6.19062138 2.04465992 6.50004567 1.86602023 6.80946995 1.68738054 7.00005651 1.35724675 7 1 7.00005651.64275325 6.80946995.312619459 6.50004567.133979768 6.19062138-.0446599227 5.80937862-.0446599227 5.49995433.133979768 5.19053005.312619459 4.99994349.64275325 5 1ZM10 1C9.99994349 1.35724675 10.19053 1.68738054 10.4999543 1.86602023 10.8093786 2.04465992 11.1906214 2.04465992 11.5000457 1.86602023 11.80947 1.68738054 12.0000565 1.35724675 12 1 12.0000565.64275325 11.80947.312619459 11.5000457.133979768 11.1906214-.0446599227 10.8093786-.0446599227 10.4999543.133979768 10.19053.312619459 9.99994349.64275325 10 1Z" transform="matrix(0 -1 -1 0 8 12)"/></g></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" width="19" height="20" viewBox="0 0 19 20"><g fill="#3D475A" transform="translate(.11 .985)"><path d="M7.58229511,1.06513035 L11.1205986,1.12946314 C11.4905075,1.13618876 11.7947327,1.41014863 11.8485195,1.76658817 L11.8568405,1.86570509 L11.9200871,5.34426702 C11.927617,5.75841213 11.5979903,6.10024728 11.1838452,6.10777719 C10.8042122,6.11467961 10.4853396,5.83827678 10.4290306,5.47316451 L10.420335,5.37153524 L10.3699419,2.61530239 L7.55502689,2.56488248 C7.17539386,2.55798006 6.86677975,2.27016838 6.82378035,1.90325051 L6.81878493,1.8013723 C6.82568735,1.42173928 7.11349903,1.11312516 7.4804169,1.07012577 L7.58229511,1.06513035 Z" transform="rotate(-45 9.37 3.587)"/><path d="M7.58229511,12.7917421 L11.1205986,12.8560749 C11.4905075,12.8628005 11.7947327,13.1367604 11.8485195,13.4931999 L11.8568405,13.5923169 L11.9200871,17.0708788 C11.927617,17.4850239 11.5979903,17.826859 11.1838452,17.834389 C10.8042122,17.8412914 10.4853396,17.5648885 10.4290306,17.1997763 L10.420335,17.098147 L10.3699419,14.3423024 L7.55502689,14.2914942 C7.17539386,14.2845918 6.86677975,13.9967801 6.82378035,13.6298623 L6.81878493,13.5279841 C6.82568735,13.148351 7.11349903,12.8397369 7.4804169,12.7967375 L7.58229511,12.7917421 Z" transform="scale(1 -1) rotate(-45 -27.6 0)"/><path d="M13.4308918,6.52858422 L16.9691953,6.59291701 C17.3391042,6.59964263 17.6433294,6.8736025 17.6971161,7.23004204 L17.7054372,7.32915897 L17.7686838,10.8077209 C17.7762137,11.221866 17.446587,11.5637011 17.0324419,11.5712311 C16.6528088,11.5781335 16.3339363,11.3017306 16.2776272,10.9366184 L16.2689317,10.8349891 L16.2179419,8.07930239 L13.4036236,8.02833635 C13.0239906,8.02143393 12.7153764,7.73362225 12.672377,7.36670438 L12.6673816,7.26482618 C12.674284,6.88519315 12.9620957,6.57657904 13.3290136,6.53357964 L13.4308918,6.52858422 Z" transform="scale(1 -1) rotate(45 37.067 0)"/><path d="M1.79931285,6.52858422 L5.33761633,6.59291701 C5.70752528,6.59964263 6.01175043,6.8736025 6.06553719,7.23004204 L6.07385829,7.32915897 L6.13710487,10.8077209 C6.14463478,11.221866 5.81500803,11.5637011 5.40086291,11.5712311 C5.02122989,11.5781335 4.70235733,11.3017306 4.64604829,10.9366184 L4.63735274,10.8349891 L4.58694189,8.07930239 L1.77204463,8.02833635 C1.39241161,8.02143393 1.08379749,7.73362225 1.04079809,7.36670438 L1.03580267,7.26482618 C1.04270509,6.88519315 1.33051677,6.57657904 1.69743464,6.53357964 L1.79931285,6.52858422 Z" transform="rotate(-135 3.587 9.05)"/><polygon points="8.641 1.015 10.141 1.015 10.141 17.015 8.641 17.015"/><polygon points="8.835 1.432 10.335 1.432 10.335 16.543 8.835 16.543" transform="rotate(-90 9.585 8.988)"/></g></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10" viewBox="0 0 10 10"><path d="M5,0 L7.39583333,2.5 L5.41666667,2.5 L5.41666667,8.33333333 L4.58333333,8.33333333 L4.58333333,2.5 L2.60416667,2.5 L5,0 Z M10,5 L9.16666667,5 L9.16666667,9.16666667 L0.833333333,9.16666667 L0.833333333,5 L0,5 L0,10 L10,10 L10,5 Z"/></svg>
\ No newline at end of file
<template>
<syCommonDialog
type="element"
:visible="visible"
:elementDialogProps="{
title: ' ',
}"
:no-padding="true"
elementDialogSize="big"
showMask
@closePopup="
$emit('update:visible', false);
previewWindow = false;
"
:btn-config="btnConfig"
>
<template #titleLeft>
<div class="flex items-center" v-if="!previewWindow">
<div
@click="templateType = 'sys'"
:class="{
'title-dark': templateType === 'sys',
'title-light': templateType !== 'sys',
}"
>
系统模板
</div>
<div
style="margin-left: 31px"
@click="templateType = 'private'"
:class="{
'title-dark': templateType !== 'sys',
'title-light': templateType === 'sys',
}"
>
我的模板
</div>
</div>
<div v-else>预览</div>
</template>
<div v-if="visible" class="px-9 pt-4">
<template-popup
:type="templateType"
v-show="visible"
ref="templatePopup"
@determine="determine"
:setPreviewWindow="(v: any) => (previewWindow = v)"
@update:preview="
(v) => {
previewWindow = v;
}
"
></template-popup>
</div>
</syCommonDialog>
</template>
<script setup lang="ts">
import { syCommonDialog } from "cqk-sy-ui";
import { ref, computed } from "vue";
import TemplatePopup from "../TemplatePopup.vue";
const props = defineProps<{
visible: boolean;
determine: (...args: any) => any;
}>();
const previewWindow = ref(false);
const templatePopup = ref();
const templateType = ref("sys");
const emit = defineEmits(["update:visible"]);
async function dialogConfirm(
component: any,
methodName: string,
params: any = undefined
) {
return component[methodName](params);
}
const btnConfig = computed(() => {
if (previewWindow.value)
return {
type: "withBorder" as const,
btns: [
{ name: "返回模板", type: "default" as const },
{
name: "使用",
type: "primary" as const,
},
],
btnFunctions: [
{
name: "返回模板",
click: () =>
dialogConfirm(templatePopup.value, "returnTemplate", "Return"),
},
{
name: "使用",
click: () =>
dialogConfirm(templatePopup.value, "returnTemplate", "Use"),
},
],
};
else {
return undefined;
}
});
</script>
<style scoped lang="scss">
.title-light {
font-size: 18px;
font-weight: 600;
color: #959595;
line-height: 25px;
cursor: pointer;
}
.title-dark {
font-size: 18px;
font-weight: 600;
color: #353535;
cursor: pointer;
}
</style>
import {
PropertyType,
RootUnit as RootUnitType,
TemplateProperty,
TmplSelectProperty,
UnitProperty,
} from "../newEditTemplate/types";
import { Property, Unit } from "../newEditTemplate/types2";
/**
* 将本地模板转换为接口json
* @param local
*/
export function formatApiJson(local: Unit[]): RootUnitType[] {
const res = local.map((unit) => {
const data =
unit.type === PropertyType.Unit
? unit.children.map((item: Unit) => formatL2Local2Api(item))
: typeJson2String(unit.children);
return {
data,
type: unit.type,
key: "",
label: unit.title,
};
});
return res;
}
function typeJson2String(json: Property[]) {
const temp: any = {};
json.forEach((item) => {
temp[item.label] = item.value;
});
const value = JSON.stringify(temp);
return {
type: "text",
format: "string",
value,
};
}
/**
* 将本地的二级字段转换为接口二级字段
* @param localL2
*/
function formatL2Local2Api(
localL2: Property | Unit
): TemplateProperty | TmplSelectProperty | UnitProperty {
if (localL2 instanceof Property) {
return formatProperty2Api(localL2);
} else {
const children = (localL2.children as Property[]) || [];
return {
key: "",
type: PropertyType.Unit,
// label: localL2.title,
value: children.map((l3) => formatProperty2Api(l3)),
};
}
}
function formatProperty2Api(
property: Property
): TemplateProperty | TmplSelectProperty | any {
if (property.type === PropertyType.Select) {
return {
key: property.key,
type: PropertyType.Select,
label: property.label,
options: property.options,
data: {
type: "text",
format: "string(string, html, json, base64)",
value: property.value,
},
};
} else if (property.type === PropertyType.Image) {
let data = [] as any;
if (property.value && property.value !== "") {
const dd = Array.from(property.value);
data = dd.map((value: any) => ({
format: "hash(hash)",
type: "image",
value: value.hash || value.value || "",
}));
} else {
data.push({
format: "hash(hash)",
type: "image",
value: "",
});
}
return {
key: property.key,
type: property.type as PropertyType.Image,
data: data,
label: property.label,
};
} else if (property.type === PropertyType.File) {
let data = [] as any;
if (property.value) {
const dd = Array.from(property.value);
data = (dd as any).map((value: any) => ({
format: "hash(hash)",
type: "file",
value: value,
}));
} else {
data.push({
format: "hash(hash)",
type: "file",
value: "",
});
}
return {
key: property.key,
type: property.type as PropertyType.File,
data: data,
label: property.label,
};
} else if (property.type === PropertyType.Input) {
// 保留key,保留data
return {
data: {
format:
property.data && property.data.format
? property.data.format
: "string",
type: property.data && property.data.type ? property.data.type : "text",
value: property.value,
},
type: PropertyType.Input,
key: property.parent.title === "ext" ? property.label : property.key,
label: property.label,
};
} else if (property.type === PropertyType.JSON) {
return {
data: {
format: "string",
type: "text",
value: property.value,
},
type: property.type,
key: property.key,
label: property.label,
};
} else if (property.type === PropertyType.Date) {
return {
data: {
format: "utc",
type: "date",
value: property.value,
},
type: PropertyType.Date,
key: property.key,
label: property.label,
};
} else if (property.type === PropertyType.Video) {
let data = [] as any;
if (property.value) {
const dd = Array.from(property.value);
data = (dd as any).map((value: any) => ({
format: "hash(hash)",
type: "media",
value: value,
}));
} else {
data.push({
format: "hash(hash)",
type: "media",
value: "",
});
}
return {
key: property.key,
type: property.type as PropertyType.Video,
data: data,
label: property.label,
};
} else if (property.type === PropertyType.Audio) {
let data = [] as any;
if (property.value) {
const dd = Array.from(property.value);
data = (dd as any).map((value: any) => ({
format: "hash(hash)",
type: "media",
value: value,
}));
} else {
data.push({
format: "hash(hash)",
type: "media",
value: "",
});
}
return {
key: property.key,
type: property.type as PropertyType.Audio,
data: data,
label: property.label,
};
} else if (
property.type === PropertyType.TextArray ||
property.type === PropertyType.ImageUrl
) {
const data =
property.value === ""
? [
{
format: "string",
type: "text",
value: "",
},
]
: (property.value as [string])?.map((item: string) => {
return {
format: "string",
type: "text",
value: item,
};
});
return {
key: property.key,
type: property.type as PropertyType.TextArray | PropertyType.ImageUrl,
data: data,
label: property.label,
};
}
//Video
else {
return {
data: {
format: "string",
type: "text",
value: property.value,
},
type: property.type as PropertyType.Image,
key: property.key,
label: property.label,
};
}
}
// 接口json数据转换为本地
export function formatTemplateApi2Local(apiList: RootUnitType[]): Unit[] {
return apiList.map((rootUnit) => {
const unit = new Unit(rootUnit.label, {}, undefined, rootUnit.type);
if (Array.isArray(rootUnit.data)) {
unit.children = rootUnit.data.map((l2) => {
return formatApiProperty2Local(l2, unit);
});
} else {
const list = [] as any;
const o = JSON.parse((rootUnit.data as { value: string })?.value || "{}");
for (const i in o) {
list.push({
type: 0,
label: i,
key: "",
value: o[i],
});
}
unit.children = list.map((item: any) => {
const p = new Property(item.label, item.key, unit, 0, item.value, {
format: "string",
type: "text",
value: item.value,
});
return p;
});
}
return unit;
});
}
// 接口json数据转换为本地
function formatApiProperty2Local(property: any, parent: Unit): Property {
const local = new Property(
property.label,
property.key,
parent,
property.type,
property.value,
property.data
);
if (property.type === PropertyType.Select) {
local.options = property.options || [];
} else if (property.type === PropertyType.Image) {
local.value = property.data;
} else if (property.type === PropertyType.File) {
local.value = property.data;
} else if (property.type === PropertyType.Video) {
local.value = property.data;
} else if (property.type === PropertyType.Audio) {
local.value = property.data;
} else if (
property.type === PropertyType.TextArray ||
property.type === PropertyType.ImageUrl
) {
local.value = property.data.map((item: { value: string }) => item.value);
}
return local;
}
This diff is collapsed.
<template>
<common-dialog
showMask
@closePopup="$emit('close')"
:visible="visible"
type="element"
:elementDialogProps="{
title: '提示',
}"
:btnConfig="{
type: 'noBorder',
btns: btns,
btnFunctions: [
{
name: '取消',
async click() {
return true;
},
},
{
name: '去认证',
click: async () => {
$emit('confirm');
confirm;
return true;
},
},
],
}"
>
<div class="delete_dialog">
<img
class="img inline-block"
src="/images/Uncertified/weirenzheng-2.png"
alt="删除"
/>
<p class="tip">您还未认证不能进行上链</p>
<!-- <div class="btnbox">
<button class="g-btn_primary btn_confirm" @click="$emit('cancel')">
取消
</button>
<button
class="g-btn_primary btn_cancel"
@click="
$emit('confirm');
confirm;
"
>
去认证
</button>
</div> -->
</div>
</common-dialog>
</template>
<script lang="ts">
import { btns } from "@/config/btns";
import { syCommonDialog as CommonDialog } from "cqk-sy-ui";
import { defineComponent } from "vue";
export default defineComponent({
components: {
CommonDialog,
},
emits: ["cancel", "confirm", "close"],
props: {
navigate: {
type: Function,
},
visible: Boolean,
},
data() {
const newBtns = JSON.parse(JSON.stringify(btns));
newBtns[1].name = "去认证";
return {
btns: newBtns,
};
},
methods: {
confirm() {
this.navigate && this.navigate("certify");
},
},
});
</script>
<style scoped>
.delete_dialog {
text-align: center;
}
.g-btn_primary {
border: none;
background: var(--sy-blue);
font-size: 14px;
color: #fff;
outline: none;
cursor: pointer;
border-radius: 8px;
}
.title {
margin: 0;
padding-left: 44px;
line-height: 106px;
font-weight: 500;
color: #000;
font-size: 22px;
text-align: left;
}
.img {
margin-top: 7px;
}
.tip {
margin: 17px 0 0 0; /* todo ui图切块有空白无法还原 */
color: #ffce57;
font-size: 18px;
line-height: 25px;
}
.btnbox {
float: right;
margin-right: 49px;
}
.btn_confirm {
float: left;
margin-top: 56px;
width: 120px;
height: 40px;
color: #5c6476;
background: white;
}
.btn_cancel {
float: left;
margin-top: 56px;
width: 120px;
padding: 0;
height: 40px;
border-radius: 4px;
text-align: center;
line-height: 40px;
}
</style>
<template>
<div class="theBox w-full flex items-center cursor-pointer">
<Icon
iconName="iconjiahao1"
size="22"
style="margin-left: 41px; margin-right: 10px"
></Icon>
添加一级标题
</div>
</template>
<script setup lang="ts">
import Icon from "@/components/Icon/index.vue";
</script>
<style>
.theBox {
height: 50px;
background: #f1f8ff;
border-radius: var(--sy-border-radius);
border: 1px solid #c5e0ff;
font-size: 16px;
font-weight: 500;
color: var(--sy-blue);
}
</style>
<template>
<div class="editHeader">
<div class="editProofName">
<input
type="text"
class="outline-none w-full h-full"
style="background-color: #f4f4f4; padding: 0 21px"
:value="title"
@input="handle"
/>
</div>
<div class="flex items-center mt-2.5">
<div>
<Icon iconName="iconjiang" size="18" style="margin-right: 8px"></Icon>
</div>
<div class="just-do-it">点击以下添加一级标题开始自定义模板吧 !</div>
</div>
</div>
</template>
<script setup lang="ts">
import Icon from "@/components/Icon/index.vue";
defineProps<{
title: string;
}>();
const emit = defineEmits(["update:title"]);
const handle = (e: Event) => {
emit("update:title", (e.target as HTMLInputElement).value);
};
</script>
<style lang="scss" scoped>
.editHeader {
height: 114px;
background: #ffffff;
border-radius: var(--sy-border-radius);
padding-top: 23px;
padding-left: 33px;
padding-right: 33px;
.editProofName {
height: 41px;
background: #f4f4f4;
input {
font-size: 20px;
font-weight: 500;
color: var(--sy-black);
}
}
.just-do-it {
font-size: 14px;
font-weight: 400;
color: #292929;
}
}
</style>
<template>
<div style="background-color: #f9f9f9" class="px-10 flex editTool">
<div
style="width: 858px"
class="flex-shrink-0 flex-grow h-full flex flex-col"
>
<TraceProofEditHeader
class="flex-shrink-0"
:title="title"
@update:title="$emit('update:title', $event)"
></TraceProofEditHeader>
<div class="flex-grow overflow-hidden">
<syScrollBar height="100%">
<div>
<Draggable
tag="div"
:list="rootUnitList"
handle=".moveUnit"
ghost-class="draggable-ghost"
item-key="id"
>
<template #item="{ element: unitData, index: indexOfList }">
<div class="list-group-item">
<root-unit
:key="unitData.id"
:unit="unitData"
:setUnit="(value: any) => changeUnit(indexOfList, value)"
@del="deleteItem"
@addNextlevel="showAddChildDialog"
@modifyTitle="modifyTitleShow"
:selectedItem="selectedEditItem"
:setSelectedItem="setSelectedItem"
@selected="handleSelectedProperty"
@modifyForms="showModifyForms"
:switchPosition="switchPosition"
/>
</div>
</template>
</Draggable>
<AddFirstLevelBox
class="mt-2.5"
@click="showAddRootDialog"
></AddFirstLevelBox>
</div>
</syScrollBar>
</div>
</div>
<div style="width: 228px; margin-left: 29px" class="flex-shrink-0">
<SetBar
:show-upload="route.name === 'tracingDetail'"
:selectTarget="selectedEditItem"
:setSelectedItem="setSelectedItem"
@select-type="$emit('select-type', $event)"
@uploadBanner="$emit('uploadBanner')"
></SetBar>
</div>
</div>
</template>
<script setup lang="ts">
import AddFirstLevelBox from "./AddFirstLevelBox.vue";
import RootUnit from "../../../newEditTemplate/RootUnit.vue";
import SetBar from "../../../newEditTemplate/SetBar.vue";
import { Unit } from "../../../newEditTemplate/types2";
import Draggable from "vuedraggable/src/vuedraggable";
import { syScrollBar } from "cqk-sy-ui";
import TraceProofEditHeader from "./TraceProofEditHeader.vue";
defineProps<{
route: any;
title: string;
showAddRootDialog: () => void;
rootUnitList: Unit[];
deleteItem: (data?: any) => void;
changeUnit: (indexOfList: number, value: any) => void;
showAddChildDialog: (data?: any) => void;
modifyTitleShow: () => void;
selectedEditItem: any;
setSelectedItem: (v: any) => void;
handleSelectedProperty: (i: any) => void;
showModifyForms: () => void;
switchPosition: (id1: string, id2: string) => void;
}>();
defineEmits(["update:title", "select-type", "uploadBanner"]);
</script>
<style lang="scss">
.draggable-ghost {
.root_unit {
border: 2px dashed gray;
.title {
box-sizing: border-box;
}
}
}
.editTool {
* {
box-sizing: border-box;
}
}
</style>
This diff is collapsed.
<template>
<div class="body">
<div class="body-center">
<root-unit
v-for="(item, i) in templateInfo"
:unit="item"
:key="item.id"
:setUnit="(v: any) => changeUnit(i, v)"
/>
</div>
</div>
</template>
<script lang="ts">
// 取本地数据转换函数
import { GO_URLS } from "cqk-sy-ui";
import { Property, Unit } from "../newEditTemplate/types2";
import RootUnit from "../newEditTemplate/RootUnit.vue";
import { formatTemplateApi2Local } from "./Template";
import { defineComponent } from "vue";
import { $ajax } from "@/service";
import { __VLS_types_PropertyType } from "./index.vue.__VLS_script";
export default defineComponent({
components: {
RootUnit,
},
props: {
systemTemplateId: { type: Number, default: 0 },
isActive: { type: Boolean, default: true },
},
data() {
return {
templateInfo: [] as Unit[],
};
},
created() {
this.obtainTemplateInformation();
},
methods: {
changeUnit(
i: any,
v: {
// 取本地数据转换函数
id: string;
title: string;
children: (
| any
| {
id: string;
label: string;
key: string;
type: __VLS_types_PropertyType;
options: string[];
value: string | string[];
parent: any;
data?:
| { value: string; format: string; type: string }
| undefined;
}
)[];
parent: any | null;
type: __VLS_types_PropertyType;
addInputChildren: (label: string) => void;
changeChild2Unit: (child: Property) => Unit;
}
) {
this.templateInfo[i] = v;
},
returnTemplate(val: string) {
this.$emit("returnTemplate", val);
},
// 查询模板
async obtainTemplateInformation() {
// 获取个人模板||获取系统模板
// let url = "";
// if (this.isActive) {
// url = URLS.SYS_TMPL_GET;
// } else {
// url = URLS.TEMPLATE_DETAIL;
// }
const data = await $ajax({
type: "get",
params: {
id: this.systemTemplateId,
},
url: GO_URLS.getSystemTemplate,
});
if (data && data.data.detail) {
this.templateInfo = formatTemplateApi2Local(
JSON.parse(data.data.detail)
);
}
},
},
});
</script>
<style lang="scss" scoped>
:deep(.root_unit) {
pointer-events: none;
.input-box {
input {
width: 500px;
}
}
.date-picker {
width: 500px;
}
}
.body {
background: rgba(255, 255, 255, 1);
border-radius: 10px;
.body-top {
height: 68px;
line-height: 68px;
text-align: center;
border-bottom: 1px solid #e9e9e9;
font-size: 22px;
font-weight: 500;
color: rgba(53, 53, 53, 1);
.body-top__right,
.body-top__left {
width: 90px;
height: 40px;
background: rgba(239, 239, 239, 1);
border-radius: 4px;
line-height: 40px;
font-size: 14px;
text-align: center;
font-weight: 400;
color: rgba(41, 41, 41, 1);
margin-top: 14px;
cursor: pointer;
}
.body-top__left {
float: left;
margin-left: 24px;
}
.body-top__right {
float: right;
margin-right: 24px;
}
}
.body-center {
height: 400px;
overflow: auto;
}
}
</style>
This diff is collapsed.
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="223" height="126" viewBox="0 0 223 126"><defs><rect id="a" width="222.604" height="125.521" x="0" y="0" rx="20"/></defs><g fill="none" fill-rule="evenodd"><rect width="221.604" height="124.521" x=".5" y=".5" stroke="#EDEEEE" rx="20"/><mask id="b" fill="#fff"><use xlink:href="#a"/></mask><rect width="221.604" height="124.521" x=".5" y=".5" stroke="#EDEEEE" rx="20"/><path fill="#C3E0FD" d="M143.55447,-0.00189607028 L204.784987,2.84217094e-14 C215.717872,1.84598003 221.657534,8.25643943 222.603975,19.2313782 C222.687945,20.2050943 222.731609,25.2602168 222.734968,34.3967458 L222.734968,36.7659074 C222.731675,46.3902283 222.689641,59.9375047 222.608866,77.4077368 C213.542164,83.6334562 202.563196,87.2764482 190.733362,87.2764482 C159.591974,87.2764482 134.346892,62.031366 134.346892,30.8899789 C134.346892,19.4850348 137.732894,8.8709339 143.55447,-0.00189607028 Z" mask="url(#b)" opacity=".299"/><path fill="#28DFFF" d="M208.384778,71.5863002 C213.530249,71.5863002 218.399423,72.7692716 222.735163,74.8780793 L222.734968,105.950877 C222.383762,110.470422 220.976556,114.345124 218.513349,117.574983 C214.818539,122.419772 209.666712,124.766774 205.352978,125.521184 C204.715989,125.632584 202.366899,125.689677 198.305709,125.692462 L197.667403,125.692462 C194.081837,125.690105 189.270043,125.648852 183.232022,125.568704 C178.427461,119.857416 175.533531,112.485439 175.533531,104.437548 C175.533531,86.2943046 190.241535,71.5863002 208.384778,71.5863002 Z" mask="url(#b)" opacity=".116"/></g></svg>
\ No newline at end of file
<template>
<div class="tinymceBase">
<Editor
api-key="0tdy8tkwpzlqdxy4zv39t99jo6er7pxdy24bkq0batry668n"
:init="{
...DefaultConfig,
setup,
}"
/>
</div>
</template>
<script lang="ts">
import Editor from "@tinymce/tinymce-vue";
import { defineComponent } from "vue";
export default defineComponent({
data() {
const Id = Date.now();
return {
Id: Id.toString(),
Editor: null as any,
DefaultConfig: {
height: 400,
menubar: false,
toolbar1: `styleselect | fontselect | formatselect | fontsizeselect | forecolor backcolor | bold italic underline strikethrough | table | alignleft aligncenter alignright alignjustify | outdent indent | numlist bullist | removeformat hr | code link | undo redo | fullscreen `,
plugins: `
paste
importcss
table
advlist
fullscreen
link
media
lists
hr
preview
wordcount
`,
forced_root_block: "p",
importcss_append: true,
content_style: `
* { padding:0; margin:0; }
html, body { height:100%; }
a { text-decoration: none; }
iframe { width: 100%; }
p { line-height:1.6; margin: 0px; }
table { word-wrap:break-word; word-break:break-all; max-width:100%; border:none; border-color:#999; }
.mce-object-iframe { width:100%; box-sizing:border-box; margin:0; padding:0; }
ul,ol { list-style-position:inside; }
`,
insert_button_items: "image link | inserttable",
paste_webkit_styles: "all",
paste_merge_formats: true,
nonbreaking_force_tab: false,
paste_auto_cleanup_on_paste: false,
fontsize_formats: "10px 11px 12px 14px 16px 18px 20px 24px",
style_formats: [
{
title: "首行缩进",
block: "p",
styles: { "text-indent": "2em" },
},
{
title: "行高",
items: [
{ title: "1", styles: { "line-height": "1" }, inline: "span" },
{
title: "1.5",
styles: { "line-height": "1.5" },
inline: "span",
},
{ title: "2", styles: { "line-height": "2" }, inline: "span" },
{
title: "2.5",
styles: { "line-height": "2.5" },
inline: "span",
},
{ title: "3", styles: { "line-height": "3" }, inline: "span" },
],
},
],
// FontSelect
font_formats: `
微软雅黑=微软雅黑;
宋体=宋体;
黑体=黑体;
仿宋=仿宋;
楷体=楷体;
隶书=隶书;
幼圆=幼圆;
Andale Mono=andale mono,times;
Arial=arial, helvetica,
sans-serif;
Arial Black=arial black, avant garde;
Book Antiqua=book antiqua,palatino;
Comic Sans MS=comic sans ms,sans-serif;
`,
tabfocus_elements: ":prev,:next",
object_resizing: true,
language: "zh_CN",
},
};
},
components: {
Editor,
},
props: {
value: {
default: "",
type: String,
},
config: {
type: Object,
default: () => {
return {
theme: "modern",
height: 300,
};
},
},
url: {
default: "",
type: String,
},
maxSize: {
default: 2097152,
type: Number,
},
withCredentials: {
default: false,
type: Boolean,
},
},
beforeUnmount() {
this.Editor?.remove();
},
methods: {
setup(editor) {
this.Editor = editor;
editor.on("input change undo redo", () => {
this.$emit("input", editor.getContent());
});
},
},
});
</script>
<style lang="scss" scoped>
.tinymceBase {
width: 100%;
margin: 0 auto;
&::-webkit-scrollbar {
width: 10px;
height: 10px;
}
&::-webkit-scrollbar-track {
background: red;
border-radius: 2px;
}
&::-webkit-scrollbar-thumb {
background: red;
border-radius: 10px;
}
&::-webkit-scrollbar-thumb:hover {
background: red;
}
&::-webkit-scrollbar-corner {
background: red;
}
:deep(.mce-flow-layout-item.mce-last) {
display: none;
}
:deep(.mce-txt) {
width: 58px;
}
}
</style>
This diff is collapsed.
<template>
<TraceProofEdit v-bind="$attrs"></TraceProofEdit>
</template>
<script setup lang="ts">
import TraceProofEdit from "./TraceProofEdit/index.vue";
</script>
<style></style>
<template>
<common-dialog
:visible="visible"
showMask
@closePopup="emitClose"
type="element"
:elementDialogProps="{
title: '添加下一级',
}"
:btnConfig="{
type: 'noBorder',
btns: btns,
btnFunctions: [
{
name: '取消',
click: async () => {
emitClose();
return true;
},
},
{
name: '确定',
click: async () => {
return emitConfirm();
},
},
],
}"
>
<div class="c-dialog" v-if="visible">
<Scroll ref="scroll" class="max-h-80" type="normal">
<div
v-for="item in propertyList"
:key="item.id"
class="flex items-center mb-4"
>
<dialog-input
ref="List"
class="l-input t-input flex-grow"
v-model:value="item.label"
:errorShowing="isErrorShowing"
maxlength="10"
>
</dialog-input>
<div class="shanchu-con ml-4">
<i class="iconfont iconshanchu-" @click="deleteTmpItem(item)"></i>
</div>
</div>
</Scroll>
<div class="btn_add mt-3" @click="addNewProperty">
<Button
iconName="iconjixutianjia"
mode="iconBtnWithoutOutline2"
:style="'color: #b1b5bc;font-size:20px;'"
>继续添加</Button
>
</div>
</div>
</common-dialog>
</template>
<script lang="ts" setup>
import { btns } from "@/config/btns";
import {
syDialogInput as DialogInput,
getUuid,
syCommonDialog as CommonDialog,
syScroll as Scroll,
syButton as Button,
} from "cqk-sy-ui";
import { onMounted, ref } from "vue";
import { watch } from "vue";
interface Item {
id: string;
label: string;
}
/**
* 添加下一级字段
* @author yuanzeyu
* @date 2019-06-04
* @desc
*/
const propertyList = ref([] as Item[]);
const isErrorShowing = ref(false);
const scroll = ref<{ scrollToEnd: any } | null>(null);
const $emit = defineEmits(["confirm", "close"]);
const props = defineProps<{
visible: boolean;
}>();
const addNewProperty = () => {
propertyList.value.push({
id: getUuid(),
label: "",
});
if (props.visible) {
setTimeout(() => {
scrollToEnd();
}, 300);
}
};
// 删除
const deleteTmpItem = (item: Item) => {
for (let i = propertyList.value.length - 1; i > -1; i--) {
let _item = propertyList.value[i];
if (_item.id == item.id) {
propertyList.value.splice(i, 1);
break;
}
}
if (propertyList.value.length == 0) {
emitClose();
}
};
const scrollToEnd = () => {
scroll.value?.scrollToEnd();
};
const emitConfirm = () => {
const empty = propertyList.value.some((item) => item.label.length === 0);
if (empty) {
isErrorShowing.value = true;
return false;
}
$emit(
"confirm",
propertyList.value.map((item) => item.label)
);
emitClose();
return true;
};
const emitClose = () => {
$emit("close");
};
onMounted(() => {
addNewProperty();
});
watch(
() => props.visible,
(newV) => {
if (newV === true) {
propertyList.value = [];
addNewProperty();
isErrorShowing.value = false;
}
}
);
</script>
<style scoped lang="scss">
/* 添加模板公用样式 */
.c-dialog {
box-sizing: content-box;
}
.g-btn_primary {
border: none;
background: var(--sy-blue);
font-size: 14px;
color: #fff;
outline: none;
cursor: pointer;
border-radius: 8px;
}
.c-dialog-title {
margin: 0;
font-size: 22px;
line-height: 30px;
color: #000;
font-weight: 500;
}
.c-dialog-input {
box-sizing: border-box;
padding: 0 26px;
width: 500px;
height: 44px;
border: 1px solid #e2e2e2;
font-weight: 400;
font-size: 18px;
background: transparent;
outline: none;
}
.c-dialog-btn_wrapper {
text-align: right;
}
.c-dialog-btn_confirm {
width: 120px;
height: 40px;
border-radius: 4px;
&:after {
clear: both;
}
}
.c-dialog-btn_cancel {
margin-right: 22px;
/* 28 - (40 - 28) / 2 */
color: #5c6476;
background: transparent;
height: 40px;
width: 60px;
}
.c-dialog-btn_wrapper {
padding-right: 50px;
}
.l-title {
margin-bottom: 42px;
}
.l-input {
display: flex;
align-items: center;
}
.btn_add {
color: #abafb6;
line-height: 20px;
height: 20px;
font-size: 0;
cursor: pointer;
white-space: nowrap;
text-overflow: ellipsis;
}
.btn_add-icon {
margin: 1px 6px 0 0;
display: inline-block;
vertical-align: top;
font-size: 20px;
color: #b1b5bc;
}
.btn_add-text {
font-size: 14px;
vertical-align: top;
}
.l-btn_wrapper {
margin-top: 11px;
}
.shanchu-con {
display: inline-block;
position: relative;
line-height: 44px;
}
.iconshanchu- {
font-size: 20px;
left: 0;
top: 0;
color: #eaeaea;
}
.dialog-input-con-con {
height: 360px;
position: relative;
}
.dialog-input-con {
position: absolute;
z-index: 1;
top: 45px;
bottom: 48px;
left: 0;
width: 100%;
background: #aaa;
overflow: auto;
}
:deep(.c-dialog) {
max-height: 600px;
}
:deep(.dialog_content) {
max-height: 570px;
}
:deep(.pc-myscroll) {
height: auto;
max-height: 360px;
}
:deep(.mylist) {
padding: 5px 0 5px 0;
}
:deep(.mybar) {
background-color: #efefef;
width: 16px;
}
</style>
<template>
<!-- 添加一级标题组件 -->
<div class="add_level1_button" @click="$emit('click')">
<div class="button">
<i class="iconfont icontianjia button-icon"></i>
</div>
<span class="label">{{ title }}</span>
</div>
</template>
<script lang="ts" setup>
defineProps<{
title?: string;
}>();
defineEmits(["click"]);
</script>
<style scoped>
.add_level1_button {
display: inline-block;
cursor: pointer;
}
.button {
display: inline-block;
width: 39px;
height: 39px;
background: #15cbba;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2);
border-radius: 50%;
color: #fff;
text-align: center;
line-height: 39px;
}
.button-icon {
font-size: 15px;
}
.label {
margin-left: 15px;
color: #15cbba;
font-size: 14px;
line-height: 39px;
font-weight: 500;
}
</style>
import { PropertyType } from "./types";
export interface RootUnitItem { // 一级单元
id: string;
title: string;
children: Array<UnitItem | PropertyItem>;
}
export interface UnitItem { // 二级单元项
id: string;
type: PropertyType.Unit;
info: UnitInfo;
}
export interface UnitInfo {
title: string;
children: PropertyItem[];
}
export interface PropertyItem { // 属性项
id: string;
type: PropertyType;
info: AllProperty;
}
export type AllProperty = InputInfo | SelectInfo | DateInfo | ImageInfo;
export interface InputInfo extends PropertyItem {
label: string;
type: PropertyType.Input;
value: string;
}
export interface SelectInfo {
label: string;
value: string;
options: string[];
}
export interface Option {
id: string;
label: string;
}
export interface DateInfo {
label: string;
value: string;
}
export interface ImageInfo {
label: string;
imgList: ImageItem[];
}
export interface ImageItem {
url: string;
dataUrl: string;
file: File | null;
}
<template>
<!-- 添加一级标题输入框 -->
<common-dialog
:visible="visible"
@closePopup="emitClose"
type="element"
showMask
:elementDialogProps="{
title: '添加一级标题',
}"
:btnConfig="{
type: 'noBorder',
btns,
btnFunctions: [
{
name: '取消',
async click() {
return true;
},
},
{
name: '确定',
click: emitConfirm,
},
],
}"
>
<div class="c-dialog" v-if="visible">
<!-- <h2 class="c-dialog-title">添加一级标题</h2> -->
<dialog-input
class="l-input t-input"
v-model:value="bindValue"
:errorShowing="isErrorShowing"
placeholder="输入一级标题名称"
:maxlength="limit"
/>
<SelectVue
class="type-select"
v-model="unitType"
placeholder="请选择类型"
>
<OptionVue label="所有类型" :value="3"></OptionVue>
<OptionVue label="JSON" :value="12"></OptionVue>
</SelectVue>
<!-- <div class="c-dialog-btn_wrapper">
<button class="g-btn_primary c-dialog-btn_cancel" @click="emitClose">
取消
</button>
<button class="g-btn_primary c-dialog-btn_confirm" @click="emitConfirm">
确定
</button>
</div> -->
</div>
</common-dialog>
</template>
<script lang="ts" setup>
import { btns } from "@/config/btns";
import {
syCommonDialog as CommonDialog,
syDialogInput as DialogInput,
sySelect as SelectVue,
syOption as OptionVue,
} from "cqk-sy-ui";
import { ref } from "vue";
const props = defineProps<{
visible: boolean;
}>();
const emit = defineEmits(["confirm", "close"]);
const limit = ref(10);
const bindValue = ref("");
const isErrorShowing = ref(false);
const unitType = ref(3);
const emitConfirm = async () => {
if (bindValue.value.length === 0) {
isErrorShowing.value = true;
return false;
}
emit("confirm", bindValue.value, unitType.value);
emitClose();
return true;
};
const emitClose = () => {
bindValue.value = "";
unitType.value = 3;
emit("close");
};
</script>
<style scoped lang="scss">
.l-input {
margin: 0px 0 20px 0;
width: 100%;
}
.type-select {
width: 100%;
:deep(.el-input.is-focus) .el-input__inner,
:deep(.el-input__inner:focus) {
border-color: var(--sy-blue);
}
}
/* 添加模板公用样式 */
.c-dialog {
box-sizing: content-box;
}
.c-dialog-title {
margin: 0;
font-size: 22px;
line-height: 30px;
color: #000;
font-weight: 500;
}
.c-dialog-btn_wrapper {
text-align: right;
}
.g-btn_primary {
border: none;
background: var(--sy-blue);
font-size: 14px;
color: #fff;
outline: none;
cursor: pointer;
border-radius: 8px;
}
.c-dialog-btn_confirm {
width: 120px;
height: 40px;
border-radius: 4px;
&:after {
clear: both;
}
}
.c-dialog-btn_cancel {
margin-right: 22px;
/* 28 - (40 - 28) / 2 */
color: #5c6476;
background: transparent;
height: 40px;
width: 60px;
}
</style>
<style lang="scss">
.el-select-dropdown__item.selected {
color: var(--sy-blue);
}
.type-select {
.el-input__inner {
padding-left: 26px;
height: 44px;
line-height: 44px;
}
}
</style>
<template>
<div class="category-add">
<!-- <h2 class="dialog_add-title">请选择模板分类</h2> -->
<SelectVue v-model="value" placeholder="请选择">
<OptionVue
v-for="item in MyCategories"
:key="item.value"
:label="item.name"
:value="item.id"
></OptionVue>
</SelectVue>
<!-- <button class="dialog_add-btn_confirm" @click="checkForm">确定</button>
<button class="dialog_add-btn_cancel" @click="closeDialog">取消</button> -->
</div>
</template>
<script lang="ts">
import { defineComponent } from "vue";
import {
GO_URLS,
sySelect as SelectVue,
syOption as OptionVue,
} from "cqk-sy-ui";
import { ElMessage } from "element-plus";
import { $ajax } from "@/service";
export default defineComponent({
components: {
SelectVue,
OptionVue,
},
data() {
return {
name: "",
// isErrorShowing: false, // 错误提示
isInActive: false,
MyCategories: [] as any,
value: "",
};
},
// components: { DialogInput },
created() {
this.getFolderList();
},
methods: {
async checkForm() {
if (this.isInActive) return;
this.isInActive = true;
// this.isErrorShowing = true;
// 追加非空验证
if (this.value === "") {
ElMessage("请选择分类");
this.isInActive = false;
return null;
}
if (this.value) {
this.$emit("successCallback", this.value);
}
this.isInActive = false;
},
closeDialog() {
this.$emit("close");
},
// 获取我的模板列表
async getFolderList() {
const res = await $ajax({
type: "post",
url: GO_URLS.folderList,
params: {
page: 1,
page_size: 100,
template_type: 1,
},
});
if (res) {
this.MyCategories = res.data.results;
}
},
},
});
</script>
<style lang="scss" scoped>
.category-add {
background: rgba(255, 255, 255, 1);
}
.dialog_add-title {
margin: 0;
color: #000;
font-size: 22px;
line-height: 30px;
padding-left: 44px;
padding-top: 45px;
padding-bottom: 45px;
}
.dialog_add-input_name {
margin-left: 50px;
margin-top: 39px;
margin-bottom: 18px;
}
.dialog_add-btn_confirm {
float: right;
width: 120px;
height: 40px;
color: #fff;
font-size: 14px;
outline: none;
background: var(--sy-blue);
border-radius: 4px;
border: none;
cursor: pointer;
margin-right: 39px;
}
.dialog_add-btn_cancel {
float: right;
margin-right: 18px; /* 28 - 10 */
border: none;
width: 48px; /* 28 + 增大20 */
height: 40px;
outline: none;
background: #fff;
color: #5c6476;
font-size: 14px;
cursor: pointer;
}
.el-select {
width: 100%;
}
:deep(.el-input__inner) {
height: 44px;
padding: 0 26px;
}
</style>
import { Unit } from "./types2";
export function findSelectTarget(unitList: Unit[], selectTargetId: string) {
const newUnitList = [...unitList];
const unit = newUnitList.find((i) => i.id === selectTargetId);
if (unit) {
return {
list: newUnitList,
item: unit,
};
} else {
for (let i = 0; i < newUnitList.length; ++i) {
const list = newUnitList[i].children;
const u = list.find((i) => i.id === selectTargetId);
if (u)
return {
list: newUnitList,
item: u,
};
}
}
return {
list: newUnitList,
item: undefined,
};
}
<template>
<div class="category-add">
<!-- <h2 class="dialog_add-title">修改标题名</h2> -->
<dialog-input
class="dialog_add-form dialog_add-input_name"
v-model:value="editTitle"
maxlength="10"
:errorShowing="isErrorShowing"
placeholder="请输入标题名称"
/>
<!-- <button class="dialog_add-btn_confirm" @click="changeEdit">确定</button>
<button class="dialog_add-btn_cancel" @click="closeDialog">取消</button> -->
</div>
</template>
<script lang="ts">
import { syDialogInput as DialogInput } from "cqk-sy-ui";
import { ElMessage } from "element-plus";
import { defineComponent } from "vue";
export default defineComponent({
// 引入组件
components: {
DialogInput,
},
props: ["selectedEditItem", "setSelectedEditItem"],
emits: ["close"],
data() {
return {
editTitle: "",
isErrorShowing: false,
};
},
watch: {
selectedEditItem: {
handler(newName, oldName) {
if (newName.title) this.editTitle = newName.title;
if (newName.label) this.editTitle = newName.label;
},
deep: true,
immediate: true,
},
},
computed: {},
methods: {
changeEdit() {
if (this.editTitle.trim() === "") {
this.isErrorShowing = true;
return;
}
this.$nextTick(() => {
if (this.selectedEditItem) {
if (
Object.prototype.hasOwnProperty.call(this.selectedEditItem, "title")
) {
const temp = this.selectedEditItem;
temp.title = this.editTitle;
this.setSelectedEditItem(temp);
}
if (
Object.prototype.hasOwnProperty.call(this.selectedEditItem, "label")
) {
const temp = this.selectedEditItem;
temp.label = this.editTitle;
this.setSelectedEditItem(temp);
}
}
});
this.$emit("close");
},
// 取消
closeDialog() {
if (
this.selectedEditItem &&
this.selectedEditItem.title &&
this.selectedEditItem.title.trim() === ""
) {
ElMessage.warning("标题不可为空");
return false;
}
this.$emit("close");
},
},
});
</script>
<style scoped lang="scss">
.category-add {
box-sizing: content-box;
}
.dialog_add-title {
margin: 0;
color: #000;
font-size: 22px;
line-height: 30px;
}
.dialog_add-select_subject {
margin-top: 29px;
}
.dialog_add-input_name {
width: 100%;
}
.dialog_add-btn_confirm {
float: right;
width: 120px;
height: 40px;
color: #fff;
font-size: 14px;
outline: none;
background: var(--sy-blue);
border-radius: 4px;
border: none;
cursor: pointer;
}
.dialog_add-btn_cancel {
float: right;
margin-right: 18px; /* 28 - 10 */
border: none;
width: 48px; /* 28 + 增大20 */
height: 40px;
outline: none;
background: #fff;
color: #5c6476;
font-size: 14px;
cursor: pointer;
}
</style>
<template>
<div>
<div class="title">
<i v-if="item.state === '上传成功'" class="iconfont iconxingzhuang2"></i
>{{ item.state }}
</div>
<div class="progress-bar" v-if="item.speed !== 100">
<div class="progress-bar__outer">
<div
class="progress-bar__inner"
:style="Style"
:class="{ bgw: suss }"
></div>
</div>
</div>
<div class="svgbox" @click="$emit('termination')">
<i class="iconfont iconshanchu1"></i>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
data() {
return {
suss: false,
};
},
props: ["item"],
watch: {
item: {
handler(val, oldVal) {
if (val.speed === 100) {
val.state = "上传成功";
this.suss = true;
}
},
deep: true,
immediate: true,
},
},
computed: {
Style() {
const style = {
width: this.item.speed + "%",
};
return style;
},
},
});
</script>
<style lang="scss" scoped>
.svgbox {
cursor: pointer;
float: right;
margin-left: 10px;
color: #b6b5ba;
i {
font-size: 12px;
}
}
.title {
width: 74px;
font-size: 14px;
float: left;
font-weight: 500;
color: rgba(53, 53, 53, 1);
line-height: 40px;
i {
vertical-align: bottom;
margin-right: 2px;
color: #33c724;
}
}
.progress-bar {
display: inline-block;
vertical-align: middle;
width: 170px;
box-sizing: border-box;
.progress-bar__outer {
height: 6px;
border-radius: 100px;
background-color: #ebeef5;
overflow: hidden;
position: relative;
vertical-align: middle;
}
.progress-bar__inner {
position: absolute;
left: 0;
top: 0;
height: 100%;
background-color: var(--sy-blue);
text-align: right;
border-radius: 100px;
line-height: 1;
white-space: nowrap;
transition: width 0.6s ease;
&::after {
display: inline-block;
content: "";
height: 100%;
vertical-align: middle;
}
}
.bgw {
background: white !important;
transition: none !important;
}
}
</style>
<template>
<div>
<base-form
v-if="property.type === PropertyType.Input"
:label="property.label"
:value="(property.value as string)"
@changeValue="changeValue"
:isDisabled="isDisabled"
/>
<date-form
v-else-if="property.type === PropertyType.Date"
:label="property.label"
:value="(property.value as string)"
@changeValue="changeValue"
:isDisabled="isDisabled"
/>
<select-form
v-else-if="property.type === PropertyType.Select"
:label="property.label"
@changeValue="changeValue"
:property="property"
:isDisabled="isDisabled"
:setPropertyOptions="setPropertyOptions"
/>
<image-form
v-else-if="property.type === PropertyType.Image"
:property="property"
:disable="isDisabled"
:setPropertyValue="setPropertyValue"
/>
<editor-form
v-if="property.type === PropertyType.Editor"
:property="property"
:label="property.label"
:setPropertyValue="setPropertyValue"
/>
<p-d-f-forms
v-else-if="property.type === PropertyType.File"
:property="property"
:setPropertyValue="setPropertyValue"
:disable="isDisabled"
/>
<video-forms
v-else-if="property.type === PropertyType.Video"
:property="property"
:setPropertyValue="setPropertyValue"
/>
<AudioForm
v-else-if="property.type === PropertyType.Audio"
:property="property"
:setPropertyValue="setPropertyValue"
/>
<TextAreaForm
v-else-if="property.type === PropertyType.TextArea"
:property="property"
:setPropertyValue="setPropertyValue"
/>
<link-form
v-else-if="property.type === PropertyType.Link"
:property="property"
:label="property.label"
:value="(property.value as string)"
@changeValue="changeValue"
:isDisabled="isDisabled"
></link-form>
<json-form
v-else-if="property.type === PropertyType.JSON"
:property="property"
:setPropertyValue="setPropertyValue"
/>
<image-url-form
v-else-if="property.type === PropertyType.ImageUrl"
:property="property"
:setPropertyValue="setPropertyValue"
/>
<text-array-form
v-if="property.type === PropertyType.TextArray"
:property="property"
:setPropertyValue="setPropertyValue"
/>
</div>
</template>
<script lang="ts" setup>
import { Property } from "./types2";
import { PropertyType } from "./types";
import ImageForm from "./form/ImageForm.vue";
import SelectForm from "./form/SelectForm.vue";
import PDFForms from "./form/PDFForms.vue";
import VideoForms from "./form/VideoForm.vue";
import BaseForm from "./form/BaseForm.vue";
import DateForm from "./form/DateForm.vue";
import EditorForm from "./form/EditorForm.vue";
import AudioForm from "./form/AudioForm.vue";
import TextAreaForm from "./form/TextAreaForm.vue";
import LinkForm from "./form/LinkForm.vue";
import JsonForm from "./form/JSONForm.vue";
import ImageUrlForm from "./form/ImageUrlForm.vue";
import TextArrayForm from "./form/TextArrayForm.vue";
import { nextTick } from "vue";
const props = withDefaults(
defineProps<{
property: Property;
isDisabled?: boolean;
setProperty: (v: any) => void;
}>(),
{
isDisabled: false,
}
);
const setPropertyValue = (v: string | string[]) => {
const p = props.property;
p.value = v;
props.setProperty(p);
};
const setPropertyOptions = (v: string[]) => {
const p = props.property;
p.options = v;
props.setProperty(p);
};
const changeValue = (newData: any, key: string) => {
nextTick(() => {
const property: any = props.property;
property[key] = newData;
props.setProperty(property);
});
};
</script>
<style scoped></style>
This diff is collapsed.
<template>
<div
class="select_box w-full"
:class="{ 'js-select_box_active': select }"
@click.stop="$emit('click')"
@click.capture="$emit('click')"
draggable="true"
@dragstart.stop="dragstart"
@dragend.stop="dragend"
@dragover.stop="dragover"
>
<i
class="iconfont iconshezhi"
:class="{ iconshezhi_right: check === 3 }"
v-show="select"
@click="showMenu"
></i>
<ul class="menu-change" v-show="select && isMenuShowing" @mousedown.stop>
<li
class="menu-item menu-item__one"
v-if="check !== 3 && check !== 12 && parent_type !== 12"
@click.stop="modifyForms"
>
修改表现形式
</li>
<li class="menu-item menu-item__two" @click.stop="modifyTitle">
修改标题
</li>
<li
class="menu-item menu-item__two"
v-if="show !== 3"
@click.stop="addNextlevel"
>
添加下一级
</li>
<li class="menu-item menu-item__two" @click.stop="del">删除</li>
</ul>
<div class="flex item-center w-full">
<slot></slot>
</div>
<div v-show="select">
<div class="dash dash_1"></div>
<div class="dash dash_2"></div>
<div class="dash dash_3"></div>
<div class="dash dash_4"></div>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref } from "vue";
const isMenuShowing = ref(false);
const props = withDefaults(
defineProps<{
select?: boolean;
check?: number;
show?: number;
parent_type?: number;
}>(),
{}
);
const emit = defineEmits([
"dragstart",
"dragend",
"dragover",
"modifyForms",
"modifyTitle",
"addNextlevel",
"del",
"click",
]);
const dragstart = ($event: any) => {
$event.dataTransfer.setData("imgInfo", $event.target.id);
emit("dragstart");
};
const dragend = ($event: any) => {
emit("dragend");
};
const dragover = ($event: any) => {
emit("dragover");
};
// 修改表现形式
const modifyForms = () => {
onMenuBlur();
emit("modifyForms");
};
// 修改标题
const modifyTitle = () => {
onMenuBlur();
emit("modifyTitle");
};
// 添加下一级
const addNextlevel = () => {
onMenuBlur();
emit("addNextlevel");
};
// 执行删除
const del = () => {
onMenuBlur();
emit("del");
};
// 显示操作栏
const showMenu = () => {
isMenuShowing.value = true;
document.addEventListener("mousedown", onMenuBlur);
};
//隐藏操作栏
const onMenuBlur = () => {
isMenuShowing.value = false;
document.removeEventListener("mousedown", onMenuBlur);
};
</script>
<style scoped lang="scss">
.menu-change {
z-index: 100; /* 避免被底部挡住 */
position: absolute;
top: 100%;
right: -63px;
margin: 0;
padding: 0;
width: 124px;
list-style: none;
background: #fff;
text-align: center;
border: 1px solid #e7e7e7;
border-radius: 2px;
}
.menu-item__one {
&::after {
content: "";
display: block;
position: absolute;
width: 10px;
height: 10px;
border-top: 1px solid #e7e7e7;
border-left: 1px solid #e7e7e7;
background: white;
top: -6px;
left: 87px;
transform: rotate(45deg);
}
&:hover {
background: rgba(242, 244, 246, 1);
&::after {
background: rgba(242, 244, 246, 1);
}
}
}
.menu-item {
line-height: 40px;
color: #797d84;
font-size: 14px;
cursor: pointer;
}
.menu-item__two {
&:hover {
background: rgba(242, 244, 246, 1);
}
}
.select_box {
position: relative;
box-sizing: border-box;
border: 1px solid transparent;
}
.js-select_box_active {
border: 1px dashed gray;
}
.iconshezhi {
color: #e6e6e6;
position: absolute;
right: -46px;
font-size: 24px;
margin-left: 22px;
cursor: pointer;
z-index: 98;
top: 50%;
transform: translateY(-50%);
}
.check {
background: rgba(63, 121, 254, 0.5);
}
.dash {
position: absolute;
width: 8px;
height: 8px;
border: 1px solid #d8d9da;
background: #fff;
}
.dash_1 {
top: -5px;
left: -5px;
}
.dash_2 {
top: -5px;
right: -5px;
}
.dash_3 {
right: -5px;
bottom: -5px;
}
.dash_4 {
left: -5px;
bottom: -5px;
}
.pre-tag {
position: absolute;
left: -30px;
top: 23px;
display: none;
}
</style>
<template>
<div class="set_bar">
<h2 class="title">重命名</h2>
<DialogInputVue
class="edit"
v-model:value="editTitle"
placeholder="请输入标题名"
:disabled="rootState?.selectEditItemId.value === ''"
:maxlength="10"
@input="changeEdit"
></DialogInputVue>
<h2
class="title"
v-show="
!(
selectTarget?.type === PropertyType.Unit ||
selectTarget?.type === PropertyType.JSON ||
selectTarget === null
)
"
>
选择表单类型
</h2>
<ul
class="menu flex flex-wrap justify-between"
v-show="
!(
selectTarget?.type === PropertyType.Unit ||
selectTarget?.type === PropertyType.JSON ||
selectTarget === null
)
"
>
<set-select-item
label="单行输入"
:selected="type === PropertyType.Input"
:disabled="selectedDisabled"
@click="handleSelect(PropertyType.Input)"
>
</set-select-item>
<set-select-item
label="外部链接"
:selected="type === PropertyType.Link"
:disabled="selectedDisabled"
@click="handleSelect(PropertyType.Link)"
>
</set-select-item>
<set-select-item
label="文本域"
:selected="type === PropertyType.TextArea"
:disabled="selectedDisabled"
@click="handleSelect(PropertyType.TextArea)"
>
</set-select-item>
<set-select-item
label="下拉框"
:selected="type === PropertyType.Select"
:disabled="selectedDisabled"
@click="handleSelect(PropertyType.Select)"
>
</set-select-item>
<set-select-item
label="上传图片"
:selected="type === PropertyType.Image"
:disabled="selectedDisabled"
@click="handleSelect(PropertyType.Image)"
>
</set-select-item>
<set-select-item
label="日期"
:selected="type === PropertyType.Date"
:disabled="selectedDisabled"
@click="handleSelect(PropertyType.Date)"
>
</set-select-item>
<set-select-item
label="上传PDF"
:selected="type === PropertyType.File"
:disabled="selectedDisabled"
@click="handleSelect(PropertyType.File)"
>
</set-select-item>
<set-select-item
label="上传视频"
:selected="type === PropertyType.Video"
:disabled="selectedDisabled"
@click="handleSelect(PropertyType.Video)"
>
</set-select-item>
<set-select-item
label="上传语音"
:selected="type === PropertyType.Audio"
:disabled="selectedDisabled"
@click="handleSelect(PropertyType.Audio)"
>
</set-select-item>
<set-select-item
label="图片链接"
:selected="type === PropertyType.ImageUrl"
:disabled="selectedDisabled"
@click="handleSelect(PropertyType.ImageUrl)"
>
</set-select-item>
<set-select-item
label="文本数组"
:selected="type === PropertyType.TextArray"
:disabled="selectedDisabled"
@click="handleSelect(PropertyType.TextArray)"
>
</set-select-item>
<set-select-item
label="编辑器"
:selected="type === PropertyType.Editor"
:disabled="selectedDisabled"
@click="handleSelect(PropertyType.Editor)"
>
</set-select-item>
</ul>
<h2 class="title" v-if="showUpload">上传banner图</h2>
<set-select-item
v-if="showUpload"
:selected="false"
:disabled="false"
label=""
@click="$emit('uploadBanner')"
>
<img src="@/assets/img/upload.svg" style="margin-right: 4px" alt="" />
点击上传
</set-select-item>
</div>
</template>
<script lang="ts" setup>
import { PropertyType } from "./types";
import { Property, Unit } from "./types2";
import SetSelectItem from "./SetSelectItem.vue";
import { computed, inject, nextTick, ref, watch, toRaw, unref, Ref } from "vue";
import { syDialogInput as DialogInputVue } from "cqk-sy-ui";
import { findSelectTarget } from "./ModifySelectTarget";
const props = defineProps<{
selectTarget: Unit | Property | null;
showUpload?: boolean;
setSelectedItem: any;
}>();
const emit = defineEmits([
"select-type",
"add-child",
"delete",
"uploadBanner",
]);
const rootState = inject<{
selectEditItemId: Ref<string>;
rootUnitList: Ref<Unit[]>;
setRootUnitList: (list: Unit[]) => void;
focusedTarget: Ref<Unit>;
}>("editRootState");
const editTitle = ref(``);
const type = computed(() => {
return rootState?.focusedTarget.value?.type;
});
watch(
() => props.selectTarget,
(newV: any) => {
if (newV) {
editTitle.value = newV.title || newV.label || "";
} else {
editTitle.value = "";
}
}
);
const changeEdit = () => {
nextTick(() => {
if (props.selectTarget) {
if (Object.prototype.hasOwnProperty.call(props.selectTarget, "title"))
if (editTitle.value.length >= 1) {
(props.selectTarget as Unit).title = editTitle.value;
}
if (Object.prototype.hasOwnProperty.call(props.selectTarget, "label"))
if (editTitle.value.length >= 1) {
(props.selectTarget as Property).label = editTitle.value;
}
}
});
};
const selectedDisabled = computed(() => {
return (
props.selectTarget?.type === PropertyType.Unit ||
props.selectTarget?.type === PropertyType.None ||
props.selectTarget?.type === PropertyType.JSON ||
props.selectTarget?.parent?.type === PropertyType.JSON
);
});
const handleSelect = (val: PropertyType) => {
if (selectedDisabled.value) return;
const { item, list } = findSelectTarget(
toRaw(unref(rootState!.rootUnitList)),
toRaw(unref(rootState!.selectEditItemId))
);
if (item) {
item.type = val;
(item as any).value = "";
rootState?.setRootUnitList(list);
}
};
</script>
<style scoped lang="scss">
.set_bar {
position: relative;
height: 100%;
}
.editor {
width: 125px;
vertical-align: middle;
display: inline-block;
background: white;
vertical-align: middle;
box-sizing: border-box;
margin-left: 10px;
display: inline-block;
height: 35px;
border: 1px solid #e7e7e7;
border-radius: 4px;
color: rgba(53, 53, 53, 0.4);
font-size: 12px;
}
.edit {
width: 100%;
margin-top: 16px;
:deep(.el-input__inner) {
font-size: 12px;
&::-webkit-input-placeholder {
/* WebKit browsers */
font-size: 12px;
}
&::-moz-placeholder {
/* Mozilla Firefox 19+ */
font-size: 12px;
}
}
}
.g-btn_primary {
border: none;
background: var(--sy-blue);
font-size: 14px;
color: #fff;
outline: none;
cursor: pointer;
border-radius: 8px;
}
.title {
font-size: 14px;
font-weight: 500;
margin-top: 9px;
margin-bottom: 14px;
color: var(--sy-black);
}
.menu {
margin: 0;
padding: 0;
list-style: none;
}
.menu-item {
padding-left: 23px;
line-height: 35px;
font-size: 0;
margin-top: 18px; /* todo ui间距不统一,文字非对齐 */
}
.menu-item-icon_check {
vertical-align: middle;
display: inline-block;
width: 15px;
height: 15px;
border: 1px solid #d1d1d1;
border-radius: 50%;
cursor: pointer;
}
.menu-item_icon_check_active {
vertical-align: middle;
color: #50b74d;
font-size: 17px;
}
.menu-item-name {
vertical-align: middle;
display: inline-block;
width: 56px;
margin-left: 9px;
font-size: 14px;
}
.menu-item-name_active {
color: #4fb64c;
}
.menu-item-example {
vertical-align: middle;
box-sizing: border-box;
margin-left: 10px;
display: inline-block;
height: 35px;
border: 1px solid #e7e7e7;
border-radius: 4px;
color: rgba(53, 53, 53, 0.4);
font-size: 12px;
}
.menu-item-example_input {
width: 125px;
padding-left: 13px;
height: 25px;
background: white;
line-height: 25px;
}
.menu-item-example_input_half {
width: 58px;
padding-left: 13px;
height: 25px;
background: white;
line-height: 25px;
}
.menu-item-example_select {
width: 125px;
padding: 0 5px 0 12px;
height: 25px;
line-height: 25px;
background: white;
i {
float: right;
font-size: 12px;
transform: scale(0.46);
}
}
.menu-item-example_image {
width: 25px;
height: 25px;
text-align: center;
background: white;
line-height: 23px;
font-size: 12px;
i {
font-size: 12px;
}
}
.menu-item-example_up {
width: 35px;
height: 25px;
background: rgba(255, 255, 255, 1);
border-radius: 4px;
text-align: center;
line-height: 25px;
border: 1px solid rgba(231, 231, 231, 1);
}
.menu-item-example_date {
width: 125px;
padding: 0 8px 0 12px;
height: 25px;
line-height: 25px;
background: white;
& i {
float: right;
font-size: 13px;
}
}
.btn_wrapper {
position: absolute;
right: 0;
bottom: 39px;
left: 0;
text-align: center;
& > button {
margin-top: 20px;
width: 220px;
height: 35px;
}
}
.js-btn_disabled {
background: #c5cfe8;
cursor: not-allowed;
}
</style>
<template>
<div
class="set_select_item cursor-pointer"
:class="{
set_select_item_active: selected,
' cursor-not-allowed': disabled,
}"
@click="() => !disabled && $emit('click')"
>
<div v-show="selected">
<div class="items-center flex">
<Icon
size="14"
iconName="icona-bianzu2"
style="margin-right: 7px"
></Icon>
<span
class="label_check label_selected"
:class="{ 'js-selected_disable': disabled }"
>{{ label }}
</span>
</div>
</div>
<div v-show="!selected">
<span class="label_check">{{ label }}</span>
</div>
<slot></slot>
</div>
</template>
<script lang="ts" setup>
import Icon from "@/components/Icon/index.vue";
defineProps<{ selected: boolean; label: string; disabled: boolean }>();
defineEmits(["click"]);
</script>
<style scoped>
.set_select_item {
width: 107px;
height: 35px;
background: #ffffff;
border-radius: 4px;
border: 1px solid #d9d9d9;
line-height: 35px;
margin-top: 8px;
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #353535;
}
.set_select_item_active {
background: #f1f6ff;
border: 1px solid var(--sy-blue);
}
.icon_selected {
vertical-align: middle;
color: #15cbba;
font-size: 17px;
}
.icon_check {
vertical-align: middle;
display: inline-block;
width: 15px;
height: 15px;
border: 1px solid #d1d1d1;
border-radius: 50%;
cursor: pointer;
}
.label_check {
vertical-align: middle;
display: inline-block;
font-size: 12px;
}
.label_selected {
color: var(--sy-blue);
}
.js-selected_disable {
color: #acaab7;
}
</style>
This diff is collapsed.
<template>
<div class="base_form">
<div class="label">
<Icon iconName="icondd" class="pre-tag" size="18"></Icon>
<div class="label-text">{{ property.label }}</div>
</div>
<div class="flex-grow">
<div class="up flex items-center justify-center" @click="upFile">
<i class="iconfont iconyinpin2"></i>
&nbsp;上传音频
</div>
<div
class="show w-full"
v-for="(item, index) in localObjects"
:key="index"
>
<i class="iconfont iconyinpin-copy"></i>
<p @click="play(item)">{{ item.name }}</p>
<div class="show-rigth">
<i class="iconfont iconxingzhuang2"></i>上传成功
<i class="iconfont iconshanchu1" @click="deleteAudios(index)"></i>
</div>
</div>
</div>
<input
type="file"
hidden
ref="inputDom"
accept="audio/*"
@change="fileChange"
/>
<common-dialog
v-if="showAudio"
@closePopup="showAudio = false"
showMask
@ClickingBackground="showAudio = false"
>
<div class="audio-box">
<audio :controls="true" style="outline: none" :src="Aurl"></audio>
</div>
</common-dialog>
</div>
</template>
<script lang="ts">
import { GO_URLS, syCommonDialog as CommonDialog } from "cqk-sy-ui";
import Icon from "@/components/Icon/index.vue";
import { defineComponent, PropType } from "vue";
import { ElMessage } from "element-plus";
import { $ajax } from "@/service";
export default defineComponent({
inject: ["showTip"],
props: {
property: {
type: Object as PropType<any>,
required: true,
},
setPropertyValue: {
type: Function as PropType<any>,
required: true,
},
},
data() {
return {
localObjects: [] as any,
localHash: [] as any, // 本地hash
showAudio: false,
Aurl: "",
};
},
components: {
CommonDialog,
Icon,
},
mounted() {
if (Array.isArray(this.property.value)) {
// this.property.value = this.property.value.filter(
// (item) => item.value !== ""
// );
this.setPropertyValue(
this.property.value.filter((item) => item.value !== "")
);
}
if (this.property.value.length > 0) {
let hashes = [] as any;
for (let index = 0; index < this.property.value.length; index++) {
const element = this.property.value[index];
if (element.value) {
hashes.push(element.value);
}
}
if (hashes.length === this.property.value.length) {
this.getAudios(hashes);
}
}
},
watch: {
localHash: {
handler(newV, oldV) {
// this.property.value = newV;
this.setPropertyValue(newV);
},
deep: true,
},
},
methods: {
play(item) {
this.Aurl = item.url;
this.showAudio = true;
},
deleteAudios(index) {
(this as any).showTip(
"此操作将永久删除该文件, 是否继续?",
() => {
this.localHash.splice(index, 1);
this.localObjects.splice(index, 1);
ElMessage({
type: "success",
message: "删除成功!",
});
},
() => {
ElMessage({
type: "info",
message: "已取消删除",
});
}
);
},
// 上传文件
upFile() {
(this.$refs as any).inputDom.click();
},
// 获取旧文件
async getAudios(hashes) {
const data = await $ajax({
type: "post",
params: { hashes },
url: GO_URLS.getFiles,
});
if (data) {
this.localObjects = data.data.files;
for (let index = 0; index < data.data.files.length; index++) {
const element = data.data.files[index];
this.localHash.push(element.hash);
}
}
},
async fileChange(e) {
const file = e.target.files[0];
e.target.value = null; //清空值
if (!file) return;
// 限制相同文件的上传
const state = this.localObjects.some((item) => item.name === file.name);
if (state) {
ElMessage({
message: "不可重复上传该音频文件",
type: "warning",
});
return;
}
if (file.size > 10485760) {
ElMessage({
message: "上传音频大小不可超过10M",
type: "warning",
});
return;
}
const formData = new FormData();
formData.append("file_data", file);
const res = await $ajax({
type: "post",
url: GO_URLS.upload + `?file_type=mp3`,
params: formData,
});
if (res) {
// 上传成功
ElMessage({
message: "上传成功",
type: "success",
});
this.localHash.push(res.data.hash);
this.localObjects.push(res.data);
}
},
},
});
</script>
<style lang="scss" scoped>
.base_form {
flex-shrink: 0;
padding-left: 18px;
font-size: 0;
padding-top: 10px;
padding-bottom: 10px;
display: flex;
justify-content: flex-start;
}
.label {
display: inline-block;
width: 100px;
flex-shrink: 0;
cursor: pointer;
color: #797d84;
line-height: 44px;
font-size: 14px;
font-weight: 300;
position: relative;
}
.pre-tag {
position: absolute;
left: -50px;
top: 14px;
display: none;
}
.label-text {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.up {
box-sizing: content-box;
width: 151px;
height: 36px;
cursor: pointer;
border-radius: 4px;
font-size: 12px;
font-weight: 400;
text-align: center;
line-height: 36px;
color: rgba(121, 125, 132, 1);
background: #f6f6f7;
border: 1px solid #dcdfe6;
.iconyinpin2 {
font-size: 24px;
vertical-align: sub;
}
}
.show {
line-height: 1;
padding-top: 20px;
padding-bottom: 4px;
p {
font-size: 14px;
margin: 0;
display: inline-block;
padding: 0;
cursor: pointer;
font-weight: 400;
color: #353535;
}
.iconyinpin-copy {
color: #33c8ff;
font-size: 16px;
margin-right: 6px;
}
.show-rigth {
float: right;
font-size: 14px;
.iconshanchu1 {
color: #b6b5ba;
font-size: 12px;
margin-left: 10px;
cursor: pointer;
}
.iconxingzhuang2 {
margin-right: 2px;
color: #33c724;
}
}
}
.audio-box {
padding: 20px;
}
</style>
<template>
<div class="base_form">
<div class="label">
<Icon iconName="icondd" class="pre-tag" size="18"></Icon>
<div class="label-text" :title="label">{{ label }}</div>
</div>
<div class="input-box">
<DialogInputVue
class="input"
v-if="showInput"
:noBoxShadowWhenFocused="true"
v-model:value="inputValue"
@update:value="change"
type="text"
:placeholder="'请输入' + label"
:readonly="isDisabled"
/>
<img
v-if="iconDown"
src="@/assets/img/arrow_down.png"
class="icon_down"
style="width: 20px"
/>
</div>
<slot></slot>
</div>
</template>
<script lang="ts" setup>
import { nextTick, onMounted, ref, watch } from "vue";
import Icon from "@/components/Icon/index.vue";
import { syDialogInput as DialogInputVue } from "cqk-sy-ui";
/**
* 以普通输入框为基础
* @author yuanzeyu
* @date 2019-05-29
* @desc
*/
const props = withDefaults(
defineProps<{
label: string;
value?: string;
watchValue?: string; // 用于显示的值
showInput?: boolean;
isDisabled?: boolean;
iconDown?: boolean;
}>(),
{
value: "",
watchValue: "",
showInput: true,
iconDown: false,
}
);
const $emit = defineEmits(["changeValue"]);
const inputValue = ref(``);
onMounted(() => {
inputValue.value = props.watchValue ? props.watchValue : props.value;
});
watch(
() => props.watchValue,
() => {
inputValue.value = props.watchValue;
}
);
const change = () => {
nextTick(() => {
$emit(`changeValue`, inputValue.value, `value`);
});
};
</script>
<style scoped lang="scss">
.base_form {
flex-shrink: 0;
padding-left: 18px;
line-height: 65px;
height: 65px;
font-size: 0;
display: flex;
justify-content: flex-start;
align-items: center;
}
.label {
display: inline-block;
width: 100px; /* 104 - 18 */
flex-shrink: 0;
height: 44px;
cursor: pointer;
line-height: 44px;
color: #797d84; /* todo ui图颜色不一致 */
font-size: 14px;
font-weight: 300;
position: relative;
}
.label-text {
text-overflow: ellipsis;
white-space: nowrap; /*规定段落中的文本不进行换行 */
overflow: hidden;
}
.icon_down {
position: absolute;
right: 26px;
color: #b8b8b8;
font-size: 12px; /* todo ui图有空白 */
top: 50%;
transform: translateY(-50%) scale(0.67);
cursor: pointer;
}
.input-box {
position: relative;
line-height: 65px;
width: 100%;
}
.input {
box-sizing: border-box;
width: 100%;
flex-shrink: 0;
margin-top: 11px;
}
.pre-tag {
position: absolute;
left: -50px;
top: 14px;
display: none;
}
</style>
<template>
<div class="myDateForm2">
<div v-if="!isDisabled" class="base_form date_form w-full">
<div class="label">
<Icon iconName="icondd" class="pre-tag" size="18"></Icon>
<div class="label-text" :title="label">{{ label }}</div>
</div>
<el-config-provider :locale="zhCn">
<el-date-picker
class="date-picker"
@change="change"
v-model="inputValue"
type="date"
placeholder="请选择日期"
></el-date-picker>
</el-config-provider>
</div>
<base-form v-else :label="label || ''" isDisabled>
<i class="iconfont iconxingzhuang icon_date"></i>
</base-form>
</div>
</template>
<script lang="ts" setup>
import { nextTick, onMounted, ref } from "vue";
import BaseForm from "./BaseForm.vue";
import { ElDatePicker, ElConfigProvider } from "element-plus";
import zhCn from "element-plus/lib/locale/lang/zh-cn";
import Icon from "@/components/Icon/index.vue";
const props = withDefaults(
defineProps<{
label?: string;
isDisabled?: boolean;
value?: string;
}>(),
{}
);
const inputValue = ref<Date | string>("");
const $emit = defineEmits(["changeValue"]);
onMounted(() => {
if (props.value) {
if (isValidDate(new Date(Number(props.value + "000")))) {
inputValue.value = new Date(Number(props.value + "000"));
} else {
inputValue.value = "";
}
} else {
inputValue.value = "";
}
});
const isValidDate = (date: any) => {
return date instanceof Date && !isNaN(date.getTime());
};
const change = () => {
nextTick(() => {
let date = new Date(inputValue.value);
let t = String(date.valueOf());
$emit(`changeValue`, t.substring(0, t.length - 3), `value`);
});
};
</script>
<style lang="scss">
.myDateForm2 {
.date_form {
.el-input {
flex-grow: 1;
}
}
.date-picker {
flex-shrink: 0;
.el-input__inner {
height: 36px;
color: #353535;
border-radius: var(--sy-border-radius);
&:hover {
box-shadow: 0 0 0 1px #c4c4c4 inset;
}
&:focus {
box-shadow: 0 0 0 1px
var(--el-input-border-color, var(--el-border-color)) inset !important;
}
.el-input__inner::placeholder {
color: #a3a7aa;
}
}
}
}
</style>
<style scoped lang="scss">
.base_form {
position: relative;
padding-left: 18px;
line-height: 65px;
height: 65px;
font-size: 0;
display: flex;
justify-content: flex-start;
align-items: center;
}
.label {
display: inline-block;
width: 100px; /* 104 - 18 */
flex-shrink: 0;
height: 44px;
line-height: 44px;
color: #797d84; /* todo ui图颜色不一致 */
font-size: 14px;
font-weight: 300;
position: relative;
}
.label-text {
text-overflow: ellipsis;
white-space: nowrap; /*规定段落中的文本不进行换行 */
overflow: hidden;
}
.icon_date {
color: #8a8a8a;
position: absolute;
right: 24px;
}
.pre-tag {
position: absolute;
left: -50px;
top: 14px;
display: none;
}
</style>
<template>
<div>
<div class="base_form">
<div class="label">
<Icon iconName="icondd" class="pre-tag" size="18"></Icon>
<div class="label-text" :title="label">{{ label }}</div>
</div>
<tinymce
@input="getContent"
:value="richTextValue"
class="tinymce22 flex-grow overflow-hidden"
></tinymce>
</div>
</div>
</template>
<script lang="ts">
import tinymce2Vue from "../../TraceProofEdit/tinymce2.vue";
import Icon from "@/components/Icon/index.vue";
// ??????该组件需要开发
import { defineComponent } from "vue";
export default defineComponent({
// 引入组件
components: {
tinymce: tinymce2Vue,
Icon,
},
props: ["label", "property", "setPropertyValue"],
data() {
return {
richTextValue: "",
};
},
mounted() {
this.richTextValue = this.property.value;
},
computed: {},
methods: {
getContent(val) {
this.setPropertyValue(val);
},
},
});
</script>
<style scoped lang="scss">
:deep(.mce-resizehandle) {
display: none;
}
.base_form {
position: relative;
padding-left: 18px;
height: 480px;
font-size: 0;
display: flex;
justify-content: flex-start;
}
.tinymce22 {
height: 400px;
margin: 0;
margin-top: 20px;
}
.label {
display: inline-block;
width: 100px; /* 104 - 18 */
flex-shrink: 0;
height: 44px;
line-height: 480px;
color: #797d84; /* todo ui图颜色不一致 */
font-size: 14px;
font-weight: 300;
position: relative;
}
.label-text {
text-overflow: ellipsis;
white-space: nowrap; /*规定段落中的文本不进行换行 */
overflow: hidden;
}
.pre-tag {
position: absolute;
left: -50px;
top: 14px;
display: none;
}
</style>
<template>
<div class="image_form">
<div class="label">
<Icon iconName="icondd" class="pre-tag" size="18"></Icon>
<div class="label-text" :title="property.label">{{ property.label }}</div>
</div>
<div
class="form_icon_require"
:class="{ 'js-form_icon_require_empty': imgList.length === 0 }"
>
*
</div>
<div class="content_wrapper">
<div class="list_wrapper">
<div class="list-items">
<div
class="list-item"
v-for="(item, index) in imgList"
:key="index"
@click="ReviewImages(item)"
>
<img class="list-item-img" :src="item.url || item.dataUrl" />
<i
class="iconfont iconshanchu3"
@click.stop="deleteimg(item, index)"
></i>
</div>
<div class="add_wrapper">
<div class="content-upload_box" @click="showSelectFile">
<i class="iconfont iconjiahao"></i>
</div>
</div>
</div>
</div>
</div>
<input
ref="inputDom"
type="file"
accept="image/jpeg, image/png, image/gif"
@change="fileChange"
hidden
/>
<!-- 图片放大镜 -->
<common-dialog
v-if="Magnifier"
@closePopup="Magnifier = false"
showMask
@ClickingBackground="Magnifier = false"
>
<div class="display-area">
<img :src="pcUrl" />
</div>
</common-dialog>
</div>
</template>
<script lang="ts">
import { Property } from "../types2";
import { GO_URLS, syCommonDialog as CommonDialog } from "cqk-sy-ui";
import Icon from "@/components/Icon/index.vue";
import { defineComponent, PropType } from "vue";
import { ElMessage } from "element-plus";
import { $ajax } from "@/service";
export default defineComponent({
inject: ["showTip"],
components: {
CommonDialog,
Icon,
},
props: {
disable: {
type: Boolean,
default: false,
},
property: {
type: Object as PropType<Property>,
required: true,
},
setPropertyValue: {
type: Function as PropType<any>,
required: true,
},
},
data() {
return {
imgList: [] as any[],
Magnifier: false,
pcUrl: "",
};
},
mounted() {
if (!Array.isArray(this.property.value)) return;
this.property.value.forEach((url) => {
this.PushList(url);
});
},
watch: {
imgList(newV) {
this.setPropertyValue(this.imgList);
},
},
methods: {
async PushList(url: any) {
if (!url || !url.value) return false;
this.imgList.push({
url: await this.requestPictures(url.value),
hash: url.value, //同时保存hash
});
},
// 图片回显
ReviewImages(item: any) {
if (item.url != "") {
this.pcUrl = item.url;
} else {
this.pcUrl = item.dataUrl;
}
this.Magnifier = true;
},
// 图片替换
async requestPictures(string: string) {
const res = await $ajax({
type: "post",
url: GO_URLS.getFiles,
params: { hashes: [string] },
});
if (res) {
return res.data.files[0].url;
}
},
showSelectFile() {
if (this.disable) {
return;
}
if (this.imgList.length > 10) {
return;
}
(this.$refs.inputDom as any).click();
},
// 删除图片
deleteimg(item: any, index: number) {
(this as any).showTip(
"此操作将永久删除该文件, 是否继续?",
() => {
this.imgList.splice(index, 1);
ElMessage({
type: "success",
message: "删除成功!",
});
},
() => {
ElMessage({
type: "info",
message: "已取消删除",
});
}
);
},
fileChange(e: any) {
const file: File = e.target.files[0];
if (!file) {
return;
}
if (file.size > 5242880) {
ElMessage({
message: "上传图片大小不可超过5M",
type: "warning",
});
return;
}
const fr = new FileReader();
fr.onload = (event: any) => {
this.imgList = [
...this.imgList,
{ url: "", dataUrl: event.target.result, file, hash: "" },
];
};
fr.readAsDataURL(file);
e.target.value = null;
},
},
});
</script>
<style scoped lang="scss">
.display-area {
max-height: 80vh;
overflow-y: auto;
img {
width: 100%;
}
}
.image_form {
flex-shrink: 0;
position: relative;
padding-top: 10px;
padding-left: 18px;
padding-bottom: 10px;
font-size: 0;
display: flex;
justify-content: flex-start;
}
.label {
display: inline-block;
width: 100px; /* 104 - 18 */
height: 44px;
line-height: 44px;
color: #797d84; /* todo ui图颜色不一致 */
font-size: 14px;
font-weight: 300;
position: relative;
}
.label-text {
text-overflow: ellipsis;
flex-shrink: 0;
white-space: nowrap; /*规定段落中的文本不进行换行 */
overflow: hidden;
}
.content_wrapper {
flex: 1;
display: flex;
}
.list_wrapper {
width: 452px;
}
.add_wrapper {
margin-right: 10px;
float: left;
}
.list-items {
float: left;
}
.content-upload_box {
width: 80px;
height: 80px;
border-radius: 4px;
border: 1px solid #dcdfe6;
text-align: center;
line-height: 80px;
.iconjiahao {
font-size: 24px;
color: #d7d7d7;
}
}
.list-item {
float: left;
margin-right: 10px;
margin-bottom: 10px;
width: 80px;
height: 80px;
cursor: pointer;
background: rgba(216, 216, 216, 1);
border-radius: 4px;
text-align: center;
position: relative;
.list-item-img {
width: 100%;
height: 100%;
border-radius: 4px;
border: 1px solid #dcdfe6;
overflow: hidden;
}
.iconshanchu3 {
position: absolute;
right: -10px;
font-size: 18px;
top: -10px;
cursor: pointer;
}
}
.form_icon_require {
position: absolute;
left: -10px;
top: 0;
color: #ff6565;
font-size: 14px;
line-height: 44px;
display: none;
}
.pre-tag {
position: absolute;
left: -50px;
top: 14px;
display: none;
}
</style>
<template>
<div class="array-form">
<div class="label flex-shrink-0">
<Icon iconName="icondd" class="pre-tag" size="18"></Icon>
<div class="label-text" :title="property.label">{{ property.label }}</div>
</div>
<div class="lists flex-grow overflow-hidden">
<div
class="list flex-grow flex w-full"
v-for="(item, index) in array"
:key="index"
>
<DialogInputVue
:noBoxShadowWhenFocused="true"
class="input"
style="flex-grow: 1"
v-model:value="item.value"
type="text"
:placeholder="'请输入' + property.label"
/>
<div class="del" @click="del(index)">
<i class="iconfont iconshanchu-"></i>
</div>
</div>
<div class="add" @click="add">
<i class="iconfont icontianjia"></i>
</div>
</div>
</div>
</template>
<script lang="ts">
import { Property } from "../types2";
import { defineComponent, PropType } from "vue";
import { ElMessage } from "element-plus";
import { GO_URLS, syDialogInput as DialogInputVue } from "cqk-sy-ui";
import Icon from "@/components/Icon/index.vue";
export default defineComponent({
inject: ["showTip"],
components: {
DialogInputVue,
Icon,
},
props: {
property: {
type: Object as PropType<Property>,
required: true,
},
setPropertyValue: {
type: Function as PropType<any>,
},
},
data() {
return {
array: [
{
value: "",
},
],
};
},
watch: {
array: {
handler() {
this.setPropertyValue(this.array.map((item) => String(item.value)));
},
deep: true,
},
},
mounted() {
if (!Array.isArray(this.property.value)) return;
this.array = this.property.value.map((value: string) => {
return { value };
});
},
methods: {
change() {
this.setPropertyValue(this.array.map((item) => String(item.value)));
},
add() {
this.array = [
...this.array,
{
value: "",
},
];
},
del(index: number) {
if (this.array.length <= 1) return;
(this as any).showTip(
"此操作将永久删除该文件, 是否继续?",
() => {
this.array.splice(index, 1);
this.array = [...this.array];
ElMessage({
type: "success",
message: "删除成功!",
});
},
() => {
ElMessage({
type: "info",
message: "已取消删除",
});
}
);
},
},
});
</script>
<style scoped lang="scss">
.label {
display: inline-block;
width: 100px; /* 104 - 18 */
flex-shrink: 0;
height: 44px;
cursor: pointer;
line-height: 44px;
color: #797d84; /* todo ui图颜色不一致 */
font-size: 14px;
font-weight: 300;
position: relative;
}
.pre-tag {
position: absolute;
left: -50px;
top: 14px;
display: none;
}
.array-form {
flex-shrink: 0;
padding-left: 18px;
height: auto;
font-size: 0;
display: flex;
justify-content: flex-start;
align-items: center;
}
.list {
display: flex;
justify-content: center;
align-items: center;
margin-top: 10px;
}
.input {
margin-right: 10px;
margin-top: 0;
flex-shrink: 0;
box-sizing: border-box;
outline: none;
}
.del {
height: 34px;
display: flex;
color: #eaeaea;
justify-content: center;
align-items: center;
cursor: pointer;
.iconfont {
font-size: 20px;
}
}
.add {
width: 34px;
height: 34px;
border-radius: 50%;
color: white;
display: flex;
background-color: var(--sy-blue);
justify-content: center;
align-items: center;
cursor: pointer;
margin: 10px 0;
}
</style>
<template>
<base-form
:label="property.label"
:watchValue="propertyValue"
:showInput="false"
class="json-form"
>
<div class="lists">
<div class="list" v-for="(i, index) in jsons" :key="index">
<input
class="input"
v-model="i.key"
@input="change"
type="text"
placeholder="key"
/>
<input
class="input"
v-model="i.value"
@input="change"
type="text"
placeholder="value"
/>
<div class="del" @click="del(index)">
<i class="iconfont iconshanchu-"></i>
</div>
</div>
<div class="add" @click="add">
<i class="iconfont icontianjia"></i>
</div>
</div>
</base-form>
</template>
<script lang="ts">
import BaseForm from "./BaseForm.vue";
import { Property } from "../types2";
import { defineComponent, PropType } from "vue";
import { ElMessage } from "element-plus";
export default defineComponent({
inject: ["showTip"],
components: {
BaseForm,
},
props: {
property: {
type: Object as PropType<Property>,
required: true,
},
setPropertyValue: Function as PropType<any>,
},
data() {
return {
jsons: [
{
key: "",
value: "",
},
],
};
},
computed: {
propertyValue() {
return this.property.value as string;
},
},
watch: {
jsons() {
let temp: any = {};
this.jsons.forEach((item) => {
temp[item.key] = item.value;
});
// this.property.value = JSON.stringify(temp);
this.setPropertyValue(JSON.stringify(temp));
},
},
mounted() {
const o = JSON.parse((this.property.value as string) || "{}");
this.jsons = [];
for (let i in o) {
this.jsons.push({
key: i,
value: o[i],
});
}
if (this.jsons.length <= 0) {
this.jsons.push({
key: "",
value: "",
});
}
},
methods: {
change() {
let temp: any = {};
this.jsons.forEach((item) => {
temp[item.key] = item.value;
});
// this.property.value = JSON.stringify(temp);
this.setPropertyValue(JSON.stringify(temp));
},
add() {
this.jsons.push({
key: "",
value: "",
});
},
del(index: number) {
if (this.jsons.length <= 1) return;
(this as any).showTip(
"此操作将永久删除该文件, 是否继续?",
() => {
this.jsons.splice(index, 1);
ElMessage({
type: "success",
message: "删除成功!",
});
},
() => {
ElMessage({
type: "info",
message: "已取消删除",
});
}
);
},
},
});
</script>
<style scoped lang="scss">
.json-form {
height: auto;
}
.list {
display: flex;
justify-content: center;
align-items: center;
margin-top: 10px;
}
.input {
width: 380px;
margin-right: 10px;
margin-top: 0;
flex-shrink: 0;
height: 44px;
}
.del {
height: 34px;
display: flex;
color: #eaeaea;
justify-content: center;
align-items: center;
cursor: pointer;
.iconfont {
font-size: 20px;
}
}
.add {
width: 34px;
height: 34px;
border-radius: 50%;
color: white;
display: flex;
background-color: var(--sy-blue);
justify-content: center;
align-items: center;
cursor: pointer;
margin: 10px 0;
}
</style>
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment