feat(产品类别)

This commit is contained in:
Ankkaya 2024-08-28 18:36:22 +08:00
parent 8f339a1ecc
commit b577f0730c
23 changed files with 3123 additions and 2795 deletions

3
androidPrivacy.json Normal file
View File

@ -0,0 +1,3 @@
{
"prompt": "template"
}

BIN
mall-app-t.rar Normal file

Binary file not shown.

View File

@ -1,5 +1,5 @@
{ {
"name": "mall-app-t", "name" : "豫京牛商家端",
"appid" : "__UNI__B201544", "appid" : "__UNI__B201544",
"description" : "", "description" : "",
"versionName" : "1.0.0", "versionName" : "1.0.0",
@ -20,7 +20,10 @@
"ignoreVersion" : true "ignoreVersion" : true
}, },
/* */ /* */
"modules": {}, "modules" : {
"Barcode" : {},
"Camera" : {}
},
/* */ /* */
"distribute" : { "distribute" : {
/* android */ /* android */
@ -44,9 +47,48 @@
] ]
}, },
/* ios */ /* ios */
"ios": {}, "ios" : {
"dSYMs" : false
},
/* SDK */ /* SDK */
"sdkConfigs": {} "sdkConfigs" : {
"ad" : {}
},
"icons" : {
"android" : {
"hdpi" : "unpackage/res/icons/72x72.png",
"xhdpi" : "unpackage/res/icons/96x96.png",
"xxhdpi" : "unpackage/res/icons/144x144.png",
"xxxhdpi" : "unpackage/res/icons/192x192.png"
},
"ios" : {
"appstore" : "unpackage/res/icons/1024x1024.png",
"ipad" : {
"app" : "unpackage/res/icons/76x76.png",
"app@2x" : "unpackage/res/icons/152x152.png",
"notification" : "unpackage/res/icons/20x20.png",
"notification@2x" : "unpackage/res/icons/40x40.png",
"proapp@2x" : "unpackage/res/icons/167x167.png",
"settings" : "unpackage/res/icons/29x29.png",
"settings@2x" : "unpackage/res/icons/58x58.png",
"spotlight" : "unpackage/res/icons/40x40.png",
"spotlight@2x" : "unpackage/res/icons/80x80.png"
},
"iphone" : {
"app@2x" : "unpackage/res/icons/120x120.png",
"app@3x" : "unpackage/res/icons/180x180.png",
"notification@2x" : "unpackage/res/icons/40x40.png",
"notification@3x" : "unpackage/res/icons/60x60.png",
"settings@2x" : "unpackage/res/icons/58x58.png",
"settings@3x" : "unpackage/res/icons/87x87.png",
"spotlight@2x" : "unpackage/res/icons/80x80.png",
"spotlight@3x" : "unpackage/res/icons/120x120.png"
}
}
},
"splashscreen" : {
"useOriginalMsgbox" : true
}
} }
}, },
/* */ /* */

View File

@ -207,9 +207,6 @@
}, },
{ {
"pagePath": "pages/index/my" "pagePath": "pages/index/my"
},
{
"pagePath": "pages/index/icons"
} }
] ]
}, },

View File

@ -1,5 +1,5 @@
<template> <template>
<pb-layout navbar="inner" tabbar="/pages/index/index" :bgStyle="bgStyle"> <pb-layout navbar="inner" tabbar="/pages/index/index" :bgStyle="bgStyle" :leftIcon="''">
<view class="dashboard-module ss-p-x-30"> <view class="dashboard-module ss-p-x-30">
<view class="merchant-info flex align-center justify-between"> <view class="merchant-info flex align-center justify-between">
<view class="flex align-center ss-gap-10"> <view class="flex align-center ss-gap-10">
@ -17,7 +17,7 @@
<view class="statistic ss-m-t-24"> <view class="statistic ss-m-t-24">
<view class="title ss-font-24 ss-m-b-20"> <view class="title ss-font-24 ss-m-b-20">
{{ `今日收款金额(成功收款${state.statistic.todayPaymentCount}笔)` }} {{ `今日收款金额(成功收款${state.statistic?.todayPaymentCount || 0}笔)` }}
</view> </view>
<view class="income flex justify-between align-center"> <view class="income flex justify-between align-center">
<view class="left flex align-center"> <view class="left flex align-center">
@ -27,8 +27,8 @@
<!-- <button class="right-btn ss-reset-button">查看详情</button> --> <!-- <button class="right-btn ss-reset-button">查看详情</button> -->
</view> </view>
<view class="des ss-m-t-20"> <view class="des ss-m-t-20">
总销售额 {{ fen2yuan(state.statistic.totalSalesAmount) }} | 成功退款 总销售额 {{ fen2yuan(state.statistic.totalSalesAmount) }} | 成功退款 {{ state.statistic.refundCount }} |
{{ state.statistic.refundCount }} | 退款金额 {{ fen2yuan(state.statistic.refundAmount) }} 退款金额 {{ fen2yuan(state.statistic.refundAmount) }}
</view> </view>
</view> </view>
@ -38,7 +38,7 @@
<view class="item" v-for="(item, index) in state.more" :key="item.name"> <view class="item" v-for="(item, index) in state.more" :key="item.name">
<view class="label">{{ item.name }}</view> <view class="label">{{ item.name }}</view>
<view class="value">{{ index !== 0 ? item.value : fen2yuan(item.value) }}</view> <view class="value">{{ index !== 0 ? item.value : fen2yuan(item.value) }}</view>
<view class="last"> 昨日 {{ index === 0 ? fen2yuan(item.last) : item.last }} </view> <view class="last"> 昨日 {{ index === 0 ? fen2yuan(item.last) : item.last ? item.last : 0 }} </view>
</view> </view>
</view> </view>
</view> </view>

