| | |
| | | submitData[k] = source[k] |
| | | }) |
| | | |
| | | console.log('提交数据:', submitData) |
| | | |
| | | const { code } = await clientVisitSignIn(submitData) |
| | | console.log('code----', code); |
| | | |
| | | if (code === 200) { |
| | | showToast('签到成功') |
| | |
| | | <template> |
| | | <view class="client-visit-list"> |
| | | <view class="sales-accoun"> |
| | | <!-- 使用通用页面头部组件 --> |
| | | <PageHeader title="客户拜访" @back="goBack" /> |
| | | |
| | | <!-- 搜索和筛选区域 --> |
| | | <view class="search-filter-section"> |
| | | <view class="search-section"> |
| | | <view class="search-bar"> |
| | | <view class="search-input"> |
| | | <input |
| | | <up-input |
| | | class="search-text" |
| | | placeholder="请输入客户名称" |
| | | v-model="customerName" |
| | | confirm-type="search" |
| | | @confirm="getList" |
| | | @blur="getList" |
| | | clearable |
| | | /> |
| | | </view> |
| | | <view class="filter-button" @click="getList"> |
| | | <up-icon name="search" size="24" color="#999"></up-icon> |
| | | <u-icon name="search" size="24" color="#999"></u-icon> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 拜访记录列表 --> |
| | | <view class="visit-list" v-if="visitList.length > 0"> |
| | | <view class="ledger-list" v-if="visitList.length > 0"> |
| | | <view v-for="(item, index) in visitList" :key="index"> |
| | | <view class="visit-item"> |
| | | <view class="ledger-item"> |
| | | <view class="item-header"> |
| | | <view class="item-left"> |
| | | <view class="document-icon"> |
| | |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .u-divider { |
| | | margin: 0 !important; |
| | | } |
| | | @import "../../../styles/sales-common.scss"; |
| | | |
| | | .client-visit-list { |
| | | // 页面特定的样式覆盖 |
| | | .sales-accoun { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | position: relative; |
| | | padding-bottom: 80px; |
| | | } |
| | | |
| | | .search-filter-section { |
| | | padding: 10px 20px; |
| | | background: #ffffff; |
| | | } |
| | | |
| | | .search-bar { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 12px; |
| | | } |
| | | |
| | | .search-input { |
| | | flex: 1; |
| | | background: #f5f5f5; |
| | | border-radius: 24px; |
| | | padding: 10px 16px; |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .search-text { |
| | | flex: 1; |
| | | font-size: 14px; |
| | | color: #333; |
| | | background: transparent; |
| | | border: none; |
| | | outline: none; |
| | | } |
| | | |
| | | .search-text::placeholder { |
| | | color: #999; |
| | | } |
| | | |
| | | .filter-button { |
| | | width: 40px; |
| | | height: 40px; |
| | | border-radius: 8px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .visit-list { |
| | | padding: 20px; |
| | | } |
| | | |
| | | .visit-item { |
| | | background: #ffffff; |
| | | border-radius: 12px; |
| | | margin-bottom: 16px; |
| | | overflow: hidden; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); |
| | | padding: 0 16px; |
| | | } |
| | | |
| | | .item-header { |
| | | padding: 16px 0; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .item-left { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 8px; |
| | | } |
| | | |
| | | // 特定的图标样式 |
| | | .document-icon { |
| | | width: 24px; |
| | | height: 24px; |
| | | background: #667eea; |
| | | border-radius: 4px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | background: #667eea; // 保持页面特有的背景色 |
| | | } |
| | | |
| | | .item-id { |
| | | font-size: 14px; |
| | | color: #333; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | // 特有样式 |
| | | .visit-status { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .item-details { |
| | | padding: 16px 0; |
| | | } |
| | | |
| | | .detail-row { |
| | | display: flex; |
| | | align-items: flex-start; |
| | | justify-content: space-between; |
| | | margin-bottom: 8px; |
| | | |
| | | &:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | } |
| | | |
| | | .detail-label { |
| | | font-size: 12px; |
| | | color: #777777; |
| | | min-width: 60px; |
| | | } |
| | | |
| | | .detail-value { |
| | | font-size: 12px; |
| | | color: #000000; |
| | | text-align: right; |
| | | flex: 1; |
| | | margin-left: 16px; |
| | | word-break: break-all; |
| | | word-break: break-all; // 保留页面特有的文本换行样式 |
| | | } |
| | | |
| | | .no-data { |
| | | padding: 40px 0; |
| | | text-align: center; |
| | | color: #999; |
| | | } |
| | | |
| | | .action-buttons { |
| | | display: flex; |
| | | gap: 12px; |
| | | padding: 0 0 16px 0; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .action-btn { |
| | | flex: 1; |
| | | } |
| | | |
| | | // 特定的浮动按钮样式 |
| | | .fab-button { |
| | | position: fixed; |
| | | bottom: calc(30px + env(safe-area-inset-bottom)); |
| | | right: 30px; |
| | | width: 56px; |
| | | height: 56px; |
| | | background: #667eea; |
| | | border-radius: 50%; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | box-shadow: 0 4px 16px rgba(102, 126, 234, 0.3); |
| | | z-index: 1000; |
| | | background: #667eea; // 保持页面特有的背景色 |
| | | box-shadow: 0 4px 16px rgba(102, 126, 234, 0.3); // 保持页面特有的阴影效果 |
| | | } |
| | | </style> |
| | | |
| | |
| | | <PageHeader title="审批管理" @back="goBack" /> |
| | | |
| | | <!-- 搜索和筛选区域 --> |
| | | <view class="search-filter-section"> |
| | | <view class="search-section"> |
| | | <view class="search-bar"> |
| | | <view class="search-input"> |
| | | <input |
| | | <up-input |
| | | class="search-text" |
| | | placeholder="请输入流程编号" |
| | | v-model="searchForm.approveId" |
| | | clearable |
| | | /> |
| | | </view> |
| | | <view class="search-button" @click="getList"> |
| | |
| | | <view v-else class="no-data"> |
| | | <text>暂无审批数据</text> |
| | | </view> |
| | | <!-- <van-floating-bubble icon="plus" @click="handleAdd"/>--> |
| | | <!-- 浮动操作按钮 --> |
| | | <view class="fab-button" @click="handleAdd"> |
| | | <up-icon name="plus" size="24" color="#ffffff"></up-icon> |
| | |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import "../../../styles/sales-common.scss"; |
| | | |
| | | .u-divider { |
| | | margin: 0 !important; |
| | | } |
| | | |
| | | .sales-account { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | position: relative; |
| | | } |
| | | .search-input { |
| | | flex: 1; |
| | | background: #f5f5f5; |
| | | border-radius: 24px; |
| | | padding: 10px 16px; |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 8px; |
| | | } |
| | | .search-text { |
| | | flex: 1; |
| | | font-size: 14px; |
| | | color: #333; |
| | | background: transparent; |
| | | border: none; |
| | | outline: none; |
| | | } |
| | | |
| | | .search-text::placeholder { |
| | | color: #999; |
| | | } |
| | | |
| | | |
| | | .search-filter-section { |
| | | padding: 10px 20px; |
| | | background: #ffffff; |
| | | } |
| | | |
| | | .search-bar { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 12px; |
| | | } |
| | | |
| | | .search-input { |
| | | flex: 1; |
| | | background: #f5f5f5; |
| | | border-radius: 24px; |
| | | padding: 10px 16px; |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 8px; |
| | | } |
| | | .search-text { |
| | | flex: 1; |
| | | font-size: 14px; |
| | | color: #333; |
| | | background: transparent; |
| | | border: none; |
| | | outline: none; |
| | | } |
| | | |
| | | .search-text::placeholder { |
| | | color: #999; |
| | | } |
| | | |
| | | .filter-button { |
| | | width: 40px; |
| | | height: 40px; |
| | | border-radius: 8px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .ledger-list { |
| | | padding: 20px; |
| | | } |
| | | |
| | | .ledger-item { |
| | | background: #ffffff; |
| | | border-radius: 12px; |
| | | margin-bottom: 16px; |
| | | overflow: hidden; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); |
| | | padding: 0 16px; |
| | | } |
| | | |
| | | .item-header { |
| | | padding: 16px 0; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .item-left { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 8px; |
| | | } |
| | | |
| | | // 文档图标样式 - 覆盖公共样式中的背景色 |
| | | .document-icon { |
| | | width: 24px; |
| | | height: 24px; |
| | | background: #ed8d05; |
| | | border-radius: 4px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .item-id { |
| | | font-size: 14px; |
| | | color: #333; |
| | | font-weight: 500; |
| | | // 浮动按钮样式 - 覆盖公共样式中的背景色 |
| | | .fab-button { |
| | | background: #ed8d05; |
| | | } |
| | | |
| | | .item-tag { |
| | | border-radius: 4px; |
| | | padding: 2px 4px; |
| | | } |
| | | |
| | | .tag-text { |
| | | font-size: 11px; |
| | | color: #ffffff; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .item-details { |
| | | padding: 16px 0; |
| | | } |
| | | |
| | | .detail-row { |
| | | display: flex; |
| | | align-items: flex-end; |
| | | justify-content: space-between; |
| | | margin-bottom: 8px; |
| | | |
| | | &:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | } |
| | | // 特有样式 |
| | | .detail-row-user { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .detail-row-approveReason { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .detail-info { |
| | | margin-top: 10px; |
| | | display: flex; |
| | | align-items: flex-start; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .detail-label { |
| | | font-size: 12px; |
| | | color: #777777; |
| | | min-width: 60px; |
| | | } |
| | | |
| | | .detail-value { |
| | | font-size: 12px; |
| | | color: #000000; |
| | | text-align: right; |
| | | flex: 1; |
| | | margin-left: 16px; |
| | | } |
| | | |
| | | .detail-value.highlightBlue { |
| | |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .no-data { |
| | | padding: 40px 0; |
| | | text-align: center; |
| | | color: #999; |
| | | } |
| | | |
| | | .fab-button { |
| | | position: fixed; |
| | | bottom: 30px; |
| | | right: 30px; |
| | | width: 56px; |
| | | height: 56px; |
| | | background: #ed8d05; |
| | | border-radius: 50%; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | box-shadow: 0 4px 16px rgba(41, 121, 255, 0.3); |
| | | z-index: 1000; |
| | | } |
| | | |
| | | .approver-value { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | } |
| | | |
| | | .approver-chip { |
| | | display: inline-flex; |
| | | align-items: center; |
| | |
| | | padding: 4px 10px; |
| | | max-width: 100%; |
| | | } |
| | | |
| | | .approver-name { |
| | | font-size: 12px; |
| | | color: #2b7cff; |
| | |
| | | line-height: 28px; |
| | | padding: 0 12px; |
| | | } |
| | | .action-btn.edit { |
| | | /* primary 样式来自组件,这里保留钩子以便后续需要扩展 */ |
| | | } |
| | | .action-btn.approve { |
| | | /* success 样式来自组件,这里保留钩子以便后续需要扩展 */ |
| | | } |
| | | /* 已移除vant组件的样式引用 */ |
| | | |
| | | </style> |
| | |
| | | <template> |
| | | <view class="device-ledger"> |
| | | <view class="sales-account"> |
| | | <!-- 使用通用页面头部组件 --> |
| | | <PageHeader title="设备台账" @back="goBack" /> |
| | | |
| | | <!-- 搜索和筛选区域 --> |
| | | <view class="search-filter-section"> |
| | | <!-- 搜索区域 --> |
| | | <view class="search-section"> |
| | | <view class="search-bar"> |
| | | <view class="search-input"> |
| | | <input |
| | | <up-input |
| | | class="search-text" |
| | | placeholder="请输入设备名称" |
| | | placeholder="请输入设备名称搜索" |
| | | v-model="searchKeyword" |
| | | confirm-type="search" |
| | | @confirm="getList" |
| | | @change="getList" |
| | | clearable |
| | | /> |
| | | </view> |
| | | <view class="filter-button" @click="getList"> |
| | |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .u-divider { |
| | | margin: 0 !important; |
| | | } |
| | | @import '@/styles/sales-common.scss'; |
| | | |
| | | .device-ledger { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | position: relative; |
| | | padding-bottom: 80px; |
| | | } |
| | | |
| | | .search-filter-section { |
| | | padding: 10px 20px; |
| | | background: #ffffff; |
| | | } |
| | | |
| | | .search-bar { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 12px; |
| | | } |
| | | |
| | | .search-input { |
| | | flex: 1; |
| | | background: #f5f5f5; |
| | | border-radius: 24px; |
| | | padding: 10px 16px; |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .search-text { |
| | | flex: 1; |
| | | font-size: 14px; |
| | | color: #333; |
| | | background: transparent; |
| | | border: none; |
| | | outline: none; |
| | | } |
| | | |
| | | .search-text::placeholder { |
| | | color: #999; |
| | | } |
| | | |
| | | .filter-button { |
| | | width: 40px; |
| | | height: 40px; |
| | | border-radius: 8px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .ledger-list { |
| | | padding: 20px; |
| | | } |
| | | |
| | | .ledger-item { |
| | | background: #ffffff; |
| | | border-radius: 12px; |
| | | margin-bottom: 16px; |
| | | overflow: hidden; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); |
| | | padding: 0 16px; |
| | | } |
| | | |
| | | .item-header { |
| | | padding: 16px 0; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .item-left { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .document-icon { |
| | | width: 24px; |
| | | height: 24px; |
| | | background: #2979ff; |
| | | border-radius: 4px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .item-id { |
| | | font-size: 14px; |
| | | color: #333; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .item-details { |
| | | padding: 16px 0; |
| | | } |
| | | |
| | | .detail-row { |
| | | display: flex; |
| | | align-items: flex-end; |
| | | justify-content: space-between; |
| | | margin-bottom: 8px; |
| | | |
| | | &:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | } |
| | | |
| | | .detail-label { |
| | | font-size: 12px; |
| | | color: #777777; |
| | | min-width: 60px; |
| | | } |
| | | |
| | | .detail-value { |
| | | font-size: 12px; |
| | | color: #000000; |
| | | text-align: right; |
| | | flex: 1; |
| | | margin-left: 16px; |
| | | } |
| | | |
| | | .detail-value.highlight { |
| | | color: #2979ff; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .no-data { |
| | | padding: 40px 0; |
| | | text-align: center; |
| | | color: #999; |
| | | } |
| | | |
| | | // 按钮样式 |
| | | .action-buttons { |
| | | display: flex; |
| | | gap: 12px; |
| | | padding: 0 0 16px 0; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .action-btn { |
| | | flex: 1; |
| | | } |
| | | |
| | | .fab-button { |
| | | position: fixed; |
| | | bottom: calc(30px + env(safe-area-inset-bottom)); |
| | | right: 30px; |
| | | width: 56px; |
| | | height: 56px; |
| | | background: #2979ff; |
| | | border-radius: 50%; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | box-shadow: 0 4px 16px rgba(41, 121, 255, 0.3); |
| | | z-index: 1000; |
| | | } |
| | | // 设备台账特有样式(所有样式都已包含在公共样式中) |
| | | </style> |
| | |
| | | if (code == 200) { |
| | | form.value.deviceLedgerId = data.deviceLedgerId; |
| | | form.value.deviceModel = data.deviceModel; |
| | | form.value.repairTime = data.repairTime; |
| | | form.value.repairTime = dayjs(data.repairTime).format("YYYY-MM-DD"); |
| | | form.value.repairName = data.repairName; |
| | | form.value.remark = data.remark; |
| | | // 设置设备名称显示 |
| | |
| | | // 新增模式 |
| | | operationType.value = 'add'; |
| | | } |
| | | }; |
| | | |
| | | // 清除表单校验状态 |
| | | const clearValidate = () => { |
| | | formRef.value?.clearValidate(); |
| | | }; |
| | | |
| | | // 重置表单数据和校验状态 |
| | | const resetForm = () => { |
| | | form.value = { |
| | | deviceLedgerId: undefined, |
| | | deviceModel: undefined, |
| | | repairTime: dayjs().format("YYYY-MM-DD"), |
| | | repairName: undefined, |
| | | remark: undefined, |
| | | }; |
| | | deviceNameText.value = ''; |
| | | }; |
| | | |
| | | // 扫描二维码功能 |
| | |
| | | // 确认日期选择 |
| | | const onDateConfirm = (e) => { |
| | | form.value.repairTime = formatDateToYMD(e.value); |
| | | pickerDateValue.value = dayjs(e.value).format("YYYY-MM-DD"); |
| | | showDate.value = false; |
| | | }; |
| | | |
| | |
| | | |
| | | // 返回上一页 |
| | | const goBack = () => { |
| | | uni.removeStorageSync('repairId'); |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | // 获取页面参数 |
| | | const getPageParams = () => { |
| | | const pages = getCurrentPages(); |
| | | const currentPage = pages[pages.length - 1]; |
| | | const options = currentPage.options; |
| | | // 使用uni.getStorageSync获取id |
| | | const id = uni.getStorageSync('repairId'); |
| | | |
| | | // 根据是否有id参数来判断是新增还是编辑 |
| | | if (options.id) { |
| | | if (id) { |
| | | // 编辑模式,获取详情 |
| | | loadForm(options.id); |
| | | loadForm(id); |
| | | // 可选:获取后清除存储的id,避免影响后续操作 |
| | | // uni.removeStorageSync('repairId'); |
| | | } else { |
| | | // 新增模式 |
| | | loadForm(); |
| | |
| | | |
| | | // 获取页面ID |
| | | const getPageId = () => { |
| | | const pages = getCurrentPages(); |
| | | const currentPage = pages[pages.length - 1]; |
| | | const options = currentPage.options; |
| | | return options.id; |
| | | // 使用uni.getStorageSync获取id |
| | | const id = uni.getStorageSync('repairId'); |
| | | return id; |
| | | }; |
| | | </script> |
| | | |
| | |
| | | <template> |
| | | <view class="device-repair"> |
| | | <view class="sales-account"> |
| | | <!-- 使用通用页面头部组件 --> |
| | | <PageHeader title="设备报修" @back="goBack" /> |
| | | |
| | | <!-- 搜索区域 --> |
| | | <view class="search-filter-section"> |
| | | <view class="search-section"> |
| | | <view class="search-bar"> |
| | | <view class="search-input"> |
| | | <input |
| | | <up-input |
| | | class="search-text" |
| | | placeholder="请输入设备名称" |
| | | placeholder="请输入设备名称搜索" |
| | | v-model="searchKeyword" |
| | | confirm-type="search" |
| | | @confirm="getList" |
| | | @change="getList" |
| | | clearable |
| | | /> |
| | | </view> |
| | | <view class="filter-button" @click="getList"> |
| | |
| | | </view> |
| | | |
| | | <!-- 设备报修列表 --> |
| | | <view class="repair-list" v-if="repairList.length > 0"> |
| | | <view class="ledger-list" v-if="repairList.length > 0"> |
| | | <view v-for="(item, index) in repairList" :key="index"> |
| | | <view class="repair-item"> |
| | | <view class="ledger-item"> |
| | | <view class="item-header"> |
| | | <view class="item-left"> |
| | | <view class="document-icon"> |
| | |
| | | type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.status === 1" |
| | | @click="edit(item.id)" |
| | | > |
| | | 编辑 |
| | |
| | | showToast('参数错误') |
| | | return |
| | | } |
| | | // 使用uni.setStorageSync存储id |
| | | uni.setStorageSync('repairId', id) |
| | | uni.navigateTo({ |
| | | url: `/pages/equipmentManagement/repair/maintain?id=${id}` |
| | | url: '/pages/equipmentManagement/repair/maintain' |
| | | }) |
| | | } |
| | | |
| | |
| | | // 编辑 - 跳转到add页面,通过id区分新增还是编辑 |
| | | const edit = (id) => { |
| | | if (!id) return |
| | | // 使用uni.setStorageSync存储id |
| | | uni.setStorageSync('repairId', id) |
| | | uni.navigateTo({ |
| | | url: `/pages/equipmentManagement/repair/add?id=${id}` |
| | | url: '/pages/equipmentManagement/repair/add' |
| | | }) |
| | | } |
| | | |
| | |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .u-divider { |
| | | margin: 0 !important; |
| | | } |
| | | @import '@/styles/sales-common.scss'; |
| | | |
| | | .device-repair { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | position: relative; |
| | | padding-bottom: 80px; |
| | | } |
| | | |
| | | .search-filter-section { |
| | | padding: 10px 20px; |
| | | background: #ffffff; |
| | | } |
| | | |
| | | .search-bar { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 12px; |
| | | } |
| | | |
| | | .search-input { |
| | | flex: 1; |
| | | background: #f5f5f5; |
| | | border-radius: 24px; |
| | | padding: 10px 16px; |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .search-text { |
| | | flex: 1; |
| | | font-size: 14px; |
| | | color: #333; |
| | | background: transparent; |
| | | border: none; |
| | | outline: none; |
| | | } |
| | | |
| | | .search-text::placeholder { |
| | | color: #999; |
| | | } |
| | | |
| | | .filter-button { |
| | | width: 40px; |
| | | height: 40px; |
| | | border-radius: 8px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .repair-list { |
| | | padding: 20px; |
| | | } |
| | | |
| | | .repair-item { |
| | | background: #ffffff; |
| | | border-radius: 12px; |
| | | margin-bottom: 16px; |
| | | overflow: hidden; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); |
| | | padding: 0 16px; |
| | | } |
| | | |
| | | .item-header { |
| | | padding: 16px 0; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .item-left { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .document-icon { |
| | | width: 24px; |
| | | height: 24px; |
| | | background: #2979ff; |
| | | border-radius: 4px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .item-id { |
| | | font-size: 14px; |
| | | color: #333; |
| | | font-weight: 500; |
| | | // 设备维修特有样式 |
| | | .sales-account { |
| | | padding-bottom: 80px; // 为浮动按钮留出空间 |
| | | } |
| | | |
| | | .status-tag { |
| | |
| | | align-items: center; |
| | | } |
| | | |
| | | .item-details { |
| | | padding: 16px 0; |
| | | } |
| | | |
| | | .detail-row { |
| | | display: flex; |
| | | align-items: flex-end; |
| | | justify-content: space-between; |
| | | margin-bottom: 8px; |
| | | |
| | | &:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | } |
| | | |
| | | .detail-label { |
| | | font-size: 12px; |
| | | color: #777777; |
| | | min-width: 60px; |
| | | } |
| | | |
| | | .detail-value { |
| | | font-size: 12px; |
| | | color: #000000; |
| | | text-align: right; |
| | | flex: 1; |
| | | margin-left: 16px; |
| | | } |
| | | |
| | | .detail-value.highlight { |
| | | color: #2979ff; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .no-data { |
| | | padding: 40px 0; |
| | | text-align: center; |
| | | color: #999; |
| | | } |
| | | |
| | | .action-buttons { |
| | | display: flex; |
| | | gap: 8px; |
| | | padding: 0 0 16px 0; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .action-btn { |
| | | flex: 1; |
| | | } |
| | | .fab-button { |
| | | position: fixed; |
| | | bottom: calc(30px + env(safe-area-inset-bottom)); |
| | | right: 30px; |
| | | width: 56px; |
| | | height: 56px; |
| | | background: #2979ff; |
| | | border-radius: 50%; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | box-shadow: 0 4px 16px rgba(41, 121, 255, 0.3); |
| | | z-index: 1000; |
| | | /* 确保浮动按钮不被底部安全区域遮挡 */ |
| | | gap: 8px; // 与公共样式中的 12px 不同 |
| | | } |
| | | </style> |
| | |
| | | <up-datetime-picker |
| | | :show="showDatePicker" |
| | | v-model="pickerDateValue" |
| | | mode="date" |
| | | mode="datetime" |
| | | title="选择日期" |
| | | format="YYYY-MM-DD HH:mm:ss" |
| | | @confirm="onDateConfirm" |
| | | @cancel="showDatePicker = false" |
| | | /> |
| | | </view> |
| | | </template> |
| | |
| | | import { addMaintain } from '@/api/equipmentManagement/repair'; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import dayjs from "dayjs"; |
| | | import { formatDateToYMD } from '@/utils/ruoyi' |
| | | |
| | | defineOptions({ |
| | | name: "设备维修表单", |
| | |
| | | const form = ref({ |
| | | maintenanceName: userStore.nickName || '', // 默认使用当前用户昵称 |
| | | maintenanceResult: undefined, // 维修结果 |
| | | maintenanceTime: dayjs().format("YYYY-MM-DD"), // 维修日期(只显示日期) |
| | | maintenanceTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), // 维修日期(只显示日期) |
| | | }); |
| | | |
| | | // 自定义showToast函数 |
| | |
| | | }) |
| | | }; |
| | | |
| | | // 清除表单校验状态 |
| | | const clearValidate = () => { |
| | | // uview-plus不需要手动清除验证状态,重置表单时会自动清除 |
| | | }; |
| | | |
| | | // 重置表单数据和校验状态 |
| | | const resetForm = () => { |
| | | form.value = { |
| | | maintenanceName: userStore.nickName || '', |
| | | maintenanceResult: undefined, |
| | | maintenanceTime: dayjs().format("YYYY-MM-DD"), |
| | | maintenanceTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), |
| | | }; |
| | | }; |
| | | |
| | |
| | | |
| | | // 准备提交数据,maintenanceTime 加上当前时分秒 |
| | | const submitData = { ...form.value }; |
| | | if (submitData.maintenanceTime && !submitData.maintenanceTime.includes(':')) { |
| | | // 如果 maintenanceTime 只包含日期,添加当前时分秒 |
| | | submitData.maintenanceTime = submitData.maintenanceTime + ' ' + dayjs().format('HH:mm:ss'); |
| | | } |
| | | |
| | | const { code } = await addMaintain({ id: id, ...submitData }); |
| | | |
| | |
| | | showToast('新增维修成功'); |
| | | resetFormAndValidate(); |
| | | setTimeout(() => { |
| | | uni.navigateBack(); |
| | | }, 1500); |
| | | goBack(); |
| | | }, 500); |
| | | } else { |
| | | loading.value = false; |
| | | } |
| | | } catch (e) { |
| | | console.log(e); |
| | | |
| | | loading.value = false; |
| | | showToast('操作失败'); |
| | | } |
| | |
| | | |
| | | // 返回上一页 |
| | | const goBack = () => { |
| | | uni.removeStorageSync('repairId'); |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | // 获取页面ID |
| | | const getPageId = () => { |
| | | const pages = getCurrentPages(); |
| | | const currentPage = pages[pages.length - 1]; |
| | | const options = currentPage.options; |
| | | return options.id; |
| | | const id = uni.getStorageSync('repairId'); |
| | | return id; |
| | | }; |
| | | |
| | | // 确认日期选择 |
| | | const onDateConfirm = (e) => { |
| | | form.value.maintenanceTime = formatDateToYMD(e.value) |
| | | pickerDateValue.value = formatDateToYMD(e.value) |
| | | form.value.maintenanceTime = dayjs(e.value).format('YYYY-MM-DD HH:mm:ss') |
| | | pickerDateValue.value = e.value |
| | | showDatePicker.value = false; |
| | | }; |
| | | |
| | |
| | | // 设置维修人为当前用户昵称 |
| | | form.value.maintenanceName = userStore.nickName || ''; |
| | | // 设置当前日期(只包含年月日) |
| | | form.value.maintenanceTime = dayjs().format('YYYY-MM-DD'); |
| | | form.value.maintenanceTime = dayjs().format('YYYY-MM-DD HH:mm:ss'); |
| | | }; |
| | | |
| | | onShow(() => { |
| | |
| | | <template> |
| | | <view class="device-upkeep"> |
| | | <view class="sales-account"> |
| | | <!-- 使用通用页面头部组件 --> |
| | | <PageHeader title="设备保养" @back="goBack" /> |
| | | |
| | | <!-- 搜索区域 --> |
| | | <view class="search-filter-section"> |
| | | <view class="search-section"> |
| | | <view class="search-bar"> |
| | | <view class="search-input"> |
| | | <input |
| | | <up-input |
| | | class="search-text" |
| | | placeholder="请输入设备名称" |
| | | placeholder="请输入设备名称搜索" |
| | | v-model="searchKeyword" |
| | | confirm-type="search" |
| | | @confirm="getList" |
| | | @change="getList" |
| | | clearable |
| | | /> |
| | | </view> |
| | | <view class="filter-button" @click="getList"> |
| | |
| | | </view> |
| | | |
| | | <!-- 设备保养列表 --> |
| | | <view class="upkeep-list" v-if="upkeepList.length > 0"> |
| | | <view class="ledger-list" v-if="upkeepList.length > 0"> |
| | | <view v-for="(item, index) in upkeepList" :key="index"> |
| | | <view class="upkeep-item" @click="toggleSelection(item)"> |
| | | <view class="ledger-item" @click="toggleSelection(item)"> |
| | | <view class="item-header"> |
| | | <view class="item-left"> |
| | | <view class="document-icon"> |
| | |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .u-divider { |
| | | margin: 0 !important; |
| | | } |
| | | @import '@/styles/sales-common.scss'; |
| | | |
| | | .device-upkeep { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | position: relative; |
| | | padding-bottom: 80px; |
| | | } |
| | | |
| | | .search-filter-section { |
| | | padding: 10px 20px; |
| | | background: #ffffff; |
| | | } |
| | | |
| | | .search-bar { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 12px; |
| | | } |
| | | |
| | | .search-input { |
| | | flex: 1; |
| | | background: #f5f5f5; |
| | | border-radius: 24px; |
| | | padding: 10px 16px; |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .search-text { |
| | | flex: 1; |
| | | font-size: 14px; |
| | | color: #333; |
| | | background: transparent; |
| | | border: none; |
| | | outline: none; |
| | | } |
| | | |
| | | .search-text::placeholder { |
| | | color: #999; |
| | | } |
| | | |
| | | .filter-button { |
| | | width: 40px; |
| | | height: 40px; |
| | | border-radius: 8px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | // 设备保养特有样式 |
| | | .sales-account { |
| | | padding-bottom: 80px; // 为浮动按钮留出空间 |
| | | } |
| | | |
| | | .action-section { |
| | |
| | | border-bottom: 1px solid #f0f0f0; |
| | | } |
| | | |
| | | .action-buttons { |
| | | display: flex; |
| | | gap: 8px; |
| | | .action-section .action-buttons { |
| | | gap: 8px; // 与公共样式中的 12px 不同 |
| | | justify-content: flex-start; |
| | | } |
| | | |
| | | .upkeep-list { |
| | | padding: 20px; |
| | | } |
| | | |
| | | .upkeep-item { |
| | | background: #ffffff; |
| | | border-radius: 12px; |
| | | margin-bottom: 16px; |
| | | overflow: hidden; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); |
| | | padding: 0 16px; |
| | | } |
| | | |
| | | .item-header { |
| | | padding: 16px 0; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .item-left { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .checkbox-wrapper { |
| | |
| | | align-items: center; |
| | | } |
| | | |
| | | .document-icon { |
| | | width: 24px; |
| | | height: 24px; |
| | | background: #2979ff; |
| | | border-radius: 4px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .item-id { |
| | | font-size: 14px; |
| | | color: #333; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .status-tag { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .item-details { |
| | | padding: 16px 0; |
| | | } |
| | | |
| | | .detail-row { |
| | | display: flex; |
| | | align-items: flex-end; |
| | | justify-content: space-between; |
| | | margin-bottom: 8px; |
| | | |
| | | &:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | } |
| | | |
| | | .detail-label { |
| | | font-size: 12px; |
| | | color: #777777; |
| | | min-width: 80px; |
| | | min-width: 80px; // 与公共样式中的 60px 不同 |
| | | } |
| | | |
| | | .detail-value { |
| | | font-size: 12px; |
| | | color: #000000; |
| | | text-align: right; |
| | | flex: 1; |
| | | margin-left: 16px; |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | align-items: center; |
| | | } |
| | | |
| | | .detail-value.highlight { |
| | | color: #2979ff; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .no-data { |
| | | padding: 40px 0; |
| | | text-align: center; |
| | | color: #999; |
| | | } |
| | | |
| | | .upkeep-item .action-buttons { |
| | | display: flex; |
| | | gap: 8px; |
| | | padding: 0 0 16px 0; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .action-btn { |
| | | flex: 1; |
| | | } |
| | | |
| | | .fab-button { |
| | | position: fixed; |
| | | bottom: calc(30px + env(safe-area-inset-bottom)); |
| | | right: 30px; |
| | | width: 56px; |
| | | height: 56px; |
| | | background: #667eea; |
| | | border-radius: 50%; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | box-shadow: 0 4px 16px rgba(102, 126, 234, 0.3); |
| | | z-index: 1000; |
| | | .ledger-item .action-buttons { |
| | | gap: 8px; // 与公共样式中的 12px 不同 |
| | | } |
| | | </style> |
| | |
| | | <view class="input-item flex align-center"> |
| | | <up-input prefixIcon="account" placeholder="请输入账号" border="bottom" |
| | | @blur="getUserLoginFacotryList" |
| | | maxlength="30" v-model="loginForm.username" clearable></up-input> |
| | | maxlength="30" v-model="loginForm.userName" clearable></up-input> |
| | | </view> |
| | | <view class="input-item flex align-center"> |
| | | <up-input prefixIcon="lock" placeholder="请输入密码" border="bottom" maxlength="20" v-model="loginForm.password" clearable type="password"></up-input> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import modal from '@/plugins/modal' |
| | | import {modal} from "@/plugins"; |
| | | |
| | | const showToast = (message) => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: 'none' |
| | | }) |
| | | } |
| | | import { userLoginFacotryList} from '@/api/login' |
| | | import { ref, onMounted } from "vue"; |
| | | import useUserStore from '@/store/modules/user' |
| | |
| | | const useWxLogin = ref(false); // 是否使用微信登录 |
| | | const rememberPassword = ref(false); // 记住密码 |
| | | const loginForm = ref({ |
| | | username: "", |
| | | userName: "", |
| | | password: "", |
| | | factoryId: "", |
| | | currentFatoryName: "", |
| | |
| | | // 保存密码到本地存储 |
| | | function savePassword() { |
| | | if (rememberPassword.value) { |
| | | uni.setStorageSync('remembered_username', loginForm.value.username); |
| | | uni.setStorageSync('remembered_username', loginForm.value.userName); |
| | | uni.setStorageSync('remembered_password', loginForm.value.password); |
| | | uni.setStorageSync('remember_password', true); |
| | | } else { |
| | |
| | | const savedUsername = uni.getStorageSync('remembered_username'); |
| | | const savedPassword = uni.getStorageSync('remembered_password'); |
| | | if (savedUsername) { |
| | | loginForm.value.username = savedUsername; |
| | | loginForm.value.userName = savedUsername; |
| | | } |
| | | if (savedPassword) { |
| | | loginForm.value.password = savedPassword; |
| | |
| | | } |
| | | |
| | | function getUserLoginFacotryList() { |
| | | if(loginForm.value.username){ |
| | | userLoginFacotryList({userName:loginForm.value.username}).then(res => { |
| | | if(loginForm.value.userName){ |
| | | userLoginFacotryList({userName:loginForm.value.userName}).then(res => { |
| | | console.log('res',res) |
| | | // 检查res.data是否为数组 |
| | | if (res.data && Array.isArray(res.data)) { |
| | | // 重新组装数据格式:deptId变成id,deptName变成name |
| | |
| | | factoryList.value = [] |
| | | } |
| | | }).catch(error => { |
| | | modal.msgError('获取公司列表失败:', error) |
| | | showToast('获取公司列表失败:', error) |
| | | factoryList.value = [] |
| | | }) |
| | | }else { |
| | |
| | | } |
| | | |
| | | async function handleLogin() { |
| | | if (loginForm.value.username === "") { |
| | | modal.msgError("请输入您的账号") |
| | | if (loginForm.value.userName === "") { |
| | | showToast("请输入您的账号") |
| | | } else if (loginForm.value.password === "") { |
| | | modal.msgError("请输入您的密码") |
| | | showToast("请输入您的密码") |
| | | } else if (loginForm.value.factoryId === "") { |
| | | modal.msgError("请选择公司") |
| | | showToast("请选择公司") |
| | | } else { |
| | | modal.loading("登录中,请耐心等待...") |
| | | showToast("登录中,请耐心等待...") |
| | | pwdLogin() |
| | | } |
| | | }; |
| | |
| | | label="产品大类" |
| | | prop="productCategory" |
| | | required |
| | | :rules="productRules" |
| | | :rules="productRules.productCategory" |
| | | > |
| | | <up-input |
| | | v-model="product.productCategory" |
| | |
| | | label="规格型号" |
| | | prop="specificationModel" |
| | | required |
| | | :rules="productRules" |
| | | :rules="productRules.specificationModel" |
| | | > |
| | | <up-input |
| | | v-model="product.specificationModel" |
| | |
| | | label="单位" |
| | | prop="unit" |
| | | required |
| | | :rules="productRules" |
| | | :rules="productRules.unit" |
| | | > |
| | | <up-input |
| | | v-model="product.unit" |
| | |
| | | label="税率(%)" |
| | | prop="taxRate" |
| | | required |
| | | :rules="productRules" |
| | | :rules="productRules.taxRate" |
| | | > |
| | | <up-input |
| | | v-model="product.taxRate" |
| | |
| | | label="含税单价(元)" |
| | | prop="taxInclusiveUnitPrice" |
| | | required |
| | | :rules="productRules" |
| | | :rules="productRules.taxInclusiveUnitPrice" |
| | | > |
| | | <up-input |
| | | v-model="product.taxInclusiveUnitPrice" |
| | |
| | | label="数量" |
| | | prop="quantity" |
| | | required |
| | | :rules="productRules" |
| | | :rules="productRules.quantity" |
| | | > |
| | | <up-input |
| | | v-model="product.quantity" |
| | |
| | | label="含税总价(元)" |
| | | prop="taxInclusiveTotalPrice" |
| | | required |
| | | :rules="productRules" |
| | | :rules="productRules.taxInclusiveTotalPrice" |
| | | > |
| | | <up-input |
| | | v-model="product.taxInclusiveTotalPrice" |
| | |
| | | label="不含税总价(元)" |
| | | prop="taxExclusiveTotalPrice" |
| | | required |
| | | :rules="productRules" |
| | | :rules="productRules.taxExclusiveTotalPrice" |
| | | > |
| | | <up-input |
| | | v-model="product.taxExclusiveTotalPrice" |
| | |
| | | label="发票类型" |
| | | prop="invoiceType" |
| | | required |
| | | :rules="productRules" |
| | | :rules="productRules.invoiceType" |
| | | > |
| | | <up-input |
| | | v-model="product.invoiceType" |
| | |
| | | import { formatDateToYMD } from '@/utils/ruoyi' |
| | | import { |
| | | addOrUpdateSalesLedger, |
| | | addOrUpdateSalesLedgerProduct, |
| | | customerList, |
| | | getSalesLedgerWithProducts, |
| | | modelList, |
| | |
| | | // 表单校验规则 |
| | | const rules = { |
| | | salesman: [ |
| | | { required: true, message: '请选择业务员', trigger: 'blur' } |
| | | { required: true, message: '请选择业务员', trigger: 'change' } |
| | | ], |
| | | customerContractNo: [ |
| | | { required: true, message: '请输入客户合同号', trigger: 'blur' } |
| | | ], |
| | | customerName: [ |
| | | { required: true, message: '请选择客户名称', trigger: 'blur' } |
| | | { required: true, message: '请选择客户名称', trigger: 'change' } |
| | | ], |
| | | projectName: [ |
| | | { required: true, message: '请输入项目名称', trigger: 'blur' } |
| | | ], |
| | | executionDate: [ |
| | | { required: true, message: '请选择签订日期', trigger: 'blur' } |
| | | { required: true, message: '请选择签订日期', trigger: 'change' } |
| | | ] |
| | | }; |
| | | |
| | | // 产品信息校验规则 |
| | | const productRules = { |
| | | productCategory: [ |
| | | { required: true, message: '请选择产品大类', trigger: 'blur' } |
| | | { required: true, message: '请选择产品大类', trigger: 'change' } |
| | | ], |
| | | specificationModel: [ |
| | | { required: true, message: '请选择规格型号', trigger: 'blur' } |
| | | { required: true, message: '请选择规格型号', trigger: 'change' } |
| | | ], |
| | | unit: [ |
| | | { required: true, message: '请输入单位', trigger: 'blur' } |
| | | ], |
| | | taxRate: [ |
| | | { required: true, message: '请选择税率', trigger: 'blur' } |
| | | { required: true, message: '请选择税率', trigger: 'change' } |
| | | ], |
| | | taxInclusiveUnitPrice: [ |
| | | { required: true, message: '请输入含税单价', trigger: 'blur' }, |
| | |
| | | { type: 'number', min: 0, message: '不含税总价必须大于0', trigger: 'blur' } |
| | | ], |
| | | invoiceType: [ |
| | | { required: true, message: '请选择发票类型', trigger: 'blur' } |
| | | { required: true, message: '请选择发票类型', trigger: 'change' } |
| | | ] |
| | | }; |
| | | |
| | |
| | | // 日期确认事件 |
| | | const onDateConfirm = (e) => { |
| | | form.value.executionDate = formatDateToYMD(e.value) |
| | | pickerDateValue.value = formatDateToYMD(e.value) |
| | | // 保持pickerDateValue为时间戳格式,而不是格式化的字符串 |
| | | pickerDateValue.value = e.value |
| | | showDatePicker.value = false; |
| | | } |
| | | |
| | |
| | | import config from '@/config.js' |
| | | |
| | | export interface LoginForm { |
| | | username: string; |
| | | userName: string; |
| | | password: string; |
| | | factoryId: string; |
| | | } |
| | |
| | | actions: { |
| | | // 部门登录 |
| | | loginCheckFactory(userInfo: any) { |
| | | const username = userInfo.username.trim() |
| | | const userName = userInfo.userName |
| | | const password = userInfo.password |
| | | const factoryId = userInfo.factoryId |
| | | return new Promise((resolve, reject) => { |
| | | loginCheckFactory(username, password, factoryId).then((res: any) => { |
| | | loginCheckFactory(userName, password, factoryId).then((res: any) => { |
| | | setToken(res.token) |
| | | this.token = res.token |
| | | resolve(null) |