feat:树形分类的新增和修改
This commit is contained in:
1 parent
4b02337db3
commit
1b1642e51d
10 files changed
+276
-177
No files matched your search
@@ -59,16 +59,7 @@
|
||||
</view>
|
||||
</z-paging>
|
||||
|
||||
<tm-drawer
|
||||
title=""
|
||||
:showClose="false"
|
||||
:showFooter="false"
|
||||
size="98%"
|
||||
placement="bottom"
|
||||
v-model:show="state.showDrawer"
|
||||
:duration="100"
|
||||
zIndex="100"
|
||||
>
|
||||
<tm-drawer title="" :showClose="false" :showFooter="false" size="98%" v-model:show="state.showDrawer" :duration="100" zIndex="100">
|
||||
<z-paging
|
||||
ref="pageRef"
|
||||
:fixed="true"
|
||||
|
||||
@@ -79,7 +79,6 @@
|
||||
:showClose="true"
|
||||
:showFooter="false"
|
||||
size="auto"
|
||||
placement="bottom"
|
||||
v-model:show="showDatePicker"
|
||||
:duration="100"
|
||||
zIndex="100"
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
<text class="c-#0094ff! sub-text-24 mr-20rpx px-2 bg-#0094ff22 rounded-2">{{ item.status == "0" ? "正常" : "禁用" }}</text>
|
||||
</view>
|
||||
<view class="flex-row-center gap-2">
|
||||
<tm-button class="px-2" size="xs" @click="">编辑</tm-button>
|
||||
<tm-button class="px-2" size="xs" :linear="['to right', '#FFC328', '#E2000099']" @click="">删除</tm-button>
|
||||
<tm-button class="px-2" size="xs" @click="editCategary(item)">编辑</tm-button>
|
||||
<tm-button class="px-2" size="xs" :linear="['to right', '#FFC328', '#E2000099']" @click="delCategary(item.id)">删除</tm-button>
|
||||
</view>
|
||||
</view>
|
||||
<view class="h-100rpx"></view>
|
||||
@@ -20,18 +20,39 @@
|
||||
<tm-drawer
|
||||
title="分类"
|
||||
:showClose="true"
|
||||
:showFooter="true"
|
||||
:showFooter="false"
|
||||
size="90%"
|
||||
placement="bottom"
|
||||
v-model:show="categaryFormDrawer"
|
||||
:duration="100"
|
||||
zIndex="100"
|
||||
bgColor="#F5F5F5"
|
||||
>
|
||||
<view>分类名称:</view>
|
||||
<tm-input v-model="form.name" type="text" :showClear="true" placeholder="请输入分类名称"></tm-input>
|
||||
<view>父级分类:</view>
|
||||
<shop-categary-tree :node-data="categoryTree" @currentNode="currentNode" />
|
||||
<view class="card p-4 mb-2">
|
||||
<view class="prefix_title mb-2">基本信息</view>
|
||||
<tm-form @submit="saveCategary" v-model="form" :rules="[]" direction="horizontal">
|
||||
<tm-form-item name="name" label="分类名称">
|
||||
<tm-input v-model="form.name" type="text" :showClear="true" placeholder="请输入分类名称"></tm-input>
|
||||
</tm-form-item>
|
||||
<tm-form-item name="status" label="状态">
|
||||
<tm-radio-group v-model="form.status" align="flex-end">
|
||||
<tm-radio
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
v-for="(item, index) in [
|
||||
{ label: '正常', value: '0' },
|
||||
{ label: '下架', value: '1' },
|
||||
]"
|
||||
:key="index"
|
||||
></tm-radio>
|
||||
</tm-radio-group>
|
||||
</tm-form-item>
|
||||
<view class="prefix_title mb-2">父级分类</view>
|
||||
<view class="card my-2">
|
||||
<shop-categary-tree v-model="selectedNode" :node-data="categoryTree" @currentNode="currentNode" />
|
||||
</view>
|
||||
<tm-button form-type="submit" block>提 交</tm-button>
|
||||
</tm-form>
|
||||
</view>
|
||||
</tm-drawer>
|
||||
</crud-layout>
|
||||
</template>
|
||||
@@ -47,9 +68,11 @@ const categaryFormDrawer = ref(false)
|
||||
const form = reactive({
|
||||
id: "",
|
||||
name: "",
|
||||
status: "0", // 状态(0正常,1下架)
|
||||
parentId: "",
|
||||
})
|
||||
const categoryTree = ref([])
|
||||
const selectedNode = ref<any>({})
|
||||
|
||||
onLoad(() => {
|
||||
getGoodsCategory()
|
||||
@@ -69,10 +92,60 @@ const getCategaryTree = async () => {
|
||||
|
||||
const addCategary = () => {
|
||||
getCategaryTree()
|
||||
Object.assign(form, {
|
||||
id: "",
|
||||
name: "",
|
||||
status: "0",
|
||||
parentId: "",
|
||||
})
|
||||
selectedNode.value = {}
|
||||
categaryFormDrawer.value = true
|
||||
}
|
||||
|
||||
const editCategary = (item) => {
|
||||
getCategaryTree()
|
||||
Object.assign(form, item)
|
||||
selectedNode.value = { id: item.parentId }
|
||||
categaryFormDrawer.value = true
|
||||
}
|
||||
|
||||
const currentNode = (item) => {
|
||||
form.parentId = item.categoryId
|
||||
// form.parentId = item.categoryId
|
||||
}
|
||||
|
||||
const saveCategary = async () => {
|
||||
console.log(form)
|
||||
if (!form.name) return uni.showToast({ title: "请填写分类名称", icon: "none" })
|
||||
if (selectedNode.value.id === form.id) return uni.showToast({ title: "父级分类不能是自身", icon: "none" })
|
||||
try {
|
||||
const params = { ...form, parentId: selectedNode.value.id }
|
||||
uni.showLoading({ title: "保存中..." })
|
||||
const { code, data, msg } = await (form.id ? prosperityShopApi.editCategary(params) : prosperityShopApi.addCategary(params))
|
||||
if (code != 0) return uni.showToast({ title: msg || "保存失败", icon: "none" })
|
||||
uni.showToast({ title: "保存成功", icon: "none" })
|
||||
categaryFormDrawer.value = false
|
||||
await getGoodsCategory()
|
||||
} finally {
|
||||
uni.hideLoading()
|
||||
}
|
||||
}
|
||||
|
||||
// 删除分类
|
||||
const delCategary = async (id: string) => {
|
||||
if (!id) return uni.showToast({ title: "分类id不存在", icon: "none" })
|
||||
uni.showModal({
|
||||
title: "确定删除分类吗?",
|
||||
content: "",
|
||||
success: async (res) => {
|
||||
if (res.confirm) {
|
||||
uni.showLoading({ title: "正在删除" })
|
||||
const { code, msg } = await prosperityShopApi.delCategary(id)
|
||||
if (code != 0) return uni.showToast({ title: msg || "删除失败", icon: "none" })
|
||||
uni.showToast({ title: "删除成功", icon: "none" })
|
||||
getGoodsCategory()
|
||||
uni.hideLoading()
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
</script>
|
||||
@@ -152,7 +152,6 @@
|
||||
:showClose="true"
|
||||
:showFooter="false"
|
||||
size="auto"
|
||||
placement="bottom"
|
||||
v-model:show="showCategaryPicker"
|
||||
:duration="100"
|
||||
zIndex="100"
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
</view>
|
||||
</z-paging>
|
||||
|
||||
<tm-drawer title="退款" :showClose="true" size="90%" placement="bottom" bgColor="#EBF6FF" v-model:show="state.showDrawer" zIndex="999">
|
||||
<tm-drawer title="退款" :showClose="true" size="90%" bgColor="#EBF6FF" v-model:show="state.showDrawer" zIndex="999">
|
||||
<view class="bg-white rounded-16rpx px-10rpx m-b-10rpx animate-both">
|
||||
<z-tabs
|
||||
:list="['同意退款', '拒绝退款']"
|
||||
|
||||
@@ -102,7 +102,6 @@
|
||||
:showClose="false"
|
||||
:showFooter="true"
|
||||
size="70%"
|
||||
placement="bottom"
|
||||
v-model:show="state.showDrawer"
|
||||
:duration="100"
|
||||
zIndex="1200"
|
||||
|
||||
@@ -78,4 +78,27 @@ export default {
|
||||
data,
|
||||
})
|
||||
},
|
||||
// 删除商品分类
|
||||
delCategary: (id: any): Promise<any> => {
|
||||
return request({
|
||||
url: `/supermarket/app/mall/merchant/category/${id}`,
|
||||
method: "DELETE",
|
||||
})
|
||||
},
|
||||
// 新增商品分类
|
||||
addCategary: (data: any): Promise<any> => {
|
||||
return request({
|
||||
url: `/supermarket/app/mall/merchant/category/create`,
|
||||
method: "POST",
|
||||
data,
|
||||
})
|
||||
},
|
||||
// 编辑商品分类
|
||||
editCategary: (data: any): Promise<any> => {
|
||||
return request({
|
||||
url: `/supermarket/app/mall/merchant/category/update`,
|
||||
method: "PUT",
|
||||
data,
|
||||
})
|
||||
},
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<view class="max-h-[60vh] overflow-y-auto mb-20rpx">
|
||||
<shop-categary-tree :node-data="categoryTree" @currentNode="currentNode" />
|
||||
<shop-categary-tree v-model="selectedNode" :node-data="categoryTree" @currentNode="currentNode" />
|
||||
<view v-if="categoryTree.length === 0" class="text-center text-[#888] py-[40rpx]">暂无数据</view>
|
||||
</view>
|
||||
<view class="px-[20rpx] py-2 flex justify-between sticky bottom-0 bg-white">
|
||||
@@ -22,19 +22,18 @@ defineProps({
|
||||
})
|
||||
const emit = defineEmits(["confirm", "cancel"])
|
||||
|
||||
const selectedNode = ref<any>({})
|
||||
const selectedCategary = ref<any>({})
|
||||
|
||||
const currentNode = (item) => {
|
||||
console.log(item)
|
||||
|
||||
selectedCategary.value = item
|
||||
}
|
||||
|
||||
function onConfirm() {
|
||||
if (!selectedCategary.value) {
|
||||
if (!selectedNode.value) {
|
||||
return uni.showToast({ title: "请选择分类", icon: "none" })
|
||||
}
|
||||
emit("confirm", { categoryId: selectedCategary.value.id, categoryName: selectedCategary.value.name })
|
||||
emit("confirm", { ...selectedNode, categoryId: selectedNode.value.id, categoryName: selectedNode.value.name })
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
<template>
|
||||
<view class="tree-container">
|
||||
<view v-for="item in nodeData" :key="item.id">
|
||||
<view class="tree-item" @click.stop="toCurrentNode(item)">
|
||||
<view class="tree-item" :style="{ backgroundColor: item.id == selectedNode.id ? '#4b93ff' : '' }" @click.stop="toCurrentNode(item)">
|
||||
<text>{{ item.name }}</text>
|
||||
</view>
|
||||
|
||||
<shop-categary-tree
|
||||
v-model="selectedNode"
|
||||
v-if="item.children && item.children.length"
|
||||
:node-data="item.children"
|
||||
:style="{ marginLeft: `${getLevel() * 60}rpx` }"
|
||||
@@ -25,9 +26,11 @@ defineProps({
|
||||
},
|
||||
})
|
||||
const emit = defineEmits(["currentNode"])
|
||||
const selectedNode = defineModel<any>("modelValue")
|
||||
|
||||
const toCurrentNode = (item) => {
|
||||
emit("currentNode", item)
|
||||
// emit("currentNode", item)
|
||||
selectedNode.value = item
|
||||
}
|
||||
|
||||
const getLevel = () => {
|
||||
@@ -43,10 +46,6 @@ const getLevel = () => {
|
||||
border-bottom: 1rpx solid #e4e7ed;
|
||||
display: flex;
|
||||
padding: 10rpx 0 10rpx 20rpx;
|
||||
}
|
||||
.tree-item:hover {
|
||||
background-color: #4b93ff;
|
||||
border-radius: 10rpx;
|
||||
color: #fff;
|
||||
}
|
||||
</style>
|
||||
@@ -1,9 +1,17 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed, onMounted, onBeforeUnmount, watch, type PropType, getCurrentInstance, onUpdated, nextTick } from 'vue';
|
||||
import { arrayNumberValid, arrayNumberValidByStyleMP, covetUniNumber, arrayNumberValidByStyleBorderColor, linearValid, getUnit, getUid } from "../../libs/tool";
|
||||
import { getDefaultColor, getDefaultColorObj, getOutlineColorObj, getTextColorObj, getThinColorObj } from "../../libs/colors";
|
||||
import { useTmConfig } from "../../libs/config";
|
||||
import { onPageScroll } from '@dcloudio/uni-app';
|
||||
import { ref, computed, onMounted, onBeforeUnmount, watch, type PropType, getCurrentInstance, onUpdated, nextTick } from "vue"
|
||||
import {
|
||||
arrayNumberValid,
|
||||
arrayNumberValidByStyleMP,
|
||||
covetUniNumber,
|
||||
arrayNumberValidByStyleBorderColor,
|
||||
linearValid,
|
||||
getUnit,
|
||||
getUid,
|
||||
} from "../../libs/tool"
|
||||
import { getDefaultColor, getDefaultColorObj, getOutlineColorObj, getTextColorObj, getThinColorObj } from "../../libs/colors"
|
||||
import { useTmConfig } from "../../libs/config"
|
||||
import { onPageScroll } from "@dcloudio/uni-app"
|
||||
|
||||
/**
|
||||
* @displayName 抽屉
|
||||
@@ -15,7 +23,7 @@ import { onPageScroll } from '@dcloudio/uni-app';
|
||||
| --- | --- | --- | --- |
|
||||
| ☑️| ☑️ | ☑️ | ☑️ | ☑️ | 1.0.0 |
|
||||
*/
|
||||
defineOptions({ name: 'TmDrawer' });
|
||||
defineOptions({ name: "TmDrawer" })
|
||||
const { config } = useTmConfig()
|
||||
|
||||
const props = defineProps({
|
||||
@@ -24,84 +32,84 @@ const props = defineProps({
|
||||
*/
|
||||
customStyle: {
|
||||
type: String,
|
||||
default: ""
|
||||
default: "",
|
||||
},
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
title: {
|
||||
type: String,
|
||||
default: "标题"
|
||||
default: "标题",
|
||||
},
|
||||
/**
|
||||
* 显示底部操作栏
|
||||
*/
|
||||
showFooter: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
/**
|
||||
* 是否显示标题
|
||||
*/
|
||||
showTitle: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
default: true,
|
||||
},
|
||||
/**
|
||||
* 是否显示底部关闭按钮
|
||||
*/
|
||||
showClose: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
/**
|
||||
* 遮罩是否允许点击被关闭
|
||||
*/
|
||||
overlayClick: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
default: true,
|
||||
},
|
||||
/**
|
||||
* 显示可v-model:show双向绑定
|
||||
*/
|
||||
show: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
/**
|
||||
* 显示取消按钮
|
||||
*/
|
||||
showCancel: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
default: true,
|
||||
},
|
||||
/**
|
||||
* 取消按钮的文本
|
||||
*/
|
||||
cancelText: {
|
||||
type: String,
|
||||
default: "取消"
|
||||
default: "取消",
|
||||
},
|
||||
/**
|
||||
* 确认按钮的文本
|
||||
*/
|
||||
confirmText: {
|
||||
type: String,
|
||||
default: "确认"
|
||||
default: "确认",
|
||||
},
|
||||
/**
|
||||
* 动画时间
|
||||
*/
|
||||
duration: {
|
||||
type: Number,
|
||||
default: 300
|
||||
default: 300,
|
||||
},
|
||||
/**
|
||||
* 打开方向。
|
||||
*/
|
||||
position: {
|
||||
type: String as PropType<"top" | "bottom" | "left" | "right">,
|
||||
default: "bottom"
|
||||
default: "bottom",
|
||||
},
|
||||
/**
|
||||
* 打开方向为上和下时的圆角
|
||||
@@ -109,7 +117,7 @@ const props = defineProps({
|
||||
*/
|
||||
round: {
|
||||
type: [String, Number],
|
||||
default: ""
|
||||
default: "",
|
||||
},
|
||||
/**
|
||||
* 左右时为内容宽,
|
||||
@@ -118,7 +126,7 @@ const props = defineProps({
|
||||
*/
|
||||
size: {
|
||||
type: [String, Number],
|
||||
default: "50%"
|
||||
default: "50%",
|
||||
},
|
||||
/**
|
||||
* 弹层最大的高度值,默认为屏幕的可视高
|
||||
@@ -126,21 +134,21 @@ const props = defineProps({
|
||||
*/
|
||||
maxHeight: {
|
||||
type: String,
|
||||
default: ""
|
||||
default: "",
|
||||
},
|
||||
/**
|
||||
* 背景颜色
|
||||
*/
|
||||
bgColor: {
|
||||
type: String,
|
||||
default: 'white'
|
||||
default: "white",
|
||||
},
|
||||
/**
|
||||
* 暗黑背景颜色,如果不提供默认读取全局的sheet配置
|
||||
*/
|
||||
darkBgColor: {
|
||||
type: String,
|
||||
default: ''
|
||||
default: "",
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -150,14 +158,14 @@ const props = defineProps({
|
||||
*/
|
||||
disabledScroll: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
/**
|
||||
* 内容区域左右和下的边距。
|
||||
*/
|
||||
contentMargin: {
|
||||
type: String,
|
||||
default: '24'
|
||||
default: "24",
|
||||
},
|
||||
/**
|
||||
* 宽屏时是否让内容剧中显示
|
||||
@@ -166,21 +174,21 @@ const props = defineProps({
|
||||
*/
|
||||
widthCoverCenter: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
/**
|
||||
* 距离顶部的偏移量
|
||||
*/
|
||||
offsetTop: {
|
||||
type: [String, Number],
|
||||
default: '0'
|
||||
default: "0",
|
||||
},
|
||||
/**
|
||||
* 弹层的层级
|
||||
*/
|
||||
zIndex: {
|
||||
type: [String, Number],
|
||||
default: 1100
|
||||
default: 1100,
|
||||
},
|
||||
/**
|
||||
* 懒加载
|
||||
@@ -189,50 +197,50 @@ const props = defineProps({
|
||||
*/
|
||||
lazy: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
/**
|
||||
* 关闭前执行,可以是异步函数,只有当用户点击confirm时才会触发。如果返回false将阻止关闭。true允许关闭。
|
||||
*/
|
||||
beforeClose: {
|
||||
type: [Function, Boolean] as PropType<() => Promise<boolean>>,
|
||||
default: true
|
||||
}
|
||||
default: true,
|
||||
},
|
||||
})
|
||||
|
||||
const emit = defineEmits([
|
||||
/**
|
||||
* 点击遮罩事件
|
||||
*/
|
||||
'click',
|
||||
"click",
|
||||
/**
|
||||
* 关闭是触发
|
||||
*/
|
||||
'close',
|
||||
"close",
|
||||
/**
|
||||
* 打开时触发
|
||||
*/
|
||||
'open',
|
||||
"open",
|
||||
/**
|
||||
* 打开前执行
|
||||
*/
|
||||
'beforeOpen',
|
||||
"beforeOpen",
|
||||
/**
|
||||
* 关闭前执行
|
||||
*/
|
||||
'beforeClose',
|
||||
"beforeClose",
|
||||
/**
|
||||
* 等同v-model:show
|
||||
*/
|
||||
'update:show',
|
||||
"update:show",
|
||||
/**
|
||||
* 取消时触发
|
||||
*/
|
||||
'cancel',
|
||||
"cancel",
|
||||
/**
|
||||
* 确认时触发
|
||||
*/
|
||||
'confirm'
|
||||
"confirm",
|
||||
])
|
||||
|
||||
const isLoading = ref(false)
|
||||
@@ -251,13 +259,16 @@ const windtopReal = ref(0)
|
||||
const tantiaoTrue = ref(false)
|
||||
const safeFooterHeight = ref(0)
|
||||
const lezyShowModal = ref(props.lazy ? false : true)
|
||||
watch(() => props.show, (newVal) => {
|
||||
if (newVal) {
|
||||
showAlert()
|
||||
} else {
|
||||
closeAlert()
|
||||
}
|
||||
})
|
||||
watch(
|
||||
() => props.show,
|
||||
(newVal) => {
|
||||
if (newVal) {
|
||||
showAlert()
|
||||
} else {
|
||||
closeAlert()
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
const _lazy = computed(() => props.lazy)
|
||||
const _customStyle = computed(() => props.customStyle)
|
||||
@@ -276,10 +287,10 @@ const _round = computed(() => {
|
||||
let radius = covetUniNumber(round, config.unit)
|
||||
|
||||
let _r = "none"
|
||||
if (props.position == 'top') {
|
||||
if (props.position == "top") {
|
||||
_r = `0px 0px ${radius} ${radius}`
|
||||
}
|
||||
if (props.position == 'bottom') {
|
||||
if (props.position == "bottom") {
|
||||
_r = `${radius} ${radius} 0px 0px`
|
||||
}
|
||||
return _r
|
||||
@@ -288,7 +299,7 @@ const _offset = computed(() => {
|
||||
let offset = covetUniNumber(props.offsetTop, config.unit)
|
||||
let x = parseFloat(offset)
|
||||
let unit = getUnit(offset)
|
||||
if (unit == 'rpx') {
|
||||
if (unit == "rpx") {
|
||||
x = uni.upx2px(x)
|
||||
}
|
||||
return x
|
||||
@@ -298,7 +309,7 @@ const _contentMargin = computed(() => covetUniNumber(props.contentMargin, config
|
||||
const _showFooter = computed(() => props.showFooter)
|
||||
const _maxHeight = computed(() => {
|
||||
if (props.maxHeight == "") return ""
|
||||
if (props.position == 'left' || props.position == 'right') return ""
|
||||
if (props.position == "left" || props.position == "right") return ""
|
||||
|
||||
return covetUniNumber(props.maxHeight, config.unit)
|
||||
})
|
||||
@@ -308,8 +319,8 @@ const _confirmText = computed(() => props.confirmText)
|
||||
const _animationFun = computed(() => config.animation)
|
||||
const _bgColor = computed(() => {
|
||||
let bgcolor = props.bgColor
|
||||
if (config.mode == 'dark') {
|
||||
if (props.darkBgColor != '') {
|
||||
if (config.mode == "dark") {
|
||||
if (props.darkBgColor != "") {
|
||||
bgcolor = props.darkBgColor
|
||||
} else {
|
||||
bgcolor = config.sheetDarkColor
|
||||
@@ -318,19 +329,19 @@ const _bgColor = computed(() => {
|
||||
return getDefaultColor(bgcolor)
|
||||
})
|
||||
const __height = computed(() => {
|
||||
let h = '100%'
|
||||
let h = "100%"
|
||||
// #ifdef WEB
|
||||
h = `calc(100% - ${windtopReal.value}px)`
|
||||
// #endif
|
||||
// #ifdef APP
|
||||
if (_offset.value > 0) {
|
||||
h = _height.value + 'px'
|
||||
h = _height.value + "px"
|
||||
}
|
||||
// #endif
|
||||
return h
|
||||
})
|
||||
const _titleFontSize = computed(() => (config.fontSizeScale * 16).toString() + 'px')
|
||||
const _isDark = computed(() => config.mode == 'dark')
|
||||
const _titleFontSize = computed(() => (config.fontSizeScale * 16).toString() + "px")
|
||||
const _isDark = computed(() => config.mode == "dark")
|
||||
|
||||
// Lifecycle hooks
|
||||
onMounted(() => {
|
||||
@@ -340,8 +351,8 @@ onMounted(() => {
|
||||
_width.value = sys.windowWidth
|
||||
_height.value = sys.windowHeight
|
||||
|
||||
windtop.value = sys.windowTop + (_position.value == 'bottom' ? 0 : _offset.value)
|
||||
windtopReal.value = _position.value == 'bottom' ? (sys.windowTop + _offset.value) : sys.windowTop
|
||||
windtop.value = sys.windowTop + (_position.value == "bottom" ? 0 : _offset.value)
|
||||
windtopReal.value = _position.value == "bottom" ? sys.windowTop + _offset.value : sys.windowTop
|
||||
// #endif
|
||||
// #ifdef APP
|
||||
_width.value = sys.windowWidth
|
||||
@@ -360,26 +371,25 @@ onBeforeUnmount(() => {
|
||||
})
|
||||
|
||||
const cancelEvt = () => {
|
||||
emit('cancel')
|
||||
emit("cancel")
|
||||
closeAlert()
|
||||
}
|
||||
|
||||
const confirmEvt = async () => {
|
||||
emit('confirm')
|
||||
let isPass = true;
|
||||
if (typeof props.beforeClose == 'function') {
|
||||
isLoading.value = true;
|
||||
emit("confirm")
|
||||
let isPass = true
|
||||
if (typeof props.beforeClose == "function") {
|
||||
isLoading.value = true
|
||||
// @ts-ignore
|
||||
isPass = await props.beforeClose();
|
||||
isPass = await props.beforeClose()
|
||||
}
|
||||
isLoading.value = false;
|
||||
isLoading.value = false
|
||||
if (!isPass) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
closeAlert()
|
||||
}
|
||||
|
||||
|
||||
const onClickOverflowy = (evt: Event) => {
|
||||
evt.stopPropagation()
|
||||
/**
|
||||
@@ -392,22 +402,21 @@ const onClickOverflowy = (evt: Event) => {
|
||||
tantiaoTrue.value = true
|
||||
tid2.value = setTimeout(() => {
|
||||
tantiaoTrue.value = false
|
||||
}, 200);
|
||||
return;
|
||||
}, 200)
|
||||
return
|
||||
}
|
||||
closeAlert()
|
||||
|
||||
}
|
||||
|
||||
const closeAlert = () => {
|
||||
if (actinon.value || isLoading.value) return
|
||||
if (status.value == 'close') return
|
||||
if (status.value == "close") return
|
||||
actinon.value = true
|
||||
status.value = 'close'
|
||||
status.value = "close"
|
||||
/**
|
||||
* 关闭前执行
|
||||
*/
|
||||
emit('beforeClose')
|
||||
emit("beforeClose")
|
||||
|
||||
clearTimeout(tid.value)
|
||||
tid.value = setTimeout(() => {
|
||||
@@ -417,17 +426,17 @@ const closeAlert = () => {
|
||||
|
||||
const showAlert = () => {
|
||||
if (actinon.value) return
|
||||
if (status.value == 'open') return
|
||||
if (status.value == "open") return
|
||||
showOverflay.value = true
|
||||
actinon.value = true
|
||||
|
||||
/**
|
||||
* 打开前执行
|
||||
*/
|
||||
emit('beforeOpen')
|
||||
emit("beforeOpen")
|
||||
clearTimeout(tid.value)
|
||||
tid.value = setTimeout(() => {
|
||||
status.value = 'open'
|
||||
status.value = "open"
|
||||
tid.value = setTimeout(() => {
|
||||
onEnd()
|
||||
}, _duration.value)
|
||||
@@ -435,35 +444,30 @@ const showAlert = () => {
|
||||
}
|
||||
|
||||
function openDrawer() {
|
||||
showAlert();
|
||||
showAlert()
|
||||
}
|
||||
|
||||
function onEnd() {
|
||||
actinon.value = false;
|
||||
actinon.value = false
|
||||
|
||||
if (status.value === 'close') {
|
||||
showOverflay.value = false;
|
||||
emit('close');
|
||||
emit('update:show', false);
|
||||
if (status.value === "close") {
|
||||
showOverflay.value = false
|
||||
emit("close")
|
||||
emit("update:show", false)
|
||||
if (_lazy.value) {
|
||||
lezyShowModal.value = false;
|
||||
lezyShowModal.value = false
|
||||
}
|
||||
} else {
|
||||
emit('open');
|
||||
emit("open")
|
||||
if (_lazy.value) {
|
||||
lezyShowModal.value = true;
|
||||
lezyShowModal.value = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function maskerMove(evt: TouchEvent) {
|
||||
evt.preventDefault();
|
||||
evt.preventDefault()
|
||||
}
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
<script lang="ts">
|
||||
export default {
|
||||
@@ -473,7 +477,7 @@ export default {
|
||||
addGlobalClass: true,
|
||||
multipleSlots: true,
|
||||
},
|
||||
};
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<view>
|
||||
@@ -490,33 +494,49 @@ export default {
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<root-portal>
|
||||
<!-- #endif -->
|
||||
<view @click="onClickOverflowy" @touchmove="maskerMove" v-if="showOverflay" :id="id" ref="tmDrawerWrap"
|
||||
class="tmDrawerWrap" :class="[
|
||||
status == 'open' ? 'tmModalWrap_on' : 'tmModalWrap_off',
|
||||
(_position == 'top' || _position == 'bottom') && _widthCoverCenter ? 'tmDrawerWrapContentMinwidthWrapDir' : '',
|
||||
'tmDrawerWrap_' + _position
|
||||
]" :style="[{
|
||||
width: '100%',
|
||||
top: (windtop + 'px'),
|
||||
height: __height,
|
||||
zIndex: zIndex,
|
||||
'transition-timing-function': _animationFun
|
||||
}, _customStyle]">
|
||||
|
||||
<view @click.stop="" ref="tmDrawerWrapContent" class="tmDrawerWrapContent" :class="[
|
||||
(_position == 'top' || _position == 'bottom') && _widthCoverCenter ? 'tmDrawerWrapContentMinwidth' : '',
|
||||
'tmDrawerWrapContent_' + _position + (status == 'open' ? '_on' : ''),
|
||||
tantiaoTrue ? 'tmModalWrapContent_Tantiao' : ''
|
||||
]" :id="wrapId" :style="{
|
||||
width: _position == 'left' || _position == 'right' ? _size : '100%',
|
||||
height: _position == 'left' || _position == 'right' ? '100%' : _size,
|
||||
borderRadius: _round,
|
||||
maxHeight: _maxHeight != '' ? _maxHeight : '100%',
|
||||
minHeight: _size == 'auto' ? '350rpx' : '0px',
|
||||
'transition-timing-function': _animationFun,
|
||||
backgroundColor: _bgColor
|
||||
}">
|
||||
|
||||
<view
|
||||
@click="onClickOverflowy"
|
||||
@touchmove="maskerMove"
|
||||
v-if="showOverflay"
|
||||
:id="id"
|
||||
ref="tmDrawerWrap"
|
||||
class="tmDrawerWrap"
|
||||
:class="[
|
||||
status == 'open' ? 'tmModalWrap_on' : 'tmModalWrap_off',
|
||||
(_position == 'top' || _position == 'bottom') && _widthCoverCenter ? 'tmDrawerWrapContentMinwidthWrapDir' : '',
|
||||
'tmDrawerWrap_' + _position,
|
||||
]"
|
||||
:style="[
|
||||
{
|
||||
width: '100%',
|
||||
top: windtop + 'px',
|
||||
height: __height,
|
||||
zIndex: zIndex,
|
||||
'transition-timing-function': _animationFun,
|
||||
},
|
||||
_customStyle,
|
||||
]"
|
||||
>
|
||||
<view
|
||||
@click.stop=""
|
||||
ref="tmDrawerWrapContent"
|
||||
class="tmDrawerWrapContent"
|
||||
:class="[
|
||||
(_position == 'top' || _position == 'bottom') && _widthCoverCenter ? 'tmDrawerWrapContentMinwidth' : '',
|
||||
'tmDrawerWrapContent_' + _position + (status == 'open' ? '_on' : ''),
|
||||
tantiaoTrue ? 'tmModalWrapContent_Tantiao' : '',
|
||||
]"
|
||||
:id="wrapId"
|
||||
:style="{
|
||||
width: _position == 'left' || _position == 'right' ? _size : '100%',
|
||||
height: _position == 'left' || _position == 'right' ? '100%' : _size,
|
||||
borderRadius: _round,
|
||||
maxHeight: _maxHeight != '' ? _maxHeight : '100%',
|
||||
minHeight: _size == 'auto' ? '350rpx' : '0px',
|
||||
'transition-timing-function': _animationFun,
|
||||
backgroundColor: _bgColor,
|
||||
}"
|
||||
>
|
||||
<view v-if="_showClose" class="tmDrawerXclose">
|
||||
<tm-icon @click="closeAlert" color="#dcdcdc" size="52" name="close-circle-fill"></tm-icon>
|
||||
</view>
|
||||
@@ -529,14 +549,15 @@ export default {
|
||||
<slot name="title" :show="show">
|
||||
<text
|
||||
:style="{ fontSize: _titleFontSize, color: _isDark ? 'white' : 'black', opacity: '0.64' }"
|
||||
class="tmDrawertitleBox">{{ _title }}</text>
|
||||
class="tmDrawertitleBox"
|
||||
>{{ _title }}</text
|
||||
>
|
||||
</slot>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="!disabledScroll && _size != 'auto'" style="flex: 1;" class="tmModalWrapBoxContent">
|
||||
<scroll-view style="height:100%;position:absolute;width:100%;" :scroll-y="true"
|
||||
:rebound="false">
|
||||
<view v-if="!disabledScroll && _size != 'auto'" style="flex: 1" class="tmModalWrapBoxContent">
|
||||
<scroll-view style="height: 100%; position: absolute; width: 100%" :scroll-y="true" :rebound="false">
|
||||
<view :style="{ padding: `0px ${_contentMargin} 0px ${_contentMargin}` }">
|
||||
<!--
|
||||
@slot 默认插槽
|
||||
@@ -545,36 +566,36 @@ export default {
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<view v-else
|
||||
:style="{ height: '100%', padding: `0px ${_contentMargin} 0px ${_contentMargin}` }">
|
||||
<view v-else :style="{ height: '100%', padding: `0px ${_contentMargin} 0px ${_contentMargin}` }">
|
||||
<!--
|
||||
@slot 默认插槽
|
||||
-->
|
||||
<slot></slot>
|
||||
</view>
|
||||
|
||||
|
||||
<view v-if="showFooter && lezyShowModal" class="tmDrawerFooter"
|
||||
:style="{ backgroundColor: _bgColor }">
|
||||
<view v-if="showFooter && lezyShowModal" class="tmDrawerFooter" :style="{ backgroundColor: _bgColor }">
|
||||
<view :style="{ height: _contentMargin }"></view>
|
||||
|
||||
<!--
|
||||
@slot 底部操作栏
|
||||
-->
|
||||
<slot name="footer">
|
||||
<view
|
||||
style="flex-direction: row;align-items: center;justify-content: center;display:flex;">
|
||||
<tm-button :loading="isLoading" width="0px" @click="cancelEvt" v-if="_showCancel"
|
||||
skin="thin" style="margin-right: 16px;flex:1">{{ _cancelText }}</tm-button>
|
||||
<tm-button :loading="isLoading" width="0px" @click="confirmEvt" style="flex:1">{{
|
||||
_confirmText
|
||||
}}</tm-button>
|
||||
<view style="flex-direction: row; align-items: center; justify-content: center; display: flex; margin: 0 20rpx">
|
||||
<tm-button
|
||||
:loading="isLoading"
|
||||
width="0px"
|
||||
@click="cancelEvt"
|
||||
v-if="_showCancel"
|
||||
skin="thin"
|
||||
style="margin-right: 16px; flex: 1"
|
||||
>{{ _cancelText }}</tm-button
|
||||
>
|
||||
<tm-button :loading="isLoading" width="0px" @click="confirmEvt" style="flex: 1">{{ _confirmText }}</tm-button>
|
||||
</view>
|
||||
</slot>
|
||||
<view :style="{ height: safeFooterHeight + 'px' }"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
</root-portal>
|
||||
@@ -613,7 +634,6 @@ export default {
|
||||
line-clamp: 1;
|
||||
display: -webkit-box;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
}
|
||||
|
||||
.tmDrawerWrap_bottom {
|
||||
@@ -661,13 +681,12 @@ export default {
|
||||
}
|
||||
|
||||
@keyframes bottomAnimate3d {
|
||||
|
||||
0% {
|
||||
transform: translate(0%, 100%) translate3d(0%, 20px, 0px) rotateX(45deg)
|
||||
transform: translate(0%, 100%) translate3d(0%, 20px, 0px) rotateX(45deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translate(0%, 0%) translate3d(0, 0, 0px) rotateX(0deg)
|
||||
transform: translate(0%, 0%) translate3d(0, 0, 0px) rotateX(0deg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -736,7 +755,6 @@ export default {
|
||||
75% {
|
||||
transform: scale(0.97);
|
||||
opacity: 0.9;
|
||||
|
||||
}
|
||||
|
||||
85% {
|
||||
@@ -746,11 +764,10 @@ export default {
|
||||
100% {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.tmModalWrapContent_Tantiao {
|
||||
animation: tantiao 0.15s linear;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
Reference in new issue
Block a user