View File

@ -6,15 +6,32 @@
</view> </view>
<uni-forms ref="smsLoginRef" v-model="state.model" :rules="state.rules" validateTrigger="bind"> <uni-forms ref="smsLoginRef" v-model="state.model" :rules="state.rules" validateTrigger="bind">
<uni-forms-item name="mobile"> <uni-forms-item name="mobile">
<uni-easyinput :styles="state.inputStyle" trim="all" placeholder="请输入手机号" v-model="state.model.mobile" <uni-easyinput
:inputBorder="false" type="number" /> :styles="state.inputStyle"
trim="all"
placeholder="请输入手机号"
v-model="state.model.mobile"
:inputBorder="false"
type="number"
/>
</uni-forms-item> </uni-forms-item>
<uni-forms-item name="code"> <uni-forms-item name="code">
<uni-easyinput :styles="state.inputStyle" trim="all" placeholder="验证码" v-model="state.model.code" <uni-easyinput
:inputBorder="false" type="number" maxlength="4"> :styles="state.inputStyle"
trim="all"
placeholder="验证码"
v-model="state.model.code"
:inputBorder="false"
type="number"
maxlength="4"
>
<template #right> <template #right>
<button :disabled="state.isMobileEnd" :class="{ 'code-btn-end': state.isMobileEnd }" <button
class="ss-reset-button code-btn code-btn-start" @tap="getSmsCode('smsLogin', state.model.mobile)"> :disabled="state.isMobileEnd"
:class="{ 'code-btn-end': state.isMobileEnd }"
class="ss-reset-button code-btn code-btn-start"
@tap="getSmsCode('smsLogin', state.model.mobile)"
>
{{ getSmsTimer('smsLogin') }} {{ getSmsTimer('smsLogin') }}
</button> </button>
</template> </template>
@ -24,8 +41,12 @@
<button class="ss-reset-button login-btn-start" @tap="smsLoginSubmit">登录</button> <button class="ss-reset-button login-btn-start" @tap="smsLoginSubmit">登录</button>
<view class="agreement-box ss-flex ss-row-center" :class="{ shake: state.isShaking }"> <view class="agreement-box ss-flex ss-row-center" :class="{ shake: state.isShaking }">
<label class="radio ss-flex" @tap="onChange"> <label class="radio ss-flex" @tap="onChange">
<radio :checked="state.agreeStatus" color="var(--ui-BG-Main)" style="transform: scale(0.8)" <radio
@tap.stop="onChange" /> :checked="state.agreeStatus"
color="var(--ui-BG-Main)"
style="transform: scale(0.8)"
@tap.stop="onChange"
/>
<view class="agreement-text ss-flex ss-m-l-8"> <view class="agreement-text ss-flex ss-m-l-8">
我已阅读并遵守 我已阅读并遵守
<view class="tcp-text" @tap.stop="onProtocol('商家入驻协议')"> 商家入驻协议 </view> <view class="tcp-text" @tap.stop="onProtocol('商家入驻协议')"> 商家入驻协议 </view>
@ -51,8 +72,8 @@ const state = ref({
agreeStatus: false, agreeStatus: false,
isShaking: false, isShaking: false,
model: { model: {
mobile: '15036370128', mobile: '',
code: '9999', code: '',
}, },
rules: { rules: {
mobile, mobile,

View File

@ -1,13 +1,9 @@
<template> <template>
<pb-layout navbar="inner" tabbar="/pages/index/my" :bgStyle="bgStyle"> <pb-layout navbar="inner" tabbar="/pages/index/my" :bgStyle="bgStyle" :leftIcon="''">
<view class="my-module ss-p-x-30"> <view class="my-module ss-p-x-30">
<view class="user-info flex align-center justify-between"> <view class="user-info flex align-center justify-between">
<view class="flex align-center ss-gap-10"> <view class="flex align-center ss-gap-10">
<image <image class="avatar" :src="userInfo.avatar || '/static/default_avatar.png'" mode="aspectFill"></image>
class="avatar"
:src="userInfo.avatar || '/static/default_avatar.png'"
mode="aspectFill"
></image>
<view class="detail flex flex-column justify-center gap-10"> <view class="detail flex flex-column justify-center gap-10">
<view class="name ss-font-26">{{ userInfo.nickname }}</view> <view class="name ss-font-26">{{ userInfo.nickname }}</view>
@ -81,7 +77,7 @@ const state = ref({
{ {
name: '提现规则', name: '提现规则',
icon: '/static/rule.png', icon: '/static/rule.png',
path: '', path: '/pages/public/richtext?title=提现规则',
}, },
], ],
}) })

