|
@@ -6,68 +6,220 @@
|
|
|
<el-button type="primary" :icon="LuPlus" @click="handleAddRow"></el-button>
|
|
<el-button type="primary" :icon="LuPlus" @click="handleAddRow"></el-button>
|
|
|
</div>
|
|
</div>
|
|
|
</template>
|
|
</template>
|
|
|
- <div
|
|
|
|
|
- class="flex items-center gap-4px mb-4px"
|
|
|
|
|
- v-for="(row, rowIndex) in modelValue || []"
|
|
|
|
|
- :key="rowIndex"
|
|
|
|
|
- >
|
|
|
|
|
- <div class="relative group/item" v-for="(_val, columnIndex) in row" :key="columnIndex">
|
|
|
|
|
- <el-input spellcheck="false" v-model="modelValue[rowIndex][columnIndex]" />
|
|
|
|
|
|
|
+ <el-scrollbar>
|
|
|
|
|
+ <div
|
|
|
|
|
+ class="flex items-center gap-4px mb-4px"
|
|
|
|
|
+ v-for="(row, rowIndex) in group || []"
|
|
|
|
|
+ :key="rowIndex"
|
|
|
|
|
+ >
|
|
|
<div
|
|
<div
|
|
|
- class="absolute top--7px right--4px cursor-pointer invisible group-hover/item:visible"
|
|
|
|
|
- @click="handleDeleteItem(rowIndex, columnIndex)"
|
|
|
|
|
|
|
+ class="relative group/item flex-1"
|
|
|
|
|
+ v-for="(_val, columnIndex) in row"
|
|
|
|
|
+ :key="columnIndex"
|
|
|
>
|
|
>
|
|
|
- <LuX size="14px" />
|
|
|
|
|
|
|
+ <el-button
|
|
|
|
|
+ class="w-full"
|
|
|
|
|
+ @click="handleEdit(group[rowIndex][columnIndex], rowIndex, columnIndex)"
|
|
|
|
|
+ >{{ group[rowIndex][columnIndex].text }}</el-button
|
|
|
|
|
+ >
|
|
|
|
|
+ <div
|
|
|
|
|
+ class="absolute top--7px right--4px cursor-pointer invisible group-hover/item:visible"
|
|
|
|
|
+ @click="handleDeleteItem(rowIndex, columnIndex)"
|
|
|
|
|
+ >
|
|
|
|
|
+ <LuX size="14px" />
|
|
|
|
|
+ </div>
|
|
|
</div>
|
|
</div>
|
|
|
- </div>
|
|
|
|
|
|
|
|
|
|
- <el-button
|
|
|
|
|
- type="primary"
|
|
|
|
|
- :icon="LuPlus"
|
|
|
|
|
- :disabled="row.length === 5"
|
|
|
|
|
- @click="handleAddItem(rowIndex)"
|
|
|
|
|
- ></el-button>
|
|
|
|
|
- </div>
|
|
|
|
|
|
|
+ <el-button
|
|
|
|
|
+ type="primary"
|
|
|
|
|
+ :icon="LuPlus"
|
|
|
|
|
+ :disabled="row.length === 5"
|
|
|
|
|
+ @click="handleAddItem(rowIndex)"
|
|
|
|
|
+ ></el-button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </el-scrollbar>
|
|
|
</el-card>
|
|
</el-card>
|
|
|
|
|
+
|
|
|
|
|
+ <el-dialog title="编辑按钮" width="600px" v-model="open" close-on-click-modal>
|
|
|
|
|
+ <el-form ref="form" :model="formData" :rules="rules" hide-required-asterisk>
|
|
|
|
|
+ <el-form-item label="名称" prop="name">
|
|
|
|
|
+ <el-input v-model="formData.name"></el-input>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ <el-form-item label="文本" prop="text">
|
|
|
|
|
+ <el-input v-model="formData.text"></el-input>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ <el-form-item label="宽度">
|
|
|
|
|
+ <input-number
|
|
|
|
|
+ v-model="formData.width"
|
|
|
|
|
+ style="width: 100%"
|
|
|
|
|
+ :min="1"
|
|
|
|
|
+ :max="255"
|
|
|
|
|
+ ></input-number>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ </el-form>
|
|
|
|
|
+ <el-collapse v-if="isCustom" :model-value="['style']">
|
|
|
|
|
+ <el-collapse-item name="style">
|
|
|
|
|
+ <template #title>
|
|
|
|
|
+ <div class="flex items-center">
|
|
|
|
|
+ <IoColorPaletteOutline size="12px" />
|
|
|
|
|
+ <span class="ml-4px text-12px">样式配置</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <el-form
|
|
|
|
|
+ ref="formRef"
|
|
|
|
|
+ class="px-12px box-border"
|
|
|
|
|
+ label-position="left"
|
|
|
|
|
+ :model="styleFormData"
|
|
|
|
|
+ >
|
|
|
|
|
+ <el-form-item label="模块/状态" class="mb-12px!">
|
|
|
|
|
+ <div class="w-full">
|
|
|
|
|
+ <StylePart
|
|
|
|
|
+ v-model="part"
|
|
|
|
|
+ :hasStyle="!!styleFormData"
|
|
|
|
|
+ @change="onChangeStyleByState"
|
|
|
|
|
+ />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+
|
|
|
|
|
+ <el-row :gutter="12" v-if="styleFormData">
|
|
|
|
|
+ <CusFormItem
|
|
|
|
|
+ v-for="(item, index) in btn.config.styles || []"
|
|
|
|
|
+ :key="item.valueType + '_' + index"
|
|
|
|
|
+ :schema="item"
|
|
|
|
|
+ :formData="styleFormData"
|
|
|
|
|
+ :widgetData="projectStore.activeWidget!"
|
|
|
|
|
+ />
|
|
|
|
|
+ </el-row>
|
|
|
|
|
+ </el-form>
|
|
|
|
|
+ </el-collapse-item>
|
|
|
|
|
+ </el-collapse>
|
|
|
|
|
+ <template #footer>
|
|
|
|
|
+ <el-button type="primary" @click="handleSubmit">确定</el-button>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-dialog>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
<script setup lang="ts">
|
|
|
-import { computed } from 'vue'
|
|
|
|
|
|
|
+import { computed, ref, provide, type Ref } from 'vue'
|
|
|
import { LuPlus, LuX } from 'vue-icons-plus/lu'
|
|
import { LuPlus, LuX } from 'vue-icons-plus/lu'
|
|
|
|
|
+import { ButtonItem } from './data'
|
|
|
|
|
+import { getNextIndex } from '@/utils'
|
|
|
|
|
+import { useProjectStore } from '@/store/modules/project'
|
|
|
|
|
+import btn from './index'
|
|
|
|
|
+import { klona } from 'klona'
|
|
|
|
|
+import { FormInstance } from 'element-plus'
|
|
|
|
|
+import StylePart from '@/views/designer/config/property/components/StylePart.vue'
|
|
|
|
|
+import CusFormItem from '@/views/designer/config/property/CusFormItem.vue'
|
|
|
|
|
|
|
|
const props = defineProps<{
|
|
const props = defineProps<{
|
|
|
- values: any
|
|
|
|
|
|
|
+ values: Ref<{
|
|
|
|
|
+ props: {
|
|
|
|
|
+ group: ButtonItem[][]
|
|
|
|
|
+ isCustom: boolean
|
|
|
|
|
+ col: number
|
|
|
|
|
+ }
|
|
|
|
|
+ }>
|
|
|
}>()
|
|
}>()
|
|
|
|
|
|
|
|
-const modelValue = computed({
|
|
|
|
|
|
|
+const open = ref(false)
|
|
|
|
|
+const projectStore = useProjectStore()
|
|
|
|
|
+const form = ref<FormInstance>()
|
|
|
|
|
+const itemParts = ref<any[]>([btn.parts.find((item) => item.name === 'items')])
|
|
|
|
|
+provide('parts', itemParts)
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 编辑表单数据
|
|
|
|
|
+ */
|
|
|
|
|
+const formData = ref<ButtonItem>({
|
|
|
|
|
+ name: '',
|
|
|
|
|
+ text: '',
|
|
|
|
|
+ type: '',
|
|
|
|
|
+ width: 0,
|
|
|
|
|
+ style: []
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+const rules = {
|
|
|
|
|
+ name: [
|
|
|
|
|
+ { required: true, message: '请输入按钮名称', trigger: 'blur' },
|
|
|
|
|
+ {
|
|
|
|
|
+ validator: (_rule: any, value: string, callback: any) => {
|
|
|
|
|
+ // 校验名称是否重复
|
|
|
|
|
+ const index = group.value.findIndex((row, rowIndex) =>
|
|
|
|
|
+ row.find((col, colIndex) => {
|
|
|
|
|
+ return value === col.name && (rowIndex !== tempRow || colIndex !== tempCol)
|
|
|
|
|
+ })
|
|
|
|
|
+ )
|
|
|
|
|
+ if (index !== -1) {
|
|
|
|
|
+ callback(new Error('名称重复'))
|
|
|
|
|
+ } else {
|
|
|
|
|
+ callback()
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ ],
|
|
|
|
|
+ text: [{ required: true, message: '请输入按钮文本', trigger: 'blur' }]
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 按钮列表
|
|
|
|
|
+const group = computed({
|
|
|
get() {
|
|
get() {
|
|
|
- return props.values?.value
|
|
|
|
|
|
|
+ return props.values?.value.props.group
|
|
|
},
|
|
},
|
|
|
set(val) {
|
|
set(val) {
|
|
|
- props.values.value = val
|
|
|
|
|
|
|
+ props.values.value.props.group = val
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * 是否自定义
|
|
|
|
|
+ */
|
|
|
|
|
+const isCustom = computed(() => {
|
|
|
|
|
+ return props.values?.value.props.isCustom
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 添加一项
|
|
* 添加一项
|
|
|
* @param rowIndex 行索引
|
|
* @param rowIndex 行索引
|
|
|
*/
|
|
*/
|
|
|
const handleAddItem = (rowIndex: number | string) => {
|
|
const handleAddItem = (rowIndex: number | string) => {
|
|
|
- const row = modelValue.value?.[rowIndex]
|
|
|
|
|
|
|
+ const i = getNextIndex(group.value.flat(), 'name')
|
|
|
|
|
+ const row = group.value?.[rowIndex]
|
|
|
if (row?.length < 5) {
|
|
if (row?.length < 5) {
|
|
|
- row.push('0')
|
|
|
|
|
|
|
+ row.push({
|
|
|
|
|
+ name: `btn_${i}`,
|
|
|
|
|
+ text: `${i}`,
|
|
|
|
|
+ type: 'button',
|
|
|
|
|
+ width: 1,
|
|
|
|
|
+ style: []
|
|
|
|
|
+ })
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+let tempRow, tempCol
|
|
|
|
|
+
|
|
|
|
|
+const handleEdit = (record: ButtonItem, rowIndex: number | string, colIndex: number | string) => {
|
|
|
|
|
+ tempRow = rowIndex
|
|
|
|
|
+ tempCol = colIndex
|
|
|
|
|
+ open.value = true
|
|
|
|
|
+ formData.value = klona(record)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const handleSubmit = () => {
|
|
|
|
|
+ form.value?.validate().then(() => {
|
|
|
|
|
+ group.value[tempRow][tempCol] = klona(formData.value)
|
|
|
|
|
+ open.value = false
|
|
|
|
|
+ })
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 删除一项
|
|
* 删除一项
|
|
|
* @param rowIndex 行索引
|
|
* @param rowIndex 行索引
|
|
|
* @param index 索引
|
|
* @param index 索引
|
|
|
*/
|
|
*/
|
|
|
-const handleDeleteItem = (rowIndex: number | string, index: number | string) => {
|
|
|
|
|
- modelValue.value[rowIndex].splice(index, 1)
|
|
|
|
|
- if (modelValue.value[rowIndex].length === 0) {
|
|
|
|
|
- modelValue.value.splice(rowIndex, 1)
|
|
|
|
|
|
|
+const handleDeleteItem = (rowIndex: number, index: number) => {
|
|
|
|
|
+ group.value[rowIndex].splice(index, 1)
|
|
|
|
|
+ if (group.value[rowIndex].length === 0) {
|
|
|
|
|
+ group.value.splice(rowIndex, 1)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -75,7 +227,70 @@ const handleDeleteItem = (rowIndex: number | string, index: number | string) =>
|
|
|
* 添加一行
|
|
* 添加一行
|
|
|
*/
|
|
*/
|
|
|
const handleAddRow = () => {
|
|
const handleAddRow = () => {
|
|
|
- modelValue.value?.push(['0', '0', '0'])
|
|
|
|
|
|
|
+ const i = getNextIndex(group.value.flat(), 'name')
|
|
|
|
|
+ const newArr = new Array(props.values.value.props.col || 3).fill({})
|
|
|
|
|
+
|
|
|
|
|
+ group.value?.push(
|
|
|
|
|
+ newArr.map((_, index) => {
|
|
|
|
|
+ return {
|
|
|
|
|
+ name: `btn_${i + index}`,
|
|
|
|
|
+ text: `${i + index}`,
|
|
|
|
|
+ type: 'button',
|
|
|
|
|
+ width: 1,
|
|
|
|
|
+ style: []
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ )
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 样式表单数据
|
|
|
|
|
+const styleFormData = computed(() => {
|
|
|
|
|
+ const item = formData.value.style?.find(
|
|
|
|
|
+ (item) => item?.part.name === part.value?.name && item?.part.state === part.value?.state
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ return item
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+const part = ref<{
|
|
|
|
|
+ name: string
|
|
|
|
|
+ state: string
|
|
|
|
|
+}>({
|
|
|
|
|
+ name: 'items',
|
|
|
|
|
+ state: 'default'
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+const onChangeStyleByState = (type: 'add' | 'delete') => {
|
|
|
|
|
+ if (!part.value.name || !part.value.state) return
|
|
|
|
|
+ if (type === 'add') {
|
|
|
|
|
+ // 从全局样式查找控件样式
|
|
|
|
|
+ const widgetType = 'lv_buttonmatrix'
|
|
|
|
|
+ const style = projectStore.globalStyle
|
|
|
|
|
+ ?.find((item) => item.widget === widgetType)
|
|
|
|
|
+ ?.part?.find((item) => item.partName === part.value.name)
|
|
|
|
|
+ ?.state?.find((item) => item.state === part.value.state)?.style
|
|
|
|
|
+
|
|
|
|
|
+ // 找多对应样式时添加
|
|
|
|
|
+ if (style) {
|
|
|
|
|
+ const result = klona({
|
|
|
|
|
+ ...style,
|
|
|
|
|
+ part: {
|
|
|
|
|
+ name: part.value.name,
|
|
|
|
|
+ state: part.value.state
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ formData.value.style?.push(result)
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 删除样式
|
|
|
|
|
+ const index =
|
|
|
|
|
+ formData.value?.style.findIndex(
|
|
|
|
|
+ (item) => item.part.name === part.value.name && item.part.state === part.value.state
|
|
|
|
|
+ ) ?? -1
|
|
|
|
|
+ if (index !== -1) {
|
|
|
|
|
+ formData.value?.style.splice(index, 1)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|