新增 护理流程类型

This commit is contained in:
YuanFeng 2024-11-25 00:59:29 +08:00
parent 86f080e474
commit 698dd3f1a8
15 changed files with 1387 additions and 7 deletions

View File

@ -21,6 +21,12 @@ public class ProductCareItemPageReqVO extends PageParam {
@Schema(description = "类型 字典oms_product_care_item_type", example = "2")
private String type;
/**
* 1洗涤 2漂白 3烘干 4自然干燥 5熨烫 6专业纺织品护理工艺
* 产品护理过程类型 字典 oms_product_care_process_type
*/
private String processType;
@Schema(description = "语言对照")
private String langMapping;

View File

@ -24,6 +24,12 @@ public class ProductCareItemRespVO {
@ExcelProperty("类型 字典oms_product_care_item_type")
private String type;
/**
* 1洗涤 2漂白 3烘干 4自然干燥 5熨烫 6专业纺织品护理工艺
* 产品护理过程类型 字典 oms_product_care_process_type
*/
private String processType;
@Schema(description = "语言对照")
@ExcelProperty("语言对照")
private String langMapping;

View File

@ -18,6 +18,11 @@ public class ProductCareItemSaveReqVO {
@Schema(description = "类型 字典oms_product_care_item_type", example = "2")
private String type;
/**
* 1洗涤 2漂白 3烘干 4自然干燥 5熨烫 6专业纺织品护理工艺
* 产品护理过程类型 字典 oms_product_care_process_type
*/
private String processType;
@Schema(description = "语言对照")
private String langMapping;

View File

@ -31,10 +31,18 @@ public class ProductCareItemDO extends BaseDO {
* 说明
*/
private String value;
/**
* 1成分比例 2 图文说明 3 文字说明 4 尺码
* 类型 字典oms_product_care_item_type
*/
private String type;
/**
* 1洗涤 2漂白 3烘干 4自然干燥 5熨烫 6专业纺织品护理工艺
* 产品护理过程类型 字典 oms_product_care_process_type
*/
private String processType;
/**
* 语言对照
*/

View File

@ -213,7 +213,7 @@
<el-select-v2
v-model="that.propInfo[tmp.key].dataInfo[index].showLabel"
filterable
:options="washingInfoListByType(that.propInfo[tmp.key].groupType)"
:options="washingInfoListByType(that.propInfo[tmp.key].groupType,orderIndex)"
placeholder="Please select"
clearable
@change="changeIconData(index,tmp.key)"
@ -554,9 +554,33 @@ const changeIconData = (index: number, key: string) => {
}
}
const findProcessTypeIndex = (index) => {
if(index < 0){
return index;
}
let processType = 0;
const washingInfoListByType = (type) => {
return that.washingInfoList.filter(item => item.type === type)
for (let i = 0; i < that.propOrderByList.length; i++) {
//
if (that.propOrderByList[i].shape === ShapeType.vueShapeImage) {
processType++;
console.log("@@@@@@",index,i)
if(index === i){
return processType
}
}
}
return processType;
}
const washingInfoListByType = (type,index = -1) => {
const typeIndex = findProcessTypeIndex(index);
return that.washingInfoList.filter(item => {
if (item.type === type && (typeIndex < 0 || (item.processType === `${typeIndex}`))) {
return item
}
})
}
const getIngredientInfoListByType = (type) => {
return that.ingredientInfoList.filter(item => item.type === type)
@ -837,6 +861,7 @@ const queryUseLabel = (label) => {
label: item.value,
type: item.type,
isCombo: item.isCombo,
processType: item.processType,
langMapping: JSON.parse(item.langMapping || '{}'),
url: replaceDomain(domain, item.iconUrl)
}
@ -941,6 +966,7 @@ const checkPropInfo = (info) => {
ratio: newInfo[key].dataInfo[j].ratio,
locale: newInfo[key].dataInfo[j].locale
});
if (newInfo[key].dataInfo[j].ratio > maxRatio) {
useMessage().alert(getLabelName(newInfo[key]) + "违反含有量的成分比例,由大到小依序排列")
}

View File

@ -9,3 +9,12 @@ export enum GroupTypeEnum {
TEXT = '3',
SIZE = '4'
}
// 1洗涤 2漂白 3烘干 4自然干燥 5熨烫 6专业纺织品护理工艺
export enum ProcessTypeEnum {
WASH = '1',
WHITE = '2',
DRY = '3',
NATURAL = '4',
IRON = '5',
PROFESSIONAL = '6'
}

View File

@ -218,5 +218,6 @@ export enum DICT_TYPE {
OMS_BILL_STATUS = 'oms_bill_status', // 单据状态
OMS_ORDER_STATUS = 'oms_order_status',// 订单状态
OMS_PRODUCT_CARE_ITEM_TYPE = 'oms_product_care_item_type', //产品保养项目类型 1.成分说明 2.洗涤说明 3.使用说明 4.尺码
OMS_PRODUCT_CARE_PROCESS_TYPE = 'oms_product_care_process_type', //产品护理过程类型 1洗涤 2漂白 3烘干 4自然干燥 5熨烫 6专业纺织品护理工艺
}

View File

@ -32,9 +32,19 @@
</el-select>
</el-form-item>
<el-form-item label="洗涤图标" v-show="formData.type === '2'" prop="iconUrl">
<el-form-item label="护理类型图标" v-show="formData.type === '2'" prop="iconUrl">
<DraftDesignImageLibDialog v-model="formData.iconUrl" placeholder="请输入icon图标" @submit="changeIcon"/>
</el-form-item>
<el-form-item label="护理类型" v-show="formData.type === '2'" prop="processType">
<el-select v-model="formData.processType">
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.OMS_PRODUCT_CARE_PROCESS_TYPE)"
:key="`${dict.value}`"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="品牌通用" prop="isAll">
<el-checkbox v-model="formData.isAll">该保养说明适用于所有品牌</el-checkbox>
@ -178,6 +188,7 @@ const formData = ref({
id: undefined,
value: undefined,
iconUrl: '',
processType: undefined,
type: '1',
brandIds: '',
isCombo: true,
@ -347,6 +358,7 @@ const resetForm = () => {
type: '1',
brandIds: '',
iconUrl: '',
processType: undefined,
isCombo: true,
isAll: true,
locale: 'zh-CN',

View File

@ -233,6 +233,8 @@ const handleExport = async () => {
let first_load = true;
/** 初始化 **/
onMounted(() => {
//
queryParams.type = '3,4'
if(first_load){
first_load = false;
queryParams.type = route.query.type

View File

@ -0,0 +1,382 @@
<template>
<Dialog
:title="dialogTitle"
width="68vw"
v-model="dialogVisible">
<el-scrollbar height="60vh">
<div>
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="名称" prop="value">
<el-input
:name="`_$_ProductCareItemForm_value`"
:autocomplete="`_$_ProductCareItemForm_value`"
v-model="formData.value"
clearable
placeholder="请输入名称"/>
</el-form-item>
<el-form-item label="类型" prop="type">
<el-select v-model="formData.type" disabled>
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.OMS_PRODUCT_CARE_ITEM_TYPE)"
:key="`${dict.value}`"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="护理类型图标" v-show="formData.type === '2'" prop="iconUrl">
<DraftDesignImageLibDialog v-model="formData.iconUrl" placeholder="请输入icon图标" @submit="changeIcon"/>
</el-form-item>
<el-form-item label="护理类型" v-show="formData.type === '2'" prop="processType">
<el-select v-model="formData.processType">
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.OMS_PRODUCT_CARE_PROCESS_TYPE)"
:key="`${dict.value}`"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="品牌通用" prop="isAll">
<el-checkbox v-model="formData.isAll">该保养说明适用于所有品牌</el-checkbox>
</el-form-item>
<el-form-item v-show="!formData.isAll" label="品牌专属" prop="brandIds">
<div>
<div>用于指定品牌</div>
<div>
<BrandDataListDialog
class="w-full"
v-model="formData.brandIds"
multiple
placeholder="请选择品牌"/>
</div>
</div>
</el-form-item>
<el-form-item label="多语言配置" prop="langMapping">
<div class="w-full">
<el-collapse accordion v-model="langeActiveName">
<el-collapse-item name="1">
<template #title>
<span> 多语言对照列表</span>
</template>
<div>
<el-button @click="addLangMapping">添加</el-button>
<el-tooltip>
<template #content>
<div>将多种语言内容拼接到一起</div>
</template>
<el-checkbox class="m-4" v-model="formData.isCombo">多语言拼接</el-checkbox>
</el-tooltip>
<el-alert
title="多语言内容可使用${r}作为占位符如:白鹅绒${r}%以上, 填写 60时, 结果为: 白鹅绒60%以上点击输入框按下Alt+T快速填入"
type="info" effect="dark"/>
<el-table
:data="that.langList"
:stripe="true"
:show-overflow-tooltip="true">
<el-table-column width="55">
<template #header>
<div>
<span>行号</span>
</div>
</template>
<template #default="scope">
<span>{{ scope.$index + 1 }}</span>
</template>
</el-table-column>
<el-table-column prop="locale" label="地区语言" width="180">
<template #header>
<div>
<span class="color-red">*</span>
<span>地区语言</span>
</div>
</template>
<template #default="scope">
<div
:class="{ 'duplicate-tips' : duplicateCheck(scope.row.locale) }">
<el-select v-model="scope.row.locale" placeholder="地区语言">
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.LANGUAGE_LOCALE)"
:key="`${dict.value}`"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</div>
</template>
</el-table-column>
<el-table-column prop="value">
<template #header>
<div>
<span class="color-red">*</span>
<span>多语言内容</span>
</div>
</template>
<template #default="scope">
<div>
<el-input :id="`rowInput_${scope.$index}`" @focus="inputFocus(scope.$index)" v-model="scope.row.value" placeholder="请输入内容"/>
</div>
</template>
</el-table-column>
<el-table-column prop="linkChar" label="连接符" width="120">
<template #default="scope">
<el-input v-model="scope.row.linkChar" placeholder="连接符"/>
</template>
</el-table-column>
<el-table-column prop="value" label="操作" width="80">
<template #default="{$index}">
<el-button size="small" type="danger" @click="removeRow($index) ">删除
</el-button>
</template>
</el-table-column>
</el-table>
</div>
</el-collapse-item>
</el-collapse>
</div>
</el-form-item>
<el-form-item label="启用状态" prop="enabled">
<el-checkbox v-model="formData.enabled">是否启用</el-checkbox>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="formData.remark" type="textarea" placeholder="请输入备注"/>
</el-form-item>
</el-form>
</div>
</el-scrollbar>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading">{{ t('common.ok') }}
</el-button>
<el-button @click="dialogVisible = false">{{ t('common.cancel') }}</el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import {getStrDictOptions, DICT_TYPE} from '@/utils/dict'
import {ProductCareItemApi, ProductCareItemVO} from '@/api/oms/productcareitem'
import DraftDesignImageLibDialog from "@/components/Dialog/src/DraftDesignImageLibDialog/index.vue";
import BrandDataListDialog from "@/components/Dialog/src/BrandDataListDialog/index.vue";
/** 产品保养项 表单 */
defineOptions({name: 'ProductCareItemForm'})
const {t} = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const imageVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
value: undefined,
iconUrl: '',
processType: undefined,
type: '1',
brandIds: '',
isCombo: true,
isAll: true,
locale: 'zh-CN',
langMapping: '',
enabled: true,
remark: "",
})
const langeActiveName = ref('1');
const formRules = reactive({
value: [{required: true, message: '说明不能为空', trigger: 'blur'}],
})
const formRef = ref() // Ref
const that = reactive({
inputIndex: -1,
langList: [{
locale: 'zh-CN', //
value: '', //
linkChar: '', //
}],
})
const duplicateCheck = (lang: string) => {
let count = 0;
for (let i = 0; i < that.langList.length; i++) {
if (that.langList[i].locale === lang) {
count++;
}
}
return count > 1;
}
const addLangMapping = () => {
that.langList.push({
locale: '',
value: '',
linkChar: '',
})
}
const removeRow = (index) => {
if (that.langList.length > 1) {
that.langList.splice(index, 1)
} else {
message.error('至少需要一个多语言内容')
}
}
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await ProductCareItemApi.getProductCareItem(id)
console.log(" formData.value", formData.value)
that.langList = JSON.parse(formData.value.langMapping || '{}')
} finally {
formLoading.value = false
}
}
}
const changeIcon = (info) => {
console.log("info", info)
}
defineExpose({open}) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = () => {
//
formRef.value.validate().then(async ()=>{
//
formLoading.value = true
try {
const data = formData.value as unknown as ProductCareItemVO
let countInfo = {};
for (let i = 0; i < that.langList.length; i++) {
const l = that.langList[i].locale
if (!l) {
message.error(`${i + 1}行语言不能为空`)
return;
}
if (!that.langList[i].value) {
message.error(`${i + 1}行翻译内容不能为空`)
return;
}
if (countInfo[l]) {
message.error(`${l} 翻译内容重复`)
return;
}
countInfo[l] = 1;
}
data.langMapping = JSON.stringify(that.langList)
if (formType.value === 'create') {
await ProductCareItemApi.createProductCareItem(data)
message.success(t('common.createSuccess'))
} else {
await ProductCareItemApi.updateProductCareItem(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}).catch(()=>{
message.error('请填写必填项')
})
}
const inputFocus = (index)=>{
that.inputIndex = index
}
// Alt + R
const handleKeydown = (event) => {
// Alt + R
if (event.altKey && event.key === 'r') {
onAltRPressed();
}
};
// Alt + R
const onAltRPressed = () => {
console.log('Alt + R 被按下了');
if(that.inputIndex >= 0){
const byId = document.getElementById("rowInput_"+that.inputIndex);
let pos = 0;
if(byId){
pos = byId.selectionStart;
}
let str = that.langList[that.inputIndex].value;
if(str && str.length > 0 && pos > 0){
if(pos >= str.length){
that.langList[that.inputIndex].value = that.langList[that.inputIndex].value+"${r}";
}else {
that.langList[that.inputIndex].value = str.substring(0,pos)+"${r}"+str.substring(pos);
}
}else {
that.langList[that.inputIndex].value = "${r}"+that.langList[that.inputIndex].value;
}
}
//
};
//
onMounted(() => {
window.addEventListener('keydown', handleKeydown);
});
//
onBeforeUnmount(() => {
window.removeEventListener('keydown', handleKeydown);
});
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
value: undefined,
type: '1',
brandIds: '',
iconUrl: '',
processType: undefined,
isCombo: true,
isAll: true,
locale: 'zh-CN',
langMapping: '',
enabled: true,
remark: "",
}
that.langList = [{
locale: 'zh-CN', //
value: '', //
linkChar: '', //
}]
formRef.value?.resetFields()
}
</script>
<style scoped lang="scss">
.duplicate-tips {
box-shadow: 2px 0 0 2px rgba(255, 0, 0, 0.85);;
}
</style>

View File

@ -0,0 +1,252 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-row>
<el-col :xs="24" :span="8">
<el-form-item label="名称" prop="value">
<el-input
v-model="queryParams.value"
placeholder="请输入保养项名称"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
</el-col>
<el-col :xs="24" :span="8">
<el-select v-model="queryParams.type" clearable multiple>
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.OMS_PRODUCT_CARE_ITEM_TYPE)"
:key="`${dict.value}`"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-col>
<el-col :xs="24" :span="8">
<el-form-item label="启用状态" prop="enabled">
<el-select
v-model="queryParams.enabled"
placeholder="请选择启用状态"
clearable
class="!w-240px"
>
<el-option label="启用" :value="true" />
<el-option label="停用" :value="false" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="创建时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-240px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['oms:product-care-item:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['oms:product-care-item:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table border v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="保养项名称" align="center" prop="value" width="200" />
<el-table-column label="品牌通用" align="center" prop="isAll" >
<template #default="scope">
<div>
{{scope.row.isAll ? '是' : '否'}}
</div>
</template>
</el-table-column>
<el-table-column label="启用状态" align="center" prop="enabled" >
<template #default="scope">
<div>
{{scope.row.enabled ? '启用' : '停用'}}
</div>
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['oms:product-care-item:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['oms:product-care-item:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<ProductCareItemForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { getStrDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { ProductCareItemApi, ProductCareItemVO } from '@/api/oms/productcareitem'
import ProductCareItemForm from './ProductCareItemForm.vue'
import {buildQuery} from "@/utils/queryUtil";
/** 产品保养项 列表 */
defineOptions({ name: 'ProductCareItem' })
const message = useMessage() //
const { t } = useI18n() //
const route = useRoute() //
const loading = ref(true) //
const list = ref<ProductCareItemVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
value: undefined,
type: undefined,
iconUrl: undefined,
brandIds: undefined,
isCombo: undefined,
isAll: undefined,
locale: undefined,
enabled: undefined,
remark: undefined,
createTime: [],
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await ProductCareItemApi.queryPage(buildQuery(queryParams,{
easyOption: "value@like,type@in",
orderBy: 'create_time desc',
ignoreField: "pageNo,pageSize"
}))
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await ProductCareItemApi.deleteProductCareItem(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await ProductCareItemApi.exportProductCareItem(queryParams)
download.excel(data, '产品保养项 .xls')
} catch {
} finally {
exportLoading.value = false
}
}
let first_load = true;
/** 初始化 **/
onMounted(() => {
//
queryParams.type = 1
if(first_load){
first_load = false;
queryParams.type = route.query.type
if(queryParams.type){
queryParams.type = queryParams.type.split(',').map(String)
}
const tmp = route.query._add
if(tmp == 1){
// url
openForm('create')
}
}
getList()
})
</script>

View File

@ -0,0 +1,384 @@
<template>
<Dialog
:title="dialogTitle"
width="68vw"
v-model="dialogVisible">
<el-scrollbar height="60vh">
<div>
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="名称" prop="value">
<el-input
:name="`_$_ProductCareItemForm_value`"
:autocomplete="`_$_ProductCareItemForm_value`"
v-model="formData.value"
clearable
placeholder="请输入名称"/>
</el-form-item>
<el-form-item label="类型" prop="type">
<el-select v-model="formData.type" disabled>
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.OMS_PRODUCT_CARE_ITEM_TYPE)"
:key="`${dict.value}`"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="护理类型图标" v-show="formData.type === '2'" prop="iconUrl">
<DraftDesignImageLibDialog v-model="formData.iconUrl" placeholder="请输入icon图标" @submit="changeIcon"/>
</el-form-item>
<el-form-item label="护理类型" v-show="formData.type === '2'" prop="processType">
<el-select v-model="formData.processType">
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.OMS_PRODUCT_CARE_PROCESS_TYPE)"
:key="`${dict.value}`"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="品牌通用" prop="isAll">
<el-checkbox v-model="formData.isAll">该保养说明适用于所有品牌</el-checkbox>
</el-form-item>
<el-form-item v-show="!formData.isAll" label="品牌专属" prop="brandIds">
<div>
<div>用于指定品牌</div>
<div>
<BrandDataListDialog
class="w-full"
v-model="formData.brandIds"
multiple
placeholder="请选择品牌"/>
</div>
</div>
</el-form-item>
<el-form-item label="多语言配置" prop="langMapping">
<div class="w-full">
<el-collapse accordion v-model="langeActiveName">
<el-collapse-item name="1">
<template #title>
<span> 多语言对照列表</span>
</template>
<div>
<el-button @click="addLangMapping">添加</el-button>
<el-tooltip>
<template #content>
<div>将多种语言内容拼接到一起</div>
</template>
<el-checkbox class="m-4" v-model="formData.isCombo">多语言拼接</el-checkbox>
</el-tooltip>
<el-alert
title="多语言内容可使用${r}作为占位符如:白鹅绒${r}%以上, 填写 60时, 结果为: 白鹅绒60%以上点击输入框按下Alt+T快速填入"
type="info" effect="dark"/>
<el-table
:data="that.langList"
:stripe="true"
:show-overflow-tooltip="true">
<el-table-column width="55">
<template #header>
<div>
<span>行号</span>
</div>
</template>
<template #default="scope">
<span>{{ scope.$index + 1 }}</span>
</template>
</el-table-column>
<el-table-column prop="locale" label="地区语言" width="180">
<template #header>
<div>
<span class="color-red">*</span>
<span>地区语言</span>
</div>
</template>
<template #default="scope">
<div
:class="{ 'duplicate-tips' : duplicateCheck(scope.row.locale) }">
<el-select v-model="scope.row.locale" placeholder="地区语言">
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.LANGUAGE_LOCALE)"
:key="`${dict.value}`"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</div>
</template>
</el-table-column>
<el-table-column prop="value">
<template #header>
<div>
<span class="color-red">*</span>
<span>多语言内容</span>
</div>
</template>
<template #default="scope">
<div>
<el-input :id="`rowInput_${scope.$index}`" @focus="inputFocus(scope.$index)" v-model="scope.row.value" placeholder="请输入内容"/>
</div>
</template>
</el-table-column>
<el-table-column prop="linkChar" label="连接符" width="120">
<template #default="scope">
<el-input v-model="scope.row.linkChar" placeholder="连接符"/>
</template>
</el-table-column>
<el-table-column prop="value" label="操作" width="80">
<template #default="{$index}">
<el-button size="small" type="danger" @click="removeRow($index) ">删除
</el-button>
</template>
</el-table-column>
</el-table>
</div>
</el-collapse-item>
</el-collapse>
</div>
</el-form-item>
<el-form-item label="启用状态" prop="enabled">
<el-checkbox v-model="formData.enabled">是否启用</el-checkbox>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="formData.remark" type="textarea" placeholder="请输入备注"/>
</el-form-item>
</el-form>
</div>
</el-scrollbar>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading">{{ t('common.ok') }}
</el-button>
<el-button @click="dialogVisible = false">{{ t('common.cancel') }}</el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import {getStrDictOptions, DICT_TYPE} from '@/utils/dict'
import {ProductCareItemApi, ProductCareItemVO} from '@/api/oms/productcareitem'
import DraftDesignImageLibDialog from "@/components/Dialog/src/DraftDesignImageLibDialog/index.vue";
import BrandDataListDialog from "@/components/Dialog/src/BrandDataListDialog/index.vue";
/** 产品保养项 表单 */
defineOptions({name: 'ProductCareItemForm'})
const {t} = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const imageVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
value: undefined,
iconUrl: '',
processType: '1',
type: '2',
brandIds: '',
isCombo: true,
isAll: true,
locale: 'zh-CN',
langMapping: '',
enabled: true,
remark: "",
})
const langeActiveName = ref('1');
const formRules = reactive({
value: [{required: true, message: '说明不能为空', trigger: 'blur'}],
iconUrl: [{required: true, message: '护理说明图标不能为空', trigger: 'blur'}],
})
const formRef = ref() // Ref
const that = reactive({
inputIndex: -1,
langList: [{
locale: 'zh-CN', //
value: '', //
linkChar: '', //
}],
})
const duplicateCheck = (lang: string) => {
let count = 0;
for (let i = 0; i < that.langList.length; i++) {
if (that.langList[i].locale === lang) {
count++;
}
}
return count > 1;
}
const addLangMapping = () => {
that.langList.push({
locale: '',
value: '',
linkChar: '',
})
}
const removeRow = (index) => {
if (that.langList.length > 1) {
that.langList.splice(index, 1)
} else {
message.error('至少需要一个多语言内容')
}
}
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await ProductCareItemApi.getProductCareItem(id)
console.log(" formData.value", formData.value)
that.langList = JSON.parse(formData.value.langMapping || '{}')
} finally {
formLoading.value = false
}
}
}
const changeIcon = (info) => {
console.log("info", info)
}
defineExpose({open}) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = () => {
//
formRef.value.validate().then(async ()=>{
//
formLoading.value = true
try {
const data = formData.value as unknown as ProductCareItemVO
let countInfo = {};
for (let i = 0; i < that.langList.length; i++) {
const l = that.langList[i].locale
if (!l) {
message.error(`${i + 1}行语言不能为空`)
return;
}
if (!that.langList[i].value) {
message.error(`${i + 1}行翻译内容不能为空`)
return;
}
if (countInfo[l]) {
message.error(`${l} 翻译内容重复`)
return;
}
countInfo[l] = 1;
}
data.langMapping = JSON.stringify(that.langList)
if (formType.value === 'create') {
await ProductCareItemApi.createProductCareItem(data)
message.success(t('common.createSuccess'))
} else {
await ProductCareItemApi.updateProductCareItem(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}).catch(()=>{
message.error('请填写必填项')
})
}
const inputFocus = (index)=>{
that.inputIndex = index
}
// Alt + R
const handleKeydown = (event) => {
// Alt + R
if (event.altKey && event.key === 'r') {
onAltRPressed();
}
};
// Alt + R
const onAltRPressed = () => {
console.log('Alt + R 被按下了');
if(that.inputIndex >= 0){
const byId = document.getElementById("rowInput_"+that.inputIndex);
let pos = 0;
if(byId){
pos = byId.selectionStart;
}
let str = that.langList[that.inputIndex].value;
if(str && str.length > 0 && pos > 0){
if(pos >= str.length){
that.langList[that.inputIndex].value = that.langList[that.inputIndex].value+"${r}";
}else {
that.langList[that.inputIndex].value = str.substring(0,pos)+"${r}"+str.substring(pos);
}
}else {
that.langList[that.inputIndex].value = "${r}"+that.langList[that.inputIndex].value;
}
}
//
};
//
onMounted(() => {
window.addEventListener('keydown', handleKeydown);
});
//
onBeforeUnmount(() => {
window.removeEventListener('keydown', handleKeydown);
});
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
value: undefined,
type: '2',
brandIds: '',
iconUrl: '',
processType: '1',
isCombo: true,
isAll: true,
locale: 'zh-CN',
langMapping: '',
enabled: true,
remark: "",
}
that.langList = [{
locale: 'zh-CN', //
value: '', //
linkChar: '', //
}]
formRef.value?.resetFields()
}
</script>
<style scoped lang="scss">
.duplicate-tips {
box-shadow: 2px 0 0 2px rgba(255, 0, 0, 0.85);;
}
</style>

View File

@ -0,0 +1,252 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-row>
<el-col :xs="24" :span="8">
<el-form-item label="名称" prop="value">
<el-input
v-model="queryParams.value"
placeholder="请输入保养项名称"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
</el-col>
<el-col :xs="24" :span="8">
<el-select v-model="queryParams.type" clearable multiple>
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.OMS_PRODUCT_CARE_ITEM_TYPE)"
:key="`${dict.value}`"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-col>
<el-col :xs="24" :span="8">
<el-form-item label="启用状态" prop="enabled">
<el-select
v-model="queryParams.enabled"
placeholder="请选择启用状态"
clearable
class="!w-240px"
>
<el-option label="启用" :value="true" />
<el-option label="停用" :value="false" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="创建时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-240px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['oms:product-care-item:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['oms:product-care-item:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table border v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="保养项名称" align="center" prop="value" width="200" />
<el-table-column label="品牌通用" align="center" prop="isAll" >
<template #default="scope">
<div>
{{scope.row.isAll ? '是' : '否'}}
</div>
</template>
</el-table-column>
<el-table-column label="启用状态" align="center" prop="enabled" >
<template #default="scope">
<div>
{{scope.row.enabled ? '启用' : '停用'}}
</div>
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['oms:product-care-item:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['oms:product-care-item:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<ProductCareItemForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { getStrDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { ProductCareItemApi, ProductCareItemVO } from '@/api/oms/productcareitem'
import ProductCareItemForm from './ProductCareItemForm.vue'
import {buildQuery} from "@/utils/queryUtil";
/** 产品保养项 列表 */
defineOptions({ name: 'ProductCareItem' })
const message = useMessage() //
const { t } = useI18n() //
const route = useRoute() //
const loading = ref(true) //
const list = ref<ProductCareItemVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
value: undefined,
type: undefined,
iconUrl: undefined,
brandIds: undefined,
isCombo: undefined,
isAll: undefined,
locale: undefined,
enabled: undefined,
remark: undefined,
createTime: [],
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await ProductCareItemApi.queryPage(buildQuery(queryParams,{
easyOption: "value@like,type@in",
orderBy: 'create_time desc',
ignoreField: "pageNo,pageSize"
}))
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await ProductCareItemApi.deleteProductCareItem(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await ProductCareItemApi.exportProductCareItem(queryParams)
download.excel(data, '产品保养项 .xls')
} catch {
} finally {
exportLoading.value = false
}
}
let first_load = true;
/** 初始化 **/
onMounted(() => {
//
queryParams.type = 2
if(first_load){
first_load = false;
queryParams.type = route.query.type
if(queryParams.type){
queryParams.type = queryParams.type.split(',').map(String)
}
const tmp = route.query._add
if(tmp == 1){
// url
openForm('create')
}
}
getList()
})
</script>

View File

@ -213,7 +213,7 @@
<el-select-v2
v-model="that.propInfo[tmp.key].dataInfo[index].showLabel"
filterable
:options="washingInfoListByType(that.propInfo[tmp.key].groupType)"
:options="washingInfoListByType(that.propInfo[tmp.key].groupType,orderIndex)"
placeholder="Please select"
clearable
@change="changeIconData(index,tmp.key)"
@ -554,9 +554,33 @@ const changeIconData = (index: number, key: string) => {
}
}
const findProcessTypeIndex = (index) => {
if(index < 0){
return index;
}
let processType = 0;
const washingInfoListByType = (type) => {
return that.washingInfoList.filter(item => item.type === type)
for (let i = 0; i < that.propOrderByList.length; i++) {
//
if (that.propOrderByList[i].shape === ShapeType.vueShapeImage) {
processType++;
console.log("@@@@@@",index,i)
if(index === i){
return processType
}
}
}
return processType;
}
const washingInfoListByType = (type,index = -1) => {
const typeIndex = findProcessTypeIndex(index);
return that.washingInfoList.filter(item => {
if (item.type === type && (typeIndex < 0 || (item.processType === `${typeIndex}`))) {
return item
}
})
}
const getIngredientInfoListByType = (type) => {
return that.ingredientInfoList.filter(item => item.type === type)
@ -837,6 +861,7 @@ const queryUseLabel = (label) => {
label: item.value,
type: item.type,
isCombo: item.isCombo,
processType: item.processType,
langMapping: JSON.parse(item.langMapping || '{}'),
url: replaceDomain(domain, item.iconUrl)
}
@ -941,6 +966,7 @@ const checkPropInfo = (info) => {
ratio: newInfo[key].dataInfo[j].ratio,
locale: newInfo[key].dataInfo[j].locale
});
if (newInfo[key].dataInfo[j].ratio > maxRatio) {
useMessage().alert(getLabelName(newInfo[key]) + "违反含有量的成分比例,由大到小依序排列")
}

View File

@ -9,3 +9,12 @@ export enum GroupTypeEnum {
TEXT = '3',
SIZE = '4'
}
// 1洗涤 2漂白 3烘干 4自然干燥 5熨烫 6专业纺织品护理工艺
export enum ProcessTypeEnum {
WASH = '1',
WHITE = '2',
DRY = '3',
NATURAL = '4',
IRON = '5',
PROFESSIONAL = '6'
}