View File

@ -6,16 +6,12 @@
:bgStyle="bgStyle" :bgStyle="bgStyle"
opacityBgUi="bg-white" opacityBgUi="bg-white"
color="black" color="black"
:leftIcon="''"
> >
<pb-sticky bgColor="#fff"> <pb-sticky bgColor="#fff">
<pb-tabs :list="tabMaps" :scrollable="false" @change="onTabsChange" :current="state.currentTab" /> <pb-tabs :list="tabMaps" :scrollable="false" @change="onTabsChange" :current="state.currentTab" />
</pb-sticky> </pb-sticky>
<p-empty <p-empty v-if="state.pagination.total === 0" icon="/static/order-empty.png" text="暂无订单" bgColor="transparent" />
v-if="state.pagination.total === 0"
icon="/static/order-empty.png"
text="暂无订单"
bgColor="transparent"
/>
<view v-if="state.pagination.total > 0"> <view v-if="state.pagination.total > 0">
<view <view
class="bg-white order-list-card-box ss-r-10 ss-m-t-14 ss-m-20" class="bg-white order-list-card-box ss-r-10 ss-m-t-14 ss-m-20"
@ -104,9 +100,7 @@
</view> </view>
<view class="pay-box ss-m-t-30 ss-flex ss-gap-40 ss-p-b-40 ss-row-right ss-p-r-20"> <view class="pay-box ss-m-t-30 ss-flex ss-gap-40 ss-p-b-40 ss-row-right ss-p-r-20">
<view class="ss-flex ss-col-center"> <view class="ss-flex ss-col-center">
<view class="discounts-title pay-color" <view class="discounts-title pay-color"> {{ totalNumsPerOrder(order) }} 件商品,总金额:</view>
> {{ totalNumsPerOrder(order) }} 件商品,总金额:</view
>
<view class="discounts-money pay-color"> {{ fen2yuan(totalPricePerOrder(order)) }} </view> <view class="discounts-money pay-color"> {{ fen2yuan(totalPricePerOrder(order)) }} </view>
</view> </view>
</view> </view>

View File

@ -7,6 +7,7 @@
:bgStyle="bgStyle" :bgStyle="bgStyle"
opacityBgUi="bg-white" opacityBgUi="bg-white"
color="black" color="black"
:leftIcon="''"
> >
<view v-if="state.pagination.total > 0" class="goods-list ss-m-t-20"> <view v-if="state.pagination.total > 0" class="goods-list ss-m-t-20">
<view class="ss-p-l-20 ss-p-r-20 ss-m-b-20" v-for="item in state.pagination.list" :key="item.id"> <view class="ss-p-l-20 ss-p-r-20 ss-m-b-20" v-for="item in state.pagination.list" :key="item.id">

View File

