|
@@ -0,0 +1,583 @@
|
|
|
|
|
+<template>
|
|
|
|
|
+ <uni-navbar-lite :showRight=false title="创建采购单"></uni-navbar-lite>
|
|
|
|
|
+ <view class="page-container">
|
|
|
|
|
+ <scroll-view class="page-content" scroll-y="true">
|
|
|
|
|
+ <view v-if="applyList.length === 0" class="empty-tip">
|
|
|
|
|
+ <text class="empty-tip-text">暂无申请单数据</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+
|
|
|
|
|
+ <view v-else>
|
|
|
|
|
+ <view class="purchase-info-section">
|
|
|
|
|
+ <view class="purchase-info-row">
|
|
|
|
|
+ <text class="purchase-info-label">采购单名称</text>
|
|
|
|
|
+ <view class="purchase-info-value-wrap">
|
|
|
|
|
+ <input
|
|
|
|
|
+ class="purchase-info-input"
|
|
|
|
|
+ v-model="purchaseName"
|
|
|
|
|
+ placeholder="请输入采购单名称"
|
|
|
|
|
+ />
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="purchase-remark-section">
|
|
|
|
|
+ <text class="purchase-remark-label">采购单备注</text>
|
|
|
|
|
+ <textarea
|
|
|
|
|
+ class="purchase-remark-input"
|
|
|
|
|
+ placeholder="请输入采购单备注"
|
|
|
|
|
+ v-model="purchaseRemark"
|
|
|
|
|
+ :maxlength="500"
|
|
|
|
|
+ ></textarea>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+
|
|
|
|
|
+ <view v-for="(apply, applyIndex) in applyList" :key="applyIndex" class="section">
|
|
|
|
|
+ <view class="section-header">
|
|
|
|
|
+ <view class="section-indicator"></view>
|
|
|
|
|
+ <text class="section-title">申请单 {{ apply.applyCode }}</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="info-card">
|
|
|
|
|
+ <view class="info-row">
|
|
|
|
|
+ <text class="info-label">申请人</text>
|
|
|
|
|
+ <text class="info-value">{{ apply.nickName }}</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="info-row">
|
|
|
|
|
+ <text class="info-label">申请时间</text>
|
|
|
|
|
+ <text class="info-value">{{ apply.createTime }}</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="info-row">
|
|
|
|
|
+ <text class="info-label">用途</text>
|
|
|
|
|
+ <text class="info-value">{{ apply.remark }}</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+
|
|
|
|
|
+ <view class="material-section">
|
|
|
|
|
+ <view class="material-section-header">
|
|
|
|
|
+ <text class="material-section-title">物料明细</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="material-list">
|
|
|
|
|
+ <view
|
|
|
|
|
+ v-for="(item, itemIndex) in apply.lineList"
|
|
|
|
|
+ :key="itemIndex"
|
|
|
|
|
+ class="material-item"
|
|
|
|
|
+ >
|
|
|
|
|
+ <view class="material-info">
|
|
|
|
|
+ <text class="material-name">{{ getItemName(item) }}</text>
|
|
|
|
|
+ <text class="material-spec" v-if="getSpecification(item)">规格:{{ getSpecification(item) }}</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="material-detail">
|
|
|
|
|
+ <view class="detail-row">
|
|
|
|
|
+ <text class="detail-label">申请数量</text>
|
|
|
|
|
+ <text class="detail-value">{{ getQuantity(item) }} {{ getMeasureName(item) }}</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="detail-row purchase-row">
|
|
|
|
|
+ <text class="detail-label">采购数量</text>
|
|
|
|
|
+ <view class="purchase-input-wrap">
|
|
|
|
|
+ <input
|
|
|
|
|
+ class="purchase-input"
|
|
|
|
|
+ type="number"
|
|
|
|
|
+ v-model="item.purchaseQty"
|
|
|
|
|
+ @input="handlePurchaseQtyChange"
|
|
|
|
|
+ />
|
|
|
|
|
+ <text class="purchase-unit">{{ getMeasureName(item) }}</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+
|
|
|
|
|
+ <view class="bottom-space"></view>
|
|
|
|
|
+ </scroll-view>
|
|
|
|
|
+
|
|
|
|
|
+ <view class="bottom-buttons">
|
|
|
|
|
+ <button class="submit-btn" @click="handleSubmit">生成采购单</button>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+</template>
|
|
|
|
|
+
|
|
|
|
|
+<script setup lang="uts">
|
|
|
|
|
+ import { ref } from 'vue'
|
|
|
|
|
+ import { getPurchaseApplyById } from '../../api/apply/index'
|
|
|
|
|
+ import { createMergePurchase } from '../../api/purchase/index'
|
|
|
|
|
+ import { getUserInfo } from '../../utils/storage'
|
|
|
|
|
+
|
|
|
|
|
+ const applyIds = ref<string>("")
|
|
|
|
|
+ const idList = ref<string[]>([])
|
|
|
|
|
+ const applyList = ref<UTSJSONObject[]>([])
|
|
|
|
|
+ const loading = ref<boolean>(false)
|
|
|
|
|
+ const purchaseName = ref<string>("")
|
|
|
|
|
+ const purchaseRemark = ref<string>("")
|
|
|
|
|
+ const currentUserId = ref<string>("")
|
|
|
|
|
+
|
|
|
|
|
+ const getItemName = (item: UTSJSONObject): string => {
|
|
|
|
|
+ if (item == null) return ''
|
|
|
|
|
+ const val = item['itemName']
|
|
|
|
|
+ return val != null ? val.toString() : ''
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const getSpecification = (item: UTSJSONObject): string => {
|
|
|
|
|
+ if (item == null) return ''
|
|
|
|
|
+ const val = item['specification']
|
|
|
|
|
+ return val != null ? val.toString() : ''
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const getQuantity = (item: UTSJSONObject): string => {
|
|
|
|
|
+ if (item == null) return '0'
|
|
|
|
|
+ const val = item['quantityApply']
|
|
|
|
|
+ return val != null ? val.toString() : '0'
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const getMeasureName = (item: UTSJSONObject): string => {
|
|
|
|
|
+ if (item == null) return ''
|
|
|
|
|
+ const val = item['measureName']
|
|
|
|
|
+ return val != null ? val.toString() : ''
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const handlePurchaseQtyChange = (): void => {
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const loadApplyDetails = (): void => {
|
|
|
|
|
+ if (idList.value.length === 0) return
|
|
|
|
|
+ loading.value = true
|
|
|
|
|
+
|
|
|
|
|
+ const promises = idList.value.map((id) => {
|
|
|
|
|
+ return getPurchaseApplyById(id)
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ Promise.all(promises).then((responses: any[]) => {
|
|
|
|
|
+ const resultList: UTSJSONObject[] = []
|
|
|
|
|
+ responses.forEach((response: any) => {
|
|
|
|
|
+ const res = response as UTSJSONObject
|
|
|
|
|
+ const data = res["data"] as UTSJSONObject
|
|
|
|
|
+ const apply = new UTSJSONObject()
|
|
|
|
|
+ apply['applyId'] = data['applyId'] != null ? parseInt(data['applyId'].toString()) : 0
|
|
|
|
|
+ apply['applyCode'] = data['applyCode'] != null ? data['applyCode'].toString() : ''
|
|
|
|
|
+ apply['nickName'] = data['nickName'] != null ? data['nickName'].toString() : ''
|
|
|
|
|
+ apply['createTime'] = data['createTime'] != null ? data['createTime'].toString() : ''
|
|
|
|
|
+ apply['remark'] = data['remark'] != null ? data['remark'].toString() : ''
|
|
|
|
|
+ apply['applyUser'] = data['applyUser'] != null ? data['applyUser'].toString() : ''
|
|
|
|
|
+ apply['applyUserId'] = data['applyUserId'] != null ? parseInt(data['applyUserId'].toString()) : 0
|
|
|
|
|
+ apply['applyDeptName'] = data['applyDeptName'] != null ? data['applyDeptName'].toString() : ''
|
|
|
|
|
+
|
|
|
|
|
+ const lines = data['wmPurchaseApplyLineList']
|
|
|
|
|
+ const lineList: UTSJSONObject[] = []
|
|
|
|
|
+ if (lines != null) {
|
|
|
|
|
+ (lines as UTSJSONObject[]).forEach((line: UTSJSONObject) => {
|
|
|
|
|
+ const lineItem = new UTSJSONObject()
|
|
|
|
|
+ lineItem['lineId'] = line['id'] != null ? line['id'].toString() : ''
|
|
|
|
|
+ lineItem['itemId'] = line['itemId'] != null ? line['itemId'].toString() : ''
|
|
|
|
|
+ lineItem['itemCode'] = line['itemCode'] != null ? line['itemCode'].toString() : ''
|
|
|
|
|
+ lineItem['itemName'] = line['itemName'] != null ? line['itemName'].toString() : ''
|
|
|
|
|
+ lineItem['specification'] = line['specification'] != null ? line['specification'].toString() : ''
|
|
|
|
|
+ lineItem['unitOfMeasure'] = line['unitOfMeasure'] != null ? line['unitOfMeasure'].toString() : ''
|
|
|
|
|
+ lineItem['measureName'] = line['measureName'] != null ? line['measureName'].toString() : ''
|
|
|
|
|
+ lineItem['quantityApply'] = line['quantityApply'] != null ? line['quantityApply'] : 0
|
|
|
|
|
+ lineItem['purchaseQty'] = line['quantityApply'] != null ? line['quantityApply'].toString() : '0'
|
|
|
|
|
+ lineList.push(lineItem)
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ apply['lineList'] = lineList
|
|
|
|
|
+ resultList.push(apply)
|
|
|
|
|
+ })
|
|
|
|
|
+ applyList.value = resultList
|
|
|
|
|
+ loading.value = false
|
|
|
|
|
+ generatePurchaseName()
|
|
|
|
|
+ }).catch((e) => {
|
|
|
|
|
+ console.error('加载申请单详情失败:', e)
|
|
|
|
|
+ loading.value = false
|
|
|
|
|
+ uni.showToast({ title: '加载失败', icon: 'none' })
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const generatePurchaseName = (): void => {
|
|
|
|
|
+ if (applyList.value.length === 0) {
|
|
|
|
|
+ purchaseName.value = ''
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const now = new Date()
|
|
|
|
|
+ const year = now.getFullYear()
|
|
|
|
|
+ const month = String(now.getMonth() + 1).padStart(2, '0')
|
|
|
|
|
+ const day = String(now.getDate()).padStart(2, '0')
|
|
|
|
|
+ const hours = String(now.getHours()).padStart(2, '0')
|
|
|
|
|
+ const minutes = String(now.getMinutes()).padStart(2, '0')
|
|
|
|
|
+ const seconds = String(now.getSeconds()).padStart(2, '0')
|
|
|
|
|
+
|
|
|
|
|
+ const dateStr = `${year}${month}${day}${hours}${minutes}${seconds}`
|
|
|
|
|
+
|
|
|
|
|
+ const applicants = new Set<string>()
|
|
|
|
|
+ applyList.value.forEach((apply) => {
|
|
|
|
|
+ const name = apply['nickName']
|
|
|
|
|
+ if (name != null && name.toString().length > 0) {
|
|
|
|
|
+ applicants.add(name.toString())
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ const applicantStr = Array.from(applicants).join(',')
|
|
|
|
|
+
|
|
|
|
|
+ purchaseName.value = `${dateStr}-${applicantStr}`
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const handleSubmit = (): void => {
|
|
|
|
|
+ const purchaseData = new UTSJSONObject()
|
|
|
|
|
+ const mergedItems: UTSJSONObject[] = []
|
|
|
|
|
+
|
|
|
|
|
+ let totalQuantity = 0
|
|
|
|
|
+
|
|
|
|
|
+ applyList.value.forEach((apply) => {
|
|
|
|
|
+ const applyId = apply['applyId']
|
|
|
|
|
+ const applyRemark = apply['remark'] != null ? apply['remark'].toString() : ''
|
|
|
|
|
+ const applyUser = apply['applyUser'] != null ? apply['applyUser'].toString() : ''
|
|
|
|
|
+ const applyUserId = apply['applyUserId']
|
|
|
|
|
+ const applyDeptName = apply['applyDeptName'] != null ? apply['applyDeptName'].toString() : ''
|
|
|
|
|
+ const lineList = apply['lineList'] as UTSJSONObject[]
|
|
|
|
|
+ lineList.forEach((item) => {
|
|
|
|
|
+ const qty = parseInt(item['purchaseQty'])
|
|
|
|
|
+ if (qty > 0 && qty <= parseInt(getQuantity(item))) {
|
|
|
|
|
+ const lineItem = new UTSJSONObject()
|
|
|
|
|
+ lineItem['applyId'] = applyId
|
|
|
|
|
+ lineItem['applyLineId'] = parseInt(item['lineId'])
|
|
|
|
|
+ lineItem['itemId'] = parseInt(item['itemId'])
|
|
|
|
|
+ lineItem['itemCode'] = item['itemCode'] != null ? item['itemCode'].toString() : ''
|
|
|
|
|
+ lineItem['itemName'] = item['itemName'] != null ? item['itemName'].toString() : ''
|
|
|
|
|
+ lineItem['specification'] = item['specification'] != null ? item['specification'].toString() : ''
|
|
|
|
|
+ lineItem['unitOfMeasure'] = item['unitOfMeasure'] != null ? item['unitOfMeasure'].toString() : ''
|
|
|
|
|
+ lineItem['measureName'] = item['measureName'] != null ? item['measureName'].toString() : ''
|
|
|
|
|
+ lineItem['quantityApply'] = parseInt(getQuantity(item))
|
|
|
|
|
+ lineItem['quantityPurchase'] = qty
|
|
|
|
|
+ lineItem['applyRemark'] = applyRemark
|
|
|
|
|
+ lineItem['applyUser'] = applyUser
|
|
|
|
|
+ lineItem['applyUserId'] = applyUserId
|
|
|
|
|
+ lineItem['applyDeptName'] = applyDeptName
|
|
|
|
|
+ mergedItems.push(lineItem)
|
|
|
|
|
+ totalQuantity += qty
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ if (mergedItems.length === 0) {
|
|
|
|
|
+ uni.showToast({ title: '请填写有效的采购数量', icon: 'none' })
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const mergePurchase = new UTSJSONObject()
|
|
|
|
|
+ mergePurchase['mergeName'] = purchaseName.value
|
|
|
|
|
+ mergePurchase['remark'] = purchaseRemark.value
|
|
|
|
|
+ mergePurchase['totalQuantity'] = totalQuantity
|
|
|
|
|
+
|
|
|
|
|
+ purchaseData['mergePurchase'] = mergePurchase
|
|
|
|
|
+ purchaseData['applyUserId'] = currentUserId.value.length > 0 ? parseInt(currentUserId.value) : 0
|
|
|
|
|
+ purchaseData['applyIds'] = idList.value.map(id => parseInt(id))
|
|
|
|
|
+ purchaseData['mergedItems'] = mergedItems
|
|
|
|
|
+ purchaseData['platform'] = 'mobile'
|
|
|
|
|
+
|
|
|
|
|
+ uni.showModal({
|
|
|
|
|
+ title: '提示',
|
|
|
|
|
+ content: '确定生成采购单吗?',
|
|
|
|
|
+ success: (res) => {
|
|
|
|
|
+ if (res.confirm) {
|
|
|
|
|
+ uni.showLoading({ title: '生成中...' })
|
|
|
|
|
+ createMergePurchase(purchaseData).then((response: any) => {
|
|
|
|
|
+ uni.hideLoading()
|
|
|
|
|
+ const result = response as UTSJSONObject
|
|
|
|
|
+ if (result['code'] === 200) {
|
|
|
|
|
+ uni.showToast({ title: '生成成功', icon: 'success' })
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ uni.redirectTo({
|
|
|
|
|
+ url: '/pages/apply/index?refresh=1'
|
|
|
|
|
+ })
|
|
|
|
|
+ }, 1500)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ const msg = result['msg'] != null ? result['msg'].toString() : '生成失败'
|
|
|
|
|
+ uni.showToast({ title: msg, icon: 'none' })
|
|
|
|
|
+ }
|
|
|
|
|
+ }).catch((e) => {
|
|
|
|
|
+ uni.hideLoading()
|
|
|
|
|
+ const error = e as UTSError
|
|
|
|
|
+ const errMsg = error?.message
|
|
|
|
|
+ uni.showToast({ title: errMsg != null ? errMsg.toString() : '生成失败', icon: 'none' })
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ onLoad((options: any) => {
|
|
|
|
|
+ const userInfo = getUserInfo()
|
|
|
|
|
+ if (userInfo != null) {
|
|
|
|
|
+ const userId = userInfo['userId']
|
|
|
|
|
+ currentUserId.value = userId != null ? userId.toString() : ''
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const params = options as UTSJSONObject
|
|
|
|
|
+ if (params != null && params['applyIds'] != null) {
|
|
|
|
|
+ applyIds.value = params['applyIds'].toString()
|
|
|
|
|
+ idList.value = applyIds.value.split(',').filter((id: string) => id.trim().length > 0)
|
|
|
|
|
+ loadApplyDetails()
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+</script>
|
|
|
|
|
+
|
|
|
|
|
+<style lang="scss">
|
|
|
|
|
+ .page-container {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ background-color: #e8f0f9;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .page-content {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ padding: 20rpx;
|
|
|
|
|
+ padding-bottom: 140rpx;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .purchase-info-section {
|
|
|
|
|
+ margin-bottom: 20rpx;
|
|
|
|
|
+ background: #ffffff;
|
|
|
|
|
+ border-radius: 16rpx;
|
|
|
|
|
+ padding: 20rpx;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .purchase-info-row {
|
|
|
|
|
+ flex-direction: row;
|
|
|
|
|
+ justify-content: space-between;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ margin-bottom: 20rpx;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .purchase-info-label {
|
|
|
|
|
+ font-size: 28rpx;
|
|
|
|
|
+ color: #666666;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .purchase-info-value-wrap {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ margin-left: 20rpx;
|
|
|
|
|
+ background-color: #f8f9fa;
|
|
|
|
|
+ border-radius: 8rpx;
|
|
|
|
|
+ padding: 12rpx 16rpx;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .purchase-info-value {
|
|
|
|
|
+ font-size: 28rpx;
|
|
|
|
|
+ color: #333333;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .purchase-info-input {
|
|
|
|
|
+ font-size: 28rpx;
|
|
|
|
|
+ color: #333333;
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ background-color: transparent;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .purchase-remark-section {
|
|
|
|
|
+ margin-top: 16rpx;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .purchase-remark-label {
|
|
|
|
|
+ font-size: 28rpx;
|
|
|
|
|
+ color: #666666;
|
|
|
|
|
+ margin-bottom: 12rpx;
|
|
|
|
|
+ display: block;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .purchase-remark-input {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ min-height: 160rpx;
|
|
|
|
|
+ background-color: #f8f9fa;
|
|
|
|
|
+ border-radius: 8rpx;
|
|
|
|
|
+ padding: 16rpx;
|
|
|
|
|
+ font-size: 28rpx;
|
|
|
|
|
+ color: #333333;
|
|
|
|
|
+ box-sizing: border-box;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .section {
|
|
|
|
|
+ margin-bottom: 20rpx;
|
|
|
|
|
+ background: #ffffff;
|
|
|
|
|
+ border-radius: 16rpx;
|
|
|
|
|
+ padding: 20rpx;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .section-header {
|
|
|
|
|
+ flex-direction: row;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ margin-bottom: 20rpx;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .section-indicator {
|
|
|
|
|
+ width: 6rpx;
|
|
|
|
|
+ height: 32rpx;
|
|
|
|
|
+ background-color: #007aff;
|
|
|
|
|
+ border-radius: 3rpx;
|
|
|
|
|
+ margin-right: 12rpx;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .section-title {
|
|
|
|
|
+ font-size: 32rpx;
|
|
|
|
|
+ color: #333333;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .info-card {
|
|
|
|
|
+ background-color: #f8f9fa;
|
|
|
|
|
+ border-radius: 8rpx;
|
|
|
|
|
+ padding: 20rpx;
|
|
|
|
|
+ margin-bottom: 20rpx;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .info-row {
|
|
|
|
|
+ flex-direction: row;
|
|
|
|
|
+ justify-content: space-between;
|
|
|
|
|
+ margin-bottom: 16rpx;
|
|
|
|
|
+
|
|
|
|
|
+ &:last-child {
|
|
|
|
|
+ margin-bottom: 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .info-label {
|
|
|
|
|
+ font-size: 28rpx;
|
|
|
|
|
+ color: #666666;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .info-value {
|
|
|
|
|
+ font-size: 28rpx;
|
|
|
|
|
+ color: #333333;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .material-section {
|
|
|
|
|
+ background-color: #f8f9fa;
|
|
|
|
|
+ border-radius: 8rpx;
|
|
|
|
|
+ padding: 20rpx;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .material-section-header {
|
|
|
|
|
+ margin-bottom: 16rpx;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .material-section-title {
|
|
|
|
|
+ font-size: 28rpx;
|
|
|
|
|
+ color: #333333;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .material-list {
|
|
|
|
|
+ background-color: #ffffff;
|
|
|
|
|
+ border-radius: 8rpx;
|
|
|
|
|
+ padding: 16rpx;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .material-item {
|
|
|
|
|
+ padding: 16rpx 0;
|
|
|
|
|
+ border-bottom: 1rpx solid #f0f0f0;
|
|
|
|
|
+
|
|
|
|
|
+ &:last-child {
|
|
|
|
|
+ border-bottom: none;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .material-info {
|
|
|
|
|
+ margin-bottom: 12rpx;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .material-name {
|
|
|
|
|
+ font-size: 28rpx;
|
|
|
|
|
+ color: #333333;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ display: block;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .material-spec {
|
|
|
|
|
+ font-size: 24rpx;
|
|
|
|
|
+ color: #999999;
|
|
|
|
|
+ margin-top: 4rpx;
|
|
|
|
|
+ display: block;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .material-detail {
|
|
|
|
|
+ flex-direction: row;
|
|
|
|
|
+ flex-wrap: wrap;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .detail-row {
|
|
|
|
|
+ flex-direction: row;
|
|
|
|
|
+ width: 50%;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ margin-bottom: 8rpx;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .detail-label {
|
|
|
|
|
+ font-size: 26rpx;
|
|
|
|
|
+ color: #666666;
|
|
|
|
|
+ margin-right: 8rpx;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .detail-value {
|
|
|
|
|
+ font-size: 26rpx;
|
|
|
|
|
+ color: #ff0000;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .purchase-row {
|
|
|
|
|
+ justify-content: flex-end;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .purchase-input-wrap {
|
|
|
|
|
+ flex-direction: row;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ background-color: #f5f5f5;
|
|
|
|
|
+ border-radius: 8rpx;
|
|
|
|
|
+ padding: 8rpx 12rpx;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .purchase-input {
|
|
|
|
|
+ width: 120rpx;
|
|
|
|
|
+ height: 48rpx;
|
|
|
|
|
+ font-size: 26rpx;
|
|
|
|
|
+ color: #ff0000;
|
|
|
|
|
+ text-align: right;
|
|
|
|
|
+ background: transparent;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .purchase-unit {
|
|
|
|
|
+ font-size: 24rpx;
|
|
|
|
|
+ color: #666666;
|
|
|
|
|
+ margin-left: 8rpx;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .empty-tip {
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ padding: 100rpx 20rpx;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .empty-tip-text {
|
|
|
|
|
+ color: #999999;
|
|
|
|
|
+ font-size: 28rpx;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .bottom-space {
|
|
|
|
|
+ height: 40rpx;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .bottom-buttons {
|
|
|
|
|
+ position: fixed;
|
|
|
|
|
+ bottom: 0;
|
|
|
|
|
+ left: 0;
|
|
|
|
|
+ right: 0;
|
|
|
|
|
+ padding: 20rpx 30rpx;
|
|
|
|
|
+ background-color: #ffffff;
|
|
|
|
|
+ border-top: 1rpx solid #e5e5e5;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .submit-btn {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ height: 88rpx;
|
|
|
|
|
+ background-color: #007aff;
|
|
|
|
|
+ color: #ffffff;
|
|
|
|
|
+ font-size: 32rpx;
|
|
|
|
|
+ font-weight: 600;
|
|
|
|
|
+ border-radius: 22rpx;
|
|
|
|
|
+ border: none;
|
|
|
|
|
+ }
|
|
|
|
|
+</style>
|