import { IconStrikethrough, IconTextBold, IconTextCenter, IconTextItalic, IconTextJustify, IconTextLeft, IconTextLetterSpacing, IconTextLineHeight, IconTextRight, IconTextSize, IconTextUnderline, } from "@/assets/icons"; import { css } from "@linaria/core"; import { Button, Checkbox, InputNumber, Tooltip } from "ant-design-vue"; import { useEditor } from "@/modules/editor"; import Select from "@queenjs-modules/queditor/components/FormUI/Items/Select"; import { queenApi } from "queenjs"; import { defineComponent, nextTick, onMounted, onUnmounted, reactive, toRaw, watch, } from "vue"; import { any, bool, func, number, object, string } from "vue-types"; import NewColorPicker from "../../formItems/NewColorPicker"; import { isNumber } from "lodash"; interface ColumnItem { label?: string; component?: ((...args: any[]) => any) | Record; dataIndex?: string; props?: { [name: string]: any }; itemProps?: { [name: string]: any }; changeExtra?: (data: any) => any; } export const TextColor = defineComponent({ props: { value: string().def("#666666"), }, emits: ["change"], setup(props, { emit }) { const state = reactive({ color: props.value, }); watch( () => props.value, () => { state.color = props.value; } ); const colorChange = (value: string) => { emit("change", value); state.color = value; }; return () => ( ); }, }); export const AlignComp = defineComponent({ props: { value: string<"left" | "right" | "center" | "justify">().def("left"), }, emits: ["change"], setup(props, { emit }) { const aligns = [ { label: "左对齐", key: "left", icon: , }, { label: "居中对齐", key: "center", icon: , }, { label: "右对齐", key: "right", icon: , }, { label: "两端对齐", key: "justify", icon: , }, ]; return () => (
{aligns.map((e: any) => { return ( ); })}
); }, }); export const LetterSpacingComp = defineComponent({ props: { value: any().def(0), }, emits: ["change"], setup(props, { emit }) { return () => { let value = typeof props.value === "string" ? parseInt(props.value) : props.value; value = isNumber(value) ? value : 0; return ( } defaultValue={0} min={0} max={100} step={1} value={value} onChange={(value: any) => { if (!value) { emit("change", "0px"); return; } emit("change", value + "px"); }} /> ); }; }, }); export const LineHeightComp = defineComponent({ props: { value: any().def(1.5), }, emits: ["change"], setup(props, { emit }) { return () => { let value = typeof props.value === "string" ? parseFloat(props.value) : props.value; value = isNumber(value) ? value : 1.5; return ( } defaultValue={1.5} min={0.5} max={3} step={0.5} value={value || 1.5} onChange={(value: any) => { if (!value) { emit("change", 1.5); return; } emit("change", value); }} /> ); }; }, }); export const FontStyleWapper = defineComponent({ emits: ["change"], setup(props, { emit }) { const fontStyleColumns = [ { label: "加粗", dataIndex: "bold", icon: , }, { label: "斜体", dataIndex: "italic", icon: , }, { label: "下划线", dataIndex: "underline", icon: , }, { label: "删除线", dataIndex: "strikethrough", icon: , }, ]; const changeVal = (e: any) => { emit("change", e); }; return () => (
{fontStyleColumns.map((e: any) => { return ( { return ; }, }} onChange={changeVal} /> ); })}
); }, }); export const FontStyleComp = defineComponent({ props: { icon: any(), value: bool().def(false), }, emits: ["change"], setup(props, { emit }) { return () => { return ( ); }; }, }); export const FontFamily = defineComponent({ props: { value: string().def(""), }, emits: ["change"], setup(props, { emit }) { const options = [ { label: "默认字体", value: "" }, { label: "宋体", value: "宋体,Songti,STSong,serif" }, { label: "黑体", value: "黑体,Heiti,STHeiti,sans-serif" }, { label: "仿宋", value: "仿宋,FangSong,STFangsong,serif" }, { label: "楷体", value: "楷体,KaiTi,STKaiti,sans-serif" }, ]; return () => { let item = options.find((e) => { return e.value.indexOf(props.value) != -1; }); const value = item ? item.value : ""; return ( ); }; }, }); export const FontSize = defineComponent({ props: { value: any().def("12px"), }, emits: ["change"], setup(props, { emit }) { return () => { let value = typeof props.value === "string" ? parseInt(props.value) : props.value; value = isNumber(value) ? value : 12; return ( } defaultValue={12} min={12} max={60} value={value} onChange={(value: any) => { if (!value) { emit("change", "12px"); return; } emit("change", value + "px"); }} /> ); }; }, }); export const TextStroke = defineComponent({ props: { value: any().def(undefined), }, emits: ["change"], setup(props, { emit }) { const state = reactive({ visible: props.value ? true : false, width: 1, color: "#666666", }); watch( () => props.value, () => { formatVal(props.value); } ); const formatVal = (value: any) => { if (!value) { state.visible = false; state.color = "#666666"; state.width = 1; return; } state.visible = true; const colorReg = /#[a-zA-Z0-9]{6}/g; let color = value.match(colorReg); if (color) { color = color[0]; } else { color = "#666666"; } state.color = color; const widthReg = /\d+px/g; let width = value.match(widthReg); if (width) { width = width[0]; } else { width = 1; } state.width = parseInt(width); }; const colorChange = (v: string) => { state.color = v; buildValueSub(); }; const visibleChange = (e: any) => { const checked = e.target.checked; state.visible = checked; buildValueSub(); }; const widthChange = (e: any) => { state.width = e; buildValueSub(); }; const buildValueSub = () => { if (!state.visible) { return; } const value = `${state.width}px ${state.color}`; emit("change", value); }; return () => { return (
{state.visible && (
)}
); }; }, }); // export const LinkButton = defineComponent({ // props: { // icon: any(), // value: any(), // }, // emits: ["change"], // setup(props, { emit }) { // const showLinkInput = async () => { // const res = await queenApi.showInput({ // title: "请输入链接地址", // defaultValue: "http://", // }); // emit("change", res); // }; // return () => ( // // ); // }, // }); const stylesKey: { [key: string]: any } = { fontSize: "font-size", fontFamily: "font-family", letterSpacing: "letter-spacing", lineHeight: "line-height", alignment: "text-align", fontColor: "color", textStroke: "-webkit-text-stroke", }; const tagsKey: { [key: string]: any } = { bold: "", italic: "", underline: "", strikethrough: "", }; export const TextToolItem = defineComponent({ props: { column: object(), index: number(), onChange: func(), }, setup(props) { const state = reactive({ value: undefined as any, }); const { controls, store, actions, helper } = useEditor(); let editor: any = null; watch( () => controls.textEditorCtrl.state.currEditor, () => { editor = toRaw(controls.textEditorCtrl.state.currEditor); initCommands(); } ); watch( () => store.currComp.value, () => { editor = toRaw(controls.textEditorCtrl.state.currEditor); if (!editor && store.currComp.compKey == "Text") { initCommands(); nextTick(() => { const element: HTMLElement | null = document.querySelector( `#editor_${store.currComp.id}` ); if (!element) { return; } const h = helper.pxToDesignSize(element.clientHeight); console.log(h); actions.updateCompData(store.currComp, "layout.size.1", h); helper.extendStreamCard(store.currStreamCardId); actions.selectObjs([]); setTimeout(() => { actions.selectObjs([store.currComp.id]); }, 0); }); } } ); function handleValueChange() { const { column } = props; if (!editor) { return; } const command = editor.commands.get(column?.dataIndex); if (command) { state.value = command.value; } } const initCommands = () => { const { column } = props; if (!editor) { if (!column?.dataIndex) { return; } const compValue = store.currComp.value; if (tagsKey[column.dataIndex]) { const hasTag = compValue.indexOf(tagsKey[column.dataIndex]); if (hasTag != -1) { state.value = true; } else { state.value = false; } return; } const regString = `(${stylesKey[column.dataIndex]}:)([\\s\\S]*?)(\\;)`; const styleReg = new RegExp(regString, "ig"); const values = compValue.match(styleReg); if (!values) { state.value = undefined; return; } let value = values[0]; value = value.replace(styleReg, "$2"); state.value = value; return; } const command = editor.commands.get(column?.dataIndex); if (command) { state.value = command.value; command.on("change:value", handleValueChange); } }; onMounted(() => { initCommands(); }); onUnmounted(() => { const { column } = props; if (!editor) { return; } const command = editor.commands.get(column?.dataIndex); if (command) { command.off("change:value", handleValueChange); } }); const changeVal = (value: any, ...args: any[]) => { const { column } = props; let params = { dataIndex: column?.dataIndex, value: { value }, ...args, }; if (column?.changeExtra) params = column.changeExtra?.(params); props.onChange?.(params); return params; }; const component = props.column?.component || null; return () => { const { column, index } = props; return (
e.stopPropagation()} > {column?.label ? ( ) : ( )}
); }; }, }); const currStyle = css` color: @inf-primary-color; &:hover, &:focus { color: @inf-primary-color; } `; const StrokeStyle = css` input { height: 28px; } `; const AlignCompWapper = css` display: flex; background-color: #303030; .ant-btn { flex: 1; width: 100%; line-height: 1; .inficon { font-size: 22px; } } `; const FontStyleCompWapper = css` flex: 1; display: flex; align-items: center; margin-right: 12px; border-radius: 2px; background-color: #303030; & > div { flex: 1; border-radius: 0; .ant-btn { width: 100%; line-height: 1; .inficon { font-size: 22px; } } } `; const formItemStyles = css` height: 100%; flex: 1; margin-right: 12px; .ant-input-number-affix-wrapper, .ant-select { background-color: #303030; } border-radius: 2px; &:last-child { margin-right: 0; } &.disabled { cursor: not-allowed; } `;