@ -9,18 +9,46 @@
<view class="property-value ss-flex ss-gap-40"> <view class="property-value ss-flex ss-gap-40">
<view class="property-value-text">规格值</view> <view class="property-value-text">规格值</view>
<view class="property-value-value ss-flex ss-gap-10"> <view class="property-value-value ss-flex ss-gap-10">
<view v-for="sitem in item.propertyValues" @tap="chooseProperty(sitem)" <view
:class="['item', sitem.checked ? 'active' : '']">{{ sitem.name }}</view> v-for="sitem in item.propertyValues"
@tap="chooseProperty(sitem)"
@longpress="longPropertyValuePress(sitem)"
:class="['item', sitem.checked ? 'active' : '']"
>{{ sitem.name }}</view
>
</view>
<view v-if="canEdit" style="height: 60rpx" @click="addPropertyValueClick(item)">
<text style="color: #ff3300; font-size: 30px" class="cicon-add-round-o"></text>
</view> </view>
</view> </view>
</view> </view>
</template> </template>
<uni-popup ref="inputPropertyValueDialogRef" type="dialog">
<uni-popup-dialog
mode="input"
:title="propertyValueTitle"
v-model="inputPropertyValueFormdata.name"
placeholder="请输入商品规格"
:before-close="true"
@confirm="dialogInputPropertyValueConfirm"
@close="inputPropertyValueDialogRef.close()"
></uni-popup-dialog>
</uni-popup>
</view> </view>
</template> </template>
<script setup> <script setup>
import { defineProps, defineEmits, ref, computed } from 'vue' import { defineProps, defineEmits, ref, computed } from 'vue'
import { goodsPropertyList, canEdit } from '../js/sku' import {
goodsPropertyList,
canEdit,
addPropertyValueClick,
inputPropertyValueDialogRef,
inputPropertyValueFormdata,
propertyValueTitle,
dialogInputPropertyValueConfirm,
longPropertyValuePress,
} from '../js/sku'
const props = defineProps({ const props = defineProps({
modelValue: { modelValue: {

View File

@ -3,14 +3,34 @@
<uni-popup type="bottom" ref="propertyListPopupRef" background-color="#fff"> <uni-popup type="bottom" ref="propertyListPopupRef" background-color="#fff">
<view class="popup-header"> <view class="popup-header">
<view class="button-cancel" @click="onClosePopup">取消</view> <view class="button-cancel" @click="onClosePopup">取消</view>
<view style="color: #c0c0c0; font-size: 12px">长按规格修改/删除</view>
<view class="button-link" @click="onConfirmPopup">确定</view> <view class="button-link" @click="onConfirmPopup">确定</view>
</view> </view>
<view class="popup-content"> <view class="popup-content">
<view v-for="item in nowGoodsPropertyList" :key="item.id" <view
:class="['property-item', item.checked ? 'active' : '']" @tap="chooseProperty(item)"> v-for="item in nowGoodsPropertyList"
:key="item.id"
:class="['property-item', item.checked ? 'active' : '']"
@tap="chooseProperty(item)"
@longpress="longPress(item)"
>
{{ item.name }} {{ item.name }}
</view> </view>
<view v-if="canEdit" style="height: 60rpx" @click="addPropertyClick">
<text style="color: #ff3300; font-size: 30px" class="cicon-add-round-o"></text>
</view> </view>
</view>
</uni-popup>
<uni-popup ref="inputDialogRef" type="dialog">
<uni-popup-dialog
mode="input"
:title="propertyTitle"
v-model="inputFormdata.name"
placeholder="请输入商品规格"
:before-close="true"
@confirm="dialogInputConfirm"
@close="inputDialogRef.close()"
></uni-popup-dialog>
</uni-popup> </uni-popup>
</view> </view>
</template> </template>
@ -18,7 +38,9 @@
<script setup> <script setup>
import { ref, computed, defineEmits, defineProps, defineExpose } from 'vue' import { ref, computed, defineEmits, defineProps, defineExpose } from 'vue'
import peach from '@/peach' import peach from '@/peach'
import { cloneDeep } from 'lodash'; import GoodsApi from '@/peach/api/trade/goods'
import { getGoodsProperty, canEdit } from '../js/sku'
import { cloneDeep } from 'lodash'
/** /**
* todo 底部高度配置 * todo 底部高度配置
@ -51,8 +73,30 @@ function chooseProperty(item) {
item.checked = !item.checked item.checked = !item.checked
} }
function onConfirmPopup() { function longPress(item) {
if (canEdit) {
//
uni.vibrateShort()
uni.showActionSheet({
itemList: ['编辑', '删除'],
success: async (res) => {
if (res.tapIndex === 0) {
propertyTitle.value = '编辑'
inputFormdata.value.id = item.id
inputFormdata.value.name = item.name
inputDialogRef.value.open()
}
if (res.tapIndex === 1) {
await GoodsApi.delProperty({ id: item.id })
await getGoodsProperty()
nowGoodsPropertyList.value = cloneDeep(props.goodsPropertyList)
}
},
})
}
}
function onConfirmPopup() {
let result = nowGoodsPropertyList.value let result = nowGoodsPropertyList.value
.filter((item) => { .filter((item) => {
if (item.checked) { if (item.checked) {
@ -67,13 +111,40 @@ function onConfirmPopup() {
} }
}) })
peach.$store('trade').selectedProperty = result peach.$store('trade').selectedProperty = result
emit('confirm') emit('confirm')
emit('update:modelValue', result) emit('update:modelValue', result)
onClosePopup() onClosePopup()
} }
const propertyTitle = ref('新增')
const inputDialogRef = ref()
const inputFormdata = ref({
id: '',
name: '',
remark: '',
})
function addPropertyClick() {
propertyTitle.value = '新增'
inputFormdata.value.name = ''
inputDialogRef.value.open()
}
async function dialogInputConfirm(value) {
if (!value) {
peach.$helper.toast('请输入商品属性')
return
}
if (inputFormdata.value.id) {
await GoodsApi.editProperty(inputFormdata.value)
} else {
await GoodsApi.createProperty(inputFormdata.value)
}
await getGoodsProperty()
inputDialogRef.value.close()
nowGoodsPropertyList.value = cloneDeep(props.goodsPropertyList)
}
function onOpen() { function onOpen() {
nowGoodsPropertyList.value = cloneDeep(props.goodsPropertyList) nowGoodsPropertyList.value = cloneDeep(props.goodsPropertyList)
propertyListPopupRef.value.open('bottom') propertyListPopupRef.value.open('bottom')

View File

@ -46,7 +46,6 @@ function pickerProperty() {
async function onPropertyConfirm(e) { async function onPropertyConfirm(e) {
await getGoodsProperty() await getGoodsProperty()
console.log(e)
} }
function onConfirm() { function onConfirm() {
@ -270,6 +269,60 @@ function initial() {
}) })
} }
const propertyValueTitle = ref('新增')
const inputPropertyValueDialogRef = ref()
const inputPropertyValueFormdata = ref({
id: '',
propertyId: '',
name: '',
remark: '',
})
function addPropertyValueClick(item) {
console.log(item)
propertyValueTitle.value = '新增'
inputPropertyValueFormdata.value.name = ''
inputPropertyValueFormdata.value.propertyId = item.id
inputPropertyValueDialogRef.value.open()
}
async function dialogInputPropertyValueConfirm(value) {
if (!value) {
peach.$helper.toast('请输入商品属性')
return
}
if (inputPropertyValueFormdata.value.id) {
await GoodsApi.editPropertyValue(inputPropertyValueFormdata.value)
} else {
await GoodsApi.createPropertyValue(inputPropertyValueFormdata.value)
}
await getGoodsProperty()
inputPropertyValueDialogRef.value.close()
}
function longPropertyValuePress(item) {
console.log(item)
if (canEdit.value) {
// 震动提示
uni.vibrateShort()
uni.showActionSheet({
itemList: ['编辑', '删除'],
success: async (res) => {
if (res.tapIndex === 0) {
propertyValueTitle.value = '编辑'
inputPropertyValueFormdata.value.id = item.id
inputPropertyValueFormdata.value.propertyId = item.propertyId
inputPropertyValueFormdata.value.name = item.name
inputPropertyValueDialogRef.value.open()
}
if (res.tapIndex === 1) {
await GoodsApi.delPropertyValue({ id: item.id })
await getGoodsProperty()
}
},
})
}
}
export { export {
initial, initial,
canEdit, canEdit,
@ -287,4 +340,11 @@ export {
showPropertyList, showPropertyList,
goodsPropertyList, goodsPropertyList,
changeSubProperty, changeSubProperty,
getGoodsProperty,
addPropertyValueClick,
dialogInputPropertyValueConfirm,
longPropertyValuePress,
inputPropertyValueDialogRef,
inputPropertyValueFormdata,
propertyValueTitle,
} }

View File

@ -89,12 +89,7 @@
</view> </view>
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="商品关键词" name="keyword" required> <uni-forms-item label="商品关键词" name="keyword" required>
<uni-easyinput <uni-easyinput type="text" v-model="formData.keyword" :disabled="!canEdit" placeholder="请输入商品关键词" />
type="text"
v-model="formData.keyword"
:disabled="!canEdit"
placeholder="请输入商品关键词"
/>
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="商品简介" name="introduction" required> <uni-forms-item label="商品简介" name="introduction" required>
<uni-easyinput <uni-easyinput
@ -152,18 +147,13 @@
</view> </view>
</view> </view>
<p-picker <p-picker ref="pickerRef" :mode="pickerMode" :options-cols="optionsCols" @confirm="onRDPickerConfirm"></p-picker>
ref="pickerRef"
:mode="pickerMode"
:options-cols="optionsCols"
@confirm="onRDPickerConfirm"
></p-picker>
</pb-layout> </pb-layout>
</template> </template>
<script setup> <script setup>
import { ref, computed } from 'vue' import { ref, computed } from 'vue'
import { onLoad } from '@dcloudio/uni-app' import { onLoad, onPageScroll } from '@dcloudio/uni-app'
import _ from 'lodash' import _ from 'lodash'
import GoodsApi from '@/peach/api/trade/goods' import GoodsApi from '@/peach/api/trade/goods'
import piaoyiEditor from '@/uni_modules/piaoyi-editor/components/piaoyi-editor/piaoyi-editor.vue' import piaoyiEditor from '@/uni_modules/piaoyi-editor/components/piaoyi-editor/piaoyi-editor.vue'
@ -197,26 +187,22 @@ const pickerRef = ref()
const richValues = ref('') const richValues = ref('')
const photoUrl = baseUrl + apiPath const photoUrl = baseUrl + apiPath
const richApi = '/infra/file/upload' const richApi = '/infra/file/upload'
const richReadOnly = ref(false) const richReadOnly = ref(true)
const formData = ref({ const formData = ref({
picUrl: 'http://101.43.181.163:9001/mall-backend/8f11e372520501531d06bfce15ea97bbecead41c5e4a36d15d7e40af85729ff3.png', picUrl: '',
sliderPicUrls: [ sliderPicUrls: [],
'http://101.43.181.163:9001/mall-backend/8f11e372520501531d06bfce15ea97bbecead41c5e4a36d15d7e40af85729ff3.png', name: '',
'http://101.43.181.163:9001/mall-backend/8f11e372520501531d06bfce15ea97bbecead41c5e4a36d15d7e40af85729ff3.png', categoryId: '',
'http://101.43.181.163:9001/mall-backend/8f11e372520501531d06bfce15ea97bbecead41c5e4a36d15d7e40af85729ff3.png',
],
name: '测试商品',
categoryId: 91,
categoryText: '', categoryText: '',
brandId: 4, brandId: '',
keyword: '香酥鸭,但家', keyword: '',
deliveryTypes: [3], deliveryTypes: [],
deliveryText: '', deliveryText: '',
sort: 0, sort: 0,
giveIntegral: 0, giveIntegral: 0,
virtualSalesCount: 0, virtualSalesCount: 0,
subCommissionType: false, subCommissionType: false,
introduction: '但家贵阳香酥鸭现榨香酥鸭无任何添加剂香酥鸭但家贵阳香酥鸭现榨香酥鸭无任何添加剂香酥鸭', introduction: '',
}) })
const rules = { const rules = {
@ -494,18 +480,17 @@ onLoad(async (options) => {
goodsTitle.value = options.title goodsTitle.value = options.title
//
// richReadOnly.value = true
/**
* todo 滚动一定距离后修改富文本状态和 canEdit 一致
*/
if (options.id) { if (options.id) {
getProduct(options.id) getProduct(options.id)
peach.$store('trade').detailTag = options.mark peach.$store('trade').detailTag = options.mark
} }
}) })
onPageScroll((e) => {
if (canEdit.value && e.scrollTop > 200) {
richReadOnly.value = false
}
})
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -30,7 +30,7 @@
</view> </view>
<template v-if="formData.specType"> <template v-if="formData.specType">
<!-- 添加商品 --> <!-- 添加商品 -->
<button v-if="canEdit" class="ss-reset-button add-property" @tap="showPropertyList">+添加规格</button> <button v-if="canEdit" class="ss-reset-button add-property" @tap="showPropertyList">选择规格</button>
<!-- 商品属性展示 --> <!-- 商品属性展示 -->
<property-detail <property-detail
v-if="propertyList.length > 0" v-if="propertyList.length > 0"

View File

@ -9,6 +9,7 @@
<script setup> <script setup>
import { onLoad } from '@dcloudio/uni-app' import { onLoad } from '@dcloudio/uni-app'
import ArticleApi from '@/peach/api/promotion/article'
import { reactive } from 'vue' import { reactive } from 'vue'
const state = reactive({ const state = reactive({
@ -17,15 +18,18 @@ const state = reactive({
}) })
async function getRichTextContent(id, title) { async function getRichTextContent(id, title) {
// const { code, data } = await ArticleApi.getArticle(id, title)
// state.content = data.content; if (code !== 0) {
return
}
state.content = data.content
// //
// if (state.title !== data.title) { if (state.title !== data.title) {
// state.title = data.title; state.title = data.title
// uni.setNavigationBarTitle({ uni.setNavigationBarTitle({
// title: state.title, title: state.title,
// }); })
// } }
} }
onLoad((options) => { onLoad((options) => {
@ -35,7 +39,7 @@ onLoad((options) => {
title: state.title, title: state.title,
}) })
} }
// getRichTextContent(options.id, options.title); getRichTextContent(options.id, options.title)
}) })
</script> </script>

