Commit 442ce459 authored by 何远江's avatar 何远江

设置区域修改为按步骤进行

parent fef2bbad
......@@ -21,9 +21,9 @@ export function chatatABC(n: number) {
}
export function getRangetxt(row0: number, row1: number, column0: number, column1: number) {
// let row0 = range["row"][0], row1 = range["row"][1];
// let column0 = range["column"][0], column1 = range["column"][1];
if (row0 == '' && row1 == '' && column0 == '' && column1 == '') {
return ''
}
if (row0 == null && row1 == null) {
return chatatABC(column0) + ':' + chatatABC(column1)
} else if (column0 == null && column1 == null) {
......@@ -38,6 +38,9 @@ export function getRangetxt(row0: number, row1: number, column0: number, column1
}
export function getRangeState(range: any) {
const sheet = luckysheet.getSheet()
const [beginRow, endRow] = sheet.luckysheet_select_save[0].row
const [beginColum, endColum] = sheet.luckysheet_select_save[0].column
let rowLen = range.length
let columnLen = range[0].length
let isOneRow = !(rowLen > 1)
......@@ -46,21 +49,36 @@ export function getRangeState(range: any) {
return {
rowLen,
columnLen,
beginRow,
endRow,
sheetNum: sheet.order,
beginColum,
endColum,
isOneRow,
isOneColumn
}
}
export function handleRangeTitle(range: any, dataArea: Recordable) {
const { isOneColumn, isOneRow, rowLen, columnLen } = getRangeState(range)
const { beginColum, beginRow, endRow, endColum, sheetNum } = dataArea
const {
beginColum,
beginRow,
endRow,
endColum,
sheetNum,
rowLen,
columnLen
} = getRangeState(range)
const titles: Recordable[] = []
let isVertical = false
// 只有一行,只能横向
if (rowLen == 1) {
isVertical = false
} else if (rowLen - 1 === endRow - beginRow && (columnLen - 1 !== endColum - beginColum || columnLen == 1)) {
} else if (
rowLen - 1 === endRow - beginRow &&
(columnLen - 1 !== endColum - beginColum || columnLen == 1)
) {
isVertical = true
}
......@@ -115,7 +133,8 @@ export function getRangePosition() {
endRow,
beginRow,
endColum,
beginColum
beginColum,
sheetNum: sheet.order
}
} else {
ElMessage.error('请选择一个区域!')
......
......@@ -4,10 +4,9 @@
<el-scrollbar height="100%">
<div class="w-[420px] h-full bg-white">
<p class="pl-2 text-lg font-bold leading-[40px] bg-slate-200">标注配置</p>
<!-- <SetArea /> -->
<el-form
<SetArea @success="onSaveSuccess" />
<!-- <el-form
ref="settingForm"
size="small"
:rules="rules"
......@@ -167,7 +166,6 @@
</vxe-column>
</vxe-table>
<p class="font-bold">附加信息</p>
<vxe-table
:data="currentAttchInfo.groupTitles"
......@@ -181,7 +179,7 @@
{{ getRangetxt(row.row, row.row, row.colum, row.colum) }}
</template>
</vxe-column>
<vxe-column title="附加title" field="area">
<vxe-column title="附加title" field="attch_title">
<template #default="{ row }">
{{ row.title }}
</template>
......@@ -210,11 +208,7 @@
>
<vxe-column title="title" field="title" :edit-render="{}">
<template #edit="{ row }">
<el-input
:disabled="isEditCurrentArea"
v-model="row.title"
size="small"
></el-input>
<el-input :disabled="isEditCurrentArea" v-model="row.title" size="small"></el-input>
</template>
</vxe-column>
<vxe-column title="单元格" field="cell" width="90">
......@@ -224,7 +218,6 @@
</vxe-column>
</vxe-table>
<el-button type="primary" size="small" @click="saveAreaMark">保存</el-button>
<el-button
v-if="isEditCurrentArea"
......@@ -233,13 +226,9 @@
@click="resetCurrentAreaState(true)"
>取消修改</el-button
>
<!-- <el-button type="default" size="small" @click="resetCurrentArea()">重置选区</el-button>
<el-button type="default" size="small" @click="resetCurrentHeadArea"
>重置标题区</el-button
> -->
</div>
</div> -->
<div class="mt-6 pl-2 pr-2 pb-2 text-sm border-b-2">
<div class="pt-2 pl-2 pr-2 pb-2 text-sm border-t-2 border-b-2">
<p class="font-bold">标记区域</p>
<vxe-table
@cell-click="cellClick"
......@@ -481,6 +470,7 @@ const formState = reactive({
watch(
() => formState.excelAreaType,
(val) => {
console.log('watch----val', val)
formState.excelAreaNicname = val
? areaTypeSelectOption.value.find((v) => v.value == val).label +
(areaList.value.filter((v) => v.excelAreaType == val).length + 1)
......@@ -501,6 +491,9 @@ const initIsSetSheetMark = (length: number) => {
const locaExcelAreaMarks: Recordable = reactive({})
const areaList = computed(() => flatten(Object.values(locaExcelAreaMarks)))
const onSaveSuccess = (data: any) => {
locaExcelAreaMarks[data.result['sheetNum']].push(data.result)
}
const initExcelAreaMarksKey = (len: number) => {
Array.from({ length: len }).forEach((item, index) => {
Reflect.set(locaExcelAreaMarks, index, [])
......@@ -802,7 +795,7 @@ const resetCurrentArea = (fn?: Function) => {
}
const hasRepeatValue = (data: any[], field: string) => {
const datas = data.map(item => item[field])
const datas = data.map((item) => item[field])
const res = Array.from(new Set(datas))
return res.length == datas.length
}
......@@ -811,7 +804,7 @@ const saveAreaMark = async () => {
return ElMessage.error('有重复标题!请修改后保存!')
}
// 保存附加信息
if(!saveAttchInfo()) {
if (!saveAttchInfo()) {
return
}
currentAreaMark.fileId = getFileInfo.value.orderFileId
......@@ -1135,6 +1128,7 @@ const setSheetAreaMark = (sheet: any) => {
}
if (item.desGroups.length) {
item?.desGroups.forEach((area) => {
if (area.beginRow !== null && area.beginRow !== '') {
luckysheet.menuButton.customUpdateFormat(
null,
'bg',
......@@ -1145,6 +1139,7 @@ const setSheetAreaMark = (sheet: any) => {
area.endColum,
false
)
}
if (area.groupTitles.length) {
area.groupTitles.forEach((a) => {
......@@ -1213,15 +1208,15 @@ const toRun = async () => {
if (!data.result.length) return
// data.result.forEach(item => {
// item.expendData = {}
// for(const key in item) {
// if (typeof item[key] == 'object') {
// item.expendData[key] = item[key]
// delete item[key]
// }
// }
// })
data.result.forEach((item) => {
item.expendData = {}
for (const key in item) {
if (typeof item[key] == 'object') {
item.expendData[key] = item[key]
delete item[key]
}
}
})
runResultData.value = data.result
runResultTitle.value = Object.keys(data.result[0]).filter((field) => {
......
<template>
<div class="setdata-step">
<el-steps :active="activeStep" finish-status="success" simple>
<el-step title="数据区" />
<el-step title="标题区" />
<el-step title="附加信息" />
</el-steps>
<SetDataArea v-show="activeStep == 0" ref="setDataAreaRef" @next="nextStep" />
<SetDataAreaTitle
ref="setDataAreaTitleRef"
v-show="activeStep == 1"
:current-area-mark="currentAreaMark"
@next="nextStep"
/>
<SetAttch
ref="setAttchRef"
v-show="activeStep == 2"
:current-area-mark="currentAreaMark"
@next="nextStep"
/>
</div>
</template>
<script lang="ts" setup>
import { ref, reactive, unref } from 'vue'
import SetDataArea from '../SetDataArea/SetDataArea.vue'
import SetDataAreaTitle from '../SetDataAreaTitle/SetDataAreaTitle.vue'
import SetAttch from '../SetAttch/SetAttch.vue'
import type { Recordable } from '@/types/global'
import { addExcelArea } from '@/api/excel'
import { ElMessage } from 'element-plus'
import { storeToRefs } from 'pinia'
import { useCommentExcel } from '@/stores/commentExcel'
const commentExcelStore = useCommentExcel()
const { getFileInfo } = storeToRefs(commentExcelStore)
const emits = defineEmits(['success'])
const activeStep = ref(0)
const setAttchRef = ref()
const setDataAreaRef = ref()
const setDataAreaTitleRef = ref()
const currentAreaMark = reactive<Recordable>({})
const nextStep = (index = 1, data: any) => {
switch (activeStep.value) {
case 0:
Object.assign(currentAreaMark, unref(data))
break
case 1:
if (data) {
Object.assign(currentAreaMark, {
titleArea: JSON.stringify(data.titleArea),
excelAreaTitle: data.excelAreaTitle
})
}
break
case 2:
if (index != -1) {
currentAreaMark.desGroups = [data.desGroups]
try {
// 保存
saveArea()
} catch {
return
}
}
break
default:
break
}
activeStep.value += index
}
const saveArea = async () => {
currentAreaMark.fileId = getFileInfo.value.orderFileId
const { data } = await addExcelArea(currentAreaMark)
if (data.code == 200 && data.result != null) {
ElMessage.success('保存成功!')
// 保存成功。清空组件状态
setDataAreaRef.value.resetFormState()
setDataAreaTitleRef.value.resetExcelAreaTitleState()
setAttchRef.value.resetFormState()
}
emits('success', data)
}
</script>
<style lang="scss">
.setdata-step {
.el-steps--simple {
padding: 8px 15px;
}
.el-step.is-simple {
.el-step__title {
font-size: 12px;
}
.el-step__arrow {
&::before {
transform: rotate(-45deg) translateY(-2px);
transform-origin: 0 0;
height: 8px;
}
&::after {
transform: rotate(45deg) translateY(2px);
transform-origin: 100% 100%;
height: 8px;
}
}
}
}
</style>
<template>
<div class="set-attch-table">
<p style="font-size: 12px">
附加区域:<el-tag>{{
getRangetxt(formState.beginRow, formState.endRow, formState.beginColum, formState.endColum)
}}</el-tag>
</p>
<vxe-table
style="margin-top: 8px"
:row-config="{ isCurrent: true }"
border
:data="groupTitles"
size="mini"
max-height="200"
:edit-config="{ trigger: 'click', mode: 'cell' }"
>
<vxe-column title="别称" field="title" :edit-render="{}">
<template #edit="{ row }">
<el-input size="small" v-model="row.title"></el-input>
</template>
</vxe-column>
<vxe-column title="单元格" field="area" width="100">
<template #default="{ row }">
{{ getRangetxt(row.row, row.row, row.colum, row.colum) }}
</template>
</vxe-column>
<vxe-column title="操作" field="action" width="90">
<template #default="{ row, $rowIndex }">
<el-link style="font-size: 12px" type="danger" @click="delGroupTitle($rowIndex)"
>删除</el-link
>
</template>
</vxe-column>
</vxe-table>
<vxe-table
style="margin-top: 8px"
:row-config="{ isCurrent: true }"
border
:data="areaTitles"
size="mini"
max-height="200"
:edit-config="{ trigger: 'click', mode: 'cell' }"
>
<vxe-column title="标题" field="title" :edit-render="{}">
<template #edit="{ row }">
<el-input v-model="row.title" size="small"></el-input>
</template>
</vxe-column>
<vxe-column title="单元格" field="cell" width="100">
<template #default="{ row }">
{{ getRangetxt(row.row, row.row, row.colum, row.colum) }}
</template>
</vxe-column>
<vxe-column title="操作" field="action" width="90">
<template #default="{ row, $rowIndex }">
<el-link style="font-size: 12px" type="danger" @click="delAreaTitle($rowIndex, row)"
>删除</el-link
>
</template>
</vxe-column>
</vxe-table>
<el-button size="small" @click="back">返回</el-button>
<el-button type="primary" size="small" @click="setAttch">设置附加信息</el-button>
<el-button type="primary" size="small" @click="setNickName">设置别称</el-button>
<el-button type="primary" size="small" @click="setAttchTitle">设置标题</el-button>
<el-button type="success" size="small" @click="save">保存</el-button>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref, unref } from 'vue'
import { getRangePosition, getRangetxt, handleRangeTitle } from '@/utils/excel'
import type { Recordable } from '@/types/global'
import { areaMarksColor } from '@/constants/excelConfig'
import { ElMessage } from 'element-plus'
const luckysheet = (window as any).luckysheet
const emits = defineEmits(['next'])
const formState = reactive<Recordable>({
beginRow: '',
beginColum: '',
endRow: '',
endColum: '',
sheetNum: ''
})
const areaTitles = ref<Recordable[]>([])
const groupTitles = ref<Recordable[]>([])
/**
* 设置附加信息
*/
const setAttch = () => {
const position = getRangePosition()
if (!position) return
if (formState.beginRow != '') {
luckysheet.menuButton.customUpdateFormat(
null,
'bg',
areaMarksColor['data'],
formState.beginRow,
formState.endRow,
formState.beginColum,
formState.endColum,
false
)
}
luckysheet.setRangeFormat('bg', areaMarksColor['attch'])
Object.assign(formState, position)
}
/**
* 设置附加信息标题
*/
const setAttchTitle = () => {
if (formState.beginRow == '') {
return ElMessage.error('请先设置附加信息区域!')
}
const position = getRangePosition()
if (!position) return
// 清除颜色
if (areaTitles.value.length) {
areaTitles.value.forEach((item) => {
luckysheet.menuButton.customUpdateFormat(
null,
'bg',
areaMarksColor['attch'],
item.row,
item.row,
item.colum,
item.colum,
false
)
})
}
const rangeData = luckysheet.getRangeValue()
const aTitles = handleRangeTitle(rangeData, unref(formState))
areaTitles.value = aTitles
luckysheet.setRangeFormat('bg', areaMarksColor['attch_title'])
}
/**
* 设置附加信息别称
* @param row
*/
const setNickName = () => {
if (formState.beginRow == '') {
return ElMessage.error('请先设置附加信息区域!')
}
const position = getRangePosition()
if (!position) return
// 清除颜色
if (groupTitles.value.length) {
groupTitles.value.forEach((item) => {
luckysheet.menuButton.customUpdateFormat(
null,
'bg',
areaMarksColor['attch'],
item.row,
item.row,
item.colum,
item.colum,
false
)
})
}
const rangeData = luckysheet.getRangeValue()
const gTitles = handleRangeTitle(rangeData, unref(formState))
groupTitles.value = gTitles
luckysheet.setRangeFormat('bg', areaMarksColor['attch_head'])
}
// 删除附加信息别称
const delGroupTitle = (index: number) => {
groupTitles.value.splice(index, 1)
}
// 删除区域标题
const delAreaTitle = (index: number) => {
areaTitles.value.splice(index, 1)
}
const save = () => {
// 如果设置了附加信息,必须要设置别称
if (formState.beginRow != '') {
if (!groupTitles.value.length) {
return ElMessage.error('请设置附加信息区域的别称!')
}
}
emits('next', -2, {
desGroups: {
...formState,
areaTitles: unref(areaTitles),
groupTitles: unref(groupTitles)
}
})
}
// 重置附加信息颜色
const resetAttchBg = () => {
if (formState.beginRow != '') {
luckysheet.menuButton.customUpdateFormat(
null,
'bg',
areaMarksColor['data'],
formState.beginRow,
formState.endRow,
formState.beginColum,
formState.endColum,
false
)
}
}
const resetFormState = () => {
Object.assign(formState, {
beginRow: '',
endRow: '',
beginColum: '',
endColum: '',
sheetNum: 0
})
groupTitles.value = []
areaTitles.value = []
}
const back = () => {
// 清空颜色
resetAttchBg()
resetFormState()
emits('next', -1)
}
defineExpose({
resetFormState
})
</script>
<style lang="scss" scoped>
.set-attch-table {
padding: 8px;
}
</style>
<template>
<el-form
size="small"
ref="form"
class="set-area-form"
:model="formState"
:rules="rules"
label-width="6em"
>
<el-row :gutter="10">
<el-col :span="24">
<el-form-item label="标记区域">
<el-tag>
{{
getRangetxt(
formState.beginRow,
formState.endRow,
formState.beginColum,
formState.endColum
)
}}
</el-tag>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="区域别称" prop="excelAreaNicname">
<el-input v-model="formState.excelAreaNicname" clearable></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="区域类型" prop="excelAreaType">
<el-select v-model="formState.excelAreaType" clearable>
<template v-for="item in areaTypeSelectOption" :key="item.value">
<el-option :label="item.label" :value="item.value"></el-option>
</template>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="循环体间隔" prop="checkNumber">
<el-input type="number" v-model="formState.checkNumber" clearable></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="标题作为数据" prop="oneself" label-width="100px">
<el-checkbox true-label="Y" false-label="N" v-model="formState.oneself"></el-checkbox>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="标题参与循环" prop="checkSelf" label-width="7em">
<el-checkbox true-label="Y" false-label="N" v-model="formState.checkSelf"></el-checkbox>
</el-form-item>
</el-col>
<el-col>
<el-form-item label-width="0">
<el-button type="primary" @click="setAreaMark('data')">标记数据区</el-button>
<el-button type="success" @click="nextStep">下一步</el-button>
</el-form-item>
</el-col>
</el-row>
</el-form>
</template>
<script lang="ts" setup>
import { apiDictList } from '@/api/common'
import { areaMarksColor } from '@/constants/excelConfig'
import type { Recordable } from '@/types/global'
import { getRangePosition, getRangetxt } from '@/utils/excel'
import { ElMessage, type FormInstance } from 'element-plus'
import { onMounted, reactive, ref, watch } from 'vue'
const luckysheet = (window as any).luckysheet
const emits = defineEmits(['next'])
const areaTypeSelectOption = ref<Recordable>([])
const formState = reactive({
excelAreaNicname: '',
excelAreaType: '',
checkNumber: 1,
oneself: 'N',
checkSelf: 'N',
sheetNum: 0,
beginRow: '',
beginColum: '',
endRow: '',
endColum: ''
})
watch(
() => formState.excelAreaType,
(val) => {
if (val) {
formState.excelAreaNicname = areaTypeSelectOption.value.find((v) => v.value == val).label
}
}
)
const form = ref<FormInstance>()
const rules = reactive({
excelAreaNicname: [{ required: true, message: '请输入区域别称!', trigger: 'change' }],
excelAreaType: [{ required: true, message: '请选择区域类型!', trigger: 'change' }],
checkNumber: [
{
validator: (rule, value, cb) => {
if (value <= 0) {
cb(new Error('请输入正整数!'))
return false
}
return true
},
trigger: 'change'
}
]
})
const resetFormState = () => {
// 重置字段
form.value?.resetFields([
'excelAreaNicname',
'excelAreaType',
'checkNumber',
'checkSelf',
'oneself'
])
// 清空位置信息
Object.assign(formState, {
sheetNum: 0,
beginRow: '',
beginColum: '',
endRow: '',
endColum: ''
})
}
const setAreaMark = (type: 'data') => {
const position = getRangePosition()
if (!position) return
// 清除已经设置过的数据区颜色
if (formState.beginColum !== '') {
luckysheet.menuButton.customUpdateFormat(
null,
'bg',
areaMarksColor['default'],
formState.beginRow,
formState.endRow,
formState.beginColum,
formState.endColum,
false
)
}
// 设置目前标记区域颜色
luckysheet.setRangeFormat('bg', areaMarksColor[type])
Object.assign(formState, position)
}
const queryDict = async (code: string) => {
const { data } = await apiDictList({
dictCodes: code
})
areaTypeSelectOption.value = data.result[code]
}
const nextStep = async () => {
// 验证是否有标记数据区
if (formState.beginRow === '') {
return ElMessage.error('请标记数据区!')
}
// 验证表单
await form.value?.validateField(['excelAreaNicname', 'excelAreaType'])
// 下一步去设置标题
emits('next', 1, formState)
}
onMounted(() => {
queryDict('excel_area_type')
})
// 暴露方法
defineExpose({
resetFormState
})
</script>
<style lang="scss" scoped>
.set-area-form {
padding: 6px;
}
</style>
<template>
<div class="excel-title-table">
<vxe-table
:row-config="{ isCurrent: true }"
border
:data="excelAreaTitle"
size="mini"
height="200"
:edit-config="{ trigger: 'click', mode: 'cell' }"
>
<vxe-column title="title" field="title" :edit-render="{}">
<template #edit="{ row }">
<el-input v-model="row.title" size="small"></el-input>
</template>
</vxe-column>
<vxe-column title="单元格" field="cell" width="90">
<template #default="{ row }">
{{ getRangetxt(row.row, row.row, row.colum, row.colum) }}
</template>
</vxe-column>
<vxe-column title="操作" field="action" width="90">
<template #default="{ row, $rowIndex }">
<el-link style="font-size: 12px" type="danger" @click="delAreaTitle($rowIndex, row)"
>删除</el-link
>
</template>
</vxe-column>
</vxe-table>
<el-button size="small" @click="nextStep(-1)">返回</el-button>
<el-button size="small" type="primary" @click="setAreaTitle">标记标题</el-button>
<el-button size="small" type="primary" @click="resetAreaTitle">重置</el-button>
<el-button size="small" type="success" @click="nextStep()">下一步</el-button>
</div>
</template>
<script lang="ts" setup>
import { ref, reactive, unref } from 'vue'
import { getRangetxt, handleRangeTitle } from '@/utils/excel'
import { areaMarksColor } from '@/constants/excelConfig'
import { ElMessage } from 'element-plus'
import type { Recordable } from '@/types/global'
const props = defineProps({
currentAreaMark: {
type: Object,
default: () => ({})
}
})
const luckysheet = (window as any).luckysheet
const emits = defineEmits(['next'])
const excelAreaTitle = ref([])
const titleArea = ref<Recordable[]>([])
const setAreaTitle = () => {
const sheet = luckysheet.getSheet()
// 判断是否在同一sheet
if (sheet.order != props.currentAreaMark.sheetNum) {
return ElMessage.error('请在同一sheet页中选择数据!')
}
const [sr, er] = sheet.luckysheet_select_save[0].row
const [sc, ec] = sheet.luckysheet_select_save[0].column
const rangeData = luckysheet.getRangeValue()
const titles = handleRangeTitle(rangeData, unref(props.currentAreaMark))
titleArea.value.push({
excelAreaNicname: props.currentAreaMark.excelAreaNicname,
sr,
sc,
er,
ec
})
if (excelAreaTitle.value.length) {
const arr = [...titles, ...unref(excelAreaTitle)]
excelAreaTitle.value = uniqArrayObject(arr)
} else {
excelAreaTitle.value = titles
}
function uniqArrayObject(arr = []) {
return arr.reduce((cur, pre, index) => {
if (index == 0) {
cur.push(pre)
} else {
const isDiff = cur.every((item) => {
return (
item.column != pre.column ||
item.row != pre.row ||
item.sheet != pre.sheet ||
item.title != pre.title
)
})
isDiff && cur.push(pre)
}
return cur
}, [])
}
setAreaTitleBg('head')
}
const delAreaTitle = (index: number, row: Recordable) => {
excelAreaTitle.value.splice(index, 1)
}
/**
* 重置标题区
* 1.重置表格数据,重置缓存标题区域
* 2.当前数据区标题区颜色
*/
const resetAreaTitle = () => {
titleArea.value.forEach((area: any) => {
luckysheet.menuButton.customUpdateFormat(
null,
'bg',
areaMarksColor['data'],
area.sr,
area.er,
area.sc,
area.ec,
false
)
})
resetExcelAreaTitleState()
}
const setAreaTitleBg = (type: 'head') => {
luckysheet.setRangeFormat('bg', areaMarksColor[type])
}
const resetExcelAreaTitleState = () => {
excelAreaTitle.value = []
titleArea.value = []
}
const nextStep = (index: number = 1) => {
// 验证是否设置标题区域
if (!excelAreaTitle.value.length && index > 0) {
return ElMessage.error('请添加标题区!')
}
emits(
'next',
index,
index > 0
? {
excelAreaTitle: unref(excelAreaTitle),
titleArea: unref(titleArea)
}
: undefined
)
// 返回重置表头标记
if (index < 0) {
resetAreaTitle()
}
}
defineExpose({
resetExcelAreaTitleState
})
</script>
<style lang="scss" scoped>
.excel-title-table {
padding: 8px;
}
</style>
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