View File

@ -24,8 +24,14 @@
</view> </view>
<view class="combo ss-m-t-90 ss-m-b-50 ss-p-x-40"> <view class="combo ss-m-t-90 ss-m-b-50 ss-p-x-40">
<button class="ss-reset-button draw-btn ui-Shadow-Main">购买5000积分/50</button> <template v-for="(item, index) in state.pointList">
<button class="ss-reset-button draw-btn-raw ui-Shadow-Main">购买5000积分/50</button> <button
:class="['ss-reset-button', state.currentIndex === index ? 'draw-btn' : 'draw-btn-raw', 'ui-Shadow-Main']"
@click="chooseItemClick(index)"
>
{{ `购买${item.point}积分/${item.price}` }}
</button>
</template>
</view> </view>
<view class="agreement-box ss-flex ss-row-center" :class="{ shake: state.isShaking }"> <view class="agreement-box ss-flex ss-row-center" :class="{ shake: state.isShaking }">
@ -47,10 +53,15 @@
<script setup> <script setup>
import { ref } from 'vue' import { ref } from 'vue'
import { onShow } from '@dcloudio/uni-app'
import PointApi from '@/peach/api/pay/point'
import peach from '@/peach'
const state = ref({ const state = ref({
isShaking: false, isShaking: false,
agreeStatus: false, agreeStatus: false,
pointList: [],
currentIndex: -1,
}) })
const bgStyle = { const bgStyle = {
@ -61,7 +72,44 @@ const bgStyle = {
height: '100%', height: '100%',
} }
function onProtocol(title) {} function onProtocol() {
peach.$router.go('/pages/public/richtext?title=积分须知')
}
function getPointConfig() {
PointApi.getPointConfig().then((res) => {
if (res.data.packagePoint) state.value.pointList = JSON.parse(res.data.packagePoint)
})
}
function onChange() {
state.value.agreeStatus = !state.value.agreeStatus
}
function chooseItemClick(index) {
if (!state.value.agreeStatus) {
state.value.isShaking = true
setTimeout(() => {
state.value.isShaking = false
}, 1000)
peach.$helper.toast('请勾选同意积分须知')
return
}
state.value.currentIndex = index
uni.showModal({
title: '提示',
content: '确认购买该积分额度?',
success: function (res) {
if (res.confirm) {
}
},
})
}
onShow(() => {
getPointConfig()
})
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -114,7 +114,7 @@ async function confirmShare() {
let user = state.value.userList.find((item) => item.point) let user = state.value.userList.find((item) => item.point)
if (!user) { if (!user) {
peach.$helper.toast('请输入要赠送的积分') peach.$helper.toast('请选择需要赠送积分的用户')
return return
} }

View File

@ -20,11 +20,11 @@ const PointApi = {
}) })
}, },
getPointList: (data) => { // 获取积分配置信息
getPointConfig: () => {
return request({ return request({
url: '/particulars/point/page-record', url: '/particulars/point/get-config',
method: 'get', method: 'get',
params: data,
}) })
}, },
} }

View File

@ -0,0 +1,15 @@
import request from '@/peach/request'
export default {
// 获得文章详情
getArticle: (id, title) => {
return request({
url: '/promotion/article/get',
method: 'GET',
params: { id, title },
custom: {
auth: false,
},
})
},
}

View File

@ -71,6 +71,72 @@ const GoodsApi = {
params: data, params: data,
}) })
}, },
// 创建商品属性项
createProperty: (data) => {
return request({
url: '/product/property/create',
method: 'POST',
data,
custom: {
successMsg: '新增成功',
},
})
},
// 修改商品属性项
editProperty: (data) => {
return request({
url: '/product/property/update',
method: 'PUT',
data,
custom: {
successMsg: '修改成功',
},
})
},
// 删除商品属性项
delProperty: (data) => {
return request({
url: '/product/property/delete',
method: 'DELETE',
params: data,
custom: {
successMsg: '删除成功',
},
})
},
// 创建商品属性值
createPropertyValue: (data) => {
return request({
url: '/property/value/create',
method: 'POST',
data,
custom: {
successMsg: '新增成功',
},
})
},
// 删除商品属性值
delPropertyValue: (data) => {
return request({
url: '/property/value/delete',
method: 'DELETE',
params: data,
custom: {
successMsg: '删除成功',
},
})
},
// 修改商品属性值
editPropertyValue: (data) => {
return request({
url: '/property/value/update',
method: 'PUT',
data,
custom: {
successMsg: '修改成功',
},
})
},
} }
export default GoodsApi export default GoodsApi

View File

@ -120,9 +120,9 @@ export function getSmsCode(event, mobile) {
} }
AuthUtil.sendSmsCode(mobile, scene).then((res) => { AuthUtil.sendSmsCode(mobile, scene).then((res) => {
// if (res.code === 0) { if (res.code === 0) {
// modalStore.lastTimer[event] = dayjs().unix() modalStore.lastTimer[event] = dayjs().unix()
// } }
}) })
} }

View File

@ -80,12 +80,6 @@ const useAppStore = defineStore(
text: '我的', text: '我的',
url: '/pages/index/my', url: '/pages/index/my',
}, },
{
activeIconUrl: 'http://mall.yudao.iocoder.cn/static/images/4-002.png',
iconUrl: 'http://mall.yudao.iocoder.cn/static/images/4-001.png',
text: 'icons',
url: '/pages/index/icons',
},
], ],
style: { style: {
activeColor: '#fc4141', activeColor: '#fc4141',

View File

@ -10,8 +10,14 @@
</view> </view>
<view v-else class="uni-dialog-content"> <view v-else class="uni-dialog-content">
<slot> <slot>
<input class="uni-dialog-input" :maxlength="maxlength" v-model="val" :type="inputType" <input
:placeholder="placeholderText" :focus="focus"> class="uni-dialog-input"
:maxlength="maxlength"
v-model="val"
:type="inputType"
:placeholder="placeholderText"
:focus="focus"
/>
</slot> </slot>
</view> </view>
<view class="uni-dialog-button-group"> <view class="uni-dialog-button-group">
@ -22,19 +28,14 @@
<text class="uni-dialog-button-text uni-button-color">{{ okText }}</text> <text class="uni-dialog-button-text uni-button-color">{{ okText }}</text>
</view> </view>
</view> </view>
</view> </view>
</template> </template>
<script> <script>
import popup from '../uni-popup/popup.js' import popup from '../uni-popup/popup.js'
import { import { initVueI18n } from '@dcloudio/uni-i18n'
initVueI18n
} from '@dcloudio/uni-i18n'
import messages from '../uni-popup/i18n/index.js' import messages from '../uni-popup/i18n/index.js'
const { const { t } = initVueI18n(messages)
t
} = initVueI18n(messages)
/** /**
* PopUp 弹出层-对话框样式 * PopUp 弹出层-对话框样式
* @description 弹出层-对话框样式 * @description 弹出层-对话框样式
@ -59,63 +60,62 @@
*/ */
export default { export default {
name: "uniPopupDialog", name: 'uniPopupDialog',
mixins: [popup], mixins: [popup],
emits: ['confirm', 'close', 'update:modelValue', 'input'], emits: ['confirm', 'close', 'update:modelValue', 'input'],
props: { props: {
inputType: { inputType: {
type: String, type: String,
default: 'text' default: 'text',
}, },
showClose: { showClose: {
type: Boolean, type: Boolean,
default: true default: true,
}, },
// #ifdef VUE2 // #ifdef VUE2
value: { value: {
type: [String, Number], type: [String, Number],
default: '' default: '',
}, },
// #endif // #endif
// #ifdef VUE3 // #ifdef VUE3
modelValue: { modelValue: {
type: [Number, String], type: [Number, String],
default: '' default: '',
}, },
// #endif // #endif
placeholder: { placeholder: {
type: [String, Number], type: [String, Number],
default: '' default: '',
}, },
type: { type: {
type: String, type: String,
default: 'error' default: 'error',
}, },
mode: { mode: {
type: String, type: String,
default: 'base' default: 'base',
}, },
title: { title: {
type: String, type: String,
default: '' default: '',
}, },
content: { content: {
type: String, type: String,
default: '' default: '',
}, },
beforeClose: { beforeClose: {
type: Boolean, type: Boolean,
default: false default: false,
}, },
cancelText: { cancelText: {
type: String, type: String,
default: '' default: '',
}, },
confirmText: { confirmText: {
type: String, type: String,
default: '' default: '',
}, },
maxlength: { maxlength: {
type: Number, type: Number,
@ -124,27 +124,27 @@
focus: { focus: {
type: Boolean, type: Boolean,
default: true, default: true,
} },
}, },
data() { data() {
return { return {
dialogType: 'error', dialogType: 'error',
val: "" val: '',
} }
}, },
computed: { computed: {
okText() { okText() {
return this.confirmText || t("uni-popup.ok") return this.confirmText || t('uni-popup.ok')
}, },
closeText() { closeText() {
return this.cancelText || t("uni-popup.cancel") return this.cancelText || t('uni-popup.cancel')
}, },
placeholderText() { placeholderText() {
return this.placeholder || t("uni-popup.placeholder") return this.placeholder || t('uni-popup.placeholder')
}, },
titleText() { titleText() {
return this.title || t("uni-popup.title") return this.title || t('uni-popup.title')
} },
}, },
watch: { watch: {
type(val) { type(val) {
@ -157,7 +157,7 @@
}, },
value(val) { value(val) {
if (this.maxlength != -1 && this.mode === 'input') { if (this.maxlength != -1 && this.mode === 'input') {
this.val = val.slice(0, this.maxlength); this.val = val.slice(0, this.maxlength)
} else { } else {
this.val = val this.val = val
} }
@ -165,13 +165,16 @@
val(val) { val(val) {
// #ifdef VUE2 // #ifdef VUE2
// TODO vue2 // TODO vue2
this.$emit('input', val); this.$emit('input', val)
// #endif // #endif
// #ifdef VUE3 // #ifdef VUE3
// TODO  vue3 // TODO  vue3
this.$emit('update:modelValue', val); this.$emit('update:modelValue', val)
// #endif // #endif
} },
modelValue(newVal, oldVal) {
this.val = newVal
},
}, },
created() { created() {
// //
@ -179,9 +182,9 @@
// this.popup.closeMask() // this.popup.closeMask()
if (this.mode === 'input') { if (this.mode === 'input') {
this.dialogType = 'info' this.dialogType = 'info'
this.val = this.value; this.val = this.value
// #ifdef VUE3 // #ifdef VUE3
this.val = this.modelValue; this.val = this.modelValue
// #endif // #endif
} else { } else {
this.dialogType = this.type this.dialogType = this.type
@ -210,8 +213,8 @@
}, },
close() { close() {
this.popup.close() this.popup.close()
} },
} },
} }
</script> </script>
@ -248,7 +251,7 @@
.uni-dialog-content-text { .uni-dialog-content-text {
font-size: 14px; font-size: 14px;
color: #6C6C6C; color: #6c6c6c;
} }
.uni-dialog-button-group { .uni-dialog-button-group {