| | |
| | | !*.allowed_extension |
| | | |
| | | # 䏿é¤ä¸åæä»¶å |
| | | !important_file.txt |
| | | !important_file.txt |
| | | |
| | | # 忽ç¥ç±äºnodeçæ¬ä¸å导è´lockæä»¶ä¸åï¼åªéè¦ä¿çpackage.jsonå³å¯ |
| | | package-lock.json |
| | | yarn.lock |
| | | pnpm-lock.yaml |
| | |
| | | "mqtt": "4.1.0", |
| | | "pinia": "2.2.2", |
| | | "tslib": "^2.7.0", |
| | | "uview-plus": "^3.5.25", |
| | | "vant": "^4.9.21", |
| | | "uview-plus": "^3.4.62", |
| | | "vue": "3.4.21", |
| | | "vue-i18n": "^9.14.2" |
| | | }, |
| | |
| | | "@vue/runtime-core": "^3.5.12", |
| | | "@vue/tsconfig": "^0.5.1", |
| | | "less": "^4.2.0", |
| | | "sass": "^1.78.0", |
| | | "sass": "1.78.0", |
| | | "sass-loader": "^16.0.1", |
| | | "typescript": "^5.6.2", |
| | | "vite": "5.2.8", |
| | | "vite": "5.4.10", |
| | | "vue-tsc": "2.1.6" |
| | | } |
| | | } |
| | |
| | | <template> |
| | | <Splash v-if="showSplash" /> |
| | | <Splash v-if="showSplash" /> |
| | | <div v-else> |
| | | <router-view /> |
| | | </div> |
| | | <router-view /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted } from 'vue' |
| | | import Splash from './components/Splash.vue' |
| | | |
| | | const showSplash = ref(true) |
| | | onMounted(() => { |
| | | setTimeout(() => { |
| | | showSplash.value = false |
| | | }, 5000) |
| | | setTimeout(() => { |
| | | showSplash.value = false |
| | | }, 5000) |
| | | }) |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | // ä½¿ç¨ @use æ¿ä»£ @importï¼å¦æuView-plusæ¯æçè¯ï¼ |
| | | // 注æï¼ç±äºuView-pluså¯è½è¿ä¸æ¯æ@useï¼è¿å¯è½ä¼å¯¼è´æ ·å¼é®é¢ |
| | | // @use "uview-plus/index.scss"; |
| | | // @use '@/static/scss/index.scss'; |
| | | |
| | | // ææ¶ä¿ç@importï¼ç´å°uView-plusæ´æ° |
| | | @import "uview-plus/index.scss"; |
| | | @import '@/static/scss/index.scss'; |
| | | </style> |
| | |
| | | |
| | | æ¹èªä½è
è¯å°æçtki-qrcodeäºç»´ç çæå¨ |
| | | |
| | | ### ä½è
ï¼è£çå¯ |
| | | ### ä½è
ï¼Dftre |
| | | |
| | | 1. H5ã微信å°ç¨åºãæ¯ä»å®å°ç¨åºãAPPï¼å
¶å®å¹³å°çå°ç¨åºæ²¡ææµè¯ |
| | | 2. 使ç¨canvasçæ |
| | | 3. å¯è®¾ç½®äºç»´ç èæ¯è²ï¼åæ¯è²ï¼è§æ è² |
| | | 4. å¯è®¾ç½®äºç»´ç logo |
| | | |
| | | ## éè¦çäºæ
说3é éè¦çäºæ
说3é éè¦çäºæ
说3é |
| | | |
| | | 1. IOSãAndroidçæºé½å¯ä»¥æ£å¸¸çæäºç»´ç |
| | | 2. 使ç¨çæ¶ååºç°æ æ³çæäºç»´ç æç©ºç½ç请å
githubç´æ¥æå
ä¸è½½ï¼é®é¢ä¾æ§ï¼è¯·githubä¸ç´æ¥æåºé®é¢å¹¶é
å¾ |
| | | 3. æé®é¢è¯·è¯´æé®é¢åå ï¼è¿æ ·ææå¥½å®ä½ï¼å¦åæä¹æ æ³è§£å³ |
| | | 4. å¦ææ¤æä»¶æå¸®å©å°ä½ 请æ5åæèµèµæï¼ä½ çæ¯ææ¯ææ´æ°çå¨å |
| | | |
| | | + å¾ç1 æ¯å¾®ä¿¡å°ç¨åºçæºå®æµ |
| | | + å¾ç2 æ¯å¾®ä¿¡å°ç¨åºæ¨¡æå®æµ |
| | | + å¾ç3 æ¯æ¯ä»å®å°ç¨åºæ¨¡æå¨å®æµ |
| | | + å¾ç4 æ¯å®åçæºå®æµ |
| | | + å¾ç5 H5 |
| | | |
| | | ### ä½¿ç¨æ¹æ³ |
| | | |
| | |
| | | |
| | | [uni-app](https://uniapp.dcloud.io/ "uni-app") |
| | | [qrcode](https://github.com/aralejs/qrcode "qrcode") |
| | | tki-qrcode |
| | |
| | | // åºç¨å
¨å±é
ç½® |
| | | const config = { |
| | | baseUrl: 'http://114.132.189.42:8089', // æµè¯åº |
| | | // baseUrl: 'http://192.168.1.147:7003', // æ¬å°èè° |
| | | // baseUrl: 'https://vue.ruoyi.vip/prod-api', |
| | | // baseUrl: 'http://localhost/prod-api', |
| | | baseUrl: 'http://114.132.189.42:8089', |
| | | //cloudåå°ç½å
³å°å |
| | | // baseUrl: 'http://192.168.10.3:8080', |
| | | // åºç¨ä¿¡æ¯ |
| | |
| | | import directive from './directive' // directive |
| | | |
| | | import { useDict } from '@/utils/dict' |
| | | import { parseTime, resetForm, addDateRange, handleTree, selectDictLabel, selectDictLabels } from '@/utils/ruoyi' |
| | | import { parseTime, resetForm, addDateRange, handleTree, selectDictLabel, selectDictLabels, formatDateToYMD } from '@/utils/ruoyi' |
| | | import { |
| | | calculateTaxExclusiveTotalPrice, |
| | | } from "@/utils/summarizeTable.js"; |
| | | |
| | | |
| | | |
| | | export function createApp() { |
| | |
| | | app.use(store) |
| | | app.use(uviewPlus) |
| | | app.use(plugins) |
| | | // ç§»é¤ä»¥ä¸è¡ Vant 注å |
| | | // app.use(Vant) |
| | | |
| | | // 注åå
¨å±ç»ä»¶ |
| | | setupGlobalComponents(app) |
| | | |
| | |
| | | app.config.globalProperties.selectDictLabel = selectDictLabel |
| | | app.config.globalProperties.selectDictLabels = selectDictLabels |
| | | app.config.globalProperties.calculateTaxExclusiveTotalPrice = calculateTaxExclusiveTotalPrice; |
| | | app.config.globalProperties.formatDateToYMD = formatDateToYMD; |
| | | |
| | | return { |
| | | app |
| | |
| | | { |
| | | "path": "pages/sales/invoiceLedger/index", |
| | | "style": { |
| | | "navigationBarTitleText": "", |
| | | "navigationBarTitleText": "å¼ç¥¨å°è´¦", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/common/webview/index", |
| | | "style": { |
| | | "navigationBarTitleText": "æµè§ç½é¡µ" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/common/textview/index", |
| | | "style": { |
| | | "navigationBarTitleText": "æµè§ææ¬" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/cooperativeOffice/collaborativeApproval/index", |
| | | "style": { |
| | | "navigationBarTitleText": "审æ¹ç®¡ç", |
| | |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/cooperativeOffice/clientVisit/detail", |
| | | "style": { |
| | | "navigationBarTitleText": "æ·»å å®¢æ·æè®¿", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/equipmentManagement/ledger/index", |
| | | "style": { |
| | | "navigationBarTitleText": "设å¤å°è´¦", |
| | |
| | | }, |
| | | { |
| | | "path": "pages/equipmentManagement/ledger/detail", |
| | | "style": { |
| | | "navigationBarTitleText": "设å¤å°è´¦è¯¦æ
", |
| | | "navigationStyle": "custom" |
| | | } |
| | | "style": { |
| | | "navigationBarTitleText": "设å¤å°è´¦è¯¦æ
", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/equipmentManagement/repair/index", |
| | | "style": { |
| | | "navigationBarTitleText": "è®¾å¤æ¥ä¿®", |
| | | "navigationStyle": "custom" |
| | | } |
| | | "style": { |
| | | "navigationBarTitleText": "è®¾å¤æ¥ä¿®", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/equipmentManagement/repair/add", |
| | | "style": { |
| | | "navigationBarTitleText": "æ°å¢è®¾å¤æ¥ä¿®", |
| | | "navigationStyle": "custom" |
| | | } |
| | | "style": { |
| | | "navigationBarTitleText": "æ°å¢è®¾å¤æ¥ä¿®", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/equipmentManagement/repair/maintain", |
| | | "style": { |
| | | "navigationBarTitleText": "设å¤ç»´ä¿®", |
| | | "navigationStyle": "custom" |
| | | } |
| | | "style": { |
| | | "navigationBarTitleText": "设å¤ç»´ä¿®", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/equipmentManagement/upkeep/index", |
| | | "style": { |
| | | "navigationBarTitleText": "设å¤ä¿å
»", |
| | | "navigationStyle": "custom" |
| | | } |
| | | "style": { |
| | | "navigationBarTitleText": "设å¤ä¿å
»", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/equipmentManagement/upkeep/add", |
| | | "style": { |
| | | "navigationBarTitleText": "æ°å¢ä¿å
»è®¡å", |
| | | "navigationStyle": "custom" |
| | | } |
| | | "style": { |
| | | "navigationBarTitleText": "æ°å¢ä¿å
»è®¡å", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/equipmentManagement/upkeep/maintain", |
| | | "style": { |
| | | "navigationBarTitleText": "ç»´ä¿®ä¿å
»", |
| | | "navigationStyle": "custom" |
| | | } |
| | | "style": { |
| | | "navigationBarTitleText": "ç»´ä¿®ä¿å
»", |
| | | "navigationStyle": "custom" |
| | | } |
| | | } |
| | | ], |
| | | "subPackages": [ |
| | |
| | | <view class="client-visit-detail"> |
| | | <PageHeader title="å®¢æ·æè®¿è¯¦æ
" @back="goBack" /> |
| | | |
| | | <u-form @submit="handleSignIn" ref="formRef" label-width="110" input-align="right" error-message-align="right"> |
| | | <u-form @submit="handleSignIn" ref="formRef" label-width="90"> |
| | | <!-- 客æ·ä¿¡æ¯ --> |
| | | <u-cell-group title="客æ·ä¿¡æ¯"> |
| | | <u-form-item label="客æ·åç§°" prop="customerName" required border-bottom> |
| | | <u-input |
| | | v-model="form.customerName" |
| | | placeholder="请è¾å
¥å®¢æ·åç§°" |
| | | readonly |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="è系人" prop="contactPerson" border-bottom> |
| | | <u-form-item label="è系人" prop="contact" border-bottom> |
| | | <u-input |
| | | v-model="form.contactPerson" |
| | | v-model="form.contact" |
| | | placeholder="请è¾å
¥è系人" |
| | | readonly |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="èç³»çµè¯" prop="contactPhone" border-bottom> |
| | | <u-input |
| | | v-model="form.contactPhone" |
| | | placeholder="请è¾å
¥èç³»çµè¯" |
| | | readonly |
| | | /> |
| | | </u-form-item> |
| | | </u-cell-group> |
| | | |
| | | <!-- æè®¿ä¿¡æ¯ --> |
| | | <u-cell-group title="æè®¿ä¿¡æ¯"> |
| | | <u-form-item label="æè®¿ç®ç" prop="visitPurpose" required border-bottom> |
| | | <u-form-item label="æè®¿ç®ç" prop="purposeVisit" required border-bottom> |
| | | <u-input |
| | | v-model="form.visitPurpose" |
| | | v-model="form.purposeVisit" |
| | | placeholder="请è¾å
¥æè®¿ç®ç" |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="æè®¿æ¶é´" prop="visitTime" required border-bottom> |
| | | <u-form-item label="æè®¿æ¶é´" prop="purposeDate" required border-bottom> |
| | | <u-input |
| | | v-model="form.visitTime" |
| | | v-model="form.purposeDate" |
| | | placeholder="è¯·éæ©æè®¿æ¶é´" |
| | | readonly |
| | | @click="showTimePicker" |
| | | /> |
| | | <template #right> |
| | | <up-icon |
| | | name="arrow-right" |
| | | @click="showTimePicker" |
| | | ></up-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="æè®¿å°ç¹" prop="visitLocation" required border-bottom> |
| | | <u-form-item label="æè®¿å°ç¹" prop="visitAddress" required border-bottom> |
| | | <u-input |
| | | v-model="form.visitLocation" |
| | | v-model="form.visitAddress" |
| | | placeholder="请è¾å
¥æè®¿å°ç¹" |
| | | > |
| | | <template #suffix> |
| | |
| | | </u-form> |
| | | |
| | | <!-- æ¶é´éæ©å¨ --> |
| | | <u-popup v-model="showTime" mode="bottom"> |
| | | <u-datetime-picker |
| | | v-model="currentTime" |
| | | title="éæ©æ¶é´" |
| | | @confirm="onTimeConfirm" |
| | | @cancel="showTime = false" |
| | | /> |
| | | </u-popup> |
| | | <up-datetime-picker |
| | | :show="showTime" |
| | | v-model="currentTime" |
| | | @confirm="onTimeConfirm" |
| | | @cancel="showTime = false" |
| | | mode="datetime" |
| | | /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | // æ¿æ¢ toast æ¹æ³ |
| | | defineOptions({name: 'client-visit-detail'}) |
| | | const showToast = (message) => { |
| | | uni.showToast({ |
| | | title: message, |
| | |
| | | import { clientVisitSignIn } from '@/api/cooperativeOffice/clientVisit' |
| | | import useUserStore from "@/store/modules/user" |
| | | import dayjs from "dayjs" |
| | | import { formatDateToYMD } from '@/utils/ruoyi' |
| | | |
| | | const userStore = useUserStore() |
| | | |
| | |
| | | const formRef = ref(null) |
| | | |
| | | // æ¶é´ç¸å
³ |
| | | const currentTime = ref(new Date()) |
| | | const currentTime = ref(Date.now()) |
| | | const showTime = ref(false) |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | |
| | | } |
| | | |
| | | // 确认æ¶é´éæ© |
| | | const onTimeConfirm = ({ selectedValues }) => { |
| | | form.value.purposeDate = selectedValues.join('-') |
| | | currentTime.value = selectedValues.join('-') |
| | | showTime.value = false |
| | | const onTimeConfirm = (e) => { |
| | | console.log(e) |
| | | form.value.purposeDate = e.value |
| | | currentTime.value = e.value |
| | | showTime.value = false; |
| | | } |
| | | |
| | | // è·åå½åä½ç½® |
| | |
| | | |
| | | // æäº¤ç¾å° |
| | | const handleSignIn = async () => { |
| | | console.log('form.value----', form.value); |
| | | |
| | | if (!form.value.customerName) { |
| | | showToast('请è¾å
¥å®¢æ·åç§°') |
| | | return |
| | |
| | | const initPageData = () => { |
| | | // 设置é»è®¤æè®¿æ¶é´ä¸ºå½åæ¶é´ |
| | | form.value.purposeDate = dayjs().format('YYYY-MM-DD HH:mm:ss') |
| | | currentTime.value = new Date() |
| | | currentTime.value = Date.now() |
| | | |
| | | // 设置æè®¿äººä¸ºå½åç»å½ç¨æ·çæµç§° |
| | | form.value.visitingPeople = userStore.nickName || '' |
| | |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import '@/static/scss/form-common.scss'; |
| | | .client-visit { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | |
| | | |
| | | <!-- æé®åºå --> |
| | | <view class="action-buttons"> |
| | | <van-button |
| | | <u-button |
| | | type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | @click="viewDetail(item.id)" |
| | | > |
| | | æ¥ç详æ
|
| | | </van-button> |
| | | <van-button |
| | | type="danger" |
| | | </u-button> |
| | | <u-button |
| | | type="error" |
| | | size="small" |
| | | plain |
| | | class="action-btn" |
| | | @click="deleteRecord(item.id)" |
| | | > |
| | | å é¤ |
| | | </van-button> |
| | | </u-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | |
| | | import { getVisitRecords, deleteVisitRecord } from '@/api/cooperativeOffice/clientVisit' |
| | | import useUserStore from "@/store/modules/user" |
| | | // æ¿æ¢ toast æ¹æ³ |
| | | defineOptions({name: 'client-visit-index'}) |
| | | const showToast = (message) => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: 'none' |
| | | }) |
| | | } |
| | | |
| | | import dayjs from "dayjs" |
| | | |
| | |
| | | </view> |
| | | |
| | | <view class="input-content"> |
| | | <van-field |
| | | <u-textarea |
| | | v-model="approvalOpinion" |
| | | type="textarea" |
| | | rows="4" |
| | | placeholder="请è¾å
¥å®¡æ ¸æè§" |
| | | maxlength="200" |
| | | show-word-limit |
| | | count |
| | | /> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- åºé¨æä½æé® --> |
| | | <view v-if="canApprove" class="footer-actions"> |
| | | <van-button class="reject-btn" @click="handleReject">驳å</van-button> |
| | | <van-button class="approve-btn" @click="handleApprove">éè¿</van-button> |
| | | <u-button class="reject-btn" @click="handleReject">驳å</u-button> |
| | | <u-button class="approve-btn" @click="handleApprove">éè¿</u-button> |
| | | </view> |
| | | </view> |
| | | </template> |
| | |
| | | } |
| | | |
| | | .reject-btn { |
| | | width: 120px; |
| | | background: #ff4d4f; |
| | | color: #fff; |
| | | border: none; |
| | | } |
| | | width: 120px; |
| | | background: #ff4d4f; |
| | | color: #fff; |
| | | } |
| | | |
| | | .approve-btn { |
| | | width: 120px; |
| | | background: #52c41a; |
| | | color: #fff; |
| | | border: none; |
| | | } |
| | | .approve-btn { |
| | | width: 120px; |
| | | background: #52c41a; |
| | | color: #fff; |
| | | } |
| | | |
| | | /* éé
u-buttonæ ·å¼ */ |
| | | :deep(.u-button) { |
| | | border-radius: 6px; |
| | | } |
| | | |
| | | @keyframes pulse { |
| | | 0% { |
| | |
| | | <view class="contact-details"> |
| | | <text class="contact-name">{{ selectedContact.nickName }}</text> |
| | | </view> |
| | | <van-icon name="cross" size="16" color="#999" @click="clearSelected" /> |
| | | <u-icon name="close" size="16" color="#999" @click="clearSelected" /> |
| | | </view> |
| | | </view> |
| | | |
| | |
| | | <text class="list-title">å
¨é¨è系人</text> |
| | | </view> |
| | | |
| | | <van-list |
| | | <u-list |
| | | v-model:loading="loading" |
| | | :finished="finished" |
| | | finished-text="æ²¡ææ´å¤äº" |
| | |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </van-list> |
| | | </u-list> |
| | | </view> |
| | | </view> |
| | | </template> |
| | |
| | | } |
| | | |
| | | // èªå®ä¹åéæé®æ ·å¼ |
| | | :deep(.van-radio) { |
| | | .van-radio__icon { |
| | | width: 20px; |
| | | height: 20px; |
| | | border: 2px solid #ddd; |
| | | border-radius: 50%; |
| | | background: #fff; |
| | | position: relative; |
| | | transition: all 0.2s; |
| | | |
| | | &::before { |
| | | content: ''; |
| | | position: absolute; |
| | | top: 50%; |
| | | left: 50%; |
| | | transform: translate(-50%, -50%) scale(0); |
| | | width: 8px; |
| | | height: 8px; |
| | | background: #006cfb; |
| | | border-radius: 50%; |
| | | transition: transform 0.2s; |
| | | } |
| | | } |
| | | |
| | | &.van-radio--checked { |
| | | .van-radio__icon { |
| | | border-color: #006cfb; |
| | | background: #fff; |
| | | |
| | | &::before { |
| | | transform: translate(-50%, -50%) scale(1); |
| | | } |
| | | |
| | | &::after { |
| | | content: ''; |
| | | position: absolute; |
| | | top: -2px; |
| | | left: -2px; |
| | | right: -2px; |
| | | bottom: -2px; |
| | | border: 2px solid rgba(0, 108, 251, 0.2); |
| | | border-radius: 50%; |
| | | animation: ripple 0.6s ease-out; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | /* uview-plusçradioç»ä»¶æ ·å¼ä¸éè¦é¢å¤çdeepæ ·å¼ç©¿éï¼ä¿æåææ ·å¼ */ |
| | | |
| | | @keyframes ripple { |
| | | 0% { |
| | |
| | | <PageHeader title="å®¡æ¹æµç¨" @back="goBack" /> |
| | | |
| | | <!-- 表ååºå --> |
| | | <view class="form-section"> |
| | | <van-form ref="formRef" @submit="submitForm" :rules="rules" input-align="right" error-message-align="right" scroll-to-error scroll-to-error-position="center"> |
| | | <van-cell-group style="margin-bottom: 16px;"> |
| | | <van-field |
| | | v-model="form.approveReason" |
| | | name="approveReason" |
| | | rows="2" |
| | | autosize |
| | | label="ç³è¯·äºç±" |
| | | type="textarea" |
| | | maxlength="200" |
| | | :rules="[{ required: true, message: 'ç³è¯·äºç±ä¸è½ä¸ºç©º' }]" |
| | | placeholder="请è¾å
¥ç³è¯·äºç±" |
| | | show-word-limit |
| | | required |
| | | /> |
| | | </van-cell-group> |
| | | <van-cell-group> |
| | | <van-field |
| | | v-model="form.approveDeptName" |
| | | readonly |
| | | name="picker" |
| | | label="ç³è¯·é¨é¨" |
| | | placeholder="è¯·éæ©ç³è¯·é¨é¨" |
| | | :rules="[{ required: true, message: 'è¯·éæ©ç³è¯·é¨é¨' }]" |
| | | <u-form ref="formRef" @submit="submitForm" :rules="rules" :model="form" label-width="140rpx"> |
| | | <u-form-item prop="approveReason" label="ç³è¯·äºç±" required> |
| | | <u-input |
| | | v-model="form.approveReason" |
| | | type="textarea" |
| | | rows="2" |
| | | auto-height |
| | | maxlength="200" |
| | | placeholder="请è¾å
¥ç³è¯·äºç±" |
| | | show-word-limit |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item prop="approveDeptName" label="ç³è¯·é¨é¨" required> |
| | | <u-input |
| | | v-model="form.approveDeptName" |
| | | readonly |
| | | placeholder="è¯·éæ©ç³è¯·é¨é¨" |
| | | @click="showPicker = true" |
| | | /> |
| | | <template #right> |
| | | <up-icon |
| | | name="arrow-right" |
| | | @click="showPicker = true" |
| | | required |
| | | /> |
| | | <van-field |
| | | v-model="form.approveUserName" |
| | | name="taxPrice" |
| | | label="ç³è¯·äºº" |
| | | placeholder="请è¾å
¥ç³è¯·äºº" |
| | | :rules="[{ required: true, message: 'ç³è¯·äººä¸è½ä¸ºç©º' }]" |
| | | required |
| | | readonly |
| | | /> |
| | | <van-popup |
| | | v-model:show="showPicker" |
| | | position="bottom" |
| | | > |
| | | <van-picker |
| | | :columns="productOptions" |
| | | :model-value="pickerValue" |
| | | @confirm="onConfirm" |
| | | @cancel="showPicker = false" |
| | | /> |
| | | </van-popup> |
| | | <van-field |
| | | v-model="form.approveTime" |
| | | label="ç³è¯·æ¥æ" |
| | | placeholder="è¯·éæ©" |
| | | readonly |
| | | required |
| | | @click="showDatePicker" |
| | | :rules="[{ required: true, message: 'è¯·éæ©æ¥æ¬¾æ¥æ' }]" |
| | | /> |
| | | <!-- æ¥æéæ©å¨ --> |
| | | <van-popup v-model:show="showDate" position="bottom"> |
| | | <van-date-picker |
| | | v-model="currentDate" |
| | | title="éæ©æ¥æ" |
| | | @confirm="onDateConfirm" |
| | | @cancel="showDate = false" |
| | | /> |
| | | </van-popup> |
| | | </van-cell-group> |
| | | </van-form> |
| | | </view> |
| | | ></up-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item prop="approveUser" label="ç³è¯·äºº" required> |
| | | <u-input |
| | | v-model="form.approveUserName" |
| | | placeholder="请è¾å
¥ç³è¯·äºº" |
| | | readonly |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item prop="approveTime" label="ç³è¯·æ¥æ" required> |
| | | <u-input |
| | | v-model="form.approveTime" |
| | | placeholder="è¯·éæ©" |
| | | readonly |
| | | @click="showDatePicker" |
| | | /> |
| | | </u-form-item> |
| | | </u-form> |
| | | |
| | | <!-- éæ©å¨å¼¹çª --> |
| | | <up-action-sheet |
| | | :show="showPicker" |
| | | :actions="productOptions" |
| | | title="éæ©é¨é¨" |
| | | @select="onConfirm" |
| | | @close="showPicker = false" |
| | | /> |
| | | |
| | | <!-- æ¥æéæ©å¨ --> |
| | | <u-popup v-model="showDate" mode="bottom"> |
| | | <u-datetime-picker |
| | | v-model="currentDate" |
| | | title="éæ©æ¥æ" |
| | | mode="date" |
| | | @confirm="onDateConfirm" |
| | | @cancel="showDate = false" |
| | | /> |
| | | </u-popup> |
| | | <!-- å®¡æ ¸æµç¨åºå --> |
| | | <view class="approval-process"> |
| | | <view class="approval-header"> |
| | |
| | | </view> |
| | | |
| | | <view class="add-step-btn"> |
| | | <van-button icon="plus" plain type="primary" style="width: 100%" @click="addApprovalStep">æ°å¢èç¹</van-button> |
| | | <u-button icon="plus" plain type="primary" style="width: 100%" @click="addApprovalStep">æ°å¢èç¹</u-button> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- åºé¨æé® --> |
| | | <view class="footer-btns"> |
| | | <van-button class="cancel-btn" @click="goBack">åæ¶</van-button> |
| | | <van-button class="save-btn" @click="submitForm">ä¿å</van-button> |
| | | <u-button class="cancel-btn" @click="goBack">åæ¶</u-button> |
| | | <u-button class="save-btn" @click="submitForm">ä¿å</u-button> |
| | | </view> |
| | | </view> |
| | | </template> |
| | |
| | | import { ref, onMounted, onUnmounted, reactive, toRefs } from "vue"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { formatDateToYMD } from '@/utils/ruoyi' |
| | | import {getDept, approveProcessGetInfo, approveProcessAdd, approveProcessUpdate} from "@/api/collaborativeApproval/approvalProcess"; |
| | | const showToast = (message) => { |
| | | uni.showToast({ |
| | |
| | | rules: { |
| | | approveTime: [{ required: false, message: "请è¾å
¥", trigger: "change" },], |
| | | approveId: [{ required: false, message: "请è¾å
¥", trigger: "blur" }], |
| | | approveUser: [{ required: false, message: "请è¾å
¥", trigger: "blur" }], |
| | | approveDeptId: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | approveReason: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | checkResult: [{ required: false, message: "请è¾å
¥", trigger: "blur" }], |
| | |
| | | }); |
| | | const { form, rules } = toRefs(data); |
| | | const result = ref(""); |
| | | const pickerValue = ref([]); |
| | | const showPicker = ref(false); |
| | | const productOptions = ref([]); |
| | | const operationType = ref(""); |
| | |
| | | getDept().then((res) => { |
| | | productOptions.value = res.data.map(item => ({ |
| | | value: item.deptId, |
| | | text: item.deptName |
| | | name: item.deptName |
| | | })) |
| | | }); |
| | | }; |
| | |
| | | uni.$off('selectContact', handleSelectContact); |
| | | }); |
| | | |
| | | const onConfirm = ({ selectedValues, selectedOptions }) => { |
| | | form.value.approveDeptName = selectedOptions[0]?.text; |
| | | form.value.approveDeptId = selectedOptions[0]?.value; |
| | | pickerValue.value = selectedValues; |
| | | const onConfirm = (item) => { |
| | | // 设置éä¸çé¨é¨ |
| | | form.value.approveDeptName = item.name; |
| | | // ç¡®ä¿è®¾ç½®çæ¯å符串类åçé¨é¨ID |
| | | form.value.approveDeptId = String(item.value || ''); |
| | | console.log('é¨é¨éæ©åçå¼:', { |
| | | approveDeptId: form.value.approveDeptId, |
| | | approveDeptName: form.value.approveDeptName |
| | | }); |
| | | showPicker.value = false; |
| | | }; |
| | | |
| | |
| | | return; |
| | | } |
| | | |
| | | formRef.value.validate().then(() => { |
| | | // è¡¨åæ ¡éªéè¿ï¼å¯ä»¥æäº¤æ°æ® |
| | | // æ¶éææèç¹ç审æ¹äººid |
| | | console.log('approverNodes---', approverNodes.value) |
| | | form.value.approveUserIds = approverNodes.value.map(node => node.userId).join(',') |
| | | form.value.approveType = 0 |
| | | if (operationType.value === "add" || currentApproveStatus.value == 3) { |
| | | approveProcessAdd(form.value).then(res => { |
| | | showToast("æäº¤æå"); |
| | | goBack() |
| | | }) |
| | | } else { |
| | | approveProcessUpdate(form.value).then(res => { |
| | | showToast("æäº¤æå"); |
| | | goBack() |
| | | }) |
| | | } |
| | | // æå¨æ£æ¥å¿
å¡«åæ®µï¼é²æ¢å æ°æ®ç±»åé®é¢å¯¼è´çæ ¡éªå¤±è´¥ |
| | | if (!form.value.approveReason || !form.value.approveReason.trim()) { |
| | | showToast('请è¾å
¥ç³è¯·äºç±'); |
| | | return; |
| | | } |
| | | |
| | | if (!form.value.approveDeptId || String(form.value.approveDeptId).trim() === '') { |
| | | showToast('è¯·éæ©ç³è¯·é¨é¨'); |
| | | return; |
| | | } |
| | | |
| | | if (!form.value.approveTime) { |
| | | showToast('è¯·éæ©ç³è¯·æ¥æ'); |
| | | return; |
| | | } |
| | | |
| | | formRef.value.validate().then((valid) => { |
| | | if (valid) { |
| | | // è¡¨åæ ¡éªéè¿ï¼å¯ä»¥æäº¤æ°æ® |
| | | // æ¶éææèç¹ç审æ¹äººid |
| | | console.log('approverNodes---', approverNodes.value) |
| | | form.value.approveUserIds = approverNodes.value.map(node => node.userId).join(',') |
| | | form.value.approveType = 0 |
| | | if (operationType.value === "add" || currentApproveStatus.value == 3) { |
| | | approveProcessAdd(form.value).then(res => { |
| | | showToast("æäº¤æå"); |
| | | goBack() |
| | | }) |
| | | } else { |
| | | approveProcessUpdate(form.value).then(res => { |
| | | showToast("æäº¤æå"); |
| | | goBack() |
| | | }) |
| | | } |
| | | } |
| | | }).catch((error) => { |
| | | console.error("è¡¨åæ ¡éªå¤±è´¥:", error); |
| | | // æ¾ç¤ºå
·ä½çéè¯¯ä¿¡æ¯ |
| | | if (error.length > 0) { |
| | | const firstError = error[0]; |
| | | uni.showToast({ |
| | | title: firstError.message || 'è¡¨åæ ¡éªå¤±è´¥', |
| | | icon: 'none' |
| | | }); |
| | | } else { |
| | | uni.showToast({ |
| | | title: 'è¡¨åæ ¡éªå¤±è´¥ï¼è¯·æ£æ¥å¿
填项', |
| | | icon: 'none' |
| | | }); |
| | | // å°è¯è·åå
·ä½çéè¯¯åæ®µ |
| | | if (error && error.errors) { |
| | | const firstError = error.errors[0]; |
| | | if (firstError) { |
| | | uni.showToast({ |
| | | title: firstError.message || 'è¡¨åæ ¡éªå¤±è´¥ï¼è¯·æ£æ¥å¿
填项', |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | } |
| | | } |
| | | // æ¾ç¤ºéç¨éè¯¯ä¿¡æ¯ |
| | | uni.showToast({ |
| | | title: 'è¡¨åæ ¡éªå¤±è´¥ï¼è¯·æ£æ¥å¿
填项', |
| | | icon: 'none' |
| | | }); |
| | | }); |
| | | }; |
| | | |
| | |
| | | } |
| | | |
| | | // ç¡®è®¤æ¥æéæ© |
| | | const onDateConfirm = ({ selectedValues }) => { |
| | | form.value.approveTime = selectedValues.join('-') |
| | | currentDate.value = selectedValues |
| | | showDate.value = false |
| | | const onDateConfirm = (e) => { |
| | | form.value.approveTime = formatDateToYMD(e.value) |
| | | currentDate.value = formatDateToYMD(e.value) |
| | | showDate.value = false; |
| | | } |
| | | // è·åå½åæ¥æå¹¶æ ¼å¼å为 YYYY-MM-DD |
| | | function getCurrentDate() { |
| | |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .account-detail { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | padding-bottom: 80px; |
| | | } |
| | | |
| | | .header { |
| | | display: flex; |
| | | align-items: center; |
| | | background: #fff; |
| | | padding: 16px 20px; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | position: sticky; |
| | | top: 0; |
| | | z-index: 100; |
| | | } |
| | | |
| | | .title { |
| | | flex: 1; |
| | | text-align: center; |
| | | font-size: 18px; |
| | | font-weight: 600; |
| | | color: #333; |
| | | } |
| | | |
| | | .form-section { |
| | | margin-top: 16px; |
| | | } |
| | | @import '@/static/scss/form-common.scss'; |
| | | |
| | | .approval-process { |
| | | background: #fff; |
| | |
| | | <text class="item-id">{{ item.approveId }}</text> |
| | | </view> |
| | | <view class="item-tag"> |
| | | <van-tag :type="getTagClass(item.approveStatus)" size="medium">{{ formatReceiptType(item.approveStatus) }}</van-tag> |
| | | <u-tag :type="getTagClass(item.approveStatus)">{{ formatReceiptType(item.approveStatus) }}</u-tag> |
| | | </view> |
| | | </view> |
| | | <up-divider></up-divider> |
| | |
| | | </view> |
| | | <view class="detail-row"> |
| | | <view class="actions"> |
| | | <van-button |
| | | <u-button |
| | | type="primary" |
| | | size="small" |
| | | class="action-btn edit" |
| | |
| | | @click="handleItemClick(item)" |
| | | > |
| | | ç¼è¾ |
| | | </van-button> |
| | | <van-button |
| | | </u-button> |
| | | <u-button |
| | | type="success" |
| | | size="small" |
| | | class="action-btn approve" |
| | |
| | | @click="approve(item)" |
| | | > |
| | | å®¡æ ¸ |
| | | </van-button> |
| | | </u-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | |
| | | } else if (type == 4) { |
| | | return "primary"; |
| | | } else { |
| | | return "danger"; |
| | | return "error"; |
| | | } |
| | | }; |
| | | |
| | |
| | | .action-btn.approve { |
| | | /* success æ ·å¼æ¥èªç»ä»¶ï¼è¿éä¿çé©å以便åç»éè¦æ©å± */ |
| | | } |
| | | :deep(.van-floating-bubble) { |
| | | background: #ed8d05; |
| | | } |
| | | /* 已移é¤vantç»ä»¶çæ ·å¼å¼ç¨ */ |
| | | </style> |
| | |
| | | <PageHeader title="设å¤å°è´¦è¯¦æ
" @back="goBack" /> |
| | | |
| | | <!-- 表åå
容 --> |
| | | <u-form @submit="sendForm" ref="formRef" label-width="110" input-align="right" error-message-align="right"> |
| | | <u-form @submit="sendForm" ref="formRef" :rules="formRules" label-width="110"> |
| | | <!-- åºæ¬ä¿¡æ¯ --> |
| | | <u-cell-group title="åºæ¬ä¿¡æ¯"> |
| | | <u-form-item label="设å¤åç§°" prop="deviceName" required border-bottom> |
| | |
| | | <u-form-item label="è§æ ¼åå·" prop="deviceModel" required border-bottom> |
| | | <u-input |
| | | v-model="form.deviceModel" |
| | | :disabled="(form.deviceModel != null && operationType === 'edit')" |
| | | placeholder="请è¾å
¥è§æ ¼åå·" |
| | | clearable |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="设å¤ç¼å·" prop="deviceNumber" required border-bottom> |
| | | <u-form-item label="设å¤åç" prop="deviceBrand" required border-bottom> |
| | | <u-input |
| | | v-model="form.deviceNumber" |
| | | placeholder="请è¾å
¥è®¾å¤ç¼å·" |
| | | v-model="form.deviceBrand" |
| | | placeholder="请è¾å
¥è®¾å¤åç" |
| | | clearable |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="è´ä¹°æ¥æ" prop="purchaseDate" required border-bottom> |
| | | <u-form-item label="ä¾åºå" prop="supplierName" required border-bottom> |
| | | <u-input |
| | | v-model="form.purchaseDate" |
| | | placeholder="è¯·éæ©è´ä¹°æ¥æ" |
| | | readonly |
| | | @click="showDatePicker" |
| | | clearable |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="è´ä¹°ä»·æ ¼" prop="purchasePrice" required border-bottom> |
| | | <u-input |
| | | v-model="form.purchasePrice" |
| | | type="number" |
| | | placeholder="请è¾å
¥è´ä¹°ä»·æ ¼" |
| | | clearable |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="ä¾åºå" prop="supplier" required border-bottom> |
| | | <u-input |
| | | v-model="form.supplier" |
| | | v-model="form.supplierName" |
| | | placeholder="请è¾å
¥ä¾åºå" |
| | | clearable |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="使ç¨é¨é¨" prop="department" required border-bottom> |
| | | <u-form-item label="åæ¾ä½ç½®" prop="storageLocation" required border-bottom> |
| | | <u-input |
| | | v-model="form.department" |
| | | placeholder="请è¾å
¥ä½¿ç¨é¨é¨" |
| | | v-model="form.storageLocation" |
| | | placeholder="请è¾å
¥åæ¾ä½ç½®" |
| | | clearable |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="ç¨ç" prop="taxRate" required border-bottom> |
| | | <u-form-item label="åä½" prop="unit" required border-bottom> |
| | | <u-input |
| | | v-model="form.unit" |
| | | placeholder="请è¾å
¥åä½" |
| | | clearable |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="å¯ç¨ææ§" prop="enableDepreciation" required border-bottom> |
| | | <u-switch |
| | | v-model="form.enableDepreciation" |
| | | :active-value="true" |
| | | :inactive-value="false" |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="æ°é" prop="number" required border-bottom> |
| | | <u-input |
| | | v-model="form.number" |
| | | type="number" |
| | | placeholder="请è¾å
¥æ°é" |
| | | clearable |
| | | @blur="mathNum" |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="å«ç¨åä»·" prop="taxIncludingPriceUnit" required border-bottom> |
| | | <u-input |
| | | v-model="form.taxIncludingPriceUnit" |
| | | type="number" |
| | | placeholder="请è¾å
¥å«ç¨åä»·" |
| | | clearable |
| | | @blur="mathNum" |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="å«ç¨æ»ä»·" prop="taxIncludingPriceTotal" required border-bottom> |
| | | <u-input |
| | | v-model="form.taxIncludingPriceTotal" |
| | | type="number" |
| | | placeholder="èªå¨çæ" |
| | | disabled |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="ç¨ç(%)" prop="taxRate" required border-bottom> |
| | | <u-input |
| | | v-model="form.taxRate" |
| | | placeholder="è¯·éæ©ç¨ç" |
| | | readonly |
| | | @click="showTaxRatePicker" |
| | | clearable |
| | | @click="showTaxRatePicker = true" |
| | | /> |
| | | <template #right> |
| | | <u-icon name="arrow-right" @click="showTaxRatePicker = true"></u-icon> |
| | | </template> |
| | | <up-action-sheet |
| | | :show="showTaxRatePicker" |
| | | :actions="taxRateActionList" |
| | | title="éæ©ç¨ç" |
| | | @select="onTaxRateSelect" |
| | | @close="showTaxRatePicker = false" |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="使ç¨ç¶æ" prop="status" required border-bottom> |
| | | <u-form-item label="ä¸å«ç¨æ»ä»·" prop="unTaxIncludingPriceTotal" required border-bottom> |
| | | <u-input |
| | | v-model="form.status" |
| | | placeholder="请è¾å
¥ä½¿ç¨ç¶æ" |
| | | clearable |
| | | v-model="form.unTaxIncludingPriceTotal" |
| | | type="number" |
| | | placeholder="èªå¨çæ" |
| | | disabled |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="夿³¨" border-bottom> |
| | | <u-textarea |
| | | v-model="form.remark" |
| | | placeholder="请è¾å
¥å¤æ³¨" |
| | | :maxlength="200" |
| | | count |
| | | :autoHeight="true" |
| | | <u-form-item label="å½å
¥æ¥æ" prop="createTime" required border-bottom> |
| | | <u-input |
| | | v-model="form.createTime" |
| | | placeholder="è¯·éæ©å½å
¥æ¥æ" |
| | | readonly |
| | | @click="showDatePicker" |
| | | clearable |
| | | /> |
| | | <template #right> |
| | | <u-icon name="arrow-right" @click="showDatePicker"></u-icon> |
| | | </template> |
| | | </u-form-item> |
| | | </u-cell-group> |
| | | |
| | | <!-- æäº¤æé® --> |
| | | <view class="footer-btns"> |
| | | <u-button class="cancel-btn" @click="goBack">åæ¶</u-button> |
| | | <u-button class="save-btn" type="primary" @click="sendForm" :loading="loading">ä¿å</u-button> |
| | | </view> |
| | | </u-form> |
| | | |
| | | <!-- æäº¤æé® --> |
| | | <view class="footer-btns"> |
| | | <u-button class="cancel-btn" @click="goBack">åæ¶</u-button> |
| | | <u-button class="save-btn" type="primary" @click="sendForm" :loading="loading">ä¿å</u-button> |
| | | </view> |
| | | </u-form> |
| | | |
| | | <!-- ç¨çéæ©å¨ --> |
| | | <u-popup v-model="showTaxRate" mode="bottom"> |
| | | <u-picker |
| | | v-model="taxRatePickerValue" |
| | | :columns="taxRateOptions" |
| | | @confirm="onTaxRateConfirm" |
| | | @cancel="showTaxRate = false" |
| | | /> |
| | | </u-popup> |
| | | |
| | | <!-- æ¥æéæ©å¨ --> |
| | | <u-popup v-model="showDate" mode="bottom"> |
| | | <u-datetime-picker |
| | | v-model="currentDate" |
| | | title="éæ©æ¥æ" |
| | | <!-- æ¥æéæ©å¨ --> |
| | | <up-datetime-picker |
| | | :show="showDate" |
| | | v-model="pickerDateValue" |
| | | @confirm="onDateConfirm" |
| | | @cancel="showDate = false" |
| | | mode="date" |
| | | /> |
| | | </u-popup> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | |
| | | const formRef = ref(null); |
| | | const operationType = ref(''); |
| | | const loading = ref(false); |
| | | const showTaxRate = ref(false); |
| | | const taxRatePickerValue = ref([]); |
| | | const showDate = ref(false); |
| | | const currentDate = ref([new Date().getFullYear(), new Date().getMonth() + 1, new Date().getDate()]); |
| | | const pickerDateValue = ref(Date.now()); |
| | | const showTaxRatePicker = ref(false); |
| | | const taxRateActionList = ref([ |
| | | { name: '1', value: 1 }, |
| | | { name: '6', value: 6 }, |
| | | { name: '13', value: 13 } |
| | | ]); |
| | | |
| | | // 表åéªè¯è§å |
| | | const formRules = { |
| | | deviceName: [{ required: true, trigger: "blur", message: "请è¾å
¥" }], |
| | | deviceModel: [{ required: true, trigger: "blur", message: "请è¾å
¥" }], |
| | | deviceBrand: [{ required: true, trigger: "blur", message: "请è¾å
¥" }], |
| | | supplierName: [{ required: true, trigger: "blur", message: "请è¾å
¥" }], |
| | | storageLocation: [{ required: true, trigger: "blur", message: "请è¾å
¥" }], |
| | | unit: [{ required: true, trigger: "blur", message: "请è¾å
¥" }], |
| | | number: [{ required: true, trigger: "blur", message: "请è¾å
¥" }], |
| | | taxIncludingPriceUnit: [{ required: true, trigger: "blur", message: "请è¾å
¥" }], |
| | | taxRate: [{ required: true, trigger: "change", message: "请è¾å
¥" }], |
| | | createTime: [{ required: true, trigger: "change", message: "è¯·éæ©" }], |
| | | }; |
| | | |
| | | // ä½¿ç¨ ref 声æè¡¨åæ°æ® |
| | | const form = ref({ |
| | | deviceName: undefined, // 设å¤åç§° |
| | | deviceModel: undefined, // è§æ ¼åå· |
| | | deviceBrand: undefined, // 设å¤åç |
| | | supplierName: undefined, // ä¾åºå |
| | | storageLocation: undefined, // åæ¾ä½ç½® |
| | | unit: undefined, // åä½ |
| | | enableDepreciation: false, // å¯ç¨ææ§ |
| | | number: undefined, // æ°é |
| | | taxIncludingPriceUnit: undefined, // å«ç¨åä»· |
| | | taxIncludingPriceTotal: undefined, // å«ç¨æ»ä»· |
| | |
| | | createTime: dayjs().format("YYYY-MM-DD"), // å½å
¥æ¥æ |
| | | }); |
| | | |
| | | // ç¨çé项 |
| | | const taxRateOptions = computed(() => { |
| | | return [ |
| | | { text: '1', value: 1 }, |
| | | { text: '6', value: 6 }, |
| | | { text: '13', value: 13 } |
| | | ] |
| | | }); |
| | | |
| | | |
| | | // å è½½è¡¨åæ°æ® |
| | | const loadForm = async (id) => { |
| | |
| | | if (code == 200) { |
| | | form.value.deviceName = data.deviceName; |
| | | form.value.deviceModel = data.deviceModel; |
| | | form.value.deviceBrand = data.deviceBrand || ''; |
| | | form.value.supplierName = data.supplierName; |
| | | form.value.storageLocation = data.storageLocation || ''; |
| | | form.value.unit = data.unit; |
| | | form.value.enableDepreciation = !!data.enableDepreciation; |
| | | form.value.number = data.number; |
| | | form.value.taxIncludingPriceUnit = data.taxIncludingPriceUnit; |
| | | form.value.taxIncludingPriceTotal = data.taxIncludingPriceTotal; |
| | |
| | | form.value = { |
| | | deviceName: undefined, |
| | | deviceModel: undefined, |
| | | deviceBrand: undefined, |
| | | supplierName: undefined, |
| | | storageLocation: undefined, |
| | | unit: undefined, |
| | | enableDepreciation: false, |
| | | number: undefined, |
| | | taxIncludingPriceUnit: undefined, |
| | | taxIncludingPriceTotal: undefined, |
| | | taxRate: undefined, |
| | | unTaxIncludingPriceTotal: undefined, |
| | | createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), |
| | | createTime: dayjs().format("YYYY-MM-DD"), |
| | | }; |
| | | }; |
| | | |
| | |
| | | return options.id; |
| | | }; |
| | | |
| | | // æ¾ç¤ºç¨çéæ©å¨ |
| | | const showTaxRatePicker = () => { |
| | | showTaxRate.value = true; |
| | | }; |
| | | |
| | | |
| | | // 确认ç¨çéæ© |
| | | const onTaxRateConfirm = ({ selectedValues, selectedOptions }) => { |
| | | form.value.taxRate = selectedOptions[0].value; |
| | | taxRatePickerValue.value = selectedValues; |
| | | showTaxRate.value = false; |
| | | const onTaxRateConfirm = (e) => { |
| | | form.value.taxRate = e.value; |
| | | mathNum(); // éæ°è®¡ç® |
| | | }; |
| | | |
| | | // éæ©ç¨ç |
| | | const onTaxRateSelect = (e) => { |
| | | form.value.taxRate = e.value; |
| | | showTaxRatePicker.value = false; |
| | | mathNum(); // éæ°è®¡ç® |
| | | }; |
| | | |
| | |
| | | }; |
| | | |
| | | // ç¡®è®¤æ¥æéæ© |
| | | const onDateConfirm = ({ selectedValues }) => { |
| | | const onDateConfirm = (e) => { |
| | | // åªä¿åå¹´ææ¥ï¼ä¸å
嫿¶åç§ |
| | | form.value.createTime = selectedValues.join('-'); |
| | | currentDate.value = selectedValues; |
| | | const date = new Date(e.value); |
| | | form.value.createTime = date.getFullYear() + '-' + |
| | | String(date.getMonth() + 1).padStart(2, '0') + '-' + |
| | | String(date.getDate()).padStart(2, '0'); |
| | | showDate.value = false; |
| | | }; |
| | | |
| | |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import '@/static/scss/form-common.scss'; |
| | | .ledger-detail { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | |
| | | <PageHeader :title="operationType === 'edit' ? 'ç¼è¾æ¥ä¿®' : 'æ°å¢æ¥ä¿®'" @back="goBack" /> |
| | | |
| | | <!-- 表åå
容 --> |
| | | <van-form @submit="sendForm" ref="formRef" label-width="110px" input-align="right" error-message-align="right" scroll-to-error scroll-to-error-position="center"> |
| | | <u-form @submit="sendForm" ref="formRef" :rules="formRules" label-width="110" input-align="right" error-message-align="right"> |
| | | <!-- åºæ¬ä¿¡æ¯ --> |
| | | <van-cell-group title="åºæ¬ä¿¡æ¯" inset> |
| | | <van-field |
| | | v-model="deviceNameText" |
| | | label="设å¤åç§°" |
| | | placeholder="è¯·éæ©è®¾å¤åç§°" |
| | | :rules="formRules.deviceLedgerId" |
| | | required |
| | | readonly |
| | | @click="showDevicePicker" |
| | | clearable |
| | | > |
| | | <template #right-icon> |
| | | <van-icon name="scan" @click.stop="startScan" class="scan-icon" /> |
| | | <u-cell-group title="åºæ¬ä¿¡æ¯"> |
| | | <u-form-item label="设å¤åç§°" prop="deviceLedgerId" required border-bottom> |
| | | <u-input |
| | | v-model="deviceNameText" |
| | | placeholder="è¯·éæ©è®¾å¤åç§°" |
| | | @click="showDevicePicker" |
| | | clearable |
| | | /> |
| | | <template #right> |
| | | <u-icon name="scan" @click="startScan" class="scan-icon" /> |
| | | </template> |
| | | </van-field> |
| | | <van-field |
| | | v-model="form.deviceModel" |
| | | label="è§æ ¼åå·" |
| | | placeholder="请è¾å
¥è§æ ¼åå·" |
| | | readonly |
| | | clearable |
| | | /> |
| | | <van-field |
| | | v-model="form.repairTime" |
| | | label="æ¥ä¿®æ¥æ" |
| | | placeholder="è¯·éæ©æ¥ä¿®æ¥æ" |
| | | :rules="formRules.repairTime" |
| | | required |
| | | readonly |
| | | @click="showDatePicker" |
| | | clearable |
| | | /> |
| | | <van-field |
| | | v-model="form.repairName" |
| | | label="æ¥ä¿®äºº" |
| | | placeholder="请è¾å
¥æ¥ä¿®äºº" |
| | | :rules="formRules.repairName" |
| | | required |
| | | clearable |
| | | /> |
| | | <van-field |
| | | v-model="form.remark" |
| | | label="æ
éç°è±¡" |
| | | type="textarea" |
| | | rows="3" |
| | | placeholder="请è¾å
¥æ
éç°è±¡" |
| | | :rules="formRules.remark" |
| | | required |
| | | clearable |
| | | maxlength="200" |
| | | show-word-limit |
| | | /> |
| | | </van-cell-group> |
| | | </u-form-item> |
| | | <u-form-item label="è§æ ¼åå·" prop="deviceModel" border-bottom> |
| | | <u-input |
| | | v-model="form.deviceModel" |
| | | placeholder="请è¾å
¥è§æ ¼åå·" |
| | | clearable |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="æ¥ä¿®æ¥æ" prop="repairTime" required border-bottom> |
| | | <u-input |
| | | v-model="form.repairTime" |
| | | placeholder="è¯·éæ©æ¥ä¿®æ¥æ" |
| | | readonly |
| | | @click="showDatePicker" |
| | | clearable |
| | | /> |
| | | <template #right> |
| | | <u-icon name="arrow-right" @click="showDatePicker"></u-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="æ¥ä¿®äºº" prop="repairName" required border-bottom> |
| | | <u-input |
| | | v-model="form.repairName" |
| | | placeholder="请è¾å
¥æ¥ä¿®äºº" |
| | | clearable |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="æ
éç°è±¡" prop="remark" required border-bottom> |
| | | <u-textarea |
| | | v-model="form.remark" |
| | | rows="3" |
| | | placeholder="请è¾å
¥æ
éç°è±¡" |
| | | clearable |
| | | count |
| | | maxlength="200" |
| | | /> |
| | | </u-form-item> |
| | | </u-cell-group> |
| | | |
| | | <!-- æäº¤æé® --> |
| | | <view class="footer-btns"> |
| | | <van-button class="cancel-btn" @click="goBack">åæ¶</van-button> |
| | | <van-button class="save-btn" native-type="submit" form-type="submit" :loading="loading">ä¿å</van-button> |
| | | <u-button class="cancel-btn" @click="goBack">åæ¶</u-button> |
| | | <u-button class="save-btn" type="primary" @click="sendForm" :loading="loading">ä¿å</u-button> |
| | | </view> |
| | | </van-form> |
| | | </u-form> |
| | | |
| | | <!-- 设å¤éæ©å¨ --> |
| | | <van-popup v-model:show="showDevice" position="bottom"> |
| | | <van-picker |
| | | :model-value="devicePickerValue" |
| | | :columns="deviceColumns" |
| | | @confirm="onDeviceConfirm" |
| | | @cancel="showDevice = false" |
| | | /> |
| | | </van-popup> |
| | | <up-action-sheet |
| | | :show="showDevice" |
| | | :actions="deviceActionList" |
| | | title="éæ©è®¾å¤åç§°" |
| | | @select="onDeviceSelect" |
| | | @close="showDevice = false" |
| | | /> |
| | | |
| | | <!-- æ¥æéæ©å¨ --> |
| | | <van-popup v-model:show="showDate" position="bottom"> |
| | | <van-date-picker |
| | | v-model="currentDate" |
| | | title="éæ©æ¥æ" |
| | | @confirm="onDateConfirm" |
| | | @cancel="showDate = false" |
| | | /> |
| | | </van-popup> |
| | | <up-datetime-picker |
| | | :show="showDate" |
| | | v-model="pickerDateValue" |
| | | @confirm="onDateConfirm" |
| | | @cancel="showDate = false" |
| | | mode="date" |
| | | /> |
| | | </view> |
| | | </template> |
| | | |
| | |
| | | import { getDeviceLedger } from '@/api/equipmentManagement/ledger'; |
| | | import { addRepair, editRepair, getRepairById } from '@/api/equipmentManagement/repair'; |
| | | import dayjs from "dayjs"; |
| | | import { showToast } from 'vant'; |
| | | import { formatDateToYMD } from '@/utils/ruoyi'; |
| | | const showToast = (message) => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: 'none' |
| | | }) |
| | | } |
| | | |
| | | defineOptions({ |
| | | name: "è®¾å¤æ¥ä¿®è¡¨å", |
| | |
| | | const operationType = ref('add'); |
| | | const loading = ref(false); |
| | | const showDevice = ref(false); |
| | | const devicePickerValue = ref([]); |
| | | const showDate = ref(false); |
| | | const currentDate = ref([new Date().getFullYear(), new Date().getMonth() + 1, new Date().getDate()]); |
| | | const pickerDateValue = ref(Date.now()); |
| | | |
| | | // 设å¤é项 |
| | | const deviceOptions = ref([]); |
| | | const deviceNameText = ref(''); |
| | | const deviceActionList = computed(() => { |
| | | return deviceOptions.value.map(item => ({ |
| | | name: item.deviceName, |
| | | value: item.id |
| | | })); |
| | | }); |
| | | |
| | | // æ«ç ç¸å
³ç¶æ |
| | | const isScanning = ref(false); |
| | |
| | | repairTime: dayjs().format("YYYY-MM-DD"), // æ¥ä¿®æ¥æ |
| | | repairName: undefined, // æ¥ä¿®äºº |
| | | remark: undefined, // æ
éç°è±¡ |
| | | }); |
| | | |
| | | // 设å¤éæ©å¨å |
| | | const deviceColumns = computed(() => { |
| | | return deviceOptions.value.map(item => ({ |
| | | text: item.deviceName, |
| | | value: item.id |
| | | })); |
| | | }); |
| | | |
| | | // å 载设å¤å表 |
| | |
| | | }; |
| | | |
| | | // 确认设å¤éæ© |
| | | const onDeviceConfirm = ({ selectedValues, selectedOptions }) => { |
| | | form.value.deviceLedgerId = selectedOptions[0].value; |
| | | devicePickerValue.value = selectedValues; |
| | | const onDeviceSelect = (e) => { |
| | | form.value.deviceLedgerId = e.value; |
| | | setDeviceModel(e.value); |
| | | showDevice.value = false; |
| | | setDeviceModel(selectedOptions[0].value); |
| | | }; |
| | | |
| | | // æ¾ç¤ºæ¥æéæ©å¨ |
| | |
| | | }; |
| | | |
| | | // ç¡®è®¤æ¥æéæ© |
| | | const onDateConfirm = ({ selectedValues }) => { |
| | | form.value.repairTime = selectedValues.join('-'); |
| | | currentDate.value = selectedValues; |
| | | const onDateConfirm = (e) => { |
| | | form.value.repairTime = formatDateToYMD(e.value); |
| | | showDate.value = false; |
| | | }; |
| | | |
| | |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import '@/static/scss/form-common.scss'; |
| | | .repair-add { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | |
| | | <text class="item-id">设å¤åç§°ï¼{{ item.deviceName }}</text> |
| | | </view> |
| | | <view class="status-tag"> |
| | | <van-tag v-if="item.status === 1" type="success">å®ç»</van-tag> |
| | | <van-tag v-if="item.status === 0" type="danger">å¾
ç»´ä¿®</van-tag> |
| | | <u-tag v-if="item.status === 1" type="success">å®ç»</u-tag> |
| | | <u-tag v-if="item.status === 0" type="error">å¾
ç»´ä¿®</u-tag> |
| | | </view> |
| | | </view> |
| | | <up-divider></up-divider> |
| | |
| | | |
| | | <!-- æé®åºå --> |
| | | <view class="action-buttons"> |
| | | <van-button |
| | | <u-button |
| | | type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | @click="edit(item.id)" |
| | | > |
| | | ç¼è¾ |
| | | </van-button> |
| | | <van-button |
| | | </u-button> |
| | | <u-button |
| | | type="warning" |
| | | size="small" |
| | | class="action-btn" |
| | |
| | | @click="addMaintain(item.id)" |
| | | > |
| | | æ°å¢ç»´ä¿® |
| | | </van-button> |
| | | <van-button |
| | | type="danger" |
| | | </u-button> |
| | | <u-button |
| | | type="error" |
| | | size="small" |
| | | plain |
| | | class="action-btn" |
| | | @click="delRepairByIds(item.id)" |
| | | > |
| | | å é¤ |
| | | </van-button> |
| | | </u-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | |
| | | <view v-else class="no-data"> |
| | | <text>ææ è®¾å¤æ¥ä¿®æ°æ®</text> |
| | | </view> |
| | | |
| | | <!-- æµ®å¨æ°æ³¡æé® --> |
| | | <van-floating-bubble |
| | | axis="xy" |
| | | icon="plus" |
| | | @click="addRepair" |
| | | /> |
| | | <!-- æµ®å¨æä½æé® --> |
| | | <view class="fab-button" @click="addRepair"> |
| | | <up-icon name="plus" size="24" color="#ffffff"></up-icon> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | |
| | | import PageHeader from '@/components/PageHeader.vue' |
| | | import { getRepairPage, delRepair } from '@/api/equipmentManagement/repair' |
| | | import useUserStore from "@/store/modules/user" |
| | | import { showToast } from 'vant'; |
| | | |
| | | const showToast = (message) => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: 'none' |
| | | }) |
| | | } |
| | | |
| | | const userStore = useUserStore() |
| | | |
| | |
| | | .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> |
| | |
| | | <PageHeader title="æ°å¢ç»´ä¿®" @back="goBack" /> |
| | | |
| | | <!-- 表åå
容 --> |
| | | <van-form @submit="sendForm" ref="formRef" label-width="110px" input-align="right" error-message-align="right" scroll-to-error scroll-to-error-position="center"> |
| | | <u-form ref="formRef" :model="form" :rules="formRules" label-width="140rpx"> |
| | | <!-- åºæ¬ä¿¡æ¯ --> |
| | | <van-cell-group title="维修信æ¯" inset> |
| | | <van-field |
| | | v-model="form.maintenanceName" |
| | | label="维修人" |
| | | placeholder="请è¾å
¥ç»´ä¿®äºº" |
| | | :rules="formRules.maintenanceName" |
| | | required |
| | | clearable |
| | | /> |
| | | <van-field |
| | | v-model="form.maintenanceResult" |
| | | label="ç»´ä¿®ç»æ" |
| | | type="textarea" |
| | | rows="3" |
| | | placeholder="请è¾å
¥ç»´ä¿®ç»æ" |
| | | :rules="formRules.maintenanceResult" |
| | | required |
| | | clearable |
| | | maxlength="200" |
| | | show-word-limit |
| | | /> |
| | | <van-field |
| | | v-model="form.maintenanceTime" |
| | | label="ç»´ä¿®æ¥æ" |
| | | placeholder="è¯·éæ©ç»´ä¿®æ¥æ" |
| | | :rules="formRules.maintenanceTime" |
| | | required |
| | | readonly |
| | | @click="showDatePicker" |
| | | clearable |
| | | /> |
| | | </van-cell-group> |
| | | <u-cell-group title="维修信æ¯" inset> |
| | | <u-form-item prop="maintenanceName" label="维修人" required> |
| | | <u-input |
| | | v-model="form.maintenanceName" |
| | | placeholder="请è¾å
¥ç»´ä¿®äºº" |
| | | clearable |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item prop="maintenanceResult" label="ç»´ä¿®ç»æ" required> |
| | | <u-input |
| | | v-model="form.maintenanceResult" |
| | | type="textarea" |
| | | rows="3" |
| | | placeholder="请è¾å
¥ç»´ä¿®ç»æ" |
| | | clearable |
| | | maxlength="200" |
| | | show-word-limit |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="ç»´ä¿®æ¥æ" prop="maintenanceTime" required border-bottom> |
| | | <u-input |
| | | v-model="form.maintenanceTime" |
| | | placeholder="è¯·éæ©ç»´ä¿®æ¥æ" |
| | | readonly |
| | | @click="showDatePicker = true" |
| | | clearable |
| | | /> |
| | | <template #right> |
| | | <u-icon name="arrow-right" @click="showDatePicker = true"></u-icon> |
| | | </template> |
| | | </u-form-item> |
| | | </u-cell-group> |
| | | |
| | | <!-- æäº¤æé® --> |
| | | <view class="footer-btns"> |
| | | <van-button class="cancel-btn" @click="goBack">åæ¶</van-button> |
| | | <van-button class="save-btn" native-type="submit" form-type="submit" :loading="loading">ä¿å</van-button> |
| | | <u-button class="cancel-btn" @click="goBack">åæ¶</u-button> |
| | | <u-button class="save-btn" @click="submitForm" :loading="loading">ä¿å</u-button> |
| | | </view> |
| | | </van-form> |
| | | </u-form> |
| | | |
| | | <!-- æ¥æéæ©å¨ --> |
| | | <van-popup v-model:show="showDate" position="bottom"> |
| | | <van-date-picker |
| | | v-model="currentDate" |
| | | title="éæ©æ¥æ" |
| | | @confirm="onDateConfirm" |
| | | @cancel="showDate = false" |
| | | /> |
| | | </van-popup> |
| | | <up-datetime-picker |
| | | :show="showDatePicker" |
| | | v-model="pickerDateValue" |
| | | mode="date" |
| | | title="éæ©æ¥æ" |
| | | @confirm="onDateConfirm" |
| | | /> |
| | | </view> |
| | | </template> |
| | | |
| | |
| | | import { addMaintain } from '@/api/equipmentManagement/repair'; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import dayjs from "dayjs"; |
| | | import { showToast } from 'vant'; |
| | | import { formatDateToYMD } from '@/utils/ruoyi' |
| | | |
| | | defineOptions({ |
| | | name: "设å¤ç»´ä¿®è¡¨å", |
| | |
| | | // 表åå¼ç¨ |
| | | const formRef = ref(null); |
| | | const loading = ref(false); |
| | | const showDate = ref(false); |
| | | const currentDate = ref([new Date().getFullYear(), new Date().getMonth() + 1, new Date().getDate()]); |
| | | const showDatePicker = ref(false); |
| | | const pickerDateValue = ref(Date.now());; // ä½¿ç¨æ¶é´æ³ |
| | | |
| | | // 表åéªè¯è§å |
| | | const formRules = { |
| | |
| | | maintenanceTime: dayjs().format("YYYY-MM-DD"), // ç»´ä¿®æ¥æï¼åªæ¾ç¤ºæ¥æï¼ |
| | | }); |
| | | |
| | | // èªå®ä¹showToast彿° |
| | | const showToast = (message) => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: 'none' |
| | | }) |
| | | }; |
| | | |
| | | // æ¸
é¤è¡¨åæ ¡éªç¶æ |
| | | const clearValidate = () => { |
| | | // Vant4ä¸ä¸éè¦æå¨æ¸
é¤éªè¯ç¶æï¼éç½®è¡¨åæ¶ä¼èªå¨æ¸
é¤ |
| | | // formRef.value?.clearValidate(); // å é¤è¿è¡ |
| | | // uview-plusä¸éè¦æå¨æ¸
é¤éªè¯ç¶æï¼éç½®è¡¨åæ¶ä¼èªå¨æ¸
é¤ |
| | | }; |
| | | |
| | | // éç½®è¡¨åæ°æ®åæ ¡éªç¶æ |
| | |
| | | |
| | | const resetFormAndValidate = () => { |
| | | resetForm(); |
| | | // clearValidate(); // å é¤è¿è¡ï¼Vant4ä¼èªå¨å¤ç |
| | | }; |
| | | |
| | | // æäº¤è¡¨å |
| | | const sendForm = async () => { |
| | | const submitForm = async () => { |
| | | try { |
| | | // 使ç¨Vant4çæ£ç¡®éªè¯æ¹å¼ |
| | | formRef.value?.validate().then(() => { |
| | | // éªè¯éè¿ |
| | | // 使ç¨uview-plusç表åéªè¯æ¹å¼ |
| | | const valid = await formRef.value.validate(); |
| | | if (valid) { |
| | | submitFormData(); |
| | | }).catch((errors) => { |
| | | // éªè¯å¤±è´¥ |
| | | showToast('请填å宿´ä¿¡æ¯'); |
| | | }); |
| | | } |
| | | } catch (e) { |
| | | showToast('表åéªè¯å¤±è´¥'); |
| | | } |
| | |
| | | return options.id; |
| | | }; |
| | | |
| | | // æ¾ç¤ºæ¥æéæ©å¨ |
| | | const showDatePicker = () => { |
| | | showDate.value = true; |
| | | }; |
| | | |
| | | // ç¡®è®¤æ¥æéæ© |
| | | const onDateConfirm = ({ selectedValues }) => { |
| | | // åªä¿åå¹´ææ¥ï¼ä¸å
嫿¶åç§ |
| | | form.value.maintenanceTime = selectedValues.join('-'); |
| | | currentDate.value = selectedValues; |
| | | showDate.value = false; |
| | | const onDateConfirm = (e) => { |
| | | form.value.maintenanceTime = formatDateToYMD(e.value) |
| | | pickerDateValue.value = formatDateToYMD(e.value) |
| | | showDatePicker.value = false; |
| | | }; |
| | | |
| | | // åå§åè¡¨åæ°æ® |
| | |
| | | form.value.maintenanceName = userStore.nickName || ''; |
| | | // 设置å½åæ¥æï¼åªå
å«å¹´ææ¥ï¼ |
| | | form.value.maintenanceTime = dayjs().format('YYYY-MM-DD'); |
| | | currentDate.value = [new Date().getFullYear(), new Date().getMonth() + 1, new Date().getDate()]; |
| | | }; |
| | | |
| | | onShow(() => { |
| | |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import '@/static/scss/form-common.scss'; |
| | | .repair-maintain { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | |
| | | <PageHeader :title="operationType === 'edit' ? 'ç¼è¾ä¿å
»è®¡å' : 'æ°å¢ä¿å
»è®¡å'" @back="goBack" /> |
| | | |
| | | <!-- 表åå
容 --> |
| | | <van-form @submit="sendForm" ref="formRef" label-width="110px" input-align="right" error-message-align="right" scroll-to-error scroll-to-error-position="center"> |
| | | <u-form ref="formRef" :model="form" :rules="formRules" label-width="110px"> |
| | | <!-- åºæ¬ä¿¡æ¯ --> |
| | | <van-cell-group title="åºæ¬ä¿¡æ¯" inset> |
| | | <van-field |
| | | v-model="deviceNameText" |
| | | label="设å¤åç§°" |
| | | <u-form-item label="设å¤åç§°" prop="deviceNameText" required border-bottom> |
| | | <u-input |
| | | v-model="form.deviceNameText" |
| | | placeholder="è¯·éæ©è®¾å¤åç§°" |
| | | :rules="formRules.deviceLedgerId" |
| | | required |
| | | readonly |
| | | @click="showDevicePicker" |
| | | clearable |
| | | > |
| | | <template #right-icon> |
| | | <van-icon name="scan" @click.stop="startScan" class="scan-icon" /> |
| | | </template> |
| | | </van-field> |
| | | <van-field |
| | | /> |
| | | <template #right> |
| | | <u-icon name="scan" @click="startScan" class="scan-icon" /> |
| | | </template> |
| | | </u-form-item> |
| | | |
| | | <u-form-item label="è§æ ¼åå·" prop="deviceModel" border-bottom> |
| | | <u-input |
| | | v-model="form.deviceModel" |
| | | label="è§æ ¼åå·" |
| | | placeholder="请è¾å
¥è§æ ¼åå·" |
| | | readonly |
| | | clearable |
| | | /> |
| | | <van-field |
| | | </u-form-item> |
| | | |
| | | <u-form-item label="计åä¿å
»æ¥æ" prop="maintenancePlanTime" required border-bottom> |
| | | <u-input |
| | | v-model="form.maintenancePlanTime" |
| | | label="计åä¿å
»æ¥æ" |
| | | placeholder="è¯·éæ©è®¡åä¿å
»æ¥æ" |
| | | :rules="formRules.maintenancePlanTime" |
| | | required |
| | | readonly |
| | | @click="showDatePicker" |
| | | clearable |
| | | /> |
| | | </van-cell-group> |
| | | <template #right> |
| | | <u-icon name="arrow-right" @click="showDatePicker" /> |
| | | </template> |
| | | </u-form-item> |
| | | |
| | | <!-- æäº¤æé® --> |
| | | <view class="footer-btns"> |
| | | <van-button class="cancel-btn" @click="goBack">åæ¶</van-button> |
| | | <van-button class="save-btn" native-type="submit" form-type="submit" :loading="loading">ä¿å</van-button> |
| | | <u-button class="cancel-btn" @click="goBack">åæ¶</u-button> |
| | | <u-button class="save-btn" @click="sendForm" :loading="loading">ä¿å</u-button> |
| | | </view> |
| | | </van-form> |
| | | </u-form> |
| | | |
| | | <!-- 设å¤éæ©å¨ --> |
| | | <van-popup v-model:show="showDevice" position="bottom"> |
| | | <van-picker |
| | | :model-value="devicePickerValue" |
| | | :columns="deviceColumns" |
| | | @confirm="onDeviceConfirm" |
| | | @cancel="showDevice = false" |
| | | /> |
| | | </van-popup> |
| | | |
| | | <!-- æ¥æéæ©å¨ --> |
| | | <van-popup v-model:show="showDate" position="bottom"> |
| | | <van-date-picker |
| | | v-model="currentDate" |
| | | title="éæ©æ¥æ" |
| | | @confirm="onDateConfirm" |
| | | @cancel="showDate = false" |
| | | /> |
| | | </van-popup> |
| | | <up-action-sheet |
| | | :show="showDevice" |
| | | :actions="deviceActions" |
| | | title="éæ©è®¾å¤" |
| | | @select="onDeviceConfirm" |
| | | @close="showDevice = false" |
| | | /> |
| | | <up-datetime-picker |
| | | :show="showDate" |
| | | v-model="pickerDateValue" |
| | | @confirm="onDateConfirm" |
| | | @cancel="showDate = false" |
| | | mode="date" |
| | | /> |
| | | |
| | | </view> |
| | | </template> |
| | | |
| | |
| | | import { getDeviceLedger } from '@/api/equipmentManagement/ledger'; |
| | | import { addUpkeep, editUpkeep, getUpkeepById } from '@/api/equipmentManagement/upkeep'; |
| | | import dayjs from "dayjs"; |
| | | import { formatDateToYMD } from '@/utils/ruoyi'; |
| | | |
| | | defineOptions({ |
| | | name: "设å¤ä¿å
»è®¡å表å", |
| | | }); |
| | | const showToast = (message) => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: 'none' |
| | | }) |
| | | } |
| | | |
| | | // 表åå¼ç¨ |
| | | const formRef = ref(null); |
| | | const operationType = ref('add'); |
| | | const loading = ref(false); |
| | | const showDevice = ref(false); |
| | | const devicePickerValue = ref([]); |
| | | const showDate = ref(false); |
| | | const pickerDateValue = ref(Date.now()); |
| | | const currentDate = ref([new Date().getFullYear(), new Date().getMonth() + 1, new Date().getDate()]); |
| | | |
| | | // 设å¤é项 |
| | | const deviceOptions = ref([]); |
| | | const deviceNameText = ref(''); |
| | | // 转æ¢ä¸º action-sheet éè¦çæ ¼å¼ |
| | | const deviceActions = computed(() => { |
| | | return deviceOptions.value.map(item => ({ |
| | | text: item.deviceName, |
| | | value: item.id, |
| | | data: item |
| | | })); |
| | | }); |
| | | |
| | | // æ«ç ç¸å
³ç¶æ |
| | | const isScanning = ref(false); |
| | |
| | | maintenancePlanTime: dayjs().format("YYYY-MM-DD"), // 计åä¿å
»æ¥æ |
| | | }); |
| | | |
| | | // 设å¤éæ©å¨å |
| | | const deviceColumns = computed(() => { |
| | | return deviceOptions.value.map(item => ({ |
| | | text: item.deviceName, |
| | | value: item.id |
| | | })); |
| | | }); |
| | | |
| | | // å 载设å¤å表 |
| | | const loadDeviceName = async () => { |
| | | try { |
| | |
| | | deviceOptions.value = data || []; |
| | | } catch (e) { |
| | | showToast('è·å设å¤å表失败'); |
| | | } |
| | | }; |
| | | |
| | | // 设置设å¤è§æ ¼åå· |
| | | const setDeviceModel = (id) => { |
| | | const option = deviceOptions.value.find((item) => item.id === id); |
| | | if (option) { |
| | | form.value.deviceModel = option.deviceModel; |
| | | deviceNameText.value = option.deviceName; |
| | | } |
| | | }; |
| | | |
| | |
| | | // 设置设å¤åç§°æ¾ç¤º |
| | | const device = deviceOptions.value.find(item => item.id === data.deviceLedgerId); |
| | | if (device) { |
| | | deviceNameText.value = device.deviceName; |
| | | form.value.deviceNameText = device.deviceName; |
| | | } |
| | | } |
| | | } catch (e) { |
| | |
| | | // æ°å¢æ¨¡å¼ |
| | | operationType.value = 'add'; |
| | | } |
| | | }; |
| | | |
| | | // æ¸
é¤è¡¨åæ ¡éªç¶æ |
| | | const clearValidate = () => { |
| | | formRef.value?.clearValidate(); |
| | | }; |
| | | |
| | | // éç½®è¡¨åæ°æ®åæ ¡éªç¶æ |
| | | const resetForm = () => { |
| | | form.value = { |
| | | deviceLedgerId: undefined, |
| | | deviceModel: undefined, |
| | | maintenancePlanTime: dayjs().format("YYYY-MM-DD"), |
| | | }; |
| | | deviceNameText.value = ''; |
| | | }; |
| | | |
| | | const resetFormAndValidate = () => { |
| | | resetForm(); |
| | | clearValidate(); |
| | | }; |
| | | |
| | | // æ«æäºç»´ç åè½ |
| | |
| | | if (matchedDevice) { |
| | | // æ¾å°å¹é
ç设å¤ï¼èªå¨å¡«å
|
| | | form.value.deviceLedgerId = matchedDevice.id; |
| | | deviceNameText.value = matchedDevice.deviceName; |
| | | form.value.deviceNameText = matchedDevice.deviceName; |
| | | form.value.deviceModel = matchedDevice.deviceModel; |
| | | showToast('设å¤ä¿¡æ¯å·²èªå¨å¡«å
'); |
| | | } else { |
| | |
| | | }; |
| | | |
| | | // 确认设å¤éæ© |
| | | const onDeviceConfirm = ({ selectedValues, selectedOptions }) => { |
| | | form.value.deviceLedgerId = selectedOptions[0].value; |
| | | devicePickerValue.value = selectedValues; |
| | | const onDeviceConfirm = (selected) => { |
| | | // selected è¿åçæ¯éä¸é¡¹ |
| | | form.value.deviceLedgerId = selected.value; |
| | | form.value.deviceNameText = selected.name; |
| | | const selectedDevice = deviceOptions.value.find(item => item.id === selected.value); |
| | | if (selectedDevice) { |
| | | form.value.deviceModel = selectedDevice.deviceModel; |
| | | } |
| | | showDevice.value = false; |
| | | setDeviceModel(selectedOptions[0].value); |
| | | }; |
| | | |
| | | // æ¾ç¤ºæ¥æéæ©å¨ |
| | |
| | | }; |
| | | |
| | | // ç¡®è®¤æ¥æéæ© |
| | | const onDateConfirm = ({ selectedValues }) => { |
| | | form.value.maintenancePlanTime = selectedValues.join('-'); |
| | | currentDate.value = selectedValues; |
| | | const onDateConfirm = (e) => { |
| | | form.value.maintenancePlanTime = formatDateToYMD(e.value); |
| | | showDate.value = false; |
| | | }; |
| | | |
| | |
| | | const sendForm = async () => { |
| | | try { |
| | | // æå¨éªè¯è¡¨å |
| | | await formRef.value?.validate(); |
| | | const valid = await formRef.value.validate(); |
| | | if (!valid) return; |
| | | |
| | | loading.value = true; |
| | | const id = getPageId(); |
| | |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import '@/static/scss/form-common.scss'; |
| | | .upkeep-add { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | |
| | | <text class="item-id">设å¤åç§°ï¼{{ item.deviceName }}</text> |
| | | </view> |
| | | <view class="status-tag"> |
| | | <van-tag v-if="item.status === 1" type="success">å®ç»</van-tag> |
| | | <van-tag v-if="item.status === 0" type="danger">å¾
ä¿å
»</van-tag> |
| | | <u-tag v-if="item.status === 1" type="success">å®ç»</u-tag> |
| | | <u-tag v-if="item.status === 0" type="error">å¾
ä¿å
»</u-tag> |
| | | </view> |
| | | </view> |
| | | <up-divider></up-divider> |
| | |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ä¿å
ȍȾ</text> |
| | | <view class="detail-value"> |
| | | <van-tag v-if="item.maintenanceResult === 1" type="success"> |
| | | å®å¥½ |
| | | </van-tag> |
| | | <van-tag v-if="item.maintenanceResult === 0" type="danger"> |
| | | ç»´ä¿® |
| | | </van-tag> |
| | | <text v-if="item.maintenanceResult === undefined || item.maintenanceResult === null">-</text> |
| | | </view> |
| | | <u-tag v-if="item.maintenanceResult === 1" type="success"> |
| | | å®å¥½ |
| | | </u-tag> |
| | | <u-tag v-if="item.maintenanceResult === 0" type="error"> |
| | | ç»´ä¿® |
| | | </u-tag> |
| | | <text v-if="item.maintenanceResult === undefined || item.maintenanceResult === null">-</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- æé®åºå --> |
| | | <view class="action-buttons"> |
| | | <van-button |
| | | <u-button |
| | | type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.status === 1" |
| | | @click.stop="edit(item.id)" |
| | | > |
| | | ç¼è¾ |
| | | </van-button> |
| | | <van-button |
| | | </u-button> |
| | | <u-button |
| | | type="warning" |
| | | size="small" |
| | | class="action-btn" |
| | |
| | | @click.stop="addMaintain(item.id)" |
| | | > |
| | | ä¿å
» |
| | | </van-button> |
| | | <van-button |
| | | type="danger" |
| | | </u-button> |
| | | <u-button |
| | | type="error" |
| | | size="small" |
| | | plain |
| | | class="action-btn" |
| | | @click.stop="delUpkeepByIds(item.id)" |
| | | > |
| | | å é¤ |
| | | </van-button> |
| | | </u-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | |
| | | <text>ææ è®¾å¤ä¿å
»æ°æ®</text> |
| | | </view> |
| | | |
| | | <!-- æµ®å¨æ°æ³¡æé® --> |
| | | <van-floating-bubble |
| | | axis="xy" |
| | | icon="plus" |
| | | @click="addPlan" |
| | | /> |
| | | <!-- æµ®å¨æ°å¢æé® --> |
| | | <view class="fab-button" @click="addPlan"> |
| | | <up-icon name="plus" size="24" color="#ffffff"></up-icon> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | |
| | | import PageHeader from '@/components/PageHeader.vue' |
| | | import { getUpkeepPage, delUpkeep } from '@/api/equipmentManagement/upkeep' |
| | | import useUserStore from "@/store/modules/user" |
| | | import { showToast } from 'vant'; |
| | | // æ¾ç¤ºæç¤ºä¿¡æ¯ |
| | | const showToast = (message) => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: 'none' |
| | | }) |
| | | }; |
| | | import dayjs from "dayjs" |
| | | |
| | | const userStore = useUserStore() |
| | |
| | | .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; |
| | | } |
| | | </style> |
| | |
| | | <PageHeader title="æ°å¢ä¿å
»" @back="goBack" /> |
| | | |
| | | <!-- 表åå
容 --> |
| | | <van-form @submit="sendForm" ref="formRef" label-width="110px" input-align="right" error-message-align="right" scroll-to-error scroll-to-error-position="center"> |
| | | <u-form ref="formRef" :model="form" :rules="formRules" label-width="110px" :error-type="['message']"> |
| | | <!-- åºæ¬ä¿¡æ¯ --> |
| | | <van-cell-group title="ä¿å
»ä¿¡æ¯" inset> |
| | | <van-field |
| | | <u-form-item label="å®é
ä¿å
»äºº" prop="maintenanceActuallyName" required border-bottom> |
| | | <u-input |
| | | v-model="form.maintenanceActuallyName" |
| | | label="å®é
ä¿å
»äºº" |
| | | placeholder="请è¾å
¥å®é
ä¿å
»äºº" |
| | | :rules="formRules.maintenanceActuallyName" |
| | | required |
| | | clearable |
| | | /> |
| | | <van-field |
| | | </u-form-item> |
| | | |
| | | <u-form-item label="å®é
ä¿å
»æ¥æ" prop="maintenanceActuallyTime" required border-bottom> |
| | | <u-input |
| | | v-model="form.maintenanceActuallyTime" |
| | | label="å®é
ä¿å
»æ¥æ" |
| | | placeholder="è¯·éæ©å®é
ä¿å
»æ¥æ" |
| | | :rules="formRules.maintenanceActuallyTime" |
| | | required |
| | | readonly |
| | | @click="showDatePicker" |
| | | clearable |
| | | /> |
| | | <van-field |
| | | <template #right> |
| | | <u-icon name="arrow-right" @click.stop="showDatePicker" /> |
| | | </template> |
| | | </u-form-item> |
| | | |
| | | <u-form-item label="ä¿å
ȍȾ" prop="maintenanceResult" required border-bottom> |
| | | <u-input |
| | | v-model="maintenanceResultText" |
| | | label="ä¿å
ȍȾ" |
| | | placeholder="è¯·éæ©ä¿å
ȍȾ" |
| | | :rules="formRules.maintenanceResult" |
| | | required |
| | | readonly |
| | | @click="showResultPicker" |
| | | clearable |
| | | /> |
| | | </van-cell-group> |
| | | <template #right> |
| | | <u-icon name="arrow-right" @click.stop="showResultPicker" /> |
| | | </template> |
| | | </u-form-item> |
| | | |
| | | <!-- æäº¤æé® --> |
| | | <view class="footer-btns"> |
| | | <van-button class="cancel-btn" @click="goBack">åæ¶</van-button> |
| | | <van-button class="save-btn" native-type="submit" form-type="submit" :loading="loading">ä¿å</van-button> |
| | | <u-button class="cancel-btn" @click="goBack">åæ¶</u-button> |
| | | <u-button class="save-btn" @click="sendForm" :loading="loading">ä¿å</u-button> |
| | | </view> |
| | | </van-form> |
| | | </u-form> |
| | | |
| | | <!-- æ¥æéæ©å¨ --> |
| | | <van-popup v-model:show="showDate" position="bottom"> |
| | | <van-date-picker |
| | | v-model="currentDate" |
| | | <u-popup v-model="showDate" mode="bottom" :closeable="true"> |
| | | <u-datetime-picker |
| | | v-model="form.maintenanceActuallyTime" |
| | | mode="date" |
| | | title="éæ©æ¥æ" |
| | | @confirm="onDateConfirm" |
| | | @cancel="showDate = false" |
| | | /> |
| | | </van-popup> |
| | | </u-popup> |
| | | |
| | | <!-- ä¿å
»ç»æéæ©å¨ --> |
| | | <van-popup v-model:show="showResult" position="bottom"> |
| | | <van-picker |
| | | :model-value="resultPickerValue" |
| | | <u-popup v-model="showResult" mode="bottom" :closeable="true"> |
| | | <view class="popup-title">éæ©ä¿å
ȍȾ</view> |
| | | <u-picker |
| | | v-model="resultPickerValue" |
| | | :columns="resultColumns" |
| | | @confirm="onResultConfirm" |
| | | @cancel="showResult = false" |
| | | /> |
| | | </van-popup> |
| | | </u-popup> |
| | | </view> |
| | | </template> |
| | | |
| | |
| | | import { addMaintenance } from '@/api/equipmentManagement/upkeep'; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import dayjs from "dayjs"; |
| | | import { showToast } from 'vant'; |
| | | import { formatDateToYMD } from '@/utils/ruoyi'; |
| | | |
| | | // æ¾ç¤ºæç¤ºä¿¡æ¯ |
| | | const showToast = (message) => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: 'none' |
| | | }) |
| | | }; |
| | | |
| | | defineOptions({ |
| | | name: "设å¤ä¿å
»è¡¨å", |
| | |
| | | |
| | | // æ¸
é¤è¡¨åæ ¡éªç¶æ |
| | | const clearValidate = () => { |
| | | // Vant4ä¸ä¸éè¦æå¨æ¸
é¤éªè¯ç¶æï¼éç½®è¡¨åæ¶ä¼èªå¨æ¸
é¤ |
| | | // formRef.value?.clearValidate(); // å é¤è¿è¡ |
| | | // uview-plusä¸éè¦æå¨æ¸
é¤éªè¯ç¶æï¼éç½®è¡¨åæ¶ä¼èªå¨æ¸
é¤ |
| | | }; |
| | | |
| | | // éç½®è¡¨åæ°æ®åæ ¡éªç¶æ |
| | |
| | | // æäº¤è¡¨å |
| | | const sendForm = async () => { |
| | | try { |
| | | // 使ç¨Vant4çæ£ç¡®éªè¯æ¹å¼ |
| | | formRef.value?.validate().then(() => { |
| | | // éªè¯éè¿ |
| | | submitFormData(); |
| | | }).catch((errors) => { |
| | | // éªè¯å¤±è´¥ |
| | | showToast('请填å宿´ä¿¡æ¯'); |
| | | }); |
| | | // 使ç¨uview-plusç表åéªè¯æ¹å¼ |
| | | const valid = await formRef.value.validate(); |
| | | if (!valid) return; |
| | | // éªè¯éè¿ |
| | | submitFormData(); |
| | | } catch (e) { |
| | | showToast('表åéªè¯å¤±è´¥'); |
| | | } |
| | |
| | | }; |
| | | |
| | | // ç¡®è®¤æ¥æéæ© |
| | | const onDateConfirm = ({ selectedValues }) => { |
| | | const onDateConfirm = (e) => { |
| | | // åªä¿åå¹´ææ¥ï¼ä¸å
嫿¶åç§ |
| | | form.value.maintenanceActuallyTime = selectedValues.join('-'); |
| | | currentDate.value = selectedValues; |
| | | form.value.maintenanceActuallyTime = formatDateToYMD(e.value); |
| | | showDate.value = false; |
| | | }; |
| | | |
| | |
| | | }; |
| | | |
| | | // 确认ä¿å
»ç»æéæ© |
| | | const onResultConfirm = ({ selectedValues, selectedOptions }) => { |
| | | form.value.maintenanceResult = selectedOptions[0].value; |
| | | maintenanceResultText.value = selectedOptions[0].text; |
| | | resultPickerValue.value = selectedValues; |
| | | const onResultConfirm = ({ selectedIndex, selectedValue, selectedLabel }) => { |
| | | form.value.maintenanceResult = selectedValue; |
| | | maintenanceResultText.value = selectedLabel; |
| | | resultPickerValue.value = selectedValue; |
| | | showResult.value = false; |
| | | }; |
| | | |
| | |
| | | <template> |
| | | <view class="content"> |
| | | <view class="content"> |
| | | <view class="header-section"> |
| | | <view class="currentFactory"> |
| | | <up-text type="primary" :text="userStore.currentFactoryName" @click="show = true" size="18" |
| | | class="factoryName" suffixIcon="arrow-right" :iconStyle="iconStyle"></up-text> |
| | | class="factoryName" suffixIcon="arrow-right" :iconStyle="iconStyle"></up-text> |
| | | </view> |
| | | <up-picker :show="show" :columns="factoryList" @confirm="changeFactory" @cancel="show = false"></up-picker> |
| | | </view> |
| | |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- <view class="notice-section">--> |
| | | <!-- <view class="notice">--> |
| | | <!-- <view class="notice-content">--> |
| | | <!-- <view class="notice-left">--> |
| | | <!-- <text class="notice-status">éç¥</text>--> |
| | | <!-- </view>--> |
| | | <!-- <view class="notice-separator"></view>--> |
| | | <!-- <view class="notice-right">--> |
| | | <!-- <text class="notice-label">{{currentStatus}}</text>--> |
| | | <!-- <text class="notice-text">彿¥éå®è®¾å¤æ°:<text class="notice-number">{{number}}<text class="notice-unit">个</text></text></text>--> |
| | | <!-- </view>--> |
| | | <!-- </view>--> |
| | | <!-- </view>--> |
| | | <!-- </view>--> |
| | | <!-- <view class="notice-section">--> |
| | | <!-- <view class="notice">--> |
| | | <!-- <view class="notice-content">--> |
| | | <!-- <view class="notice-left">--> |
| | | <!-- <text class="notice-status">éç¥</text>--> |
| | | <!-- </view>--> |
| | | <!-- <view class="notice-separator"></view>--> |
| | | <!-- <view class="notice-right">--> |
| | | <!-- <text class="notice-label">{{currentStatus}}</text>--> |
| | | <!-- <text class="notice-text">彿¥éå®è®¾å¤æ°:<text class="notice-number">{{number}}<text class="notice-unit">个</text></text></text>--> |
| | | <!-- </view>--> |
| | | <!-- </view>--> |
| | | <!-- </view>--> |
| | | <!-- </view>--> |
| | | |
| | | <!-- è¥éç®¡çæ¨¡å --> |
| | | <view class="common-module marketing-module"> |
| | |
| | | </up-grid> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | |
| | | right: 0; |
| | | bottom: 0; |
| | | background: radial-gradient(circle at 20% 80%, rgba(41, 121, 255, 0.02) 0%, transparent 50%), |
| | | radial-gradient(circle at 80% 20%, rgba(156, 39, 176, 0.02) 0%, transparent 50%); |
| | | radial-gradient(circle at 80% 20%, rgba(156, 39, 176, 0.02) 0%, transparent 50%); |
| | | pointer-events: none; |
| | | z-index: -1; |
| | | } |
| | |
| | | |
| | | |
| | | @keyframes shine { |
| | | 0% { |
| | | transform: translateX(-100%) translateY(-100%) rotate(45deg); |
| | | 0% { |
| | | transform: translateX(-100%) translateY(-100%) rotate(45deg); |
| | | } |
| | | 100% { |
| | | transform: translateX(100%) translateY(100%) rotate(45deg); |
| | | 100% { |
| | | transform: translateX(100%) translateY(100%) rotate(45deg); |
| | | } |
| | | } |
| | | |
| | |
| | | <template> |
| | | <view class="normal-login-container"> |
| | | <view class="logo-content"> |
| | | <text>è´¦å·å¯ç ç»å½</text> |
| | | </view> |
| | | <view class="login-form-content"> |
| | | <view class="input-item flex align-center"> |
| | | <view class="normal-login-container"> |
| | | <view class="logo-content"> |
| | | <text>è´¦å·å¯ç ç»å½</text> |
| | | </view> |
| | | <view class="login-form-content"> |
| | | <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> |
| | | </view> |
| | | <view class="input-item flex align-center"> |
| | | </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> |
| | | </view> |
| | | </view> |
| | | <view class="input-item flex align-center select-container"> |
| | | <up-icon name="tags" size="18"></up-icon> |
| | | <up-picker-data |
| | |
| | | labelKey="name"> |
| | | </up-picker-data> |
| | | </view> |
| | | <view> |
| | | <button @click="handleLogin" class="login-btn cu-btn block bg-blue lg round">ç»å½</button> |
| | | </view> |
| | | </view> |
| | | <view> |
| | | <button @click="handleLogin" class="login-btn cu-btn block bg-blue lg round">ç»å½</button> |
| | | </view> |
| | | </view> |
| | | <!-- è®°ä½å¯ç é项 --> |
| | | <view class="remember-password"> |
| | | <up-checkbox |
| | |
| | | > |
| | | </up-checkbox> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | |
| | | const useWxLogin = ref(false); // æ¯å¦ä½¿ç¨å¾®ä¿¡ç»å½ |
| | | const rememberPassword = ref(false); // è®°ä½å¯ç |
| | | const loginForm = ref({ |
| | | username: "", |
| | | password: "", |
| | | username: "", |
| | | password: "", |
| | | factoryId: "", |
| | | currentFatoryName: "", |
| | | }); |
| | |
| | | |
| | | // ä¿åå¯ç å°æ¬å°åå¨ |
| | | function savePassword() { |
| | | if (rememberPassword.value) { |
| | | uni.setStorageSync('remembered_username', loginForm.value.username); |
| | | uni.setStorageSync('remembered_password', loginForm.value.password); |
| | | uni.setStorageSync('remember_password', true); |
| | | } else { |
| | | uni.removeStorageSync('remembered_username'); |
| | | uni.removeStorageSync('remembered_password'); |
| | | uni.setStorageSync('remember_password', false); |
| | | } |
| | | if (rememberPassword.value) { |
| | | uni.setStorageSync('remembered_username', loginForm.value.username); |
| | | uni.setStorageSync('remembered_password', loginForm.value.password); |
| | | uni.setStorageSync('remember_password', true); |
| | | } else { |
| | | uni.removeStorageSync('remembered_username'); |
| | | uni.removeStorageSync('remembered_password'); |
| | | uni.setStorageSync('remember_password', false); |
| | | } |
| | | } |
| | | |
| | | // 仿¬å°åå¨å è½½å¯ç |
| | | function loadPassword() { |
| | | const remembered = uni.getStorageSync('remember_password'); |
| | | if (remembered) { |
| | | rememberPassword.value = true; |
| | | const savedUsername = uni.getStorageSync('remembered_username'); |
| | | const savedPassword = uni.getStorageSync('remembered_password'); |
| | | if (savedUsername) { |
| | | loginForm.value.username = savedUsername; |
| | | } |
| | | if (savedPassword) { |
| | | loginForm.value.password = savedPassword; |
| | | } |
| | | } |
| | | const remembered = uni.getStorageSync('remember_password'); |
| | | if (remembered) { |
| | | rememberPassword.value = true; |
| | | const savedUsername = uni.getStorageSync('remembered_username'); |
| | | const savedPassword = uni.getStorageSync('remembered_password'); |
| | | if (savedUsername) { |
| | | loginForm.value.username = savedUsername; |
| | | } |
| | | if (savedPassword) { |
| | | loginForm.value.password = savedPassword; |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (useWxLogin.value) { |
| | | getWxCode().then(res => { |
| | | console.log(res); |
| | | wxLogin('miniapp',res).then(res => { |
| | | if(res.token != null){ |
| | | setToken(res.token); |
| | | loginSuccess() |
| | | } |
| | | }); |
| | | }) |
| | | getWxCode().then(res => { |
| | | console.log(res); |
| | | wxLogin('miniapp',res).then(res => { |
| | | if(res.token != null){ |
| | | setToken(res.token); |
| | | loginSuccess() |
| | | } |
| | | }); |
| | | }) |
| | | } |
| | | |
| | | function getUserLoginFacotryList() { |
| | |
| | | } |
| | | |
| | | async function handleLogin() { |
| | | if (loginForm.value.username === "") { |
| | | modal.msgError("请è¾å
¥æ¨çè´¦å·") |
| | | } else if (loginForm.value.password === "") { |
| | | modal.msgError("请è¾å
¥æ¨çå¯ç ") |
| | | } else if (loginForm.value.factoryId === "") { |
| | | modal.msgError("è¯·éæ©å
¬å¸") |
| | | } else { |
| | | modal.loading("ç»å½ä¸ï¼è¯·èå¿çå¾
...") |
| | | pwdLogin() |
| | | } |
| | | if (loginForm.value.username === "") { |
| | | modal.msgError("请è¾å
¥æ¨çè´¦å·") |
| | | } else if (loginForm.value.password === "") { |
| | | modal.msgError("请è¾å
¥æ¨çå¯ç ") |
| | | } else if (loginForm.value.factoryId === "") { |
| | | modal.msgError("è¯·éæ©å
¬å¸") |
| | | } else { |
| | | modal.loading("ç»å½ä¸ï¼è¯·èå¿çå¾
...") |
| | | pwdLogin() |
| | | } |
| | | }; |
| | | // å¯ç ç»å½ |
| | | async function pwdLogin() { |
| | | userStore.loginCheckFactory(loginForm.value).then(() => { |
| | | modal.closeLoading() |
| | | // ç»å½æååä¿åå¯ç |
| | | savePassword(); |
| | | loginSuccess() |
| | | }).catch(() => { |
| | | userStore.loginCheckFactory(loginForm.value).then(() => { |
| | | modal.closeLoading() |
| | | }) |
| | | // ç»å½æååä¿åå¯ç |
| | | savePassword(); |
| | | loginSuccess() |
| | | }).catch(() => { |
| | | modal.closeLoading() |
| | | }) |
| | | }; |
| | | |
| | | function loginSuccess(result) { |
| | | // è®¾ç½®ç¨æ·ä¿¡æ¯ |
| | | userStore.getInfo().then(res => { |
| | | uni.switchTab({ |
| | | url: '/pages/index' |
| | | }); |
| | | }) |
| | | // è®¾ç½®ç¨æ·ä¿¡æ¯ |
| | | userStore.getInfo().then(res => { |
| | | uni.switchTab({ |
| | | url: '/pages/index' |
| | | }); |
| | | }) |
| | | } |
| | | // 页é¢å è½½æ¶æ£æ¥æ¯å¦æä¿åçå¯ç |
| | | onMounted(() => { |
| | |
| | | |
| | | <style lang="scss"> |
| | | page { |
| | | background-color: #ffffff; |
| | | background-color: #ffffff; |
| | | } |
| | | |
| | | .normal-login-container { |
| | | width: 100%; |
| | | width: 100%; |
| | | height: 100vh; |
| | | |
| | | .logo-content { |
| | | width: 90%; |
| | | |
| | | .logo-content { |
| | | width: 90%; |
| | | font-weight: 400; |
| | | font-size: 30px; |
| | | color: #333333; |
| | | margin: 80px 0 0 30px; |
| | | |
| | | image { |
| | | border-radius: 4px; |
| | | } |
| | | |
| | | .title { |
| | | margin-left: 10px; |
| | | } |
| | | } |
| | | |
| | | image { |
| | | border-radius: 4px; |
| | | } |
| | | |
| | | .title { |
| | | margin-left: 10px; |
| | | } |
| | | } |
| | | .u-checkbox { |
| | | margin-left: 34px; |
| | | } |
| | | |
| | | .login-form-content { |
| | | text-align: center; |
| | | margin: 58px auto; |
| | | |
| | | .login-form-content { |
| | | text-align: center; |
| | | margin: 58px auto; |
| | | padding: 0 30px; |
| | | |
| | | |
| | | .input-item { |
| | | margin: 30px auto; |
| | | height: 45px; |
| | | |
| | | .icon { |
| | | font-size: 38rpx; |
| | | margin-left: 10px; |
| | | color: #999; |
| | | } |
| | | |
| | | .input { |
| | | width: 100%; |
| | | font-size: 14px; |
| | | line-height: 20px; |
| | | text-align: left; |
| | | padding-left: 15px; |
| | | } |
| | | } |
| | | margin: 30px auto; |
| | | height: 45px; |
| | | |
| | | .icon { |
| | | font-size: 38rpx; |
| | | margin-left: 10px; |
| | | color: #999; |
| | | } |
| | | |
| | | .input { |
| | | width: 100%; |
| | | font-size: 14px; |
| | | line-height: 20px; |
| | | text-align: left; |
| | | padding-left: 15px; |
| | | } |
| | | } |
| | | .select-container { |
| | | flex: 1; |
| | | border-bottom: 1px solid #e5e5e5; |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | .login-btn { |
| | | margin-top: 60px; |
| | | height: 50px; |
| | | |
| | | .login-btn { |
| | | margin-top: 60px; |
| | | height: 50px; |
| | | background: linear-gradient( 140deg, #00BAFF 0%, #006CFB 100%); |
| | | box-shadow: 0px 4px 10px 0px rgba(3,88,185,0.2); |
| | | border-radius: 40px 40px 40px 40px; |
| | | } |
| | | |
| | | .xieyi { |
| | | color: #333; |
| | | margin-top: 20px; |
| | | } |
| | | |
| | | .login-code { |
| | | height: 38px; |
| | | float: right; |
| | | |
| | | .login-code-img { |
| | | height: 38px; |
| | | position: absolute; |
| | | margin-left: 10px; |
| | | width: 200rpx; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .xieyi { |
| | | color: #333; |
| | | margin-top: 20px; |
| | | } |
| | | |
| | | .login-code { |
| | | height: 38px; |
| | | float: right; |
| | | |
| | | .login-code-img { |
| | | height: 38px; |
| | | position: absolute; |
| | | margin-left: 10px; |
| | | width: 200rpx; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | |
| | | <!-- 表åå
容 --> |
| | | <u-form @submit="submitForm" ref="formRef" label-width="110" input-align="right" error-message-align="right"> |
| | | <!-- åºæ¬ä¿¡æ¯ --> |
| | | <u-cell-group title="åºæ¬ä¿¡æ¯"> |
| | | <u-form-item label="éè´ååå·" prop="contractNo" required border-bottom> |
| | | <u-input v-model="form.contractNo" placeholder="请è¾å
¥éè´ååå·" clearable /> |
| | | <view class="form-section"> |
| | | <u-form-item label="éè´ååå·" prop="purchaseLedgerNo" required> |
| | | <u-input v-model="form.purchaseLedgerNo" placeholder="èªå¨å¡«å
" disabled /> |
| | | </u-form-item> |
| | | <u-form-item label="ä¾åºååç§°" prop="supplierName" required border-bottom> |
| | | <u-input v-model="form.supplierName" placeholder="请è¾å
¥ä¾åºååç§°" clearable /> |
| | | <u-form-item label="éå®ååå·" prop="salesContractNo" required> |
| | | <u-input v-model="form.salesContractNo" placeholder="èªå¨å¡«å
" disabled /> |
| | | </u-form-item> |
| | | <u-form-item label="å票å·" prop="invoiceNo" required border-bottom> |
| | | <u-input v-model="form.invoiceNo" placeholder="请è¾å
¥å票å·" clearable /> |
| | | <u-form-item label="ä¾åºååç§°" prop="supplierName" required> |
| | | <u-input v-model="form.supplierName" placeholder="èªå¨å¡«å
" disabled /> |
| | | </u-form-item> |
| | | <u-form-item label="å票éé¢" prop="invoiceAmount" required border-bottom> |
| | | <u-input v-model="form.invoiceAmount" type="number" placeholder="请è¾å
¥å票éé¢" clearable /> |
| | | <u-form-item label="项ç®åç§°" prop="projectName" required> |
| | | <u-input v-model="form.projectName" placeholder="èªå¨å¡«å
" disabled /> |
| | | </u-form-item> |
| | | <u-form-item label="ç¨ç" prop="taxRate" required border-bottom> |
| | | <u-input v-model="form.taxRate" placeholder="请è¾å
¥ç¨ç" clearable /> |
| | | <u-form-item label="å票å·" prop="invoiceNumber" required> |
| | | <u-input v-model="form.invoiceNumber" placeholder="请è¾å
¥" clearable /> |
| | | </u-form-item> |
| | | <u-form-item label="å¼ç¥¨æ¥æ" prop="issueDate" required border-bottom> |
| | | <u-input v-model="form.issueDate" placeholder="è¯·éæ©å¼ç¥¨æ¥æ" readonly @click="showIssueDatePicker = true" clearable /> |
| | | <u-form-item label="å票éé¢(å
)" prop="invoiceAmount" required> |
| | | <u-input v-model="form.invoiceAmount" type="number" placeholder="èªå¨å¡«å
" disabled /> |
| | | </u-form-item> |
| | | <u-form-item label="å½å
¥äºº" border-bottom> |
| | | <u-input v-model="form.recorder" placeholder="èªå¨å¡«å
" readonly /> |
| | | <u-form-item label="å½å
¥äºº"> |
| | | <u-input v-model="form.issUer" placeholder="èªå¨å¡«å
" disabled /> |
| | | </u-form-item> |
| | | <u-form-item label="å建æ¶é´" border-bottom> |
| | | <u-input v-model="form.createTime" placeholder="è¯·éæ©å建æ¶é´" readonly @click="showCreateTimePicker = true" clearable /> |
| | | <u-form-item |
| | | label="å¼ç¥¨æ¥æ" |
| | | prop="entryDate" |
| | | required |
| | | @click="showEntryDatePicker = true" |
| | | > |
| | | <u-input |
| | | v-model="form.entryDate" |
| | | placeholder="è¯·éæ©å¼ç¥¨æ¥æ" |
| | | readonly |
| | | @click="showEntryDatePicker = true" |
| | | /> |
| | | <template #right> |
| | | <u-icon name="arrow-right" @click="showEntryDatePicker = true"></u-icon> |
| | | </template> |
| | | </u-form-item> |
| | | </u-cell-group> |
| | | |
| | | <!-- 产åä¿¡æ¯ --> |
| | | <view class="product-section" v-if="!productData || productData.length === 0"> |
| | | <u-empty description="ææ äº§åæ°æ®" /> |
| | | <u-form-item |
| | | label="å½å
¥æ¥æ" |
| | | prop="enterDate" |
| | | required |
| | | @click="showEnterDatePicker = true" |
| | | > |
| | | <u-input |
| | | v-model="form.enterDate" |
| | | placeholder="è¯·éæ©å½å
¥æ¥æ" |
| | | readonly |
| | | @click="showEnterDatePicker = true" |
| | | /> |
| | | <template #right> |
| | | <u-icon name="arrow-right" @click="showEnterDatePicker = true"></u-icon> |
| | | </template> |
| | | </u-form-item> |
| | | </view> |
| | | |
| | | <!-- 产åå表 --> |
| | | <view class="product-list" v-if="productData && productData.length > 0"> |
| | | <view class="product-card" v-for="(product, idx) in productData" :key="idx"> |
| | | <view class="product-header"> |
| | | <view class="product-title"> |
| | | <u-icon name="file-text" color="#2979ff" size="15" /> |
| | | <text class="product-name">产å {{ idx + 1 }}</text> |
| | | </view> |
| | | <!-- 产åä¿¡æ¯ --> |
| | | <view class="product-section"> |
| | | <view class="section-header"> |
| | | <view> |
| | | <text class="section-title">产åä¿¡æ¯</text> |
| | | </view> |
| | | |
| | | <!-- 产åä¿¡æ¯è¡¨å --> |
| | | <view class="product-form"> |
| | | <u-form-item label="产ååç§°" border-bottom> |
| | | <u-input v-model="product.productName" placeholder="请è¾å
¥äº§ååç§°" /> |
| | | </u-form-item> |
| | | <u-form-item label="è§æ ¼åå·" border-bottom> |
| | | <u-input v-model="product.specification" placeholder="请è¾å
¥è§æ ¼åå·" /> |
| | | </u-form-item> |
| | | <u-form-item label="åä½" border-bottom> |
| | | <u-input v-model="product.unit" placeholder="请è¾å
¥åä½" /> |
| | | </u-form-item> |
| | | <u-form-item label="æ°é" border-bottom> |
| | | <u-input v-model="product.quantity" type="number" placeholder="请è¾å
¥æ°é" /> |
| | | </u-form-item> |
| | | <u-form-item label="åä»·" border-bottom> |
| | | <u-input v-model="product.unitPrice" type="number" placeholder="请è¾å
¥åä»·" /> |
| | | </u-form-item> |
| | | <u-form-item label="éé¢" border-bottom> |
| | | <u-input v-model="product.amount" type="number" placeholder="请è¾å
¥éé¢" /> |
| | | </u-form-item> |
| | | <u-form-item label="ç¨ç" border-bottom> |
| | | <u-input v-model="product.taxRate" placeholder="请è¾å
¥ç¨ç" /> |
| | | </u-form-item> |
| | | <u-form-item label="ç¨é¢" border-bottom> |
| | | <u-input v-model="product.taxAmount" type="number" placeholder="请è¾å
¥ç¨é¢" /> |
| | | </u-form-item> |
| | | <u-form-item label="å«ç¨éé¢" border-bottom> |
| | | <u-input v-model="product.totalAmount" type="number" placeholder="请è¾å
¥å«ç¨éé¢" /> |
| | | </u-form-item> |
| | | <u-form-item label="夿³¨" border-bottom> |
| | | <u-textarea v-model="product.remark" placeholder="请è¾å
¥å¤æ³¨" :maxlength="200" count :autoHeight="true" /> |
| | | </u-form-item> |
| | | </view> |
| | | |
| | | <view v-if="!productData || productData.length === 0" class="empty-state"> |
| | | <view class="empty-text">ææ äº§åæ°æ®</view> |
| | | </view> |
| | | |
| | | <view v-else class="product-list"> |
| | | <view |
| | | v-for="(item, index) in productData" |
| | | :key="index" |
| | | class="product-card" |
| | | > |
| | | <!-- 产åå¤´é¨ --> |
| | | <view class="product-header"> |
| | | <view class="product-title"> |
| | | <view class="document-icon"> |
| | | <u-icon name="file-text" size="16" color="#ffffff"></u-icon> |
| | | </view> |
| | | <text class="product-productCategory">产å {{ index + 1 }}</text> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 产åä¿¡æ¯è¡¨å --> |
| | | <view class="product-form"> |
| | | <u-form-item label="产å大类" prop="productCategory" border-bottom> |
| | | <u-input v-model="item.productCategory" placeholder="" disabled /> |
| | | </u-form-item> |
| | | <u-form-item label="è§æ ¼åå·" prop="specificationModel" border-bottom> |
| | | <u-input v-model="item.specificationModel" placeholder="" disabled /> |
| | | </u-form-item> |
| | | <u-form-item label="åä½" prop="unit" border-bottom> |
| | | <u-input v-model="item.unit" placeholder="" disabled /> |
| | | </u-form-item> |
| | | <u-form-item label="æ°é" prop="quantity" border-bottom> |
| | | <u-input v-model="item.quantity" placeholder="" disabled /> |
| | | </u-form-item> |
| | | <u-form-item label="ç¨ç(%)" prop="taxRate" border-bottom> |
| | | <u-input v-model="item.taxRate" placeholder="" disabled /> |
| | | </u-form-item> |
| | | <u-form-item label="å½å
¥æ¥æ" prop="registerDate" border-bottom> |
| | | <u-input v-model="item.registerDate" placeholder="" disabled /> |
| | | </u-form-item> |
| | | <u-form-item label="å«ç¨åä»·(å
)" prop="taxInclusiveUnitPrice" border-bottom> |
| | | <u-input v-model="item.taxInclusiveUnitPrice" placeholder="" disabled /> |
| | | </u-form-item> |
| | | <u-form-item label="å«ç¨æ»ä»·(å
)" prop="taxInclusiveTotalPrice" border-bottom> |
| | | <u-input v-model="item.taxInclusiveTotalPrice" placeholder="" disabled /> |
| | | </u-form-item> |
| | | <u-form-item label="ä¸å«ç¨æ»ä»·(å
)" prop="taxExclusiveTotalPrice" border-bottom> |
| | | <u-input v-model="item.taxExclusiveTotalPrice" placeholder="" disabled /> |
| | | </u-form-item> |
| | | |
| | | <!-- æ¬æ¬¡æ¥ç¥¨ä¿¡æ¯ --> |
| | | <u-form-item label="æ¬æ¬¡æ¥ç¥¨æ°" prop="ticketsNum" border-bottom> |
| | | <u-input |
| | | v-model="item.ticketsNum" |
| | | type="number" |
| | | placeholder="请è¾å
¥æ¥ç¥¨æ°é" |
| | | @blur="invoiceNumBlur(item)" |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="æ¬æ¬¡æ¥ç¥¨éé¢(å
)" prop="ticketsAmount" border-bottom> |
| | | <u-input |
| | | v-model="item.ticketsAmount" |
| | | type="number" |
| | | placeholder="请è¾å
¥æ¥ç¥¨éé¢" |
| | | @blur="invoiceAmountBlur(item)" |
| | | /> |
| | | </u-form-item> |
| | | |
| | | <!-- æªæ¥ç¥¨ä¿¡æ¯ --> |
| | | <u-form-item label="æªæ¥ç¥¨æ°" prop="futureTickets" border-bottom> |
| | | <u-input v-model="item.futureTickets" placeholder="" disabled /> |
| | | </u-form-item> |
| | | <u-form-item label="æªæ¥ç¥¨éé¢(å
)" prop="futureTicketsAmount" border-bottom> |
| | | <u-input v-model="item.futureTicketsAmount" placeholder="" disabled /> |
| | | </u-form-item> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- æäº¤æé® --> |
| | | <view class="footer-btns"> |
| | | <u-button class="cancel-btn" @click="goBack">åæ¶</u-button> |
| | | <u-button class="save-btn" type="primary" @click="submitForm">ä¿å</u-button> |
| | | </view> |
| | | <!-- 使ç¨FooterButtonsç»ä»¶ --> |
| | | <FooterButtons |
| | | @cancel="goBack" |
| | | @confirm="submitForm" |
| | | :loading="submitting" |
| | | /> |
| | | |
| | | <!-- 为åºé¨æé®çåºç©ºé´ --> |
| | | <view style="height: 80px;"></view> |
| | | </u-form> |
| | | |
| | | <!-- å¼ç¥¨æ¥æéæ©å¨ --> |
| | | <u-popup v-model="showIssueDatePicker" mode="bottom"> |
| | | <u-popup :show="showEntryDatePicker" mode="bottom" @close="showEntryDatePicker = false"> |
| | | <u-datetime-picker |
| | | v-model="issueDateValue" |
| | | title="éæ©å¼ç¥¨æ¥æ" |
| | | @confirm="onIssueDateConfirm" |
| | | @cancel="showIssueDatePicker = false" |
| | | :show="true" |
| | | v-model="entryDateValue" |
| | | @confirm="onEntryDateConfirm" |
| | | @cancel="showEntryDatePicker = false" |
| | | mode="date" |
| | | /> |
| | | </u-popup> |
| | | |
| | | <!-- å建æ¶é´éæ©å¨ --> |
| | | <u-popup v-model="showCreateTimePicker" mode="bottom"> |
| | | <!-- å½å
¥æ¥æéæ©å¨ --> |
| | | <u-popup :show="showEnterDatePicker" mode="bottom" @close="showEnterDatePicker = false"> |
| | | <u-datetime-picker |
| | | v-model="createTimeValue" |
| | | title="éæ©å建æ¶é´" |
| | | @confirm="onCreateTimeConfirm" |
| | | @cancel="showCreateTimePicker = false" |
| | | :show="true" |
| | | v-model="enterDateValue" |
| | | @confirm="onEnterDateConfirm" |
| | | @cancel="showEnterDatePicker = false" |
| | | mode="date" |
| | | /> |
| | | </u-popup> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | // æ¿æ¢ Vant ç toast æ¹æ³ |
| | | // import { showToast, showLoadingToast, closeToast } from 'vant' |
| | | |
| | | // æ¿æ¢ toast æ¹æ³ |
| | | import { ref, onMounted } from 'vue' |
| | | import FooterButtons from '@/components/FooterButtons.vue' |
| | | const showToast = (message) => { |
| | | uni.showToast({ |
| | | title: message, |
| | |
| | | const closeToast = () => { |
| | | uni.hideLoading() |
| | | } |
| | | import useUserStore from '@/store/modules/user' |
| | | import {addOrUpdateRegistration, getPurchaseNoById} from "@/api/procurementManagement/invoiceEntry"; |
| | | import {getInfo} from "@/api/procurementManagement/invoiceEntry.js"; |
| | | import { formatDateToYMD } from '@/utils/ruoyi' |
| | | |
| | | const userStore = useUserStore() |
| | | const editData = ref(null); |
| | | |
| | | // 表åå¼ç¨ |
| | | const formRef = ref() |
| | | |
| | | // è¡¨åæ°æ® |
| | | let form = ref({ |
| | | purchaseLedgerNo: '', |
| | | salesContractNo: '', |
| | | supplierName: '', |
| | | projectName: '', |
| | | issUer: '', |
| | | entryDate: '', |
| | | enterDate: '', |
| | | invoiceAmount: '', |
| | | invoiceNumber: '', |
| | | fileIds: [] |
| | | }) |
| | | |
| | | // äº§åæ°æ® |
| | | const productData = ref([]) |
| | | |
| | | // æä»¶ä¸ä¼ ç¸å
³ |
| | | const action = ref('/dev-api/common/upload') |
| | | const getToken = () => { |
| | | return userStore.token || '' |
| | | } |
| | | |
| | | // æ¥æéæ©å¨ç¶æ |
| | | const showEntryDatePicker = ref(false) |
| | | const showEnterDatePicker = ref(false) |
| | | const entryDateValue = ref(Date.now()) |
| | | const enterDateValue = ref(Date.now()) |
| | | |
| | | // æäº¤ç¶æ |
| | | const submitting = ref(false) |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | // æ¸
çæ¬å°åå¨çæ°æ® |
| | | uni.removeStorageSync('editData'); |
| | | uni.navigateBack() |
| | | } |
| | | |
| | | // æ ¼å¼åæ°å |
| | | const formatNumber = (value, precision = 2) => { |
| | | if (!value && value !== 0) return '0.00' |
| | | return Number(value).toFixed(precision) |
| | | } |
| | | |
| | | // æ´æ°æªæ¥ç¥¨æ°æ® |
| | | const updateFutureTicketData = (row) => { |
| | | const totalQuantity = parseFloat(row.quantity) || 0 |
| | | const currentTicketNum = parseFloat(row.ticketsNum) || 0 |
| | | const totalAmount = parseFloat(row.taxInclusiveTotalPrice) || 0 |
| | | const currentTicketAmount = parseFloat(row.ticketsAmount) || 0 |
| | | |
| | | row.futureTickets = Math.max(0, totalQuantity - currentTicketNum).toFixed(2) |
| | | row.futureTicketsAmount = Math.max(0, totalAmount - currentTicketAmount).toFixed(2) |
| | | } |
| | | |
| | | // æ¥ç¥¨æ°éååå¤ç |
| | | const invoiceNumBlur = (row) => { |
| | | if (!row.ticketsNum || row.ticketsNum === "") { |
| | | row.ticketsNum = 0; |
| | | } |
| | | if (Number(row.ticketsNum) > Number(row.tempFutureTickets)) { |
| | | showToast("æ¬æ¬¡å¼ç¥¨æ°ä¸å¾å¤§äºæªå¼ç¥¨æ°"); |
| | | row.ticketsNum = 0; |
| | | return; |
| | | } |
| | | // è®¡ç®æ¬æ¬¡æ¥ç¥¨éé¢ |
| | | row.ticketsAmount = row.ticketsNum * row.taxInclusiveUnitPrice; |
| | | // è®¡ç®æªæ¥ç¥¨æ° |
| | | row.futureTickets = row.tempFutureTickets - row.ticketsNum; |
| | | // è®¡ç®æªæ¥ç¥¨éé¢ |
| | | row.futureTicketsAmount = row.tempFutureTicketsAmount - row.ticketsAmount; |
| | | calculateinvoiceAmount(); |
| | | } |
| | | |
| | | // æ¥ç¥¨éé¢ååå¤ç |
| | | const invoiceAmountBlur = (row) => { |
| | | if (!row.ticketsAmount) { |
| | | row.ticketsAmount = 0; |
| | | } |
| | | // è®¡ç®æ¯å¦è¶
è¿æ¥ç¥¨æ»éé¢ |
| | | if (Number(row.ticketsAmount) > Number(row.taxInclusiveTotalPrice)) { |
| | | showToast('æ¬æ¬¡æ¥ç¥¨éé¢ä¸å¾å¤§äºå«ç¨æ»éé¢'); |
| | | row.ticketsAmount = 0; |
| | | } |
| | | // è®¡ç®æ¬æ¬¡æ¥ç¥¨æ° |
| | | row.ticketsNum = Number( |
| | | (row.ticketsAmount / row.taxInclusiveUnitPrice).toFixed(2) |
| | | ); |
| | | // è®¡ç®æªæ¥ç¥¨æ°åæªæ¥ç¥¨éé¢ |
| | | updateFutureTicketData(row) |
| | | calculateinvoiceAmount(); |
| | | } |
| | | |
| | | const calculateinvoiceAmount = () => { |
| | | let invoiceAmountTotal = 0; |
| | | productData.value.forEach((item) => { |
| | | if (item.ticketsAmount) { |
| | | invoiceAmountTotal += Number(item.ticketsAmount); |
| | | } |
| | | }); |
| | | form.value.invoiceAmount = invoiceAmountTotal.toFixed(2); |
| | | } |
| | | |
| | | // æä»¶ä¸ä¼ æååè° |
| | | const uploadSuccess = (res) => { |
| | | if (res && res.data && res.data.fileId) { |
| | | form.value.fileIds.push(res.data.fileId) |
| | | } |
| | | } |
| | | |
| | | // æä»¶å é¤åè° |
| | | const removeFile = (index, file) => { |
| | | if (file.fileId) { |
| | | const fileIndex = form.value.fileIds.indexOf(file.fileId) |
| | | if (fileIndex > -1) { |
| | | form.value.fileIds.splice(fileIndex, 1) |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | // å¼ç¥¨æ¥æç¡®è®¤ |
| | | const onEntryDateConfirm = (e) => { |
| | | form.value.entryDate = formatDateToYMD(e.value) |
| | | entryDateValue.value = e.value |
| | | showEntryDatePicker.value = false; |
| | | }; |
| | | |
| | | // å½å
¥æ¥æç¡®è®¤ |
| | | const onEnterDateConfirm = (e) => { |
| | | form.value.enterDate = formatDateToYMD(e.value) |
| | | enterDateValue.value = e.value |
| | | showEnterDatePicker.value = false; |
| | | } |
| | | |
| | | // æ ¼å¼åæ¥æ |
| | | const formatDate = (date) => { |
| | | const year = date.getFullYear() |
| | | const month = String(date.getMonth() + 1).padStart(2, '0') |
| | | const day = String(date.getDate()).padStart(2, '0') |
| | | return `${year}-${month}-${day}` |
| | | } |
| | | |
| | | // è·å产åå表 |
| | | const getProductList = async () => { |
| | | try { |
| | | showLoadingToast('å è½½ä¸...') |
| | | const res = await getPurchaseNoById({ id: editData.value.id }) |
| | | form.value.purchaseLedgerNo = res.data.purchaseContractNumber; |
| | | form.value.invoiceAmount = res.data.invoiceAmount; |
| | | form.value.invoiceNumber = res.data.invoiceNumber; |
| | | const data = await getInfo({ id: editData.value.id }); |
| | | productData.value = data.data.productData; |
| | | form.value.salesContractNo = data.data.salesContractNo; |
| | | form.value.projectName = data.data.projectName; |
| | | form.value.supplierName = data.data.supplierName; |
| | | form.value.productData = data.data.productData; |
| | | // 设置é»è®¤å½å
¥äºº |
| | | form.value.issUer = userStore.nickName |
| | | |
| | | // 设置é»è®¤æ¥æ |
| | | const today = new Date() |
| | | form.value.enterDate = formatDate(today) |
| | | form.value.entryDate = formatDate(today) |
| | | |
| | | closeToast() |
| | | } catch (error) { |
| | | closeToast() |
| | | showToast('è·å产åå表失败') |
| | | } |
| | | } |
| | | |
| | | // æäº¤è¡¨å |
| | | const submitForm = async () => { |
| | | try { |
| | | submitting.value = true |
| | | |
| | | // éªè¯åç¥¨å·æ¯å¦å¡«å |
| | | if (!form.value.invoiceNumber) { |
| | | showToast('请è¾å
¥å票å·') |
| | | return |
| | | } |
| | | |
| | | // éªè¯äº§åæ°æ® |
| | | if (productData.value.length === 0) { |
| | | showToast('请å
æ·»å 产åä¿¡æ¯') |
| | | return |
| | | } |
| | | |
| | | // éªè¯æ¥ç¥¨æ°æ® |
| | | const hasInvoiceData = productData.value.some(item => { |
| | | const num = parseFloat(item.ticketsNum) || 0 |
| | | const amount = parseFloat(item.ticketsAmount) || 0 |
| | | return num > 0 || amount > 0 |
| | | }) |
| | | |
| | | if (!hasInvoiceData) { |
| | | showToast('请è³å°è¾å
¥ä¸ä¸ªäº§åçæ¥ç¥¨ä¿¡æ¯') |
| | | return |
| | | } |
| | | |
| | | const submitData = { |
| | | ...form.value, |
| | | productData: productData.value |
| | | } |
| | | |
| | | await addOrUpdateRegistration(submitData) |
| | | showToast('æäº¤æå') |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | setTimeout(() => { |
| | | goBack() |
| | | }, 800) |
| | | |
| | | } catch (error) { |
| | | showToast('æäº¤å¤±è´¥ï¼è¯·éè¯') |
| | | } finally { |
| | | submitting.value = false |
| | | } |
| | | } |
| | | |
| | | // 页é¢å è½½æ¶åå§åæ°æ® |
| | | onMounted(() => { |
| | | // ä»é¡µé¢åæ°æç¼åä¸è·åéå®ååä¿¡æ¯ |
| | | const contractInfo = uni.getStorageSync('editData') |
| | | if (contractInfo) { |
| | | editData.value = JSON.parse(contractInfo); |
| | | const contract = JSON.parse(contractInfo) |
| | | form.value.purchaseLedgerNo = contract.purchaseLedgerNo || '' |
| | | form.value.salesContractNo = contract.salesContractNo || '' |
| | | form.value.supplierName = contract.supplierName || '' |
| | | form.value.projectName = contract.projectName || '' |
| | | form.value.invoiceAmount = contract.invoiceAmount || '' |
| | | form.value.invoiceNumber = contract.invoiceNumber || '' |
| | | form.value.purchaseLedgerId = contract.id || '' |
| | | |
| | | // è·å产åå表 |
| | | getProductList() |
| | | } |
| | | }) |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .account-detail { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | padding-bottom: 5rem; |
| | | } |
| | | @import '@/static/scss/form-common.scss'; |
| | | |
| | | .empty-state { |
| | | padding: 40px 0; |
| | | } |
| | | |
| | | .product-section { |
| | | background: #fff; |
| | | margin-top: 1rem; |
| | | padding: 1rem; |
| | | box-shadow: 0 0.125rem 0.5rem rgba(0,0,0,0.04); |
| | | } |
| | | |
| | | .section-header { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | margin-bottom: 1rem; |
| | | } |
| | | |
| | | .section-title { |
| | | font-size: 1rem; |
| | | font-weight: 600; |
| | | color: #333; |
| | | } |
| | | |
| | | .product-list { |
| | | .product-card { |
| | | background: #FFFFFF; |
| | | box-shadow: 0 0 1.25rem 0 rgba(0,57,117,0.08); |
| | | border-radius: 0.5rem 0.5rem 0.5rem 0.5rem; |
| | | padding: 1rem 0.5rem 0 0.5rem; |
| | | position: relative; |
| | | margin-bottom: 1rem; |
| | | } |
| | | } |
| | | |
| | | .product-header { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | padding: 0 0.5rem 0.75rem 0.5rem; |
| | | border-bottom: 0.0625rem solid #e8e8e8; |
| | | } |
| | | |
| | | .product-title { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .product-productCategory { |
| | | margin-left: 0.5rem; |
| | | font-size: 0.875rem; |
| | | font-weight: 500; |
| | | color: #333; |
| | | } |
| | | |
| | | .product-form { |
| | | margin-bottom: 1rem; |
| | | } |
| | | .footer-btns { |
| | | position: fixed; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | background: #fff; |
| | | display: flex; |
| | | justify-content: space-around; |
| | | align-items: center; |
| | | padding: 0.75rem 0; |
| | | box-shadow: 0 -0.125rem 0.5rem rgba(0,0,0,0.05); |
| | | z-index: 1000; |
| | | } |
| | | .cancel-btn { |
| | | font-weight: 400; |
| | | font-size: 1rem; |
| | | color: #FFFFFF; |
| | | width: 6.375rem; |
| | | background: #C7C9CC; |
| | | box-shadow: 0 0.25rem 0.625rem 0 rgba(3,88,185,0.2); |
| | | border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; |
| | | } |
| | | .save-btn { |
| | | font-weight: 400; |
| | | font-size: 1rem; |
| | | color: #FFFFFF; |
| | | width: 14rem; |
| | | background: linear-gradient( 140deg, #00BAFF 0%, #006CFB 100%); |
| | | box-shadow: 0 0.25rem 0.625rem 0 rgba(3,88,185,0.2); |
| | | border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; |
| | | } |
| | | // ååºå¼è°æ´ |
| | | @media (max-width: 768px) { |
| | | .submit-section { |
| | | padding: 12px; |
| | | } |
| | | } |
| | | </style> |
| | |
| | | |
| | | <!-- æä½æé®åºå --> |
| | | <view class="action-buttons"> |
| | | <van-button |
| | | <u-button |
| | | type="primary" |
| | | size="small" |
| | | @click="handleAddInvoice(item)" |
| | |
| | | :disabled="item.unReceiptPaymentAmount == 0" |
| | | > |
| | | æ°å¢å¼ç¥¨ |
| | | </van-button> |
| | | <van-button |
| | | type="default" |
| | | </u-button> |
| | | <u-button |
| | | size="small" |
| | | @click="handleViewDetail(item)" |
| | | class="action-btn" |
| | | > |
| | | æ¥ç详æ
|
| | | </van-button> |
| | | </u-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | |
| | | <!-- 表åå
容 --> |
| | | <u-form @submit="onSubmit" ref="formRef" label-width="110" input-align="right" error-message-align="right"> |
| | | <!-- åºæ¬ä¿¡æ¯ --> |
| | | <u-cell-group title="åºæ¬ä¿¡æ¯"> |
| | | <u-form-item label="éè´ååå·" border-bottom> |
| | | <u-cell-group title="åºæ¬ä¿¡æ¯" class="form-section"> |
| | | <u-form-item label="éè´ååå·" class="form-item"> |
| | | <u-input |
| | | v-model="form.purchaseContractNumber" |
| | | placeholder="èªå¨å¡«å
" |
| | | readonly |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="éå®ååå·" border-bottom> |
| | | <u-form-item label="éå®ååå·" class="form-item"> |
| | | <u-input |
| | | v-model="form.salesContractNo" |
| | | placeholder="èªå¨å¡«å
" |
| | | readonly |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="ä¾åºååç§°" border-bottom> |
| | | <u-form-item label="ä¾åºååç§°" class="form-item"> |
| | | <u-input |
| | | v-model="form.supplierName" |
| | | placeholder="èªå¨å¡«å
" |
| | | readonly |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="å票å·" border-bottom> |
| | | <u-form-item label="å票å·" class="form-item"> |
| | | <u-input |
| | | v-model="form.invoiceNumber" |
| | | placeholder="èªå¨å¡«å
" |
| | | readonly |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="å票éé¢(å
)" border-bottom> |
| | | <u-form-item label="å票éé¢(å
)" class="form-item"> |
| | | <u-input |
| | | v-model="form.invoiceAmount" |
| | | placeholder="èªå¨å¡«å
" |
| | |
| | | /> |
| | | </u-form-item> |
| | | <view class="tip-text">å¾
仿¬¾éé¢ï¼{{ currentNoReceiptAmount }} å
</view> |
| | | <u-form-item label="æ¬æ¬¡ä»æ¬¾éé¢" prop="currentPaymentAmount" required border-bottom> |
| | | <u-form-item label="æ¬æ¬¡ä»æ¬¾éé¢" prop="currentPaymentAmount" required class="form-item"> |
| | | <u-input |
| | | v-model="form.currentPaymentAmount" |
| | | type="number" |
| | |
| | | clearable |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="仿¬¾å½¢å¼" prop="paymentMethod" required border-bottom> |
| | | <u-form-item label="仿¬¾å½¢å¼" prop="paymentMethod" required class="form-item"> |
| | | <u-input |
| | | v-model="form.paymentMethod" |
| | | placeholder="è¯·éæ©" |
| | | readonly |
| | | @click="showPaymentTypePicker" |
| | | /> |
| | | <template #right> |
| | | <up-icon |
| | | name="arrow-right" |
| | | @click="showPaymentTypePicker" |
| | | ></up-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="仿¬¾æ¥æ" prop="paymentDate" required border-bottom> |
| | | <u-form-item label="仿¬¾æ¥æ" prop="paymentDate" required class="form-item"> |
| | | <u-input |
| | | v-model="form.paymentDate" |
| | | placeholder="è¯·éæ©" |
| | | readonly |
| | | @click="showDatePicker" |
| | | /> |
| | | <template #right> |
| | | <up-icon |
| | | name="arrow-right" |
| | | @click="showDatePicker" |
| | | ></up-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="ç»è®°äºº" border-bottom> |
| | | <u-form-item label="ç»è®°äºº" class="form-item"> |
| | | <u-input |
| | | v-model="form.registrant" |
| | | placeholder="èªå¨å¡«å
" |
| | | readonly |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="ç»è®°æ¥æ" prop="registrationtDate" required border-bottom> |
| | | <u-form-item label="ç»è®°æ¥æ" prop="registrationtDate" required class="form-item"> |
| | | <u-input |
| | | v-model="form.registrationtDate" |
| | | placeholder="è¯·éæ©" |
| | |
| | | </u-cell-group> |
| | | |
| | | <!-- æäº¤æé® --> |
| | | <view class="footer-btns"> |
| | | <u-button class="cancel-btn" @click="onClickLeft">åæ¶</u-button> |
| | | <u-button class="save-btn" type="primary" @click="onSubmit" :loading="loading">ä¿å</u-button> |
| | | </view> |
| | | <FooterButtons |
| | | :loading="loading" |
| | | @cancel="onClickLeft" |
| | | @confirm="onSubmit" |
| | | /> |
| | | </u-form> |
| | | |
| | | <!-- 仿¬¾æ¹å¼éæ©å¨ --> |
| | | <u-popup v-model="showPaymentType" mode="bottom"> |
| | | <u-picker |
| | | v-model="pickerValue" |
| | | :columns="receipt_payment_type" |
| | | @confirm="onPaymentTypeConfirm" |
| | | @cancel="showPaymentType = false" |
| | | /> |
| | | </u-popup> |
| | | <up-action-sheet |
| | | :show="showPaymentType" |
| | | title="鿩仿¬¾æ¹å¼" |
| | | :actions="receipt_payment_type" |
| | | @select="onPaymentTypeConfirm" |
| | | @close="showPaymentType = false" |
| | | /> |
| | | |
| | | <!-- æ¥æéæ©å¨ --> |
| | | <u-popup v-model="showDate" mode="bottom"> |
| | | <u-datetime-picker |
| | | v-model="currentDate" |
| | | title="éæ©æ¥æ" |
| | | @confirm="onDateConfirm" |
| | | @cancel="showDate = false" |
| | | /> |
| | | </u-popup> |
| | | <up-datetime-picker |
| | | :show="showDate" |
| | | v-model="form.paymentDate" |
| | | @confirm="onDateConfirm" |
| | | @cancel="showDate = false" |
| | | mode="date" |
| | | /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted, computed } from 'vue' |
| | | import FooterButtons from '@/components/FooterButtons.vue' |
| | | import useUserStore from '@/store/modules/user' |
| | | import { useDict } from '@/utils/dict' |
| | | import {paymentRegistrationAdd} from "@/api/procurementManagement/paymentEntry"; |
| | | import { formatDateToYMD } from '@/utils/ruoyi' |
| | | |
| | | // æ¿æ¢ toast å notify æ¹æ³ |
| | | const showToast = (message) => { |
| | |
| | | // ååºå¼æ°æ® |
| | | const loading = ref(false) |
| | | const showPaymentType = ref(false) |
| | | const pickerValue = ref([]) |
| | | const showDate = ref(false) |
| | | const currentDate = ref([new Date().getFullYear(), new Date().getMonth() + 1, new Date().getDate()]) |
| | | |
| | | // è¡¨åæ°æ® |
| | | const form = ref({ |
| | |
| | | // 转æ¢åå
¸æ°æ®æ ¼å¼ä¸ºéæ©å¨éè¦çæ ¼å¼ |
| | | const receipt_payment_type = computed(() => { |
| | | return dictReceiptPaymentType.value.map(item => ({ |
| | | text: item.label, |
| | | name: item.label, |
| | | value: item.value |
| | | })) |
| | | }) |
| | |
| | | } |
| | | |
| | | // ç¡®è®¤ä»æ¬¾æ¹å¼éæ© |
| | | const onPaymentTypeConfirm = ({ selectedValues, selectedOptions }) => { |
| | | form.value.receiptPaymentType = selectedOptions[0].value |
| | | form.value.paymentMethod = selectedOptions[0].text |
| | | pickerValue.value = selectedValues; |
| | | const onPaymentTypeConfirm = (item) => { |
| | | form.value.receiptPaymentType = item.value |
| | | form.value.paymentMethod = item.name |
| | | showPaymentType.value = false |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | // ç¡®è®¤æ¥æéæ© |
| | | const onDateConfirm = ({ selectedValues }) => { |
| | | form.value.paymentDate = selectedValues.join('-') |
| | | currentDate.value = selectedValues |
| | | const onDateConfirm = (e) => { |
| | | form.value.paymentDate = formatDateToYMD(e.value) |
| | | showDate.value = false |
| | | } |
| | | |
| | |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .account-detail { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | padding-bottom: 5rem; |
| | | } |
| | | |
| | | .footer-btns { |
| | | position: fixed; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | background: #fff; |
| | | display: flex; |
| | | justify-content: space-around; |
| | | align-items: center; |
| | | padding: 0.75rem 0; |
| | | box-shadow: 0 -0.125rem 0.5rem rgba(0,0,0,0.05); |
| | | z-index: 1000; |
| | | } |
| | | |
| | | .cancel-btn { |
| | | font-weight: 400; |
| | | font-size: 1rem; |
| | | color: #FFFFFF; |
| | | width: 6.375rem; |
| | | background: #C7C9CC; |
| | | box-shadow: 0 0.25rem 0.625rem 0 rgba(3,88,185,0.2); |
| | | border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; |
| | | } |
| | | |
| | | .save-btn { |
| | | font-weight: 400; |
| | | font-size: 1rem; |
| | | color: #FFFFFF; |
| | | width: 14rem; |
| | | background: linear-gradient( 140deg, #00BAFF 0%, #006CFB 100%); |
| | | box-shadow: 0 0.25rem 0.625rem 0 rgba(3,88,185,0.2); |
| | | border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; |
| | | } |
| | | |
| | | // ååºå¼è°æ´ |
| | | @media (max-width: 768px) { |
| | | .submit-section { |
| | | padding: 12px; |
| | | } |
| | | } |
| | | .tip-text { padding: 4px 16px 0 16px; font-size: 12px; color: #888; } |
| | | @import '@/static/scss/form-common.scss'; |
| | | </style> |
| | |
| | | <!-- 表åå
容 --> |
| | | <u-form @submit="onSubmit" ref="formRef" label-width="110" input-align="right" error-message-align="right"> |
| | | <!-- åºæ¬ä¿¡æ¯ --> |
| | | <u-cell-group title="åºæ¬ä¿¡æ¯"> |
| | | <u-form-item label="éè´ååå·" border-bottom> |
| | | <u-input v-model="form.contractNo" placeholder="èªå¨å¡«å
" readonly /> |
| | | <u-cell-group title="åºæ¬ä¿¡æ¯" class="form-section"> |
| | | <u-form-item label="éè´ååå·" class="form-item"> |
| | | <u-input v-model="form.purchaseContractNumber" placeholder="èªå¨å¡«å
" readonly /> |
| | | </u-form-item> |
| | | <u-form-item label="ä¾åºååç§°" border-bottom> |
| | | <u-form-item label="éå®ååå·" class="form-item"> |
| | | <u-input v-model="form.salesContractNo" placeholder="èªå¨å¡«å
" readonly /> |
| | | </u-form-item> |
| | | <u-form-item label="ä¾åºååç§°" class="form-item"> |
| | | <u-input v-model="form.supplierName" placeholder="èªå¨å¡«å
" readonly /> |
| | | </u-form-item> |
| | | <u-form-item label="å票å·" border-bottom> |
| | | <u-input v-model="form.invoiceNo" placeholder="èªå¨å¡«å
" readonly /> |
| | | <u-form-item label="å票å·" class="form-item"> |
| | | <u-input v-model="form.invoiceNumber" placeholder="èªå¨å¡«å
" readonly /> |
| | | </u-form-item> |
| | | <u-form-item label="å票éé¢(å
)" class="form-item"> |
| | | <u-input v-model="form.invoiceAmount" placeholder="èªå¨å¡«å
" readonly /> |
| | | </u-form-item> |
| | | <view class="tip-text">å¾
仿¬¾éé¢ï¼{{ currentNoReceiptAmount }} å
</view> |
| | | <u-form-item label="æ¬æ¬¡ä»æ¬¾éé¢" prop="currentPaymentAmount" required class="form-item"> |
| | | <u-input v-model="form.currentPaymentAmount" type="number" placeholder="请è¾å
¥" @blur="changeNum" clearable /> |
| | | </u-form-item> |
| | | <u-form-item label="仿¬¾å½¢å¼" prop="paymentMethod" required class="form-item"> |
| | | <u-input v-model="form.paymentMethod" placeholder="è¯·éæ©" readonly @click="showPaymentTypePicker" /> |
| | | <template #right> |
| | | <up-icon |
| | | name="arrow-right" |
| | | @click="showPaymentTypePicker" |
| | | ></up-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="å票éé¢(å
)" border-bottom> |
| | | <u-input v-model="form.invoiceAmount" placeholder="èªå¨å¡«å
" readonly /> |
| | | </u-form-item> |
| | | <u-form-item label="æ¬æ¬¡ä»æ¬¾éé¢" prop="paymentAmount" required border-bottom> |
| | | <u-input v-model="form.paymentAmount" type="number" placeholder="请è¾å
¥" @blur="changeNum" clearable /> |
| | | </u-form-item> |
| | | <u-form-item label="仿¬¾å½¢å¼" prop="paymentType" required border-bottom> |
| | | <u-input v-model="form.paymentType" placeholder="è¯·éæ©" readonly @click="showPaymentTypePicker" /> |
| | | </u-form-item> |
| | | <u-form-item label="仿¬¾æ¥æ" prop="paymentDate" required border-bottom> |
| | | <u-form-item label="仿¬¾æ¥æ" prop="paymentDate" required class="form-item"> |
| | | <u-input v-model="form.paymentDate" placeholder="è¯·éæ©" readonly @click="showDatePicker" /> |
| | | <template #right> |
| | | <up-icon |
| | | name="arrow-right" |
| | | @click="showDatePicker" |
| | | ></up-icon> |
| | | </template> |
| | | </u-form-item> |
| | | </u-cell-group> |
| | | <u-form-item label="ç»è®°äºº" class="form-item"> |
| | | <u-input v-model="form.registrant" placeholder="èªå¨å¡«å
" readonly /> |
| | | </u-form-item> |
| | | <u-form-item label="ç»è®°æ¥æ" prop="registrationtDate" required class="form-item"> |
| | | <u-input v-model="form.registrationtDate" placeholder="è¯·éæ©" readonly /> |
| | | </u-form-item> |
| | | </u-cell-group> |
| | | |
| | | <!-- æäº¤æé® --> |
| | | <view class="footer-btns"> |
| | | <u-button class="cancel-btn" @click="onClickLeft">åæ¶</u-button> |
| | | <u-button class="save-btn" type="primary" @click="onSubmit" :loading="loading">ä¿å</u-button> |
| | | </view> |
| | | <FooterButtons |
| | | :loading="loading" |
| | | @cancel="onClickLeft" |
| | | @confirm="onSubmit" |
| | | /> |
| | | </u-form> |
| | | |
| | | <!-- 仿¬¾æ¹å¼éæ©å¨ --> |
| | | <u-popup v-model="showPaymentType" mode="bottom"> |
| | | <u-picker |
| | | v-model="pickerValue" |
| | | :columns="paymentTypeOptions" |
| | | @confirm="onPaymentTypeConfirm" |
| | | @cancel="showPaymentType = false" |
| | | /> |
| | | </u-popup> |
| | | <up-action-sheet |
| | | :show="showPaymentType" |
| | | title="鿩仿¬¾æ¹å¼" |
| | | :actions="receipt_payment_type" |
| | | @select="onPaymentTypeConfirm" |
| | | @close="showPaymentType = false" |
| | | /> |
| | | |
| | | <!-- æ¥æéæ©å¨ --> |
| | | <u-popup v-model="showDate" mode="bottom"> |
| | | <u-datetime-picker |
| | | v-model="currentDate" |
| | | title="éæ©æ¥æ" |
| | | @confirm="onDateConfirm" |
| | | @cancel="showDate = false" |
| | | /> |
| | | </u-popup> |
| | | <up-datetime-picker |
| | | :show="showDate" |
| | | v-model="form.paymentDate" |
| | | @confirm="onDateConfirm" |
| | | @cancel="showDate = false" |
| | | mode="date" |
| | | /> |
| | | </view> |
| | | </template> |
| | | |
| | |
| | | } |
| | | |
| | | import { ref, onMounted, computed } from 'vue' |
| | | import FooterButtons from '@/components/FooterButtons.vue' |
| | | import useUserStore from '@/store/modules/user' |
| | | import { useDict } from '@/utils/dict' |
| | | import {paymentRegistrationAdd, paymentRegistrationEdit} from "@/api/procurementManagement/paymentEntry"; |
| | | import { formatDateToYMD } from '@/utils/ruoyi' |
| | | |
| | | const userStore = useUserStore() |
| | | |
| | |
| | | // ååºå¼æ°æ® |
| | | const loading = ref(false) |
| | | const showPaymentType = ref(false) |
| | | const pickerValue = ref([]) |
| | | const showDate = ref(false) |
| | | const currentDate = ref([new Date().getFullYear(), new Date().getMonth() + 1, new Date().getDate()]) |
| | | |
| | | // è¡¨åæ°æ® |
| | | const form = ref({ |
| | |
| | | ticketRegistrationId: '' |
| | | }) |
| | | const currentNoReceiptAmount = ref(0) |
| | | const operationType = ref('') |
| | | |
| | | // è·ååå
¸æ°æ® |
| | | const { receipt_payment_type: dictReceiptPaymentType } = useDict('receipt_payment_type') |
| | |
| | | // 转æ¢åå
¸æ°æ®æ ¼å¼ä¸ºéæ©å¨éè¦çæ ¼å¼ |
| | | const receipt_payment_type = computed(() => { |
| | | return dictReceiptPaymentType.value.map(item => ({ |
| | | text: item.label, |
| | | name: item.label, |
| | | value: item.value |
| | | })) |
| | | }) |
| | |
| | | } |
| | | |
| | | // ç¡®è®¤ä»æ¬¾æ¹å¼éæ© |
| | | const onPaymentTypeConfirm = ({ selectedValues, selectedOptions }) => { |
| | | form.value.receiptPaymentType = selectedOptions[0].value |
| | | form.value.paymentMethod = selectedOptions[0].text |
| | | pickerValue.value = selectedValues; |
| | | const onPaymentTypeConfirm = (item) => { |
| | | form.value.receiptPaymentType = item.value |
| | | form.value.paymentMethod = item.name |
| | | showPaymentType.value = false |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | // ç¡®è®¤æ¥æéæ© |
| | | const onDateConfirm = ({ selectedValues }) => { |
| | | form.value.paymentDate = selectedValues.join('-') |
| | | currentDate.value = selectedValues |
| | | const onDateConfirm = (e) => { |
| | | form.value.paymentDate = formatDateToYMD(e.value) |
| | | showDate.value = false |
| | | } |
| | | |
| | |
| | | } |
| | | if (!form.value.receiptPaymentType) { |
| | | showNotify({ type: 'warning', message: 'è¯·éæ©ä»æ¬¾å½¢å¼' }) |
| | | return |
| | | } |
| | | if (!form.value.paymentDate) { |
| | | showNotify({ type: 'warning', message: 'è¯·éæ©ä»æ¬¾æ¥æ' }) |
| | | return |
| | | } |
| | | loading.value = true |
| | |
| | | const rowStr = uni.getStorageSync('invoiceLedgerEditRow') |
| | | const row = JSON.parse(rowStr) |
| | | form.value = { ...row }; |
| | | form.value.ticketRegistrationId = row.id; |
| | | form.value.id = ""; |
| | | if (operationType.value === 'add') { |
| | | currentNoReceiptAmount.value = row.unPaymentAmountTotal |
| | | form.value.registrant = userStore.nickName |
| | | form.value.registrationtDate = getCurrentDate(); |
| | | form.value.paymentDate = getCurrentDate(); |
| | | } |
| | | currentNoReceiptAmount.value = row.unPaymentAmountTotal || 0; |
| | | } |
| | | // è·åå½åæ¥æå¹¶æ ¼å¼å为 YYYY-MM-DD |
| | | function getCurrentDate() { |
| | |
| | | return `${year}-${month}-${day}`; |
| | | } |
| | | onMounted(() => { |
| | | operationType.value = uni.getStorageSync('operationType') || ''; |
| | | initData() |
| | | }) |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .account-detail { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | padding-bottom: 5rem; |
| | | } |
| | | |
| | | .footer-btns { |
| | | position: fixed; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | background: #fff; |
| | | display: flex; |
| | | justify-content: space-around; |
| | | align-items: center; |
| | | padding: 0.75rem 0; |
| | | box-shadow: 0 -0.125rem 0.5rem rgba(0,0,0,0.05); |
| | | z-index: 1000; |
| | | } |
| | | |
| | | .cancel-btn { |
| | | font-weight: 400; |
| | | font-size: 1rem; |
| | | color: #FFFFFF; |
| | | width: 6.375rem; |
| | | background: #C7C9CC; |
| | | box-shadow: 0 0.25rem 0.625rem 0 rgba(3,88,185,0.2); |
| | | border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; |
| | | } |
| | | |
| | | .save-btn { |
| | | font-weight: 400; |
| | | font-size: 1rem; |
| | | color: #FFFFFF; |
| | | width: 14rem; |
| | | background: linear-gradient( 140deg, #00BAFF 0%, #006CFB 100%); |
| | | box-shadow: 0 0.25rem 0.625rem 0 rgba(3,88,185,0.2); |
| | | border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; |
| | | } |
| | | |
| | | // ååºå¼è°æ´ |
| | | @media (max-width: 768px) { |
| | | .submit-section { |
| | | padding: 12px; |
| | | } |
| | | } |
| | | .tip-text { padding: 4px 16px 0 16px; font-size: 12px; color: #888; } |
| | | @import '@/static/scss/form-common.scss'; |
| | | </style> |
| | |
| | | <!-- çéå¼å
³ --> |
| | | <view class="switch-row"> |
| | | <text class="switch-label">䏿¾ç¤ºå¾
仿¬¾ä¸º0</text> |
| | | <van-switch v-model="searchForm.status" @change="getList" size="18"/> |
| | | <u-switch v-model="searchForm.status" @change="getList" active-color="#2979ff" inactive-color="#e5e5e5"/> |
| | | </view> |
| | | </view> |
| | | |
| | |
| | | |
| | | <!-- æä½æé® --> |
| | | <view class="action-buttons"> |
| | | <van-button |
| | | <u-button |
| | | type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | |
| | | @click="openForm('add', item)" |
| | | > |
| | | æ°å¢ä»æ¬¾ |
| | | </van-button> |
| | | </u-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | |
| | | <script setup> |
| | | import { ref } from 'vue' |
| | | import useUserStore from '@/store/modules/user' |
| | | import { showToast } from 'vant' |
| | | // æ¿æ¢ toast æ¹æ³ |
| | | const showToast = (message) => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: 'none' |
| | | }) |
| | | } |
| | | import {onShow} from "@dcloudio/uni-app"; |
| | | import {invoiceListPage} from "@/api/procurementManagement/procurementInvoiceLedger"; |
| | | |
| | |
| | | <template> |
| | | <view class="receipt-payment-detail"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader title="客æ·å¾æ¥è¯¦æ
" @back="goBack" /> |
| | | <PageHeader title="ä¾åºå徿¥è¯¦æ
" @back="goBack" /> |
| | | |
| | | <!-- ç»è®¡ä¿¡æ¯ --> |
| | | <view class="summary-info" v-if="tableData.length > 0"> |
| | |
| | | } |
| | | const param = { |
| | | supplierId: supplierId.value, |
| | | current: -1, |
| | | size: -1 |
| | | }; |
| | | paymentLedgerList(param).then((res) => { |
| | | tableData.value = res.data; |
| | | tableData.value = res.data.records; |
| | | }).catch(() => { |
| | | uni.showToast({ |
| | | title: 'æ¥è¯¢å¤±è´¥', |
| | |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader title="ç¼è¾æ¥ç¥¨å°è´¦" @back="goBack" /> |
| | | |
| | | <van-form @submit="submitForm" ref="formRef" label-width="120px" input-align="right" error-message-align="right" scroll-to-error scroll-to-error-position="center"> |
| | | <van-cell-group title="åºæ¬ä¿¡æ¯" inset> |
| | | <van-field v-model="form.purchaseContractNumber" label="éè´ååå·" readonly /> |
| | | <van-field v-model="form.salesContractNo" label="éå®ååå·" readonly /> |
| | | <van-field v-model="form.taxInclusiveUnitPrice" label="å«ç¨åä»·(å
)" readonly /> |
| | | <van-field v-model="form.createdAt" label="å建æ¶é´" readonly /> |
| | | <van-field v-model="form.invoiceNumber" label="å票å·" placeholder="请è¾å
¥" readonly /> |
| | | <van-field v-model="form.ticketsNum" label="æ¥ç¥¨æ°" type="number" placeholder="请è¾å
¥" required :rules="[{ required: true, message: '请è¾å
¥æ¥ç¥¨æ°' }]" @change="inputTicketsNum"/> |
| | | <van-field v-model="form.ticketsAmount" label="æ¬æ¬¡æ¥ç¥¨éé¢(å
)" type="number" placeholder="请è¾å
¥" required :rules="[{ required: true, message: '请è¾å
¥æ¬æ¬¡æ¥ç¥¨éé¢' }]" @change="inputTicketsAmount"/> |
| | | <view class="tip-text">æªæ¥ç¥¨æ°ï¼{{ formatAmount(form.futureTickets) }} å
</view> |
| | | <!-- <van-field v-model="form.invoicePerson" label="æªæ¥ç¥¨æ°" readonly />--> |
| | | </van-cell-group> |
| | | <up-form @submit="submitForm" ref="formRef" label-width="120" :model="form"> |
| | | <up-form-item label="éè´ååå·" prop="purchaseContractNumber"> |
| | | <up-input v-model="form.purchaseContractNumber" placeholder="èªå¨çæ" disabled /> |
| | | </up-form-item> |
| | | <up-form-item label="éå®ååå·" prop="salesContractNo"> |
| | | <up-input v-model="form.salesContractNo" placeholder="èªå¨çæ" disabled /> |
| | | </up-form-item> |
| | | <up-form-item label="å«ç¨åä»·(å
)" prop="taxInclusiveUnitPrice"> |
| | | <up-input v-model="form.taxInclusiveUnitPrice" placeholder="èªå¨çæ" disabled /> |
| | | </up-form-item> |
| | | <up-form-item label="å建æ¶é´" prop="createdAt"> |
| | | <up-input v-model="form.createdAt" placeholder="èªå¨çæ" disabled /> |
| | | </up-form-item> |
| | | <up-form-item label="å票å·" prop="invoiceNumber"> |
| | | <up-input v-model="form.invoiceNumber" placeholder="请è¾å
¥" disabled /> |
| | | </up-form-item> |
| | | <up-form-item label="æ¥ç¥¨æ°" prop="ticketsNum" required :rules="rules.ticketsNum"> |
| | | <up-input |
| | | v-model="form.ticketsNum" |
| | | type="number" |
| | | placeholder="请è¾å
¥" |
| | | @blur="inputTicketsNum" |
| | | /> |
| | | </up-form-item> |
| | | <up-form-item label="æ¬æ¬¡æ¥ç¥¨éé¢(å
)" prop="ticketsAmount" required :rules="rules.ticketsAmount"> |
| | | <up-input |
| | | v-model="form.ticketsAmount" |
| | | type="number" |
| | | placeholder="请è¾å
¥" |
| | | @blur="inputTicketsAmount" |
| | | /> |
| | | </up-form-item> |
| | | <view class="tip-text">æªæ¥ç¥¨æ°ï¼{{ formatAmount(form.futureTickets) }} å
</view> |
| | | |
| | | <!-- <van-cell-group title="éä»¶ææï¼ä»
æ¯æ pdfï¼" inset>--> |
| | | <!-- <van-uploader--> |
| | | <!-- accept=".pdf"--> |
| | | <!-- multiple--> |
| | | <!-- :after-read="afterReadUpload"--> |
| | | <!-- :before-read="beforeReadPdf"--> |
| | | <!-- >--> |
| | | <!-- <van-button class="upload-btn" icon="plus" type="primary" block>ä¸ä¼ æä»¶</van-button>--> |
| | | <!-- </van-uploader>--> |
| | | <!-- <view class="uploaded-list" v-if="fileList.length">--> |
| | | <!-- <view class="uploaded-item" v-for="(f, idx) in fileList" :key="idx">--> |
| | | <!-- <text class="file-name">{{ f.name || getFileNameFromUrl(f.url) }}</text>--> |
| | | <!-- <van-button size="mini" type="danger" plain @click="removeUploaded(idx)">ç§»é¤</van-button>--> |
| | | <!-- </view>--> |
| | | <!-- </view>--> |
| | | <!-- </van-cell-group>--> |
| | | |
| | | <view class="footer-btns"> |
| | | <van-button class="cancel-btn" @click="goBack">åæ¶</van-button> |
| | | <van-button class="save-btn" native-type="submit" form-type="submit">ä¿å</van-button> |
| | | </view> |
| | | </van-form> |
| | | <!-- 使ç¨å
Œ
±åºé¨æé®ç»ä»¶ --> |
| | | <FooterButtons |
| | | show |
| | | cancelText="åæ¶" |
| | | confirmText="ä¿å" |
| | | @cancel="goBack" |
| | | @confirm="onSubmit" |
| | | /> |
| | | </up-form> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted } from 'vue' |
| | | import { showToast, showLoadingToast, closeToast } from 'vant' |
| | | import dayjs from 'dayjs' |
| | | import useUserStore from '@/store/modules/user' |
| | | import { getToken } from '@/utils/auth' |
| | | import { invoiceLedgerSaveOrUpdate } from '@/api/salesManagement/invoiceLedger.js' |
| | | import config from '@/config.js' |
| | | import {getProductRecordById, updateRegistration} from "@/api/procurementManagement/procurementInvoiceLedger"; |
| | | import PageHeader from '@/components/PageHeader.vue'; |
| | | import FooterButtons from '@/components/FooterButtons.vue'; |
| | | |
| | | const userStore = useUserStore() |
| | | |
| | |
| | | const currentId = ref('') |
| | | const temFutureTickets = ref(0) |
| | | |
| | | // æ¥æéæ© |
| | | const currentInvoiceDate = ref([new Date().getFullYear(), new Date().getMonth() + 1, new Date().getDate()]) |
| | | // è¡¨åæ ¡éªè§å |
| | | const rules = { |
| | | ticketsNum: [ |
| | | { required: true, message: '请è¾å
¥æ¥ç¥¨æ°', trigger: 'blur' } |
| | | ], |
| | | ticketsAmount: [ |
| | | { required: true, message: '请è¾å
¥æ¬æ¬¡æ¥ç¥¨éé¢', trigger: 'blur' } |
| | | ] |
| | | }; |
| | | |
| | | const goBack = () => { |
| | | uni.removeStorageSync('invoiceLedgerEditRow'); |
| | | uni.navigateBack() |
| | | } |
| | | const inputTicketsNum = (val) => { |
| | | const inputTicketsNum = () => { |
| | | // ç¡®ä¿å«ç¨åä»·åå¨ä¸ä¸ä¸ºé¶ |
| | | if (!form.value.taxInclusiveUnitPrice || Number(form.value.taxInclusiveUnitPrice) === 0) { |
| | | showToast("å«ç¨åä»·ä¸è½ä¸ºé¶ææªå®ä¹"); |
| | | uni.showToast({ |
| | | title: "å«ç¨åä»·ä¸è½ä¸ºé¶ææªå®ä¹", |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | } |
| | | if (Number(form.value.ticketsNum) > Number(temFutureTickets.value)) { |
| | | showToast("æ¥ç¥¨æ°ä¸å¾å¤§äºæªæ¥ç¥¨æ°"); |
| | | uni.showToast({ |
| | | title: "æ¥ç¥¨æ°ä¸å¾å¤§äºæªæ¥ç¥¨æ°", |
| | | icon: 'none' |
| | | }); |
| | | form.value.ticketsNum = temFutureTickets.value |
| | | } |
| | | |
| | |
| | | form.value.futureTickets = Number(futureTickets.toFixed(2)); |
| | | form.value.ticketsAmount = Number(ticketsAmount.toFixed(2)); |
| | | }; |
| | | const inputTicketsAmount = (val) => { |
| | | const inputTicketsAmount = () => { |
| | | // ç¡®ä¿å«ç¨åä»·åå¨ä¸ä¸ä¸ºé¶ |
| | | if (!form.value.taxInclusiveUnitPrice || Number(form.value.taxInclusiveUnitPrice) === 0) { |
| | | showToast("å«ç¨åä»·ä¸è½ä¸ºé¶ææªå®ä¹"); |
| | | uni.showToast({ |
| | | title: "å«ç¨åä»·ä¸è½ä¸ºé¶ææªå®ä¹", |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | if (Number(val) > Number(form.value.futureTickets*form.value.taxInclusiveUnitPrice)) { |
| | | showToast("æ¬æ¬¡æ¥ç¥¨éé¢ä¸å¾å¤§äºæ»éé¢"); |
| | | if (Number(form.value.ticketsAmount) > Number(form.value.futureTickets*form.value.taxInclusiveUnitPrice)) { |
| | | uni.showToast({ |
| | | title: "æ¬æ¬¡æ¥ç¥¨éé¢ä¸å¾å¤§äºæ»éé¢", |
| | | icon: 'none' |
| | | }); |
| | | form.value.ticketsAmount = (form.value.futureTickets*form.value.taxInclusiveUnitPrice).toFixed(2) |
| | | const ticketsNum = Number(form.value.ticketsAmount) / Number(form.value.taxInclusiveUnitPrice); |
| | | form.value.ticketsNum = Number(ticketsNum.toFixed(2)) |
| | |
| | | } |
| | | |
| | | // ç¡®ä¿æææ°å¼é½è½¬æ¢ä¸ºæ°åç±»åè¿è¡è®¡ç® |
| | | const ticketsNum = Number(val) / Number(form.value.taxInclusiveUnitPrice); |
| | | const ticketsNum = Number(form.value.ticketsAmount) / Number(form.value.taxInclusiveUnitPrice); |
| | | form.value.ticketsNum = Number(ticketsNum.toFixed(2)); |
| | | }; |
| | | const formatAmount = (val) => { |
| | |
| | | return num.toFixed(2) |
| | | } |
| | | |
| | | // ä¸ä¼ åæ ¡éªï¼å
¼å®¹ Vant Uploader ç file/fileList ç»æï¼ |
| | | const beforeReadPdf = (file) => { |
| | | const items = Array.isArray(file) ? file : [file] |
| | | for (const it of items) { |
| | | const raw = it?.file || it |
| | | const fileName = raw?.name || it?.name || '' |
| | | const ext = fileName.split('.').pop()?.toLowerCase() |
| | | const sizeOk = (raw?.size || 0) <= 10 * 1024 * 1024 |
| | | if (ext !== 'pdf') { |
| | | showToast('ä»
æ¯æpdfæä»¶') |
| | | return false |
| | | } |
| | | if (!sizeOk) { |
| | | showToast('ä¸ä¼ æä»¶å¤§å°ä¸è½è¶
è¿10MB') |
| | | return false |
| | | } |
| | | } |
| | | return true |
| | | } |
| | | |
| | | const uploadSingleFile = async (fileObj) => { |
| | | return new Promise((resolve, reject) => { |
| | | showLoadingToast({ message: 'æ£å¨ä¸ä¼ ...' }) |
| | | const baseUrl = config.baseUrl + '/invoiceLedger/uploadFile' |
| | | |
| | | const filePath = fileObj?.url || fileObj?.tempFilePath || fileObj?.file?.path |
| | | if (filePath) { |
| | | uni.uploadFile({ |
| | | url: baseUrl, |
| | | filePath, |
| | | name: 'file', |
| | | header: { Authorization: 'Bearer ' + getToken() }, |
| | | success: (res) => { |
| | | closeToast() |
| | | try { |
| | | const data = JSON.parse(res.data || '{}') |
| | | if (data.code === 200) { |
| | | resolve(data.data) |
| | | } else { |
| | | reject(new Error(data.msg || 'ä¸ä¼ 失败')) |
| | | } |
| | | } catch (err) { |
| | | reject(err) |
| | | } |
| | | }, |
| | | fail: (err) => { |
| | | closeToast() |
| | | reject(err) |
| | | } |
| | | }) |
| | | return |
| | | } |
| | | |
| | | // H5: 使ç¨åå§ Fileï¼input éæ©ï¼ |
| | | const rawFile = fileObj?.file |
| | | if (rawFile) { |
| | | // uni.uploadFile å¨ H5 䏿¯æåç File 对象ï¼è¿éç¨ fetch åé FormData |
| | | const formData = new FormData() |
| | | formData.append('file', rawFile, rawFile.name || 'file.pdf') |
| | | formData.append('salesLedgerId', form.value.salesLedgerId || currentId.value || '') |
| | | fetch(baseUrl, { |
| | | method: 'POST', |
| | | headers: { Authorization: 'Bearer ' + getToken() }, |
| | | body: formData |
| | | }).then(async (res) => { |
| | | closeToast() |
| | | const data = await res.json() |
| | | if (data.code === 200) { |
| | | resolve(data.data) |
| | | } else { |
| | | reject(new Error(data.msg || 'ä¸ä¼ 失败')) |
| | | } |
| | | }).catch((err) => { |
| | | closeToast() |
| | | reject(err) |
| | | }) |
| | | return |
| | | } |
| | | |
| | | closeToast() |
| | | reject(new Error('æªæ¾å°å¯ä¸ä¼ çæä»¶')) |
| | | }) |
| | | } |
| | | |
| | | const afterReadUpload = async (file) => { |
| | | try { |
| | | const files = Array.isArray(file) ? file : file?.file ? [file] : [file] |
| | | for (const f of files) { |
| | | const uploaded = await uploadSingleFile(f) |
| | | fileList.value.push(uploaded) |
| | | } |
| | | showToast('ä¸ä¼ æå') |
| | | } catch (e) { |
| | | showToast('ä¸ä¼ 失败') |
| | | } |
| | | } |
| | | |
| | | const removeUploaded = (index) => { |
| | | fileList.value.splice(index, 1) |
| | | } |
| | | |
| | | const getFileNameFromUrl = (url) => { |
| | | try { if (!url) return ''; return decodeURIComponent(url.split('/').pop()) } catch (e) { return url } |
| | | } |
| | | |
| | | const loadDetail = async (id) => { |
| | | try { |
| | | showLoadingToast({ message: 'å è½½ä¸...' }) |
| | | uni.showLoading({ |
| | | title: 'å è½½ä¸...' |
| | | }); |
| | | const res = await getProductRecordById({ id }) |
| | | const data = res?.data || res |
| | | form.value = { ...data } |
| | |
| | | if (!form.value.invoiceDate) { |
| | | form.value.invoiceDate = dayjs().format('YYYY-MM-DD') |
| | | } |
| | | closeToast() |
| | | uni.hideLoading(); |
| | | } catch (e) { |
| | | closeToast() |
| | | showToast('å 载失败') |
| | | uni.hideLoading(); |
| | | uni.showToast({ |
| | | title: 'å 载失败', |
| | | icon: 'none' |
| | | }); |
| | | } |
| | | } |
| | | |
| | | const submitForm = async () => { |
| | | try { |
| | | showLoadingToast({ message: 'æäº¤ä¸...' }) |
| | | // æäº¤è¡¨åçå
·ä½é»è¾ |
| | | await updateRegistration(form.value) |
| | | closeToast() |
| | | showToast('æäº¤æå') |
| | | uni.showToast({ |
| | | title: 'æäº¤æå', |
| | | icon: 'success' |
| | | }); |
| | | setTimeout(() => { goBack() }, 800) |
| | | } catch (e) { |
| | | closeToast() |
| | | showToast('æäº¤å¤±è´¥ï¼è¯·éè¯') |
| | | uni.showToast({ |
| | | title: 'æäº¤å¤±è´¥ï¼è¯·éè¯', |
| | | icon: 'none' |
| | | }); |
| | | } |
| | | } |
| | | |
| | | // 表åæäº¤ |
| | | const onSubmit = () => { |
| | | formRef.value.validate().then(() => { |
| | | // 表åéªè¯éè¿ï¼æäº¤è¡¨å |
| | | submitForm(); |
| | | }).catch(error => { |
| | | // 表åéªè¯å¤±è´¥ |
| | | console.log('表åéªè¯å¤±è´¥', error); |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | const rowStr = uni.getStorageSync('invoiceLedgerEditRow') |
| | |
| | | // ignore |
| | | } |
| | | } |
| | | }) |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .account-detail { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | padding-bottom: 5rem; |
| | | } |
| | | .uploaded-list { padding: 8px 16px 0 16px; } |
| | | .uploaded-item { display: flex; align-items: center; justify-content: space-between; padding: 8px 0; border-bottom: 1px solid #f5f5f5; } |
| | | .file-name { font-size: 12px; color: #333; margin-right: 8px; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } |
| | | .tip-text { padding: 4px 16px 0 16px; font-size: 12px; color: #888; } |
| | | .footer-btns { position: fixed; left: 0; right: 0; bottom: 0; background: #fff; display: flex; justify-content: space-around; align-items: center; padding: 0.75rem 0; box-shadow: 0 -0.125rem 0.5rem rgba(0,0,0,0.05); z-index: 1000; } |
| | | .cancel-btn { font-weight: 400; font-size: 1rem; color: #FFFFFF; width: 6.375rem; background: #C7C9CC; box-shadow: 0 0.25rem 0.625rem 0 rgba(3,88,185,0.2); border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; } |
| | | .save-btn { font-weight: 400; font-size: 1rem; color: #FFFFFF; width: 14rem; background: linear-gradient( 140deg, #00BAFF 0%, #006CFB 100%); box-shadow: 0 0.25rem 0.625rem 0 rgba(3,88,185,0.2); border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; } |
| | | @import '@/static/scss/form-common.scss'; |
| | | </style> |
| | | |
| | |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader title="æ¥ç¥¨å°è´¦" @back="goBack" /> |
| | | |
| | | <!-- æç´¢åçéåºåï¼ä¿æä¸éå®å°è´¦é£æ ¼ä¸è´ï¼ --> |
| | | <!-- æç´¢åºå --> |
| | | <view class="search-filter-section"> |
| | | <view class="search-bar"> |
| | | <view class="search-input"> |
| | |
| | | @confirm="handleQuery" |
| | | /> |
| | | </view> |
| | | <!-- <view class="filter-button" @click="showFilter = true">--> |
| | | <!-- <up-icon name="list" size="24" color="#999"></up-icon>--> |
| | | <!-- </view>--> |
| | | <view class="filter-button" @click="handleQuery"> |
| | | <up-icon name="search" size="24" color="#999"></up-icon> |
| | | </view> |
| | |
| | | <text class="detail-label">å½å
¥æ¥æ</text> |
| | | <text class="detail-value">{{ item.createdAt }}</text> |
| | | </view> |
| | | |
| | | </view> |
| | | <view class="action-buttons"> |
| | | <van-button |
| | | <u-button |
| | | type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | |
| | | @click="openEdit(item)" |
| | | > |
| | | ç¼è¾ |
| | | </van-button> |
| | | <van-button |
| | | type="danger" |
| | | </u-button> |
| | | <u-button |
| | | type="error" |
| | | size="small" |
| | | plain |
| | | class="action-btn" |
| | |
| | | @click="handleDelete(item)" |
| | | > |
| | | å é¤ |
| | | </van-button> |
| | | <van-button |
| | | </u-button> |
| | | <u-button |
| | | type="default" |
| | | size="small" |
| | | plain |
| | |
| | | @click="openFileActions(item.commonFiles || [])" |
| | | > |
| | | æ¥çéä»¶ |
| | | </van-button> |
| | | <van-button |
| | | </u-button> |
| | | <u-button |
| | | type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | |
| | | @click="openUpload(item)" |
| | | > |
| | | ä¸ä¼ |
| | | </van-button> |
| | | </u-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | |
| | | <text>ææ æ¥ç¥¨å°è´¦æ°æ®</text> |
| | | </view> |
| | | |
| | | <!-- çéå¼¹çª --> |
| | | <van-popup v-model:show="showFilter" position="bottom" round> |
| | | <view class="filter-popup"> |
| | | <van-cell-group title="ç鿡件" inset> |
| | | <van-field |
| | | label="æ¥ç¥¨æ¥æ" |
| | | readonly |
| | | @click="showInvoiceRange = true" |
| | | :placeholder="invoiceRangeLabel || 'è¯·éæ©æ¥æèå´'" |
| | | /> |
| | | <van-field |
| | | label="å½å
¥æ¥æ" |
| | | readonly |
| | | @click="showCreateDatePicker = true" |
| | | :placeholder="searchForm.createTimeStart || 'è¯·éæ©å½å
¥æ¥æ'" |
| | | /> |
| | | <view class="switch-row"> |
| | | <text class="switch-label">䏿¾ç¤ºæå票è¡</text> |
| | | <van-switch v-model="searchForm.status" size="20" /> |
| | | </view> |
| | | </van-cell-group> |
| | | <view class="filter-actions"> |
| | | <van-button @click="resetFilter">éç½®</van-button> |
| | | <van-button type="primary" @click="confirmFilter">ç¡®å®</van-button> |
| | | </view> |
| | | </view> |
| | | </van-popup> |
| | | |
| | | <!-- æ¥åï¼æ¥ç¥¨æ¥æèå´ --> |
| | | <van-popup v-model:show="showInvoiceRange" position="bottom"> |
| | | <van-calendar |
| | | title="éæ©æ¥ç¥¨æ¥æèå´" |
| | | type="range" |
| | | color="#2979ff" |
| | | @confirm="onInvoiceRangeConfirm" |
| | | @cancel="showInvoiceRange = false" |
| | | /> |
| | | </van-popup> |
| | | |
| | | <!-- æ¥æï¼å½å
¥æ¥æ --> |
| | | <van-popup v-model:show="showCreateDatePicker" position="bottom"> |
| | | <van-date-picker |
| | | v-model="currentCreateDate" |
| | | title="éæ©å½å
¥æ¥æ" |
| | | @confirm="onCreateDateConfirm" |
| | | @cancel="showCreateDatePicker = false" |
| | | /> |
| | | </van-popup> |
| | | |
| | | |
| | | |
| | | <!-- åè¡ä¸ä¼ å¼¹çªï¼æ 表åï¼ --> |
| | | <van-popup v-model:show="showUpload" position="bottom" round> |
| | | <u-popup v-model="showUpload" mode="bottom" border-radius="10"> |
| | | <view class="upload-container"> |
| | | <van-cell-group title="ä¸ä¼ éä»¶ï¼ä»
æ¯æ pdfï¼æå¤§10MBï¼æå¤10个ï¼" inset> |
| | | <van-uploader |
| | | accept="*" |
| | | multiple |
| | | :max-count="10" |
| | | :after-read="afterReadRowUpload" |
| | | :before-read="beforeReadPdf" |
| | | /> |
| | | <view class="uploaded-list" v-if="fileList.length"> |
| | | <view class="uploaded-item" v-for="(f, idx) in fileList" :key="idx"> |
| | | <text class="file-name">{{ f.name || getFileNameFromUrl(f.url) }}</text> |
| | | <van-button size="mini" type="danger" plain @click="removeUploaded(idx)">ç§»é¤</van-button> |
| | | </view> |
| | | <view class="popup-header"> |
| | | <text class="popup-title">ä¸ä¼ éä»¶ï¼ä»
æ¯æ pdfï¼æå¤§10MBï¼æå¤10个ï¼</text> |
| | | </view> |
| | | <u-upload |
| | | ref="uploadRef" |
| | | accept="file" |
| | | multiple |
| | | :max-count="10" |
| | | :show-progress="true" |
| | | :before-upload="beforeReadPdf" |
| | | :action="uploadUrl" |
| | | :header="{ Authorization: 'Bearer ' + getToken() }" |
| | | name="file" |
| | | @on-success="onUploadSuccess" |
| | | @on-error="onUploadError" |
| | | /> |
| | | <view class="uploaded-list" v-if="fileList.length"> |
| | | <view class="uploaded-item" v-for="(f, idx) in fileList" :key="idx"> |
| | | <text class="file-name">{{ f.name || getFileNameFromUrl(f.url) }}</text> |
| | | <u-button size="mini" type="error" plain @click="removeUploaded(idx)">ç§»é¤</u-button> |
| | | </view> |
| | | </van-cell-group> |
| | | </view> |
| | | <view class="filter-actions"> |
| | | <van-button @click="showUpload = false">åæ¶</van-button> |
| | | <van-button type="primary" @click="confirmUpload">确认</van-button> |
| | | <u-button @click="showUpload = false" type="default" size="default" style="width: 150px;">åæ¶</u-button> |
| | | <u-button @click="confirmUpload" type="primary" size="default" style="width: 150px;">确认</u-button> |
| | | </view> |
| | | </view> |
| | | </van-popup> |
| | | </u-popup> |
| | | |
| | | <!-- éä»¶åè¡¨éæ© --> |
| | | <van-action-sheet v-model:show="showFileSheet" :actions="fileActions" cancel-text="åæ¶" close-on-click-action @select="onSelectFile" /> |
| | | <u-action-sheet v-model="showFileSheet" :list="fileActions" :cancel-btn="true" @click="onSelectFile" @close="showFileSheet = false" /> |
| | | </view> |
| | | </template> |
| | | |
| | |
| | | import {onShow} from "@dcloudio/uni-app"; |
| | | import {productRecordPage} from "@/api/procurementManagement/procurementInvoiceLedger"; |
| | | import {delRegistration} from "@/api/procurementManagement/invoiceEntry"; |
| | | import PageHeader from '@/components/PageHeader.vue'; |
| | | import FooterButtons from '@/components/FooterButtons.vue'; |
| | | |
| | | const userStore = useUserStore() |
| | | |
| | |
| | | const page = reactive({ current: -1, size: -1 }) |
| | | const searchForm = reactive({ |
| | | searchText: '', |
| | | status: false, |
| | | createTimeStart: '' |
| | | }) |
| | | |
| | | // é¡¶é¨äº¤äº |
| | | const showFilter = ref(false) |
| | | const showInvoiceRange = ref(false) |
| | | const showCreateDatePicker = ref(false) |
| | | const invoiceRangeLabel = ref('') |
| | | const currentCreateDate = ref([new Date().getFullYear(), new Date().getMonth() + 1, new Date().getDate()]) |
| | | |
| | | const currentId = ref('') |
| | | const fileList = ref([]) // è¡ä¸ä¼ æéç¨ä¸ä¼ å表 |
| | | const uploadRef = ref() |
| | | const uploadUrl = config.baseUrl + '/invoiceLedger/uploadFile' |
| | | |
| | | // è¡ä¸ä¼ å¼¹çª |
| | | const showUpload = ref(false) |
| | |
| | | |
| | | const getList = async () => { |
| | | try { |
| | | showLoadingToast({ message: 'å è½½ä¸...' }) |
| | | const { invoiceDate, ...rest } = searchForm |
| | | const res = await productRecordPage({ ...rest, ...page }) |
| | | uni.showLoading({ |
| | | title: 'å è½½ä¸...' |
| | | }); |
| | | const res = await productRecordPage({ ...searchForm, ...page }) |
| | | // å
¼å®¹ä¸åè¿åç»æ |
| | | const records = res?.data?.records || res?.records || res?.data || [] |
| | | const totalVal = res?.data?.total || res?.total || records.length || 0 |
| | | ledgerList.value = records |
| | | total.value = totalVal |
| | | closeToast() |
| | | uni.hideLoading(); |
| | | } catch (e) { |
| | | closeToast() |
| | | uni.hideLoading(); |
| | | showToast('è·åå表失败') |
| | | } |
| | | } |
| | | |
| | | // çéé»è¾ |
| | | const resetFilter = () => { |
| | | searchForm.searchText = '' |
| | | searchForm.status = false |
| | | const start = dayjs().startOf('month').format('YYYY-MM-DD') |
| | | const end = dayjs().endOf('month').format('YYYY-MM-DD') |
| | | searchForm.invoiceDate = [start, end] |
| | | searchForm.invoiceDateStart = start |
| | | searchForm.invoiceDateEnd = end |
| | | searchForm.createTimeStart = '' |
| | | invoiceRangeLabel.value = '' |
| | | } |
| | | const confirmFilter = () => { |
| | | showFilter.value = false |
| | | getList() |
| | | } |
| | | const onInvoiceRangeConfirm = (e) => { |
| | | // e 为 [start, end] ç Date 对象æå符串ï¼uni-app ä¸ Vant Calendar è¿åæ¶é´æ³æ°ç» |
| | | try { |
| | | let start, end |
| | | if (Array.isArray(e)) { |
| | | const [s, ed] = e |
| | | start = dayjs(s).format('YYYY-MM-DD') |
| | | end = dayjs(ed).format('YYYY-MM-DD') |
| | | } else if (e && e.detail && Array.isArray(e.detail)) { |
| | | const [s, ed] = e.detail |
| | | start = dayjs(s).format('YYYY-MM-DD') |
| | | end = dayjs(ed).format('YYYY-MM-DD') |
| | | } |
| | | searchForm.invoiceDateStart = start |
| | | searchForm.invoiceDateEnd = end |
| | | invoiceRangeLabel.value = `${start} è³ ${end}` |
| | | showInvoiceRange.value = false |
| | | } catch (err) { |
| | | showInvoiceRange.value = false |
| | | } |
| | | } |
| | | const onCreateDateConfirm = ({ selectedValues }) => { |
| | | try { |
| | | searchForm.createTimeStart = selectedValues.join('-') |
| | | currentCreateDate.value = selectedValues |
| | | showCreateDatePicker.value = false |
| | | } catch (err) { |
| | | showCreateDatePicker.value = false |
| | | } |
| | | } |
| | | |
| | |
| | | success: async (res) => { |
| | | if (res.confirm) { |
| | | try { |
| | | showLoadingToast({ message: 'å¤çä¸...' }) |
| | | uni.showLoading({ |
| | | title: 'å¤çä¸...' |
| | | }); |
| | | await delRegistration(ids) |
| | | closeToast() |
| | | uni.hideLoading(); |
| | | showToast('å 餿å') |
| | | await getList() |
| | | } catch (e) { |
| | | closeToast() |
| | | uni.hideLoading(); |
| | | showToast('å é¤å¤±è´¥ï¼è¯·éè¯') |
| | | } |
| | | } |
| | |
| | | const confirmUpload = async () => { |
| | | try { |
| | | const payload = { fileList: fileList.value, id: currentId.value } |
| | | showLoadingToast({ message: 'æäº¤ä¸...' }) |
| | | uni.showLoading({ |
| | | title: 'æäº¤ä¸...' |
| | | }); |
| | | await commitFile(payload) |
| | | closeToast() |
| | | uni.hideLoading(); |
| | | showToast('æäº¤æå') |
| | | showUpload.value = false |
| | | fileList.value = [] |
| | | currentId.value = '' |
| | | getList() |
| | | } catch (e) { |
| | | closeToast() |
| | | uni.hideLoading(); |
| | | showToast('æäº¤å¤±è´¥ï¼è¯·éè¯') |
| | | } |
| | | } |
| | |
| | | return true |
| | | } |
| | | |
| | | const uploadSingleFile = async (fileObj) => { |
| | | return new Promise((resolve, reject) => { |
| | | showLoadingToast({ message: 'æ£å¨ä¸ä¼ ...' }) |
| | | uni.uploadFile({ |
| | | url: config.baseUrl + '/invoiceLedger/uploadFile', |
| | | filePath: fileObj.url || fileObj.file?.path || fileObj.tempFilePath, |
| | | name: 'file', |
| | | header: { Authorization: 'Bearer ' + getToken() }, |
| | | success: (res) => { |
| | | closeToast() |
| | | try { |
| | | const data = JSON.parse(res.data || '{}') |
| | | if (data.code === 200) { |
| | | resolve(data.data) |
| | | } else { |
| | | reject(new Error(data.msg || 'ä¸ä¼ 失败')) |
| | | } |
| | | } catch (err) { |
| | | reject(err) |
| | | } |
| | | }, |
| | | fail: (err) => { |
| | | closeToast() |
| | | reject(err) |
| | | } |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | const afterReadEditUpload = async (file) => { |
| | | // uview-plus çä¸ä¼ æååè° |
| | | const onUploadSuccess = (res, file) => { |
| | | try { |
| | | const files = Array.isArray(file) ? file : file?.file ? [file] : [file] |
| | | for (const f of files) { |
| | | const uploaded = await uploadSingleFile(f) |
| | | fileList.value.push(uploaded) |
| | | const data = JSON.parse(res.data || '{}') |
| | | if (data.code === 200) { |
| | | fileList.value.push(data.data) |
| | | showToast('ä¸ä¼ æå') |
| | | } else { |
| | | showToast('ä¸ä¼ 失败: ' + (data.msg || 'æªç¥é误')) |
| | | } |
| | | showToast('ä¸ä¼ æå') |
| | | } catch (e) { |
| | | } catch (err) { |
| | | showToast('ä¸ä¼ 失败') |
| | | } |
| | | } |
| | | |
| | | const afterReadRowUpload = async (file) => { |
| | | try { |
| | | const files = Array.isArray(file) ? file : file?.file ? [file] : [file] |
| | | for (const f of files) { |
| | | const uploaded = await uploadSingleFile(f) |
| | | fileList.value.push(uploaded) |
| | | } |
| | | showToast('ä¸ä¼ æå') |
| | | } catch (e) { |
| | | showToast('ä¸ä¼ 失败') |
| | | } |
| | | // uview-plus çä¸ä¼ 失败åè° |
| | | const onUploadError = (err) => { |
| | | showToast('ä¸ä¼ 失败') |
| | | } |
| | | |
| | | const removeUploaded = (index) => { |
| | |
| | | // éä»¶æ¥ç |
| | | const openFileActions = (commonFiles) => { |
| | | currentFilesToOpen = commonFiles || [] |
| | | fileActions.value = (commonFiles || []).map((f, idx) => ({ name: getFileNameFromUrl(f.url || ''), index: idx })) |
| | | fileActions.value = (commonFiles || []).map((f, idx) => ({ |
| | | title: getFileNameFromUrl(f.url || ''), |
| | | index: idx |
| | | })) |
| | | showFileSheet.value = true |
| | | } |
| | | const onSelectFile = async (action) => { |
| | | try { |
| | | const item = currentFilesToOpen[action.index] |
| | | if (!item || !item.url) return |
| | | showLoadingToast({ message: 'ä¸è½½ä¸...' }) |
| | | uni.showLoading({ |
| | | title: 'ä¸è½½ä¸...' |
| | | }); |
| | | uni.downloadFile({ |
| | | url: item.url, |
| | | success: (res) => { |
| | | closeToast() |
| | | uni.hideLoading(); |
| | | if (res.statusCode === 200) { |
| | | uni.openDocument({ filePath: res.tempFilePath }) |
| | | } else { |
| | |
| | | } |
| | | }, |
| | | fail: () => { |
| | | closeToast() |
| | | uni.hideLoading(); |
| | | showToast('ä¸è½½å¤±è´¥') |
| | | } |
| | | }) |
| | | } catch (e) { |
| | | closeToast() |
| | | uni.hideLoading(); |
| | | showToast('æå¼å¤±è´¥') |
| | | } |
| | | } |
| | |
| | | padding: 12px 12px 20px; |
| | | } |
| | | |
| | | .switch-row { |
| | | padding: 12px 16px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | .popup-header { |
| | | padding: 10px 16px; |
| | | border-bottom: 1px solid #f5f5f5; |
| | | } |
| | | |
| | | .switch-label { |
| | | font-size: 14px; |
| | | .popup-title { |
| | | font-size: 16px; |
| | | font-weight: 500; |
| | | color: #333; |
| | | } |
| | | |
| | | .filter-actions { |
| | | display: flex; |
| | | gap: 12px; |
| | | padding: 12px 16px 16px; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .edit-container { |
| | | padding-bottom: 5rem; |
| | | } |
| | | |
| | | .uploaded-list { |
| | |
| | | color: #888; |
| | | } |
| | | |
| | | .filter-actions { |
| | | display: flex; |
| | | gap: 12px; |
| | | padding: 12px 16px 16px; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .footer-btns { |
| | | position: fixed; |
| | | left: 0; |
| | |
| | | <PageHeader title="å°è´¦è¯¦æ
" @back="goBack" /> |
| | | |
| | | <!-- 表ååºå --> |
| | | <van-form @submit="onSubmit" label-width="110px" input-align="right" style="margin-top: 10px" error-message-align="right" scroll-to-error scroll-to-error-position="center"> |
| | | <van-field label="éè´ååå·" name="purchaseContractNumber" borderBottom="true" v-model="form.purchaseContractNumber" placeholder="èªå¨çæ" :rules="[{ required: true, message: '请è¾å
¥' }]"> |
| | | </van-field> |
| | | <van-field |
| | | v-model="form.salesContractNo" |
| | | is-link |
| | | readonly |
| | | name="salesContractNo" |
| | | label="éå®ååå·" |
| | | required |
| | | placeholder="ç¹å»éæ©éå®ååå·" |
| | | :rules="[{ required: true, message: 'è¯·éæ©éå®ååå·' }]" |
| | | @click="showPicker = true" |
| | | /> |
| | | <van-field |
| | | v-model="form.supplierName" |
| | | is-link |
| | | readonly |
| | | required |
| | | name="supplierName" |
| | | label="ä¾åºååç§°" |
| | | placeholder="ç¹å»éæ©ä¾åºå" |
| | | :rules="[{ required: true, message: 'è¯·éæ©ä¾åºå' }]" |
| | | @click="showCustomerPicker = true" |
| | | /> |
| | | <van-field label="项ç®åç§°" name="projectName" borderBottom="true" v-model="form.projectName" placeholder="请è¾å
¥é¡¹ç®åç§°" :rules="[{ required: true, message: '项ç®åç§°ä¸è½ä¸ºç©º' }]" required> |
| | | </van-field> |
| | | <van-field label="仿¬¾æ¹å¼" name="paymentMethod" borderBottom="true" v-model="form.paymentMethod" placeholder="请è¾å
¥ä»æ¬¾æ¹å¼"> |
| | | </van-field> |
| | | <van-field label="å½å
¥äºº" name="recorderName" borderBottom="true" v-model="form.recorderName" placeholder="请è¾å
¥" disabled> |
| | | </van-field> |
| | | <van-field label="å½å
¥æ¥æ" name="entryDate" borderBottom="true" v-model="form.entryDate" placeholder="请è¾å
¥" disabled> |
| | | </van-field> |
| | | <van-popup v-model:show="showPicker" destroy-on-close position="bottom"> |
| | | <van-picker |
| | | :columns="salesContractList" |
| | | v-model="pickerValue" |
| | | @confirm="onConfirm" |
| | | @cancel="showPicker = false" |
| | | <up-form @submit="onSubmit" label-width="110" ref="formRef" :rules="rules" :model="form"> |
| | | <up-form-item label="éè´ååå·" prop="purchaseContractNumber"> |
| | | <up-input v-model="form.purchaseContractNumber" placeholder="èªå¨çæ" disabled /> |
| | | </up-form-item> |
| | | <up-form-item |
| | | label="éå®ååå·" |
| | | prop="salesContractNo" |
| | | required |
| | | @click="showPicker = true" |
| | | > |
| | | <up-input |
| | | v-model="form.salesContractNo" |
| | | readonly="" |
| | | @click="showPicker = true" |
| | | placeholder="ç¹å»éæ©éå®ååå·" |
| | | /> |
| | | <template #right> |
| | | <up-icon |
| | | name="arrow-right" |
| | | @click="showPicker = true" |
| | | ></up-icon> |
| | | </template> |
| | | </up-form-item> |
| | | <up-form-item |
| | | label="ä¾åºååç§°" |
| | | prop="supplierName" |
| | | required |
| | | @click="showCustomerPicker = true" |
| | | > |
| | | <up-input |
| | | v-model="form.supplierName" |
| | | readonly="" |
| | | @click="showCustomerPicker = true" |
| | | placeholder="ç¹å»éæ©ä¾åºå" |
| | | /> |
| | | <template #right> |
| | | <up-icon |
| | | name="arrow-right" |
| | | @click="showCustomerPicker = true" |
| | | ></up-icon> |
| | | </template> |
| | | </up-form-item> |
| | | <up-form-item label="项ç®åç§°" prop="projectName" required > |
| | | <up-input |
| | | v-model="form.projectName" |
| | | placeholder="请è¾å
¥é¡¹ç®åç§°" |
| | | /> |
| | | </up-form-item> |
| | | <up-form-item label="仿¬¾æ¹å¼" prop="paymentMethod" > |
| | | <up-input v-model="form.paymentMethod" placeholder="请è¾å
¥ä»æ¬¾æ¹å¼" /> |
| | | </up-form-item> |
| | | <up-form-item label="å½å
¥äºº" prop="recorderName" > |
| | | <up-input v-model="form.recorderName" placeholder="请è¾å
¥" disabled /> |
| | | </up-form-item> |
| | | <up-form-item label="å½å
¥æ¥æ" prop="entryDate" > |
| | | <up-input v-model="form.entryDate" placeholder="请è¾å
¥" disabled /> |
| | | </up-form-item> |
| | | |
| | | <!-- éå®ååå·éæ© --> |
| | | <up-action-sheet |
| | | :show="showPicker" |
| | | :actions="salesContractActionList" |
| | | title="éæ©éå®ååå·" |
| | | @select="onSalesmanSelect" |
| | | @close="showPicker = false" |
| | | /> |
| | | </van-popup> |
| | | <van-popup v-model:show="showCustomerPicker" destroy-on-close position="bottom"> |
| | | <van-picker |
| | | :columns="supplierList" |
| | | v-model="pickerCustomerValue" |
| | | @confirm="onCustomerConfirm" |
| | | @cancel="showCustomerPicker = false" |
| | | |
| | | <!-- ä¾åºåéæ© --> |
| | | <up-action-sheet |
| | | :show="showCustomerPicker" |
| | | :actions="supplierActionList" |
| | | title="éæ©ä¾åºå" |
| | | @select="onCustomerSelect" |
| | | @close="showCustomerPicker = false" |
| | | /> |
| | | </van-popup> |
| | | |
| | | <!-- 产åå¤§ç±»éæ©å¨ --> |
| | | <van-popup v-model:show="showCategoryPicker" destroy-on-close position="bottom"> |
| | | <!-- 头鍿é®åºå --> |
| | | <view class="popup-header"> |
| | | <view @click="showCategoryPicker = false" class="cancelButton">åæ¶</view> |
| | | <view @click="confirmCategorySelection" class="confirmButton">ç¡®å®</view> |
| | | </view> |
| | | <up-tree |
| | | :data="productOptions" |
| | | :props="defaultProps" |
| | | show-checkbox |
| | | default-expand-all |
| | | check-strictly |
| | | @check-change="onCategoryConfirm" |
| | | |
| | | <!-- 产åå¤§ç±»éæ©å¨ --> |
| | | <up-popup :show="showCategoryPicker" mode="bottom"> |
| | | <!-- 头鍿é®åºå --> |
| | | <view class="popup-header"> |
| | | <view @click="showCategoryPicker = false" class="cancelButton">åæ¶</view> |
| | | <view @click="confirmCategorySelection" class="confirmButton">ç¡®å®</view> |
| | | </view> |
| | | <u-tree |
| | | :data="productOptions" |
| | | :props="defaultProps" |
| | | show-checkbox |
| | | default-expand-all |
| | | check-strictly |
| | | @check-change="onCategoryConfirm" |
| | | /> |
| | | </up-popup> |
| | | |
| | | <!-- è§æ ¼åå·éæ©å¨ --> |
| | | <up-action-sheet |
| | | :show="showSpecificationPicker" |
| | | :actions="specificationActionList" |
| | | title="éæ©è§æ ¼åå·" |
| | | @select="onSpecificationSelect" |
| | | @close="showSpecificationPicker = false" |
| | | /> |
| | | </van-popup> |
| | | |
| | | <!-- è§æ ¼åå·éæ©å¨ --> |
| | | <van-popup v-model:show="showSpecificationPicker" destroy-on-close position="bottom"> |
| | | <van-picker |
| | | :columns="modelOptions" |
| | | v-model="pickerSpecificationValue" |
| | | @confirm="onSpecificationConfirm" |
| | | @cancel="showSpecificationPicker = false" |
| | | |
| | | <!-- ç¨çéæ©å¨ --> |
| | | <up-action-sheet |
| | | :show="showTaxRatePicker" |
| | | :actions="taxRateActionList" |
| | | title="éæ©ç¨ç" |
| | | @select="onTaxRateSelect" |
| | | @close="showTaxRatePicker = false" |
| | | /> |
| | | </van-popup> |
| | | |
| | | <!-- ç¨çéæ©å¨ --> |
| | | <van-popup v-model:show="showTaxRatePicker" destroy-on-close position="bottom"> |
| | | <van-picker |
| | | :columns="taxRateOptions" |
| | | v-model="pickerTaxRateValue" |
| | | @confirm="onTaxRateConfirm" |
| | | @cancel="showTaxRatePicker = false" |
| | | |
| | | <!-- å票类åéæ©å¨ --> |
| | | <up-action-sheet |
| | | :show="showInvoiceTypePicker" |
| | | :actions="invoiceTypeActionList" |
| | | title="éæ©å票类å" |
| | | @select="onInvoiceTypeSelect" |
| | | @close="showInvoiceTypePicker = false" |
| | | /> |
| | | </van-popup> |
| | | |
| | | <!-- å票类åéæ©å¨ --> |
| | | <van-popup v-model:show="showInvoiceTypePicker" destroy-on-close position="bottom"> |
| | | <van-picker |
| | | :columns="invoiceTypeOptions" |
| | | v-model="pickerInvoiceTypeValue" |
| | | @confirm="onInvoiceTypeConfirm" |
| | | @cancel="showInvoiceTypePicker = false" |
| | | /> |
| | | </van-popup> |
| | | <!-- 产åä¿¡æ¯ --> |
| | | <view class="product-section"> |
| | | <view class="section-header"> |
| | | <text class="section-title">产åä¿¡æ¯</text> |
| | | <van-button type="primary" size="small" @click="addProduct" class="add-btn" icon="plus" v-if="operationType !== 'view'">æ°å¢</van-button> |
| | | </view> |
| | | <view class="product-card" v-for="(product, idx) in productData" :key="idx"> |
| | | <!-- 产åç±» --> |
| | | <view class="product-header"> |
| | | <view class="product-title"> |
| | | <van-icon name="description" color="#2979ff" size="15" /> |
| | | <text class="product-productCategory">产å {{ idx + 1 }}</text> |
| | | <!-- 产åä¿¡æ¯ --> |
| | | <view class="product-section"> |
| | | <view class="section-header"> |
| | | <view> |
| | | <text class="section-title">产åä¿¡æ¯</text> |
| | | </view> |
| | | <!-- æä½æé® --> |
| | | <view class="product-actions" v-if="operationType !== 'view'"> |
| | | <van-button type="danger" size="mini" @click="removeProduct(idx)" class="del-btn" icon="delete">å é¤</van-button> |
| | | <view> |
| | | <up-button type="primary" size="small" @click="addProduct" class="add-btn" v-if="operationType !== 'view'"> |
| | | æ°å¢ |
| | | </up-button> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 产åä¿¡æ¯è¡¨å --> |
| | | <view class="product-form"> |
| | | <!-- 产å大类 --> |
| | | <van-field |
| | | v-model="product.productCategory" |
| | | is-link |
| | | readonly |
| | | name="productCategory" |
| | | label="产å大类" |
| | | required |
| | | placeholder="è¯·éæ©" |
| | | :rules="[{ required: true, message: 'è¯·éæ©' }]" |
| | | @click="openCategoryPicker(idx)" |
| | | /> |
| | | <view class="product-card" v-for="(product, idx) in productData" :key="idx"> |
| | | <!-- 产åç±» --> |
| | | <view class="product-header"> |
| | | <view class="product-title"> |
| | | <up-icon name="file-text" size="16" color="#2979ff"></up-icon> |
| | | <text class="product-productCategory">产å {{ idx + 1 }}</text> |
| | | </view> |
| | | <!-- æä½æé® --> |
| | | <view class="product-actions" v-if="operationType !== 'view'"> |
| | | <up-button type="error" size="mini" @click="removeProduct(idx)" class="del-btn"> |
| | | å é¤ |
| | | </up-button> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- è§æ ¼åå· --> |
| | | <van-field |
| | | v-model="product.specificationModel" |
| | | is-link |
| | | readonly |
| | | name="specificationModel" |
| | | label="è§æ ¼åå·" |
| | | required |
| | | :rules="[{ required: true, message: 'è¯·éæ©' }]" |
| | | placeholder="è¯·éæ©" |
| | | @click="openSpecificationPicker(idx)" |
| | | /> |
| | | |
| | | <!-- åä½ --> |
| | | <van-field |
| | | v-model="product.unit" |
| | | name="unit" |
| | | label="åä½" |
| | | required |
| | | :rules="[{ required: true, message: '请è¾å
¥' }]" |
| | | placeholder="请è¾å
¥" |
| | | /> |
| | | |
| | | <!-- ç¨ç --> |
| | | <van-field |
| | | v-model="product.taxRate" |
| | | is-link |
| | | readonly |
| | | name="taxRate" |
| | | label="ç¨ç(%)" |
| | | required |
| | | :rules="[{ required: true, message: 'è¯·éæ©' }]" |
| | | placeholder="è¯·éæ©" |
| | | @click="openTaxRatePicker(idx)" |
| | | /> |
| | | |
| | | <!-- å«ç¨åä»· --> |
| | | <van-field |
| | | v-model="product.taxInclusiveUnitPrice" |
| | | name="taxInclusiveUnitPrice" |
| | | label="å«ç¨åä»·(å
)" |
| | | type="number" |
| | | required |
| | | :rules="[{ required: true, message: '请è¾å
¥' }]" |
| | | placeholder="请è¾å
¥" |
| | | @blur="formatTaxPrice(idx)" |
| | | /> |
| | | |
| | | <!-- æ°é --> |
| | | <van-field |
| | | v-model="product.quantity" |
| | | name="quantity" |
| | | label="æ°é" |
| | | type="number" |
| | | :rules="[{ required: true, message: '请è¾å
¥' }]" |
| | | required |
| | | placeholder="请è¾å
¥" |
| | | @blur="formatAmount(idx)" |
| | | /> |
| | | |
| | | <!-- å«ç¨æ»ä»· --> |
| | | <van-field |
| | | v-model="product.taxInclusiveTotalPrice" |
| | | name="taxInclusiveTotalPrice" |
| | | label="å«ç¨æ»ä»·(å
)" |
| | | type="number" |
| | | :rules="[{ required: true, message: '请è¾å
¥' }]" |
| | | required |
| | | placeholder="请è¾å
¥" |
| | | @blur="formatTaxTotal(idx)" |
| | | /> |
| | | |
| | | <!-- ä¸å«ç¨æ»ä»· --> |
| | | <van-field |
| | | v-model="product.taxExclusiveTotalPrice" |
| | | name="taxExclusiveTotalPrice" |
| | | label="ä¸å«ç¨æ»ä»·(å
)" |
| | | type="number" |
| | | required |
| | | :rules="[{ required: true, message: '请è¾å
¥' }]" |
| | | placeholder="请è¾å
¥" |
| | | @blur="formatNoTaxTotal(idx)" |
| | | /> |
| | | |
| | | <!-- å票类å --> |
| | | <van-field |
| | | v-model="product.invoiceType" |
| | | is-link |
| | | readonly |
| | | name="invoiceType" |
| | | label="å票类å" |
| | | :rules="[{ required: true, message: 'è¯·éæ©' }]" |
| | | required |
| | | placeholder="è¯·éæ©" |
| | | @click="openInvoiceTypePicker(idx)" |
| | | /> |
| | | <!-- 产åä¿¡æ¯è¡¨å --> |
| | | <view class="product-form"> |
| | | <!-- 产å大类 --> |
| | | <up-form-item |
| | | label="产å大类" |
| | | prop="productCategory" |
| | | required |
| | | :rules="productRules" |
| | | > |
| | | <up-input |
| | | v-model="product.productCategory" |
| | | readonly |
| | | placeholder="è¯·éæ©" |
| | | @click="openCategoryPicker(idx)" |
| | | /> |
| | | <template #right> |
| | | <up-icon |
| | | name="arrow-right" |
| | | @click="showCategoryPicker = true" |
| | | ></up-icon> |
| | | </template> |
| | | </up-form-item> |
| | | |
| | | <!-- è§æ ¼åå· --> |
| | | <up-form-item |
| | | label="è§æ ¼åå·" |
| | | prop="specificationModel" |
| | | required |
| | | :rules="productRules" |
| | | > |
| | | <up-input |
| | | v-model="product.specificationModel" |
| | | readonly |
| | | placeholder="è¯·éæ©" |
| | | @click="openSpecificationPicker(idx)" |
| | | /> |
| | | <template #right> |
| | | <up-icon |
| | | name="arrow-right" |
| | | @click="showSpecificationPicker = true" |
| | | ></up-icon> |
| | | </template> |
| | | </up-form-item> |
| | | |
| | | <!-- åä½ --> |
| | | <up-form-item |
| | | label="åä½" |
| | | prop="unit" |
| | | required |
| | | :rules="productRules" |
| | | > |
| | | <up-input |
| | | v-model="product.unit" |
| | | placeholder="请è¾å
¥" |
| | | /> |
| | | </up-form-item> |
| | | |
| | | <!-- ç¨ç --> |
| | | <up-form-item |
| | | label="ç¨ç(%)" |
| | | prop="taxRate" |
| | | required |
| | | :rules="productRules" |
| | | > |
| | | <up-input |
| | | v-model="product.taxRate" |
| | | readonly |
| | | placeholder="è¯·éæ©" |
| | | @click="openTaxRatePicker(idx)" |
| | | /> |
| | | <template #right> |
| | | <up-icon |
| | | name="arrow-right" |
| | | @click="showTaxRatePicker = true" |
| | | ></up-icon> |
| | | </template> |
| | | </up-form-item> |
| | | |
| | | <!-- å«ç¨åä»· --> |
| | | <up-form-item |
| | | label="å«ç¨åä»·(å
)" |
| | | prop="taxInclusiveUnitPrice" |
| | | required |
| | | :rules="productRules" |
| | | > |
| | | <up-input |
| | | v-model="product.taxInclusiveUnitPrice" |
| | | type="number" |
| | | placeholder="请è¾å
¥" |
| | | @blur="formatTaxPrice(idx)" |
| | | /> |
| | | </up-form-item> |
| | | |
| | | <!-- æ°é --> |
| | | <up-form-item |
| | | label="æ°é" |
| | | prop="quantity" |
| | | required |
| | | :rules="productRules" |
| | | > |
| | | <up-input |
| | | v-model="product.quantity" |
| | | type="number" |
| | | placeholder="请è¾å
¥" |
| | | @blur="formatAmount(idx)" |
| | | /> |
| | | </up-form-item> |
| | | |
| | | <!-- å«ç¨æ»ä»· --> |
| | | <up-form-item |
| | | label="å«ç¨æ»ä»·(å
)" |
| | | prop="taxInclusiveTotalPrice" |
| | | required |
| | | :rules="productRules" |
| | | > |
| | | <up-input |
| | | v-model="product.taxInclusiveTotalPrice" |
| | | type="number" |
| | | placeholder="请è¾å
¥" |
| | | @blur="formatTaxTotal(idx)" |
| | | /> |
| | | </up-form-item> |
| | | |
| | | <!-- ä¸å«ç¨æ»ä»· --> |
| | | <up-form-item |
| | | label="ä¸å«ç¨æ»ä»·(å
)" |
| | | prop="taxExclusiveTotalPrice" |
| | | required |
| | | :rules="productRules" |
| | | > |
| | | <up-input |
| | | v-model="product.taxExclusiveTotalPrice" |
| | | type="number" |
| | | placeholder="请è¾å
¥" |
| | | @blur="formatNoTaxTotal(idx)" |
| | | /> |
| | | </up-form-item> |
| | | |
| | | <!-- å票类å --> |
| | | <up-form-item |
| | | label="å票类å" |
| | | prop="invoiceType" |
| | | required |
| | | :rules="productRules" |
| | | > |
| | | <up-input |
| | | v-model="product.invoiceType" |
| | | readonly |
| | | placeholder="è¯·éæ©" |
| | | @click="openInvoiceTypePicker(idx)" |
| | | /> |
| | | <template #right> |
| | | <up-icon |
| | | name="arrow-right" |
| | | @click="showInvoiceTypePicker = true" |
| | | ></up-icon> |
| | | </template> |
| | | </up-form-item> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view class="footer-btns" v-if="operationType !== 'view'"> |
| | | <van-button class="cancel-btn" @click="goBack">åæ¶</van-button> |
| | | <van-button class="save-btn" native-type="submit" form-type="submit">ä¿å</van-button> |
| | | </view> |
| | | </van-form> |
| | | |
| | | <!-- 使ç¨å
Œ
±åºé¨æé®ç»ä»¶ --> |
| | | <FooterButtons |
| | | :show="operationType !== 'view'" |
| | | cancelText="åæ¶" |
| | | confirmText="ä¿å" |
| | | @cancel="goBack" |
| | | @confirm="onSubmit" |
| | | /> |
| | | </up-form> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {onMounted, ref} from 'vue'; |
| | | import {onMounted, ref, computed} from 'vue'; |
| | | import { modelList, productTreeList } from "@/api/basicData/product.js"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import {calculateTaxExclusiveTotalPrice} from "@/utils/summarizeTable"; |
| | | import {formatDateToYMD} from '@/utils/ruoyi' |
| | | import { |
| | | addOrEditPurchase, createPurchaseNo, |
| | | getOptions, |
| | | getPurchaseById, |
| | | getSalesNo |
| | | } from "@/api/procurementManagement/procurementLedger"; |
| | | import PageHeader from '@/components/PageHeader.vue'; |
| | | import FooterButtons from '@/components/FooterButtons.vue'; |
| | | |
| | | // è·å页é¢åæ° |
| | | const operationType = ref(''); |
| | | const editData = ref(null); |
| | | const formRef = ref(null); |
| | | |
| | | const userStore = useUserStore() |
| | | const form = ref({ |
| | |
| | | recorderName: '', |
| | | entryDate: '', |
| | | }); |
| | | const pickerValue = ref(['']); |
| | | const pickerDateValue = ref([]); |
| | | const showPicker = ref(false); |
| | | const pickerCustomerValue = ref(['']); |
| | | const showCustomerPicker = ref(false); |
| | | const salesContractList = ref([]); |
| | | const supplierList = ref([]); |
| | | const productData = ref([]); |
| | | |
| | | // 计ç®éå®ååå·éæ©å表 |
| | | const salesContractActionList = computed(() => { |
| | | return salesContractList.value.map(item => ({ |
| | | name: item.text, |
| | | value: item.value |
| | | })) |
| | | }) |
| | | |
| | | // 计ç®ä¾åºåéæ©å表 |
| | | const supplierActionList = computed(() => { |
| | | return supplierList.value.map(item => ({ |
| | | name: item.text, |
| | | value: item.value |
| | | })) |
| | | }) |
| | | |
| | | // éæ©å¨ç¸å
³åé |
| | | const showCategoryPicker = ref(false); |
| | | const showSpecificationPicker = ref(false); |
| | | const showTaxRatePicker = ref(false); |
| | | const showInvoiceTypePicker = ref(false); |
| | | const pickerSpecificationValue = ref(['']); |
| | | const pickerTaxRateValue = ref(['']); |
| | | const pickerInvoiceTypeValue = ref(['']); |
| | | const currentProductIndex = ref(0); |
| | | |
| | | // éé¡¹æ°æ® |
| | |
| | | }); |
| | | |
| | | const modelOptions = ref([]); |
| | | // 鲿¢å¾ªç¯è®¡ç®çæ å¿ |
| | | const taxRateOptions = ref([ |
| | | { text: '1', value: '1' }, |
| | | { text: '6', value: '6' }, |
| | |
| | | { text: '墿®ç¥¨', value: '墿®ç¥¨' }, |
| | | { text: 'å¢ä¸ç¥¨', value: 'å¢ä¸ç¥¨' }, |
| | | ]); |
| | | |
| | | // 计ç®è§æ ¼åå·éæ©å表 |
| | | const specificationActionList = computed(() => { |
| | | return modelOptions.value.map(model => ({ |
| | | name: model.text, |
| | | value: model.value, |
| | | unit: model.unit |
| | | })) |
| | | }) |
| | | |
| | | // 计ç®ç¨çéæ©å表 |
| | | const taxRateActionList = computed(() => { |
| | | return taxRateOptions.value.map(rate => ({ |
| | | name: rate.text, |
| | | value: rate.value |
| | | })) |
| | | }) |
| | | |
| | | // 计ç®å票类åéæ©å表 |
| | | const invoiceTypeActionList = computed(() => { |
| | | return invoiceTypeOptions.value.map(type => ({ |
| | | name: type.text, |
| | | value: type.value |
| | | })) |
| | | }) |
| | | |
| | | // è¡¨åæ ¡éªè§å |
| | | const rules = { |
| | | salesContractNo: [ |
| | | { required: true, message: 'è¯·éæ©éå®ååå·', trigger: 'blur' } |
| | | ], |
| | | supplierName: [ |
| | | { required: true, message: 'è¯·éæ©ä¾åºååç§°', trigger: 'blur' } |
| | | ], |
| | | projectName: [ |
| | | { required: true, message: '请è¾å
¥é¡¹ç®åç§°', trigger: 'blur' } |
| | | ] |
| | | }; |
| | | |
| | | // 产åä¿¡æ¯æ ¡éªè§å |
| | | const productRules = { |
| | | productCategory: [ |
| | | { required: true, message: 'è¯·éæ©äº§å大类', trigger: 'blur' } |
| | | ], |
| | | specificationModel: [ |
| | | { required: true, message: 'è¯·éæ©è§æ ¼åå·', trigger: 'blur' } |
| | | ], |
| | | unit: [ |
| | | { required: true, message: '请è¾å
¥åä½', trigger: 'blur' } |
| | | ], |
| | | taxRate: [ |
| | | { required: true, message: 'è¯·éæ©ç¨ç', trigger: 'blur' } |
| | | ], |
| | | taxInclusiveUnitPrice: [ |
| | | { required: true, message: '请è¾å
¥å«ç¨åä»·', trigger: 'blur' }, |
| | | { type: 'number', min: 0, message: 'å«ç¨åä»·å¿
须大äº0', trigger: 'blur' } |
| | | ], |
| | | quantity: [ |
| | | { required: true, message: '请è¾å
¥æ°é', trigger: 'blur' }, |
| | | { type: 'number', min: 0, message: 'æ°éå¿
须大äº0', trigger: 'blur' } |
| | | ], |
| | | taxInclusiveTotalPrice: [ |
| | | { required: true, message: '请è¾å
¥å«ç¨æ»ä»·', trigger: 'blur' }, |
| | | { type: 'number', min: 0, message: 'å«ç¨æ»ä»·å¿
须大äº0', trigger: 'blur' } |
| | | ], |
| | | taxExclusiveTotalPrice: [ |
| | | { required: true, message: '请è¾å
¥ä¸å«ç¨æ»ä»·', trigger: 'blur' }, |
| | | { type: 'number', min: 0, message: 'ä¸å«ç¨æ»ä»·å¿
须大äº0', trigger: 'blur' } |
| | | ], |
| | | invoiceType: [ |
| | | { required: true, message: 'è¯·éæ©å票类å', trigger: 'blur' } |
| | | ] |
| | | }; |
| | | |
| | | const addProduct = () => { |
| | | if (productData.value === null) { |
| | |
| | | invoiceType: '' |
| | | }); |
| | | }; |
| | | const onConfirm = ({ selectedValues, selectedOptions }) => { |
| | | form.value.salesContractNo = selectedOptions[0]?.text; |
| | | form.value.salesLedgerId = selectedOptions[0]?.value; |
| | | pickerValue.value = [selectedValues[0]]; |
| | | |
| | | // éå®ååå·éæ©äºä»¶ |
| | | const onSalesmanSelect = (item) => { |
| | | form.value.salesContractNo = item.name |
| | | // æ¥æ¾å¯¹åºçid |
| | | const selectedItem = salesContractList.value.find(contract => contract.text === item.name); |
| | | if (selectedItem) { |
| | | form.value.salesLedgerId = selectedItem.value; |
| | | } |
| | | showPicker.value = false; |
| | | }; |
| | | const onCustomerConfirm = ({ selectedValues, selectedOptions }) => { |
| | | form.value.supplierName = selectedOptions[0]?.text; |
| | | form.value.supplierId = selectedOptions[0]?.value; |
| | | pickerCustomerValue.value = [selectedValues[0]]; |
| | | } |
| | | |
| | | // ä¾åºåéæ©äºä»¶ |
| | | const onCustomerSelect = (item) => { |
| | | form.value.supplierName = item.name |
| | | // æ¥æ¾å¯¹åºçid |
| | | const selectedItem = supplierList.value.find(supplier => supplier.text === item.name); |
| | | if (selectedItem) { |
| | | form.value.supplierId = selectedItem.value; |
| | | } |
| | | showCustomerPicker.value = false; |
| | | }; |
| | | } |
| | | |
| | | const removeProduct = (idx) => { |
| | | productData.value.splice(idx, 1); |
| | | }; |
| | |
| | | selectedCategoryNode.value = null; |
| | | productData.value[currentProductIndex.value].specificationModel = '' |
| | | productData.value[currentProductIndex.value].productModelId = '' |
| | | productData.value[currentProductIndex.value].pickerSpecificationValue = [''] |
| | | getModels(id) |
| | | } |
| | | showCategoryPicker.value = false; |
| | | }; |
| | | |
| | | // è·åè§æ ¼åå· |
| | | const getModels = (value) => { |
| | | modelList({ id: value }).then((res) => { |
| | |
| | | })); |
| | | }); |
| | | }; |
| | | // éæ©è§æ ¼åå· |
| | | const onSpecificationConfirm = ({ selectedValues, selectedOptions }) => { |
| | | productData.value[currentProductIndex.value].specificationModel = selectedOptions[0]?.text; |
| | | productData.value[currentProductIndex.value].productModelId = selectedOptions[0]?.value; |
| | | productData.value[currentProductIndex.value].unit = selectedOptions[0]?.unit; |
| | | pickerSpecificationValue.value = [selectedValues[0]]; |
| | | showSpecificationPicker.value = false; |
| | | }; |
| | | // éæ©ç¨ç |
| | | const onTaxRateConfirm = ({ selectedValues, selectedOptions }) => { |
| | | productData.value[currentProductIndex.value].taxRate = selectedOptions[0]?.value; |
| | | pickerTaxRateValue.value = [selectedValues[0]]; |
| | | showTaxRatePicker.value = false; |
| | | // if (isCalculating.value) return; |
| | | const inclusiveTotalPrice = parseFloat(productData.value[currentProductIndex.value].taxInclusiveTotalPrice); |
| | | const taxRate = parseFloat(productData.value[currentProductIndex.value].taxRate); |
| | | if (!inclusiveTotalPrice || !taxRate) { |
| | | return; |
| | | } |
| | | // isCalculating.value = true; |
| | | // 计ç®ä¸å«ç¨æ»ä»· |
| | | productData.value[currentProductIndex.value].taxExclusiveTotalPrice = |
| | | calculateTaxExclusiveTotalPrice( |
| | | inclusiveTotalPrice, |
| | | taxRate |
| | | ); |
| | | // isCalculating.value = false; |
| | | |
| | | // è§æ ¼åå·éæ©äºä»¶ |
| | | const onSpecificationSelect = (item) => { |
| | | productData.value[currentProductIndex.value].specificationModel = item.name |
| | | productData.value[currentProductIndex.value].productModelId = item.value |
| | | productData.value[currentProductIndex.value].unit = item.unit |
| | | showSpecificationPicker.value = false; |
| | | }; |
| | | |
| | | const onInvoiceTypeConfirm = ({ selectedValues, selectedOptions }) => { |
| | | productData.value[currentProductIndex.value].invoiceType = selectedOptions[0]?.text; |
| | | pickerInvoiceTypeValue.value = [selectedValues[0]]; |
| | | showInvoiceTypePicker.value = false; |
| | | // ç¨çéæ©äºä»¶ |
| | | const onTaxRateSelect = (item) => { |
| | | productData.value[currentProductIndex.value].taxRate = item.value |
| | | showTaxRatePicker.value = false; |
| | | // éæ°è®¡ç®ä¸å«ç¨æ»ä»· |
| | | const inclusiveTotalPrice = parseFloat(productData.value[currentProductIndex.value].taxInclusiveTotalPrice) |
| | | const taxRate = parseFloat(item.value) |
| | | if (inclusiveTotalPrice && taxRate) { |
| | | productData.value[currentProductIndex.value].taxExclusiveTotalPrice = |
| | | calculateTaxExclusiveTotalPrice(inclusiveTotalPrice, taxRate) |
| | | } |
| | | }; |
| | | |
| | | // å票类åéæ©äºä»¶ |
| | | const onInvoiceTypeSelect = (item) => { |
| | | productData.value[currentProductIndex.value].invoiceType = item.name |
| | | showInvoiceTypePicker.value = false; |
| | | }; |
| | | |
| | | // æ ¼å¼å彿° - åºå®ä¸¤ä½å°æ° |
| | |
| | | |
| | | // 妿æç¨çï¼è®¡ç®ä¸å«ç¨æ»ä»· |
| | | if (productData.value[currentProductIndex.value].taxRate) { |
| | | productData.value[currentProductIndex.value].taxExclusiveTotalPrice = |
| | | productData.value[currentProductIndex.value].taxExclusiveTotalPrice = |
| | | calculateTaxExclusiveTotalPrice( |
| | | productData.value[currentProductIndex.value].taxInclusiveTotalPrice, |
| | | productData.value[currentProductIndex.value].taxRate |
| | | ); |
| | | } |
| | | }; |
| | | |
| | | // æ°éè¾å
¥æ¡å¤±ç¦ |
| | | const formatAmount = (idx) => { |
| | | if (productData.value[idx].quantity) { |
| | |
| | | productData.value[currentProductIndex.value].taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2); |
| | | // 妿æç¨çï¼è®¡ç®ä¸å«ç¨æ»ä»· |
| | | if (productData.value[currentProductIndex.value].taxRate) { |
| | | productData.value[currentProductIndex.value].taxExclusiveTotalPrice = |
| | | productData.value[currentProductIndex.value].taxExclusiveTotalPrice = |
| | | calculateTaxExclusiveTotalPrice( |
| | | productData.value[currentProductIndex.value].taxInclusiveTotalPrice, |
| | | productData.value[currentProductIndex.value].taxRate |
| | | ); |
| | | } |
| | | }; |
| | | |
| | | // å«ç¨æ»ä»·å¤±ç¦ï¼æ ¹æ®å«ç¨æ»ä»·è®¡ç®å«ç¨åä»·åæ°é |
| | | const formatTaxTotal = (idx) => { |
| | | if (productData.value[idx].taxInclusiveTotalPrice) { |
| | |
| | | productData.value[currentProductIndex.value].taxInclusiveUnitPrice = (totalPrice / quantity).toFixed(2); |
| | | // 妿æç¨çï¼è®¡ç®ä¸å«ç¨æ»ä»· |
| | | if (productData.value[currentProductIndex.value].taxRate) { |
| | | productData.value[currentProductIndex.value].taxExclusiveTotalPrice = |
| | | productData.value[currentProductIndex.value].taxExclusiveTotalPrice = |
| | | calculateTaxExclusiveTotalPrice( |
| | | totalPrice, |
| | | productData.value[currentProductIndex.value].taxRate |
| | | ); |
| | | } |
| | | }; |
| | | |
| | | // ä¸å«ç¨æ»ä»·å¤±ç¦, æ ¹æ®ä¸å«ç¨æ»ä»·è®¡ç®å«ç¨åä»·åæ°é |
| | | const formatNoTaxTotal = (idx) => { |
| | | if (productData.value[idx].taxExclusiveTotalPrice) { |
| | |
| | | // 计ç®å«ç¨åä»· = å«ç¨æ»ä»· / æ°é |
| | | productData.value[currentProductIndex.value].taxInclusiveUnitPrice = (inclusiveTotalPrice / quantity).toFixed(2); |
| | | }; |
| | | |
| | | const goBack = () => { |
| | | // æ¸
çæ¬å°åå¨çæ°æ® |
| | | uni.removeStorageSync('operationType'); |
| | | uni.removeStorageSync('editData'); |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | const onSubmit = () => { |
| | | if (productData.value !== null && productData.value.length > 0) { |
| | | form.value.productData = JSON.parse(JSON.stringify(productData.value)); |
| | |
| | | goBack(); |
| | | }); |
| | | }; |
| | | |
| | | const setUserInfo = () => { |
| | | form.value.recorderId = userStore.id; |
| | | form.value.recorderName = userStore.nickName; |
| | |
| | | const month = String(today.getMonth() + 1).padStart(2, '0') |
| | | const day = String(today.getDate()).padStart(2, '0') |
| | | form.value.entryDate = `${year}-${month}-${day}` |
| | | pickerDateValue.value = [year.toString(), month.toString(), day.toString()] |
| | | } |
| | | }; |
| | | |
| | | // å¡«å
è¡¨åæ°æ®ï¼ç¼è¾æ¨¡å¼ï¼ |
| | | const fillFormData = () => { |
| | | if (!editData.value) return; |
| | |
| | | form.value.salesContractNo = editData.value.salesContractNo || ''; |
| | | form.value.supplierName = editData.value.supplierName || ''; |
| | | form.value.projectName = editData.value.projectName || ''; |
| | | form.value.executionDate = editData.value.executionDate || ''; |
| | | form.value.paymentMethod = editData.value.paymentMethod || ''; |
| | | form.value.salesLedgerId = editData.value.salesLedgerId || ''; |
| | | form.value.recorderId = editData.value.recorderId || ''; |
| | |
| | | form.value.entryDate = editData.value.entryDate || ''; |
| | | form.value.id = editData.value.id || ''; |
| | | form.value.supplierId = editData.value.supplierId || ''; |
| | | |
| | | // 设置éå®ååå·éæ©å¨çå¼ |
| | | if (editData.value.salesContractNo) { |
| | | const salesmanIndex = salesContractList.value.findIndex(user => user.text === editData.value.salesContractNo); |
| | | if (salesmanIndex !== -1) { |
| | | pickerValue.value = [salesContractList.value[salesmanIndex].value]; |
| | | } |
| | | } |
| | | |
| | | // 设置ä¾åºåéæ©å¨çå¼ |
| | | if (editData.value.supplierName) { |
| | | const customerIndex = supplierList.value.findIndex(customer => customer.text === editData.value.supplierName); |
| | | if (customerIndex !== -1) { |
| | | pickerCustomerValue.value = [supplierList.value[customerIndex].value] |
| | | } |
| | | } |
| | | |
| | | // è®¾ç½®æ¥æéæ©å¨çå¼ |
| | | if (editData.value.executionDate) { |
| | | pickerDateValue.value = editData.value.executionDate.split('-').map(num => parseInt(num, 10)) |
| | | console.log(pickerDateValue.value) |
| | | } |
| | | }; |
| | | |
| | | const getSalesNoList = () => { |
| | | getSalesNo().then((res) => { |
| | | // å°ç¨æ·æ°æ®ç»è£
æ picker éè¦çæ ¼å¼ |
| | |
| | | value: user.id |
| | | })); |
| | | }) |
| | | } |
| | | }; |
| | | |
| | | const getOptionsLIst = () => { |
| | | getOptions().then((res) => { |
| | | // å°ç¨æ·æ°æ®ç»è£
æ picker éè¦çæ ¼å¼ |
| | |
| | | value: item.id |
| | | })); |
| | | }) |
| | | } |
| | | }; |
| | | |
| | | const convertIdToValue = (data) => { |
| | | // å¦æä¼ å
¥ç䏿¯æ°ç»ï¼åè¿å空æ°ç» |
| | | if (!Array.isArray(data)) { |
| | |
| | | return mappedItem; |
| | | }); |
| | | }; |
| | | |
| | | // è·å产å大类treeæ°æ® |
| | | const getProductOptions = () => { |
| | | productTreeList().then((res) => { |
| | | productOptions.value = convertIdToValue(res); |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | // è·å页é¢åæ° |
| | | operationType.value = uni.getStorageSync('operationType') || ''; |
| | |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .account-detail { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | padding-bottom: 5rem; |
| | | } |
| | | .header { |
| | | display: flex; |
| | | align-items: center; |
| | | background: #fff; |
| | | padding: 1rem 1.25rem; |
| | | border-bottom: 0.0625rem solid #f0f0f0; |
| | | position: sticky; |
| | | top: 0; |
| | | z-index: 100; |
| | | /* å
¼å®¹ iOS åæµ·/çµå¨å²å®å
¨åº */ |
| | | padding-top: env(safe-area-inset-top); |
| | | } |
| | | .title { |
| | | flex: 1; |
| | | text-align: center; |
| | | font-size: 1.125rem; |
| | | font-weight: 600; |
| | | color: #333; |
| | | } |
| | | .form-section { |
| | | margin-top: 1rem; |
| | | } |
| | | .van-field { |
| | | height: 3.4rem; |
| | | } |
| | | .van-cell { |
| | | align-items: center; |
| | | } |
| | | .product-section { |
| | | background: #fff; |
| | | margin-top: 1rem; |
| | | padding: 1rem; |
| | | box-shadow: 0 0.125rem 0.5rem rgba(0,0,0,0.04); |
| | | } |
| | | .section-header { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | margin-bottom: 1rem; |
| | | } |
| | | .section-title { |
| | | font-size: 1rem; |
| | | font-weight: 600; |
| | | color: #333; |
| | | } |
| | | .product-card { |
| | | background: #FFFFFF; |
| | | box-shadow: 0 0 1.25rem 0 rgba(0,57,117,0.08); |
| | | border-radius: 0.5rem 0.5rem 0.5rem 0.5rem; |
| | | padding: 1rem 0.5rem 0 0.5rem; |
| | | position: relative; |
| | | } |
| | | .product-header { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | padding: 0 0.5rem 0.75rem 0.5rem; |
| | | border-bottom: 0.0625rem solid #e8e8e8; |
| | | } |
| | | .product-productCategory { |
| | | margin-left: 0.5rem; |
| | | font-size: 0.875rem; |
| | | font-weight: 500; |
| | | color: #333; |
| | | } |
| | | .info-grid { |
| | | display: grid; |
| | | grid-template-columns: 1fr 1fr; |
| | | gap: 0.75rem; |
| | | margin-bottom: 1rem; |
| | | } |
| | | .info-item { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 0.25rem; |
| | | } |
| | | .info-label { |
| | | font-size: 0.75rem; |
| | | color: #666; |
| | | font-weight: 400; |
| | | } |
| | | .info-value { |
| | | font-size: 0.875rem; |
| | | color: #333; |
| | | font-weight: 500; |
| | | } |
| | | .info-value.highlight { |
| | | color: #2979ff; |
| | | font-weight: 600; |
| | | } |
| | | .product-form { |
| | | margin-bottom: 1rem; |
| | | } |
| | | .footer-btns { |
| | | position: fixed; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | background: #fff; |
| | | display: flex; |
| | | justify-content: space-around; |
| | | align-items: center; |
| | | padding: 0.75rem 0; |
| | | box-shadow: 0 -0.125rem 0.5rem rgba(0,0,0,0.05); |
| | | z-index: 1000; |
| | | } |
| | | .cancel-btn { |
| | | font-weight: 400; |
| | | font-size: 1rem; |
| | | color: #FFFFFF; |
| | | width: 6.375rem; |
| | | background: #C7C9CC; |
| | | box-shadow: 0 0.25rem 0.625rem 0 rgba(3,88,185,0.2); |
| | | border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; |
| | | } |
| | | .save-btn { |
| | | font-weight: 400; |
| | | font-size: 1rem; |
| | | color: #FFFFFF; |
| | | width: 14rem; |
| | | background: linear-gradient( 140deg, #00BAFF 0%, #006CFB 100%); |
| | | box-shadow: 0 0.25rem 0.625rem 0 rgba(3,88,185,0.2); |
| | | border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; |
| | | } |
| | | |
| | | .popup-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding: 1rem; |
| | | background: #fff; |
| | | position: sticky; |
| | | top: 0; |
| | | z-index: 10; |
| | | } |
| | | .cancelButton { |
| | | color: #969799 |
| | | } |
| | | .confirmButton { |
| | | color: #1989FA |
| | | } |
| | | .u-tree { |
| | | height: 13rem; |
| | | } |
| | | @import '@/static/scss/form-common.scss'; |
| | | </style> |
| | |
| | | </view> |
| | | <!-- æä½æé® --> |
| | | <view class="action-buttons"> |
| | | <van-button |
| | | <u-button |
| | | type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | |
| | | @click="openForm(item)" |
| | | > |
| | | ç¼è¾ä»æ¬¾ |
| | | </van-button> |
| | | </u-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | |
| | | <template> |
| | | <view class="invoice-detail"> |
| | | <view class="account-view"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader title="å票详æ
" @back="goBack" /> |
| | | |
| | |
| | | :beforeRead="beforeReadPdf" |
| | | > |
| | | <u-button class="upload-btn" type="primary"> |
| | | <u-icon name="plus" size="14" /> |
| | | ä¸ä¼ æä»¶ |
| | | </u-button> |
| | | </u-upload> |
| | |
| | | |
| | | import { ref, onMounted } from 'vue' |
| | | import dayjs from 'dayjs' |
| | | import { formatDateToYMD } from '@/utils/ruoyi' |
| | | import useUserStore from '@/store/modules/user' |
| | | import { getToken } from '@/utils/auth' |
| | | import { invoiceLedgerProductInfo, invoiceLedgerSaveOrUpdate } from '@/api/salesManagement/invoiceLedger.js' |
| | |
| | | return num.toFixed(2) |
| | | } |
| | | |
| | | const onInvoiceDateConfirm = ({ selectedValues }) => { |
| | | form.value.invoiceDate = selectedValues.join('-') |
| | | currentInvoiceDate.value = selectedValues |
| | | showInvoiceDatePicker.value = false |
| | | // æ¥æç¡®è®¤äºä»¶ |
| | | const onInvoiceDateConfirm = (e) => { |
| | | form.value.invoiceDate = formatDateToYMD(e.value) |
| | | currentInvoiceDate.value = formatDateToYMD(e.value) |
| | | showInvoiceDatePicker.value = false; |
| | | } |
| | | |
| | | // ä¸ä¼ åæ ¡éªï¼å
¼å®¹ Vant Uploader ç file/fileList ç»æï¼ |
| | |
| | | |
| | | const uploadSingleFile = async (fileObj) => { |
| | | return new Promise((resolve, reject) => { |
| | | showLoadingToast({ message: 'æ£å¨ä¸ä¼ ...' }) |
| | | showLoadingToast('æ£å¨ä¸ä¼ ...') |
| | | const baseUrl = config.baseUrl + '/invoiceLedger/uploadFile' |
| | | |
| | | const filePath = fileObj?.url || fileObj?.tempFilePath || fileObj?.file?.path |
| | |
| | | |
| | | const loadDetail = async (id) => { |
| | | try { |
| | | showLoadingToast({ message: 'å è½½ä¸...' }) |
| | | showLoadingToast('å è½½ä¸...') |
| | | const res = await invoiceLedgerProductInfo({ id }) |
| | | const data = res?.data || res |
| | | form.value = { ...data } |
| | |
| | | if (!form.value.invoiceNo) { showToast('请è¾å
¥å票å·'); return } |
| | | if (!form.value.invoiceTotal) { showToast('请è¾å
¥å票éé¢'); return } |
| | | if (!form.value.invoiceDate) { showToast('è¯·éæ©å¼ç¥¨æ¥æ'); return } |
| | | showLoadingToast({ message: 'æäº¤ä¸...' }) |
| | | showLoadingToast('æäº¤ä¸...') |
| | | form.value.fileList = fileList.value |
| | | await invoiceLedgerSaveOrUpdate(form.value) |
| | | closeToast() |
| | |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .account-detail { |
| | | @import '@/static/scss/form-common.scss'; |
| | | .account-view { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | padding-bottom: 5rem; |
| | | } |
| | | |
| | | .info-section { |
| | | background: #fff; |
| | | margin-bottom: 16px; |
| | | } |
| | | |
| | | .info-grid { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | padding: 16px; |
| | | } |
| | | |
| | | .info-item { |
| | | display: flex; |
| | | width: 100%; |
| | | margin-bottom: 12px; |
| | | |
| | | &:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .info-label { |
| | | font-size: 14px; |
| | | color: #999; |
| | | min-width: 100px; |
| | | } |
| | | |
| | | .info-value { |
| | | font-size: 14px; |
| | | color: #333; |
| | | flex: 1; |
| | | } |
| | | |
| | | .info-value.highlight { |
| | | color: #2979ff; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .info-value.medium { |
| | | font-size: 16px; |
| | | } |
| | | } |
| | | |
| | | .uploaded-list { padding: 8px 16px 0 16px; } |
| | | .uploaded-item { display: flex; align-items: center; justify-content: space-between; padding: 8px 0; border-bottom: 1px solid #f5f5f5; } |
| | | .file-name { font-size: 12px; color: #333; margin-right: 8px; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } |
| | | .tip-text { padding: 4px 16px 0 16px; font-size: 12px; color: #888; } |
| | | .footer-btns { position: fixed; left: 0; right: 0; bottom: 0; background: #fff; display: flex; justify-content: space-around; align-items: center; padding: 0.75rem 0; box-shadow: 0 -0.125rem 0.5rem rgba(0,0,0,0.05); z-index: 1000; } |
| | | .cancel-btn { font-weight: 400; font-size: 1rem; color: #FFFFFF; width: 6.375rem; background: #C7C9CC; box-shadow: 0 0.25rem 0.625rem 0 rgba(3,88,185,0.2); border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; } |
| | | .save-btn { font-weight: 400; font-size: 1rem; color: #FFFFFF; width: 14rem; background: linear-gradient( 140deg, #00BAFF 0%, #006CFB 100%); box-shadow: 0 0.25rem 0.625rem 0 rgba(3,88,185,0.2); border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; } |
| | | .footer-btns { |
| | | position: fixed; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | background: #fff; |
| | | display: flex; |
| | | justify-content: space-around; |
| | | align-items: center; |
| | | padding: 0.75rem 0; |
| | | box-shadow: 0 -0.125rem 0.5rem rgba(0,0,0,0.05); |
| | | z-index: 1000; |
| | | } |
| | | .cancel-btn { |
| | | font-weight: 400; |
| | | font-size: 1rem; |
| | | color: #FFFFFF; |
| | | width: 6.375rem; |
| | | background: #C7C9CC; |
| | | box-shadow: 0 0.25rem 0.625rem 0 rgba(3,88,185,0.2); |
| | | border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; |
| | | } |
| | | .save-btn { |
| | | font-weight: 400; |
| | | font-size: 1rem; |
| | | color: #FFFFFF; |
| | | width: 14rem; |
| | | background: linear-gradient( 140deg, #00BAFF 0%, #006CFB 100%); |
| | | box-shadow: 0 0.25rem 0.625rem 0 rgba(3,88,185,0.2); |
| | | border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; |
| | | } |
| | | </style> |
| | | |
| | |
| | | </view> |
| | | </view> |
| | | <view class="action-buttons"> |
| | | <van-button |
| | | <up-button |
| | | type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | |
| | | @click="openEdit(item)" |
| | | > |
| | | ç¼è¾ |
| | | </van-button> |
| | | <van-button |
| | | type="danger" |
| | | </up-button> |
| | | <up-button |
| | | type="error" |
| | | size="small" |
| | | plain |
| | | class="action-btn" |
| | |
| | | @click="handleDelete(item)" |
| | | > |
| | | å é¤ |
| | | </van-button> |
| | | <van-button |
| | | type="default" |
| | | </up-button> |
| | | <up-button |
| | | size="small" |
| | | plain |
| | | class="action-btn" |
| | |
| | | @click="openFileActions(item.commonFiles || [])" |
| | | > |
| | | æ¥çéä»¶ |
| | | </van-button> |
| | | <van-button |
| | | </up-button> |
| | | <up-button |
| | | type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | |
| | | @click="openUpload(item)" |
| | | > |
| | | ä¸ä¼ |
| | | </van-button> |
| | | </up-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | |
| | | </view> |
| | | |
| | | <!-- çéå¼¹çª --> |
| | | <van-popup v-model:show="showFilter" position="bottom" round> |
| | | <up-popup v-model="showFilter" mode="bottom" round><up-transition> |
| | | <view class="filter-popup"> |
| | | <van-cell-group title="ç鿡件" inset> |
| | | <van-field |
| | | <up-cell-group title="ç鿡件" inset> |
| | | <up-input |
| | | label="å¼ç¥¨æ¥æ" |
| | | readonly |
| | | placeholder="è¯·éæ©æ¥æèå´" |
| | | @click="showInvoiceRange = true" |
| | | :placeholder="invoiceRangeLabel || 'è¯·éæ©æ¥æèå´'" |
| | | v-model="invoiceRangeLabel" |
| | | /> |
| | | <van-field |
| | | <up-input |
| | | label="å½å
¥æ¥æ" |
| | | readonly |
| | | @click="showCreateDatePicker = true" |
| | | :placeholder="searchForm.createTimeStart || 'è¯·éæ©å½å
¥æ¥æ'" |
| | | v-model="searchForm.createTimeStart" |
| | | /> |
| | | <view class="switch-row"> |
| | | <text class="switch-label">䏿¾ç¤ºæå票è¡</text> |
| | | <van-switch v-model="searchForm.status" size="20" /> |
| | | <up-switch v-model="searchForm.status" size="20" /> |
| | | </view> |
| | | </van-cell-group> |
| | | </up-cell-group> |
| | | <view class="filter-actions"> |
| | | <van-button @click="resetFilter">éç½®</van-button> |
| | | <van-button type="primary" @click="confirmFilter">ç¡®å®</van-button> |
| | | <up-button @click="resetFilter">éç½®</up-button> |
| | | <up-button type="primary" @click="confirmFilter">ç¡®å®</up-button> |
| | | </view> |
| | | </view> |
| | | </van-popup> |
| | | </up-transition></up-popup> |
| | | |
| | | <!-- æ¥åï¼å¼ç¥¨æ¥æèå´ --> |
| | | <van-popup v-model:show="showInvoiceRange" position="bottom"> |
| | | <van-calendar |
| | | title="éæ©å¼ç¥¨æ¥æèå´" |
| | | <up-popup v-model="showInvoiceRange" mode="bottom"><up-transition> |
| | | <up-datetime-picker |
| | | mode="date" |
| | | type="range" |
| | | color="#2979ff" |
| | | title="éæ©å¼ç¥¨æ¥æèå´" |
| | | @confirm="onInvoiceRangeConfirm" |
| | | @cancel="showInvoiceRange = false" |
| | | /> |
| | | </van-popup> |
| | | </up-transition></up-popup> |
| | | |
| | | <!-- æ¥æï¼å½å
¥æ¥æ --> |
| | | <van-popup v-model:show="showCreateDatePicker" position="bottom"> |
| | | <van-date-picker |
| | | <up-popup v-model="showCreateDatePicker" mode="bottom"><up-transition> |
| | | <up-datetime-picker |
| | | mode="date" |
| | | type="selector" |
| | | v-model="currentCreateDate" |
| | | title="éæ©å½å
¥æ¥æ" |
| | | @confirm="onCreateDateConfirm" |
| | | @cancel="showCreateDatePicker = false" |
| | | /> |
| | | </van-popup> |
| | | </up-transition></up-popup> |
| | | |
| | | |
| | | |
| | | <!-- åè¡ä¸ä¼ å¼¹çªï¼æ 表åï¼ --> |
| | | <van-popup v-model:show="showUpload" position="bottom" round> |
| | | <up-popup v-model="showUpload" mode="bottom" round><up-transition> |
| | | <view class="upload-container"> |
| | | <van-cell-group title="ä¸ä¼ éä»¶ï¼ä»
æ¯æ pdfï¼æå¤§10MBï¼æå¤10个ï¼" inset> |
| | | <van-uploader |
| | | accept="*" |
| | | <up-cell-group title="ä¸ä¼ éä»¶ï¼ä»
æ¯æ pdfï¼æå¤§10MBï¼æå¤10个ï¼" inset> |
| | | <up-upload |
| | | accept="pdf" |
| | | multiple |
| | | :max-count="10" |
| | | :after-read="afterReadRowUpload" |
| | | :before-read="beforeReadPdf" |
| | | /> |
| | | :maxCount="10" |
| | | :afterRead="afterReadRowUpload" |
| | | :beforeRead="beforeReadPdf" |
| | | > |
| | | <up-button type="primary">ç¹å»ä¸ä¼ </up-button> |
| | | </up-upload> |
| | | <view class="uploaded-list" v-if="fileList.length"> |
| | | <view class="uploaded-item" v-for="(f, idx) in fileList" :key="idx"> |
| | | <text class="file-name">{{ f.name || getFileNameFromUrl(f.url) }}</text> |
| | | <van-button size="mini" type="danger" plain @click="removeUploaded(idx)">ç§»é¤</van-button> |
| | | <up-button size="mini" type="error" plain @click="removeUploaded(idx)">ç§»é¤</up-button> |
| | | </view> |
| | | </view> |
| | | </van-cell-group> |
| | | </up-cell-group> |
| | | <view class="filter-actions"> |
| | | <van-button @click="showUpload = false">åæ¶</van-button> |
| | | <van-button type="primary" @click="confirmUpload">确认</van-button> |
| | | <up-button @click="showUpload = false">åæ¶</up-button> |
| | | <up-button type="primary" @click="confirmUpload">确认</up-button> |
| | | </view> |
| | | </view> |
| | | </van-popup> |
| | | </up-transition></up-popup> |
| | | |
| | | <!-- éä»¶åè¡¨éæ© --> |
| | | <van-action-sheet v-model:show="showFileSheet" :actions="fileActions" cancel-text="åæ¶" close-on-click-action @select="onSelectFile" /> |
| | | <up-action-sheet v-model="showFileSheet" :actions="fileActions" cancel-text="åæ¶" close-on-click-action @select="onSelectFile"> |
| | | <view class="up-action-sheet__cancel" @click="showFileSheet = false"> |
| | | åæ¶ |
| | | </view> |
| | | </up-action-sheet> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, onMounted } from 'vue' |
| | | import dayjs from 'dayjs' |
| | | import PageHeader from '@/components/PageHeader.vue' |
| | | const showToast = (message) => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: 'none' |
| | | }) |
| | | } |
| | | const showLoadingToast = (message) => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | mask: true |
| | | }) |
| | | } |
| | | const closeToast = () => { |
| | | uni.hideLoading() |
| | | } |
| | | import useUserStore from '@/store/modules/user' |
| | | import { getToken } from '@/utils/auth' |
| | |
| | | |
| | | const getList = async () => { |
| | | try { |
| | | showLoadingToast({ message: 'å è½½ä¸...' }) |
| | | showLoadingToast('å è½½ä¸...') |
| | | const { invoiceDate, ...rest } = searchForm |
| | | const res = await registrationProductPage({ ...rest, ...page }) |
| | | // å
¼å®¹ä¸åè¿åç»æ |
| | |
| | | showFilter.value = false |
| | | getList() |
| | | } |
| | | const onInvoiceRangeConfirm = (e) => { |
| | | // e 为 [start, end] ç Date 对象æå符串ï¼uni-app ä¸ Vant Calendar è¿åæ¶é´æ³æ°ç» |
| | | const onInvoiceRangeConfirm = ({ selectedValues }) => { |
| | | try { |
| | | let start, end |
| | | if (Array.isArray(e)) { |
| | | const [s, ed] = e |
| | | start = dayjs(s).format('YYYY-MM-DD') |
| | | end = dayjs(ed).format('YYYY-MM-DD') |
| | | } else if (e && e.detail && Array.isArray(e.detail)) { |
| | | const [s, ed] = e.detail |
| | | start = dayjs(s).format('YYYY-MM-DD') |
| | | end = dayjs(ed).format('YYYY-MM-DD') |
| | | } |
| | | const start = dayjs(selectedValues[0]).format('YYYY-MM-DD') |
| | | const end = dayjs(selectedValues[1]).format('YYYY-MM-DD') |
| | | searchForm.invoiceDateStart = start |
| | | searchForm.invoiceDateEnd = end |
| | | invoiceRangeLabel.value = `${start} è³ ${end}` |
| | |
| | | success: async (res) => { |
| | | if (res.confirm) { |
| | | try { |
| | | showLoadingToast({ message: 'å¤çä¸...' }) |
| | | showLoadingToast('å¤çä¸...') |
| | | await delInvoiceLedgerByRegProductId(row.id) |
| | | closeToast() |
| | | showToast('å 餿å') |
| | |
| | | const confirmUpload = async () => { |
| | | try { |
| | | const payload = { fileList: fileList.value, id: currentId.value } |
| | | showLoadingToast({ message: 'æäº¤ä¸...' }) |
| | | showLoadingToast('æäº¤ä¸...') |
| | | await commitFile(payload) |
| | | closeToast() |
| | | showToast('æäº¤æå') |
| | |
| | | |
| | | const uploadSingleFile = async (fileObj) => { |
| | | return new Promise((resolve, reject) => { |
| | | showLoadingToast({ message: 'æ£å¨ä¸ä¼ ...' }) |
| | | showLoadingToast('æ£å¨ä¸ä¼ ...') |
| | | uni.uploadFile({ |
| | | url: config.baseUrl + '/invoiceLedger/uploadFile', |
| | | filePath: fileObj.url || fileObj.file?.path || fileObj.tempFilePath, |
| | |
| | | try { |
| | | const item = currentFilesToOpen[action.index] |
| | | if (!item || !item.url) return |
| | | showLoadingToast({ message: 'ä¸è½½ä¸...' }) |
| | | showLoadingToast('ä¸è½½ä¸...') |
| | | uni.downloadFile({ |
| | | url: item.url, |
| | | success: (res) => { |
| | |
| | | <PageHeader title="æ°å¢å¼ç¥¨ç»è®°" @back="goBack" /> |
| | | |
| | | <!-- 表åå
容 --> |
| | | <van-form @submit="submitForm" ref="formRef" label-width="110px" input-align="right" error-message-align="right" scroll-to-error scroll-to-error-position="center"> |
| | | <up-form @submit="submitForm" ref="formRef" label-width="130" :rules="rules" :model="form"> |
| | | <!-- åºæ¬ä¿¡æ¯ --> |
| | | <van-cell-group title="åºæ¬ä¿¡æ¯" inset> |
| | | <van-field |
| | | v-model="form.salesContractNo" |
| | | label="éå®ååå·" |
| | | readonly |
| | | placeholder="èªå¨å¡«å
" |
| | | /> |
| | | <van-field |
| | | v-model="form.customerName" |
| | | label="客æ·åç§°" |
| | | readonly |
| | | placeholder="èªå¨å¡«å
" |
| | | /> |
| | | <van-field |
| | | v-model="form.salesman" |
| | | label="ä¸å¡å" |
| | | readonly |
| | | placeholder="èªå¨å¡«å
" |
| | | /> |
| | | <van-field |
| | | v-model="form.projectName" |
| | | label="项ç®åç§°" |
| | | readonly |
| | | placeholder="èªå¨å¡«å
" |
| | | /> |
| | | <van-field |
| | | v-model="form.createUer" |
| | | label="å½å
¥äºº" |
| | | readonly |
| | | placeholder="请è¾å
¥å½å
¥äºº" |
| | | /> |
| | | <van-field |
| | | v-model="form.createTime" |
| | | label="å½å
¥æ¥æ" |
| | | readonly |
| | | placeholder="è¯·éæ©å½å
¥æ¥æ" |
| | | @click="showCreateTimePicker = true" |
| | | /> |
| | | <van-field |
| | | v-model="form.invoiceNo" |
| | | label="å票å·ç " |
| | | required |
| | | placeholder="请è¾å
¥å票å·ç " |
| | | :rules="[{ required: true, message: '请è¾å
¥å票å·ç ' }]" |
| | | /> |
| | | <van-field |
| | | v-model="form.issueDate" |
| | | label="å¼ç¥¨æ¥æ" |
| | | readonly |
| | | placeholder="è¯·éæ©å¼ç¥¨æ¥æ" |
| | | required |
| | | <view class="form-section"> |
| | | <up-form-item label="éå®ååå·" prop="salesContractNo"> |
| | | <up-input v-model="form.salesContractNo" placeholder="èªå¨å¡«å
" disabled /> |
| | | </up-form-item> |
| | | <up-form-item label="客æ·åç§°" prop="customerName"> |
| | | <up-input v-model="form.customerName" placeholder="èªå¨å¡«å
" disabled /> |
| | | </up-form-item> |
| | | <up-form-item label="ä¸å¡å" prop="salesman"> |
| | | <up-input v-model="form.salesman" placeholder="èªå¨å¡«å
" disabled /> |
| | | </up-form-item> |
| | | <up-form-item label="项ç®åç§°" prop="projectName"> |
| | | <up-input v-model="form.projectName" placeholder="èªå¨å¡«å
" disabled /> |
| | | </up-form-item> |
| | | <up-form-item label="å½å
¥äºº" prop="createUer"> |
| | | <up-input v-model="form.createUer" placeholder="请è¾å
¥å½å
¥äºº" disabled /> |
| | | </up-form-item> |
| | | <up-form-item |
| | | label="å½å
¥æ¥æ" |
| | | prop="createTime" |
| | | @click="showCreateTimePicker = true" |
| | | > |
| | | <up-input |
| | | v-model="form.createTime" |
| | | placeholder="è¯·éæ©å½å
¥æ¥æ" |
| | | readonly |
| | | @click="showCreateTimePicker = true" |
| | | /> |
| | | <template #right> |
| | | <up-icon name="arrow-right" @click="showCreateTimePicker = true"></up-icon> |
| | | </template> |
| | | </up-form-item> |
| | | <up-form-item label="å票å·ç " prop="invoiceNo" required> |
| | | <up-input v-model="form.invoiceNo" placeholder="请è¾å
¥å票å·ç " /> |
| | | </up-form-item> |
| | | <up-form-item |
| | | label="å¼ç¥¨æ¥æ" |
| | | prop="issueDate" |
| | | required |
| | | @click="showIssueDatePicker = true" |
| | | :rules="[{ required: true, message: 'è¯·éæ©å¼ç¥¨æ¥æ' }]" |
| | | /> |
| | | </van-cell-group> |
| | | > |
| | | <up-input |
| | | v-model="form.issueDate" |
| | | placeholder="è¯·éæ©å¼ç¥¨æ¥æ" |
| | | readonly |
| | | @click="showIssueDatePicker = true" |
| | | /> |
| | | <template #right> |
| | | <up-icon name="arrow-right" @click="showIssueDatePicker = true"></up-icon> |
| | | </template> |
| | | </up-form-item> |
| | | </view> |
| | | |
| | | <!-- 产åä¿¡æ¯ --> |
| | | <view class="product-section"> |
| | | <view class="section-header"> |
| | | <text class="section-title">产åä¿¡æ¯</text> |
| | | <view> |
| | | <text class="section-title">产åä¿¡æ¯</text> |
| | | </view> |
| | | </view> |
| | | |
| | | <view v-if="productData.length === 0" class="empty-state"> |
| | | <van-empty description="ææ äº§åæ°æ®" /> |
| | | <view class="empty-text">ææ äº§åæ°æ®</view> |
| | | </view> |
| | | |
| | | <view v-else class="product-list"> |
| | |
| | | <!-- 产åå¤´é¨ --> |
| | | <view class="product-header"> |
| | | <view class="product-title"> |
| | | <van-icon name="description" color="#2979ff" size="15" /> |
| | | <view class="document-icon"> |
| | | <up-icon name="file-text" size="16" color="#ffffff"></up-icon> |
| | | </view> |
| | | <text class="product-productCategory">产å {{ index + 1 }}</text> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 产åä¿¡æ¯è¡¨å --> |
| | | <view class="product-form"> |
| | | <van-field |
| | | v-model="item.productCategory" |
| | | label="产å大类" |
| | | readonly |
| | | /> |
| | | <van-field |
| | | v-model="item.specificationModel" |
| | | label="è§æ ¼åå·" |
| | | readonly |
| | | /> |
| | | <van-field |
| | | v-model="item.unit" |
| | | label="åä½" |
| | | readonly |
| | | /> |
| | | <van-field |
| | | v-model="item.quantity" |
| | | label="æ°é" |
| | | readonly |
| | | /> |
| | | <van-field |
| | | v-model="item.taxRate" |
| | | label="ç¨ç(%)" |
| | | readonly |
| | | /> |
| | | <van-field |
| | | v-model="item.taxInclusiveUnitPrice" |
| | | label="å«ç¨åä»·(å
)" |
| | | readonly |
| | | /> |
| | | <van-field |
| | | v-model="item.taxInclusiveTotalPrice" |
| | | label="å«ç¨æ»ä»·(å
)" |
| | | readonly |
| | | /> |
| | | <van-field |
| | | v-model="item.taxExclusiveTotalPrice" |
| | | label="ä¸å«ç¨æ»ä»·(å
)" |
| | | readonly |
| | | /> |
| | | <up-form-item label="产å大类" prop="productCategory"> |
| | | <up-input v-model="item.productCategory" placeholder="" disabled /> |
| | | </up-form-item> |
| | | <up-form-item label="è§æ ¼åå·" prop="specificationModel"> |
| | | <up-input v-model="item.specificationModel" placeholder="" disabled /> |
| | | </up-form-item> |
| | | <up-form-item label="åä½" prop="unit"> |
| | | <up-input v-model="item.unit" placeholder="" disabled /> |
| | | </up-form-item> |
| | | <up-form-item label="æ°é" prop="quantity"> |
| | | <up-input v-model="item.quantity" placeholder="" disabled /> |
| | | </up-form-item> |
| | | <up-form-item label="ç¨ç(%)" prop="taxRate"> |
| | | <up-input v-model="item.taxRate" placeholder="" disabled /> |
| | | </up-form-item> |
| | | <up-form-item label="å«ç¨åä»·(å
)" prop="taxInclusiveUnitPrice"> |
| | | <up-input v-model="item.taxInclusiveUnitPrice" placeholder="" disabled /> |
| | | </up-form-item> |
| | | <up-form-item label="å«ç¨æ»ä»·(å
)" prop="taxInclusiveTotalPrice"> |
| | | <up-input v-model="item.taxInclusiveTotalPrice" placeholder="" disabled /> |
| | | </up-form-item> |
| | | <up-form-item label="ä¸å«ç¨æ»ä»·(å
)" prop="taxExclusiveTotalPrice"> |
| | | <up-input v-model="item.taxExclusiveTotalPrice" placeholder="" disabled /> |
| | | </up-form-item> |
| | | |
| | | <!-- æ¬æ¬¡å¼ç¥¨ä¿¡æ¯ --> |
| | | <van-field |
| | | v-model="item.currentInvoiceNum" |
| | | label="æ¬æ¬¡å¼ç¥¨æ°" |
| | | type="number" |
| | | placeholder="请è¾å
¥å¼ç¥¨æ°é" |
| | | @blur="invoiceNumBlur(item)" |
| | | /> |
| | | <van-field |
| | | v-model="item.currentInvoiceAmount" |
| | | label="æ¬æ¬¡å¼ç¥¨éé¢(å
)" |
| | | type="number" |
| | | placeholder="请è¾å
¥å¼ç¥¨éé¢" |
| | | @blur="invoiceAmountBlur(item)" |
| | | /> |
| | | <up-form-item label="æ¬æ¬¡å¼ç¥¨æ°" prop="currentInvoiceNum"> |
| | | <up-input |
| | | v-model="item.currentInvoiceNum" |
| | | type="number" |
| | | placeholder="请è¾å
¥å¼ç¥¨æ°é" |
| | | @blur="invoiceNumBlur(item)" |
| | | /> |
| | | </up-form-item> |
| | | <up-form-item label="æ¬æ¬¡å¼ç¥¨éé¢(å
)" prop="currentInvoiceAmount"> |
| | | <up-input |
| | | v-model="item.currentInvoiceAmount" |
| | | type="number" |
| | | placeholder="请è¾å
¥å¼ç¥¨éé¢" |
| | | @blur="invoiceAmountBlur(item)" |
| | | /> |
| | | </up-form-item> |
| | | |
| | | <!-- æªå¼ç¥¨ä¿¡æ¯ --> |
| | | <van-field |
| | | v-model="item.noInvoiceNum" |
| | | label="æªå¼ç¥¨æ°" |
| | | readonly |
| | | /> |
| | | <van-field |
| | | v-model="item.noInvoiceAmount" |
| | | label="æªå¼ç¥¨éé¢(å
)" |
| | | readonly |
| | | /> |
| | | <up-form-item label="æªå¼ç¥¨æ°" prop="noInvoiceNum"> |
| | | <up-input v-model="item.noInvoiceNum" placeholder="" disabled /> |
| | | </up-form-item> |
| | | <up-form-item label="æªå¼ç¥¨éé¢(å
)" prop="noInvoiceAmount"> |
| | | <up-input v-model="item.noInvoiceAmount" placeholder="" disabled /> |
| | | </up-form-item> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- æäº¤æé® --> |
| | | <view class="footer-btns"> |
| | | <van-button class="cancel-btn" @click="goBack">åæ¶</van-button> |
| | | <van-button class="save-btn" native-type="submit" form-type="submit">ä¿å</van-button> |
| | | </view> |
| | | </van-form> |
| | | <!-- 使ç¨å
Œ
±åºé¨æé®ç»ä»¶ --> |
| | | <FooterButtons |
| | | show |
| | | cancelText="åæ¶" |
| | | confirmText="ä¿å" |
| | | @cancel="goBack" |
| | | @confirm="submitForm" |
| | | /> |
| | | </up-form> |
| | | |
| | | <!-- æ¥æéæ©å¨ --> |
| | | <van-popup v-model:show="showIssueDatePicker" position="bottom"> |
| | | <van-date-picker |
| | | v-model="currentIssueDate" |
| | | title="éæ©å¼ç¥¨æ¥æ" |
| | | <up-popup :show="showIssueDatePicker" mode="bottom" @close="showIssueDatePicker = false"> |
| | | <up-datetime-picker |
| | | :show="true" |
| | | v-model="pickerIssueDateValue" |
| | | @confirm="onIssueDateConfirm" |
| | | @cancel="showIssueDatePicker = false" |
| | | mode="date" |
| | | /> |
| | | </van-popup> |
| | | </up-popup> |
| | | |
| | | <van-popup v-model:show="showCreateTimePicker" position="bottom"> |
| | | <van-date-picker |
| | | v-model="currentCreateTime" |
| | | title="éæ©å½å
¥æ¥æ" |
| | | <up-popup :show="showCreateTimePicker" mode="bottom" @close="showCreateTimePicker = false"> |
| | | <up-datetime-picker |
| | | :show="true" |
| | | v-model="pickerCreateTimeValue" |
| | | @confirm="onCreateTimeConfirm" |
| | | @cancel="showCreateTimePicker = false" |
| | | mode="date" |
| | | /> |
| | | </van-popup> |
| | | </up-popup> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, onMounted } from 'vue' |
| | | import { ref, onMounted } from 'vue' |
| | | // æ¿æ¢ toast æ¹æ³ |
| | | const showToast = (message) => { |
| | | uni.showToast({ |
| | |
| | | import { invoiceRegistrationSave } from '@/api/salesManagement/invoiceRegistration' |
| | | import useUserStore from '@/store/modules/user' |
| | | import {getSalesLedgerWithProducts} from "@/api/salesManagement/salesLedger"; |
| | | import FooterButtons from '@/components/FooterButtons.vue'; |
| | | import { formatDateToYMD } from '@/utils/ruoyi' |
| | | |
| | | const userStore = useUserStore() |
| | | const editData = ref(null); |
| | |
| | | invoiceNo: '' |
| | | }) |
| | | |
| | | // è¡¨åæ ¡éªè§å |
| | | const rules = { |
| | | invoiceNo: [ |
| | | { required: true, message: '请è¾å
¥å票å·ç ', trigger: 'blur' } |
| | | ], |
| | | issueDate: [ |
| | | { required: true, message: 'è¯·éæ©å¼ç¥¨æ¥æ', trigger: 'blur' } |
| | | ] |
| | | }; |
| | | |
| | | // äº§åæ°æ® |
| | | const productData = ref([]) |
| | | |
| | | // æ¥æéæ©å¨ç¶æ |
| | | const showIssueDatePicker = ref(false) |
| | | const showCreateTimePicker = ref(false) |
| | | const currentIssueDate = ref([new Date().getFullYear(), new Date().getMonth() + 1, new Date().getDate()]) |
| | | const currentCreateTime = ref([new Date().getFullYear(), new Date().getMonth() + 1, new Date().getDate()]) |
| | | const pickerIssueDateValue = ref(Date.now()) |
| | | const pickerCreateTimeValue = ref(Date.now()) |
| | | |
| | | // æäº¤ç¶æ |
| | | const submitting = ref(false) |
| | |
| | | } |
| | | |
| | | // å¼ç¥¨æ¥æç¡®è®¤ |
| | | const onIssueDateConfirm = ({ selectedValues }) => { |
| | | console.log('selectedValues--', selectedValues) |
| | | form.value.issueDate = selectedValues.join('-'); |
| | | currentIssueDate.value = selectedValues; |
| | | const onIssueDateConfirm = (e) => { |
| | | form.value.issueDate = formatDateToYMD(e.value) |
| | | pickerIssueDateValue.value = e.value |
| | | showIssueDatePicker.value = false; |
| | | }; |
| | | |
| | | // å½å
¥æ¥æç¡®è®¤ |
| | | const onCreateTimeConfirm = (value) => { |
| | | try { |
| | | // å¤çä¸åç弿 ¼å¼ |
| | | let year, month, day; |
| | | |
| | | if (Array.isArray(value)) { |
| | | // æ°ç»æ ¼å¼ [year, month, day] |
| | | [year, month, day] = value; |
| | | } else if (value && typeof value === 'object') { |
| | | // Dateå¯¹è±¡æ ¼å¼ |
| | | year = value.getFullYear(); |
| | | month = value.getMonth() + 1; |
| | | day = value.getDate(); |
| | | } else { |
| | | // å
¶ä»æ ¼å¼ï¼ä½¿ç¨å½åæ¥æ |
| | | const now = new Date(); |
| | | year = now.getFullYear(); |
| | | month = now.getMonth() + 1; |
| | | day = now.getDate(); |
| | | } |
| | | |
| | | form.value.createTime = `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`; |
| | | showCreateTimePicker.value = false; |
| | | } catch (error) { |
| | | console.error('æ¥æå¤çé误:', error); |
| | | showToast('æ¥æéæ©å¤±è´¥ï¼è¯·éè¯'); |
| | | } |
| | | } |
| | | const onCreateTimeConfirm = (e) => { |
| | | form.value.createTime = formatDateToYMD(e.value) |
| | | pickerCreateTimeValue.value = e.value |
| | | showCreateTimePicker.value = false; |
| | | }; |
| | | |
| | | |
| | | |
| | | // æ ¼å¼åæ¥æ |
| | | const formatDate = (date) => { |
| | |
| | | }) |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .account-detail { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | padding-bottom: 5rem; |
| | | } |
| | | |
| | | .empty-state { |
| | | padding: 40px 0; |
| | | } |
| | | |
| | | .product-section { |
| | | background: #fff; |
| | | margin-top: 1rem; |
| | | padding: 1rem; |
| | | box-shadow: 0 0.125rem 0.5rem rgba(0,0,0,0.04); |
| | | } |
| | | |
| | | .section-header { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | margin-bottom: 1rem; |
| | | } |
| | | |
| | | .section-title { |
| | | font-size: 1rem; |
| | | font-weight: 600; |
| | | color: #333; |
| | | } |
| | | |
| | | .product-list { |
| | | .product-card { |
| | | background: #FFFFFF; |
| | | box-shadow: 0 0 1.25rem 0 rgba(0,57,117,0.08); |
| | | border-radius: 0.5rem 0.5rem 0.5rem 0.5rem; |
| | | padding: 1rem 0.5rem 0 0.5rem; |
| | | position: relative; |
| | | margin-bottom: 1rem; |
| | | } |
| | | } |
| | | |
| | | .product-header { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | padding: 0 0.5rem 0.75rem 0.5rem; |
| | | border-bottom: 0.0625rem solid #e8e8e8; |
| | | } |
| | | |
| | | .product-title { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .product-productCategory { |
| | | margin-left: 0.5rem; |
| | | font-size: 0.875rem; |
| | | font-weight: 500; |
| | | color: #333; |
| | | } |
| | | |
| | | .product-form { |
| | | margin-bottom: 1rem; |
| | | } |
| | | .footer-btns { |
| | | position: fixed; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | background: #fff; |
| | | display: flex; |
| | | justify-content: space-around; |
| | | align-items: center; |
| | | padding: 0.75rem 0; |
| | | box-shadow: 0 -0.125rem 0.5rem rgba(0,0,0,0.05); |
| | | z-index: 1000; |
| | | } |
| | | .cancel-btn { |
| | | font-weight: 400; |
| | | font-size: 1rem; |
| | | color: #FFFFFF; |
| | | width: 6.375rem; |
| | | background: #C7C9CC; |
| | | box-shadow: 0 0.25rem 0.625rem 0 rgba(3,88,185,0.2); |
| | | border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; |
| | | } |
| | | .save-btn { |
| | | font-weight: 400; |
| | | font-size: 1rem; |
| | | color: #FFFFFF; |
| | | width: 14rem; |
| | | background: linear-gradient( 140deg, #00BAFF 0%, #006CFB 100%); |
| | | box-shadow: 0 0.25rem 0.625rem 0 rgba(3,88,185,0.2); |
| | | border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; |
| | | } |
| | | // ååºå¼è°æ´ |
| | | @media (max-width: 768px) { |
| | | .submit-section { |
| | | padding: 12px; |
| | | } |
| | | } |
| | | <style lang="scss"> |
| | | @import '@/static/scss/form-common.scss'; |
| | | </style> |
| | |
| | | |
| | | <!-- æä½æé®åºå --> |
| | | <view class="action-buttons"> |
| | | <van-button |
| | | type="primary" |
| | | size="small" |
| | | @click="handleAddInvoice(item)" |
| | | class="action-btn" |
| | | :disabled="item.noInvoiceAmountTotal == 0" |
| | | > |
| | | æ°å¢å¼ç¥¨ |
| | | </van-button> |
| | | <van-button |
| | | type="default" |
| | | size="small" |
| | | @click="handleViewDetail(item)" |
| | | class="action-btn" |
| | | > |
| | | æ¥ç详æ
|
| | | </van-button> |
| | | <up-button |
| | | type="primary" |
| | | size="small" |
| | | @click="handleAddInvoice(item)" |
| | | class="action-btn" |
| | | :disabled="item.noInvoiceAmountTotal == 0" |
| | | > |
| | | æ°å¢å¼ç¥¨ |
| | | </up-button> |
| | | <up-button |
| | | size="small" |
| | | @click="handleViewDetail(item)" |
| | | class="action-btn" |
| | | > |
| | | æ¥ç详æ
|
| | | </up-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | |
| | | </view> |
| | | <view class="info-item"> |
| | | <text class="info-label">客æ·ååå·</text> |
| | | <text class="info-value">{{ form.customerContractNo }}</text> |
| | | <text class="info-value highlight">{{ form.customerContractNo }}</text> |
| | | </view> |
| | | <view class="info-item"> |
| | | <text class="info-label">客æ·åç§°</text> |
| | |
| | | </view> |
| | | <view class="info-item"> |
| | | <text class="info-label">æªå¼ç¥¨éé¢(å
)</text> |
| | | <text class="info-value redlight">{{ form.noInvoiceAmountTotal }}</text> |
| | | <text class="info-value highlight">{{ form.noInvoiceAmountTotal }}</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | |
| | | <view class="product-card" v-for="(product, idx) in productData" :key="idx"> |
| | | <view class="product-header"> |
| | | <view class="product-title"> |
| | | <van-icon name="description" color="#2979ff" size="15" /> |
| | | <!-- 使ç¨u-iconæ¿ä»£up-icon --> |
| | | <u-icon name="file-text" color="#2979ff" size="15" /> |
| | | <text class="product-productCategory">产å {{ idx + 1 }}</text> |
| | | </view> |
| | | </view> |
| | |
| | | <text class="info-label">æ°é</text> |
| | | <text class="info-value highlight">{{ product.quantity }}</text> |
| | | </view> |
| | | <view class="info-item"> |
| | | <text class="info-label">å«ç¨åä»·(å
)</text> |
| | | <text class="info-value highlight">{{ product.taxInclusiveUnitPrice }}</text> |
| | | </view> |
| | | <view class="info-item"> |
| | | <text class="info-label">å«ç¨åä»·(å
)</text> |
| | | <text class="info-value highlight">{{ product.taxInclusiveUnitPrice }}</text> |
| | | </view> |
| | | <view class="info-item"> |
| | | <text class="info-label">å«ç¨æ»ä»·(å
)</text> |
| | | <text class="info-value highlight">{{ product.taxInclusiveTotalPrice }}</text> |
| | |
| | | </view> |
| | | <view class="info-item"> |
| | | <text class="info-label">æªå¼ç¥¨éé¢(å
)</text> |
| | | <text class="info-value redlight">{{ product.noInvoiceAmount }}</text> |
| | | <text class="info-value highlight">{{ product.noInvoiceAmount }}</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- æ 产åä¿¡æ¯æç¤º --> |
| | | <view class="no-product" v-else> |
| | | |
| | | <view v-else class="no-product"> |
| | | <text>ææ äº§åä¿¡æ¯</text> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { onMounted, ref } from 'vue'; |
| | | import { getSalesLedgerWithProducts } from "@/api/salesManagement/salesLedger"; |
| | | import {onMounted, ref} from 'vue'; |
| | | import {getSalesLedgerWithProducts} from "@/api/salesManagement/salesLedger"; |
| | | |
| | | // è¡¨åæ°æ® |
| | | const form = ref({ |
| | |
| | | // è·å宿´ç产åä¿¡æ¯ |
| | | getSalesLedgerWithProducts({ id: editData.value.id, type: 1 }).then((res) => { |
| | | productData.value = res.productData || []; |
| | | form.value = {...editData.value} |
| | | }); |
| | | |
| | | // å¡«å
åºæ¬ä¿¡æ¯ |
| | | form.value.salesContractNo = editData.value.salesContractNo || ''; |
| | | form.value.customerContractNo = editData.value.customerContractNo || ''; |
| | | form.value.customerName = editData.value.customerName || ''; |
| | | form.value.projectName = editData.value.projectName || ''; |
| | | form.value.executionDate = editData.value.executionDate || ''; |
| | | form.value.contractAmount = editData.value.contractAmount || ''; |
| | | form.value.salesman = editData.value.salesman || ''; |
| | | form.value.invoiceTotal = editData.value.invoiceTotal || 0; |
| | | form.value.noInvoiceAmountTotal = editData.value.noInvoiceAmountTotal || 0; |
| | | form.value.id = editData.value.id || ''; |
| | | form.value.customerId = editData.value.customerId || ''; |
| | | }; |
| | | |
| | | onMounted(() => { |
| | |
| | | position: sticky; |
| | | top: 0; |
| | | z-index: 100; |
| | | /* å
¼å®¹ iOS åæµ·/çµå¨å²å®å
¨åº */ |
| | | padding-top: env(safe-area-inset-top); |
| | | } |
| | | |
| | | .title { |
| | |
| | | box-shadow: 0 0.125rem 0.5rem rgba(0,0,0,0.04); |
| | | } |
| | | |
| | | .product-section { |
| | | background: #fff; |
| | | margin: 1rem; |
| | | padding: 1rem; |
| | | border-radius: 0.5rem; |
| | | box-shadow: 0 0.125rem 0.5rem rgba(0,0,0,0.04); |
| | | } |
| | | |
| | | .section-title { |
| | | font-size: 1rem; |
| | | font-weight: 600; |
| | | color: #333; |
| | | margin-bottom: 1rem; |
| | | padding-bottom: 1rem; |
| | | padding-bottom: 0.5rem; |
| | | border-bottom: 0.0625rem solid #e8e8e8; |
| | | } |
| | | |
| | |
| | | color: #2979ff; |
| | | font-weight: 600; |
| | | } |
| | | .info-value.redlight { |
| | | color: red; |
| | | font-weight: 600; |
| | | } |
| | | |
| | | .product-section { |
| | | background: #fff; |
| | | margin: 1rem; |
| | | padding: 1rem; |
| | | border-radius: 0.5rem; |
| | | box-shadow: 0 0.125rem 0.5rem rgba(0,0,0,0.04); |
| | | } |
| | | |
| | | .product-card { |
| | | background: #f8f9fa; |
| | | border-radius: 0.5rem; |
| | | padding: 1rem; |
| | | margin-bottom: 1rem; |
| | | } |
| | | |
| | | .product-card:last-child { |
| | | margin-bottom: 0; |
| | | border: 0.0625rem solid #e8e8e8; |
| | | } |
| | | |
| | | .product-header { |
| | | display: flex; |
| | | align-items: center; |
| | | padding-bottom: 0.75rem; |
| | | border-bottom: 0.0625rem solid #e8e8e8; |
| | | justify-content: space-between; |
| | | margin-bottom: 1rem; |
| | | padding-bottom: 0.5rem; |
| | | border-bottom: 0.0625rem solid #e8e8e8; |
| | | } |
| | | |
| | | .product-title { |
| | |
| | | readonly |
| | | @click="showPaymentTypePicker" |
| | | /> |
| | | <template #right> |
| | | <up-icon |
| | | name="arrow-right" |
| | | @click="showPaymentTypePicker" |
| | | ></up-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="æ¥æ¬¾æ¥æ" prop="receiptPaymentDate" required border-bottom> |
| | | <u-input |
| | |
| | | readonly |
| | | @click="showDatePicker" |
| | | /> |
| | | <template #right> |
| | | <up-icon |
| | | name="arrow-right" |
| | | @click="showDatePicker" |
| | | ></up-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="ç»è®°äºº" border-bottom> |
| | | <u-input |
| | |
| | | </u-cell-group> |
| | | |
| | | <!-- æäº¤æé® --> |
| | | <view class="footer-btns"> |
| | | <u-button class="cancel-btn" @click="onClickLeft">åæ¶</u-button> |
| | | <u-button class="save-btn" type="primary" @click="onSubmit" :loading="loading">ä¿å</u-button> |
| | | </view> |
| | | <FooterButtons |
| | | cancelText="åæ¶" |
| | | confirmText="ä¿å" |
| | | :loading="loading" |
| | | @cancel="onClickLeft" |
| | | @confirm="onSubmit" |
| | | /> |
| | | </u-form> |
| | | |
| | | <!-- 忬¾æ¹å¼éæ©å¨ --> |
| | | <u-popup v-model="showPaymentType" mode="bottom"> |
| | | <u-picker |
| | | v-model="pickerValue" |
| | | :columns="receipt_payment_type" |
| | | @confirm="onPaymentTypeConfirm" |
| | | @cancel="showPaymentType = false" |
| | | /> |
| | | </u-popup> |
| | | <up-action-sheet |
| | | :show="showPaymentType" |
| | | :actions="receiptPaymentType" |
| | | title="鿩忬¾å½¢å¼" |
| | | @select="onPaymentTypeConfirm" |
| | | @close="showPaymentType = false" |
| | | /> |
| | | |
| | | <!-- æ¥æéæ©å¨ --> |
| | | <u-popup v-model="showDate" mode="bottom"> |
| | | <u-datetime-picker |
| | | <up-popup :show="showDate" mode="bottom" @close="showDate = false"> |
| | | <up-datetime-picker |
| | | :show="true" |
| | | v-model="currentDate" |
| | | title="éæ©æ¥æ" |
| | | @confirm="onDateConfirm" |
| | | @cancel="showDate = false" |
| | | mode="date" |
| | | /> |
| | | </u-popup> |
| | | </up-popup> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted, computed } from 'vue' |
| | | import FooterButtons from '@/components/FooterButtons.vue' |
| | | import { receiptPaymentSaveOrUpdate, invoiceInfo } from '@/api/salesManagement/receiptPayment' |
| | | import useUserStore from '@/store/modules/user' |
| | | import { useDict } from '@/utils/dict' |
| | | import { formatDateToYMD } from '@/utils/ruoyi' |
| | | |
| | | // æ¿æ¢ toast å notify æ¹æ³ |
| | | // æ¾ç¤ºæç¤ºä¿¡æ¯ |
| | | const showToast = (message) => { |
| | | uni.showToast({ |
| | | title: message, |
| | |
| | | }) |
| | | } |
| | | |
| | | const showNotify = ({ type, message }) => { |
| | | uni.showToast({ |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | const showLoadingToast = (message) => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | icon: type === 'warning' ? 'none' : 'success' |
| | | }) |
| | | } |
| | | mask: true |
| | | }); |
| | | }; |
| | | |
| | | // å
³éå è½½æç¤º |
| | | const closeToast = () => { |
| | | uni.hideLoading(); |
| | | }; |
| | | |
| | | const userStore = useUserStore() |
| | | |
| | |
| | | const { receipt_payment_type: dictReceiptPaymentType } = useDict('receipt_payment_type') |
| | | |
| | | // 转æ¢åå
¸æ°æ®æ ¼å¼ä¸ºéæ©å¨éè¦çæ ¼å¼ |
| | | const receipt_payment_type = computed(() => { |
| | | const receiptPaymentType = computed(() => { |
| | | return dictReceiptPaymentType.value.map(item => ({ |
| | | text: item.label, |
| | | name: item.label, |
| | | value: item.value |
| | | })) |
| | | }) |
| | |
| | | } |
| | | |
| | | // ç¡®è®¤åæ¬¾æ¹å¼éæ© |
| | | const onPaymentTypeConfirm = ({ selectedValues, selectedOptions }) => { |
| | | form.value.receiptPaymentType = selectedOptions[0].value |
| | | form.value.receiptPaymentTypeName = selectedOptions[0].text |
| | | pickerValue.value = selectedValues; |
| | | const onPaymentTypeConfirm = (action) => { |
| | | form.value.receiptPaymentType = action.value |
| | | form.value.receiptPaymentTypeName = action.name |
| | | showPaymentType.value = false |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | // ç¡®è®¤æ¥æéæ© |
| | | const onDateConfirm = ({ selectedValues }) => { |
| | | form.value.receiptPaymentDate = selectedValues.join('-') |
| | | currentDate.value = selectedValues |
| | | showDate.value = false |
| | | const onDateConfirm = (e) => { |
| | | form.value.receiptPaymentDate = formatDateToYMD(e.value) |
| | | currentDate.value = formatDateToYMD(e.value) |
| | | showDate.value = false; |
| | | } |
| | | |
| | | // æäº¤è¡¨å |
| | | const onSubmit = () => { |
| | | // 表åéªè¯ |
| | | if (!form.value.receiptPaymentAmount) { |
| | | showNotify({ type: 'warning', message: '请è¾å
¥å款éé¢' }) |
| | | showToast('请è¾å
¥å款éé¢') |
| | | return |
| | | } |
| | | |
| | | if (!form.value.receiptPaymentType) { |
| | | showNotify({ type: 'warning', message: 'è¯·éæ©åæ¬¾å½¢å¼' }) |
| | | showToast('è¯·éæ©åæ¬¾å½¢å¼') |
| | | return |
| | | } |
| | | |
| | | if (!form.value.receiptPaymentDate) { |
| | | showNotify({ type: 'warning', message: 'è¯·éæ©æ¥æ¬¾æ¥æ' }) |
| | | showToast('è¯·éæ©æ¥æ¬¾æ¥æ') |
| | | return |
| | | } |
| | | |
| | |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .account-detail { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | padding-bottom: 5rem; |
| | | } |
| | | |
| | | .footer-btns { |
| | | position: fixed; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | background: #fff; |
| | | display: flex; |
| | | justify-content: space-around; |
| | | align-items: center; |
| | | padding: 0.75rem 0; |
| | | box-shadow: 0 -0.125rem 0.5rem rgba(0,0,0,0.05); |
| | | z-index: 1000; |
| | | } |
| | | |
| | | .cancel-btn { |
| | | font-weight: 400; |
| | | font-size: 1rem; |
| | | color: #FFFFFF; |
| | | width: 6.375rem; |
| | | background: #C7C9CC; |
| | | box-shadow: 0 0.25rem 0.625rem 0 rgba(3,88,185,0.2); |
| | | border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; |
| | | } |
| | | |
| | | .save-btn { |
| | | font-weight: 400; |
| | | font-size: 1rem; |
| | | color: #FFFFFF; |
| | | width: 14rem; |
| | | background: linear-gradient( 140deg, #00BAFF 0%, #006CFB 100%); |
| | | box-shadow: 0 0.25rem 0.625rem 0 rgba(3,88,185,0.2); |
| | | border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; |
| | | } |
| | | |
| | | // ååºå¼è°æ´ |
| | | @media (max-width: 768px) { |
| | | .submit-section { |
| | | padding: 12px; |
| | | } |
| | | } |
| | | .tip-text { padding: 4px 16px 0 16px; font-size: 12px; color: #888; } |
| | | @import '@/static/scss/form-common.scss'; |
| | | </style> |
| | |
| | | readonly |
| | | @click="showPaymentTypePicker" |
| | | /> |
| | | <template #right> |
| | | <up-icon |
| | | name="arrow-right" |
| | | @click="showPaymentTypePicker" |
| | | ></up-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="æ¥æ¬¾æ¥æ" prop="receiptPaymentDate" required border-bottom> |
| | | <u-input |
| | | v-model="form.receiptPaymentDate" |
| | | placeholder="è¯·éæ©" |
| | | readonly |
| | | @click="showDatePicker" |
| | | /> |
| | | <template #right> |
| | | <up-icon |
| | | name="arrow-right" |
| | | @click="showDatePicker" |
| | | ></up-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="ç»è®°äºº" border-bottom> |
| | | <u-input |
| | |
| | | </u-cell-group> |
| | | |
| | | <!-- æäº¤æé® --> |
| | | <view class="footer-btns"> |
| | | <u-button class="cancel-btn" @click="onClickLeft">åæ¶</u-button> |
| | | <u-button class="save-btn" type="primary" @click="onSubmit" :loading="loading">ä¿å</u-button> |
| | | </view> |
| | | <FooterButtons |
| | | cancelText="åæ¶" |
| | | confirmText="ä¿å" |
| | | :loading="loading" |
| | | @cancel="onClickLeft" |
| | | @confirm="onSubmit" |
| | | /> |
| | | </u-form> |
| | | |
| | | <!-- 忬¾æ¹å¼éæ©å¨ --> |
| | | <u-popup v-model="showPaymentType" mode="bottom"> |
| | | <u-picker |
| | | v-model="pickerValue" |
| | | :columns="receipt_payment_type" |
| | | @confirm="onPaymentTypeConfirm" |
| | | @cancel="showPaymentType = false" |
| | | /> |
| | | </u-popup> |
| | | <up-action-sheet |
| | | :show="showPaymentType" |
| | | :actions="receipt_payment_type" |
| | | title="鿩忬¾å½¢å¼" |
| | | @select="onPaymentTypeConfirm" |
| | | @close="showPaymentType = false" |
| | | /> |
| | | |
| | | <!-- æ¥æéæ©å¨ --> |
| | | <u-popup v-model="showDate" mode="bottom"> |
| | | <u-datetime-picker |
| | | <up-popup :show="showDate" mode="bottom" @close="showDate = false"> |
| | | <up-datetime-picker |
| | | :show="true" |
| | | v-model="currentDate" |
| | | title="éæ©æ¥æ" |
| | | @confirm="onDateConfirm" |
| | | @cancel="showDate = false" |
| | | mode="date" |
| | | /> |
| | | </u-popup> |
| | | </up-popup> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted, computed } from 'vue' |
| | | import FooterButtons from '@/components/FooterButtons.vue' |
| | | import { receiptPaymentSaveOrUpdate, invoiceInfo } from '@/api/salesManagement/receiptPayment' |
| | | import useUserStore from '@/store/modules/user' |
| | | import { useDict } from '@/utils/dict' |
| | | import { formatDateToYMD } from '@/utils/ruoyi' |
| | | |
| | | // æ¿æ¢ toast å notify æ¹æ³ |
| | | // æ¾ç¤ºæç¤ºä¿¡æ¯ |
| | | const showToast = (message) => { |
| | | uni.showToast({ |
| | | title: message, |
| | |
| | | }) |
| | | } |
| | | |
| | | const showNotify = ({ type, message }) => { |
| | | uni.showToast({ |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | const showLoadingToast = (message) => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | icon: type === 'warning' ? 'none' : 'success' |
| | | }) |
| | | } |
| | | mask: true |
| | | }); |
| | | }; |
| | | |
| | | // å
³éå è½½æç¤º |
| | | const closeToast = () => { |
| | | uni.hideLoading(); |
| | | }; |
| | | |
| | | const userStore = useUserStore() |
| | | |
| | |
| | | // 转æ¢åå
¸æ°æ®æ ¼å¼ä¸ºéæ©å¨éè¦çæ ¼å¼ |
| | | const receipt_payment_type = computed(() => { |
| | | return dictReceiptPaymentType.value.map(item => ({ |
| | | text: item.label, |
| | | name: item.label, |
| | | value: item.value |
| | | })) |
| | | }) |
| | |
| | | } |
| | | |
| | | // ç¡®è®¤åæ¬¾æ¹å¼éæ© |
| | | const onPaymentTypeConfirm = ({ selectedValues, selectedOptions }) => { |
| | | form.value.receiptPaymentType = selectedOptions[0].value |
| | | form.value.receiptPaymentTypeName = selectedOptions[0].text |
| | | pickerValue.value = selectedValues; |
| | | const onPaymentTypeConfirm = (action) => { |
| | | form.value.receiptPaymentType = action.value |
| | | form.value.receiptPaymentTypeName = action.name |
| | | showPaymentType.value = false |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | // ç¡®è®¤æ¥æéæ© |
| | | const onDateConfirm = ({ selectedValues }) => { |
| | | form.value.receiptPaymentDate = selectedValues.join('-') |
| | | currentDate.value = selectedValues |
| | | showDate.value = false |
| | | const onDateConfirm = (e) => { |
| | | form.value.receiptPaymentDate = formatDateToYMD(e.value) |
| | | currentDate.value = formatDateToYMD(e.value) |
| | | showDate.value = false; |
| | | } |
| | | |
| | | // æäº¤è¡¨å |
| | | const onSubmit = () => { |
| | | // 表åéªè¯ |
| | | if (!form.value.receiptPaymentAmount) { |
| | | showNotify({ type: 'warning', message: '请è¾å
¥å款éé¢' }) |
| | | showToast('请è¾å
¥å款éé¢') |
| | | return |
| | | } |
| | | |
| | | if (!form.value.receiptPaymentType) { |
| | | showNotify({ type: 'warning', message: 'è¯·éæ©åæ¬¾å½¢å¼' }) |
| | | showToast('è¯·éæ©åæ¬¾å½¢å¼') |
| | | return |
| | | } |
| | | loading.value = true |
| | |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import '@/static/scss/form-common.scss'; |
| | | |
| | | .account-detail { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | padding-bottom: 5rem; |
| | | min-height: 100vh; |
| | | background: #f5f5f5; |
| | | padding-bottom: 5rem; |
| | | } |
| | | |
| | | .footer-btns { |
| | | position: fixed; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | background: #fff; |
| | | display: flex; |
| | | justify-content: space-around; |
| | | align-items: center; |
| | | padding: 0.75rem 0; |
| | | box-shadow: 0 -0.125rem 0.5rem rgba(0,0,0,0.05); |
| | | z-index: 1000; |
| | | } |
| | | |
| | | .cancel-btn { |
| | | font-weight: 400; |
| | | font-size: 1rem; |
| | | color: #FFFFFF; |
| | | width: 6.375rem; |
| | | background: #C7C9CC; |
| | | box-shadow: 0 0.25rem 0.625rem 0 rgba(3,88,185,0.2); |
| | | border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; |
| | | } |
| | | |
| | | .save-btn { |
| | | font-weight: 400; |
| | | font-size: 1rem; |
| | | color: #FFFFFF; |
| | | width: 14rem; |
| | | background: linear-gradient( 140deg, #00BAFF 0%, #006CFB 100%); |
| | | box-shadow: 0 0.25rem 0.625rem 0 rgba(3,88,185,0.2); |
| | | border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; |
| | | } |
| | | |
| | | // ååºå¼è°æ´ |
| | | @media (max-width: 768px) { |
| | | .submit-section { |
| | | padding: 12px; |
| | | } |
| | | } |
| | | .tip-text { padding: 4px 16px 0 16px; font-size: 12px; color: #888; } |
| | | </style> |
| | |
| | | <template> |
| | | <view class="receipt-payment"> |
| | | <view class="sales-account"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader title="忬¾ç»è®°" @back="goBack" /> |
| | | |
| | |
| | | <!-- çéå¼å
³ --> |
| | | <view class="switch-row"> |
| | | <text class="switch-label">䏿¾ç¤ºå¾
忬¾ä¸º0</text> |
| | | <van-switch v-model="searchForm.status" @change="getList" size="18"/> |
| | | <up-switch v-model="searchForm.status" @change="getList" size="18"/> |
| | | </view> |
| | | </view> |
| | | |
| | |
| | | |
| | | <!-- æä½æé® --> |
| | | <view class="action-buttons"> |
| | | <van-button |
| | | <up-button |
| | | type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | |
| | | @click="openForm(item)" |
| | | > |
| | | æ°å¢å款 |
| | | </van-button> |
| | | </up-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | |
| | | bindInvoiceNoRegPage, |
| | | } from '@/api/salesManagement/receiptPayment' |
| | | import useUserStore from '@/store/modules/user' |
| | | |
| | | // æ¾ç¤ºæç¤ºä¿¡æ¯ |
| | | const showToast = (message) => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: 'none' |
| | | }) |
| | | } |
| | | |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | const showLoadingToast = (message) => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | mask: true |
| | | }); |
| | | }; |
| | | |
| | | // å
³éå è½½æç¤º |
| | | const closeToast = () => { |
| | | uni.hideLoading(); |
| | | }; |
| | | |
| | | import {onShow} from "@dcloudio/uni-app"; |
| | | |
| | | // ååºå¼æ°æ® |
| | |
| | | |
| | | // è·ååè¡¨æ°æ® |
| | | const getList = () => { |
| | | tableLoading.value = true |
| | | showLoadingToast('å è½½ä¸...') |
| | | bindInvoiceNoRegPage({ ...searchForm.value, ...page.value }) |
| | | .then((res) => { |
| | | tableLoading.value = false |
| | | tableData.value = res.data.records || [] |
| | | }) |
| | | .catch(() => { |
| | | tableLoading.value = false |
| | | showToast('è·åæ°æ®å¤±è´¥') |
| | | }) |
| | | .finally(() => { |
| | | closeToast() |
| | | }) |
| | | } |
| | | |
| | |
| | | margin: 0 !important; |
| | | } |
| | | |
| | | .receipt-payment { |
| | | .sales-account { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | position: relative; |
| | |
| | | </view> |
| | | <!-- æä½æé® --> |
| | | <view class="action-buttons"> |
| | | <van-button |
| | | <u-button |
| | | type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | |
| | | @click="openForm(item)" |
| | | > |
| | | ç¼è¾å款 |
| | | </van-button> |
| | | </u-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | |
| | | |
| | | const param = { |
| | | customerId: customerId.value, |
| | | current: -1, |
| | | size: -1 |
| | | }; |
| | | |
| | | customerInteractions(param).then((res) => { |
| | |
| | | <PageHeader title="å°è´¦è¯¦æ
" @back="goBack" /> |
| | | |
| | | <!-- 表ååºå --> |
| | | <u-form @submit="onSubmit" label-width="110" input-align="right" style="margin-top: 10px" error-message-align="right"> |
| | | <u-form-item label="éå®ååå·" prop="salesContractNo" border-bottom> |
| | | <u-input v-model="form.salesContractNo" placeholder="èªå¨çæ" disabled /> |
| | | </u-form-item> |
| | | <u-form-item |
| | | <up-form @submit="onSubmit" label-width="110" ref="formRef" :rules="rules" :model="form"> |
| | | |
| | | <up-form-item label="éå®ååå·" prop="salesContractNo" > |
| | | <up-input v-model="form.salesContractNo" placeholder="èªå¨çæ" disabled /> |
| | | </up-form-item> |
| | | <up-form-item |
| | | label="ä¸å¡å" |
| | | prop="salesman" |
| | | required |
| | | border-bottom |
| | | @click="showPicker = true" |
| | | > |
| | | <u-input |
| | | <up-input |
| | | v-model="form.salesman" |
| | | readonly |
| | | placeholder="ç¹å»éæ©ä¸å¡å" |
| | | readonly="" |
| | | @click="showPicker = true" |
| | | placeholder="ç¹å»éæ©ä¸å¡å" |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="客æ·ååå·" prop="customerContractNo" required border-bottom> |
| | | <u-input |
| | | <template #right> |
| | | <up-icon |
| | | name="arrow-right" |
| | | @click="showPicker = true" |
| | | ></up-icon> |
| | | </template> |
| | | </up-form-item> |
| | | <up-form-item label="客æ·ååå·" prop="customerContractNo" required > |
| | | <up-input |
| | | v-model="form.customerContractNo" |
| | | placeholder="请è¾å
¥å®¢æ·ååå·" |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item |
| | | </up-form-item> |
| | | <up-form-item |
| | | label="客æ·åç§°" |
| | | prop="customerName" |
| | | required |
| | | border-bottom |
| | | > |
| | | <u-input |
| | | <up-input |
| | | v-model="form.customerName" |
| | | readonly |
| | | placeholder="ç¹å»éæ©å®¢æ·" |
| | | @click="showCustomerPicker = true" |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="项ç®åç§°" prop="projectName" required border-bottom> |
| | | <u-input v-model="form.projectName" placeholder="请è¾å
¥é¡¹ç®åç§°" /> |
| | | </u-form-item> |
| | | <u-form-item |
| | | <template #right> |
| | | <up-icon |
| | | name="arrow-right" |
| | | @click="showCustomerPicker = true" |
| | | ></up-icon> |
| | | </template> |
| | | </up-form-item> |
| | | <up-form-item label="项ç®åç§°" prop="projectName" required > |
| | | <up-input v-model="form.projectName" placeholder="请è¾å
¥é¡¹ç®åç§°" /> |
| | | </up-form-item> |
| | | <up-form-item |
| | | label="ç¾è®¢æ¥æ" |
| | | prop="executionDate" |
| | | required |
| | | border-bottom |
| | | > |
| | | <u-input |
| | | <up-input |
| | | v-model="form.executionDate" |
| | | readonly |
| | | placeholder="ç¹å»éæ©æ¶é´" |
| | | @click="showDatePicker = true" |
| | | /> |
| | | </u-form-item> |
| | | <u-popup v-model="showDatePicker" mode="bottom"> |
| | | <u-datetime-picker |
| | | <template #right> |
| | | <up-icon |
| | | name="arrow-right" |
| | | @click="showDatePicker = true" |
| | | ></up-icon> |
| | | </template> |
| | | </up-form-item> |
| | | <up-form-item label="仿¬¾æ¹å¼" prop="paymentMethod" > |
| | | <up-input v-model="form.paymentMethod" placeholder="请è¾å
¥ä»æ¬¾æ¹å¼" /> |
| | | </up-form-item> |
| | | <up-form-item label="å½å
¥äºº" prop="entryPersonName" > |
| | | <up-input v-model="form.entryPersonName" placeholder="请è¾å
¥" disabled /> |
| | | </up-form-item> |
| | | <up-form-item label="å½å
¥æ¥æ" prop="entryDate" > |
| | | <up-input v-model="form.entryDate" placeholder="请è¾å
¥" disabled /> |
| | | </up-form-item> |
| | | <!-- ä¸å¡åéæ© --> |
| | | <up-action-sheet |
| | | :show="showPicker" |
| | | :actions="userActionList" |
| | | title="éæ©ä¸å¡å" |
| | | @select="onSalesmanSelect" |
| | | @close="showPicker = false" |
| | | /> |
| | | |
| | | <!-- æ¥æéæ© --> |
| | | <up-popup :show="showDatePicker" mode="bottom" @close="showDatePicker = false"> |
| | | <up-datetime-picker |
| | | :show="true" |
| | | v-model="pickerDateValue" |
| | | @confirm="onDateConfirm" |
| | | @cancel="showDatePicker = false" |
| | | mode="date" |
| | | /> |
| | | </u-popup> |
| | | <u-form-item label="仿¬¾æ¹å¼" prop="paymentMethod" border-bottom> |
| | | <u-input v-model="form.paymentMethod" placeholder="请è¾å
¥ä»æ¬¾æ¹å¼" /> |
| | | </u-form-item> |
| | | <u-form-item label="å½å
¥äºº" prop="entryPersonName" border-bottom> |
| | | <u-input v-model="form.entryPersonName" placeholder="请è¾å
¥" disabled /> |
| | | </u-form-item> |
| | | <u-form-item label="å½å
¥æ¥æ" prop="entryDate" border-bottom> |
| | | <u-input v-model="form.entryDate" placeholder="请è¾å
¥" disabled /> |
| | | </u-form-item> |
| | | <!-- ä¸å¡åéæ©å¼¹çª --> |
| | | <u-popup v-model="showPicker" mode="bottom"> |
| | | <view class="picker-header"> |
| | | <view class="picker-cancel" @click="showPicker = false">åæ¶</view> |
| | | <view class="picker-title">éæ©ä¸å¡å</view> |
| | | <view class="picker-confirm" @click="confirmSalesman">ç¡®å®</view> |
| | | </view> |
| | | <u-picker |
| | | :columns="userList" |
| | | v-model="pickerValue" |
| | | @change="onPickerChange" |
| | | /> |
| | | </u-popup> |
| | | |
| | | <!-- 客æ·éæ©å¼¹çª --> |
| | | <u-popup v-model="showCustomerPicker" mode="bottom"> |
| | | <view class="picker-header"> |
| | | <view class="picker-cancel" @click="showCustomerPicker = false">åæ¶</view> |
| | | <view class="picker-title">鿩客æ·</view> |
| | | <view class="picker-confirm" @click="confirmCustomer">ç¡®å®</view> |
| | | </view> |
| | | <u-picker |
| | | :columns="customerOption" |
| | | v-model="pickerCustomerValue" |
| | | @change="onCustomerPickerChange" |
| | | /> |
| | | </u-popup> |
| | | </up-popup> |
| | | <!-- 客æ·éæ© --> |
| | | <up-action-sheet |
| | | :show="showCustomerPicker" |
| | | :actions="customerActionList" |
| | | title="鿩客æ·" |
| | | @select="onCustomerSelect" |
| | | @close="showCustomerPicker = false" |
| | | /> |
| | | |
| | | <!-- 产åå¤§ç±»éæ©å¨ --> |
| | | <u-popup v-model="showCategoryPicker" mode="bottom"> |
| | | <up-popup :show="showCategoryPicker" mode="bottom"> |
| | | <!-- 头鍿é®åºå --> |
| | | <view class="popup-header"> |
| | | <view @click="showCategoryPicker = false" class="cancelButton">åæ¶</view> |
| | | <view @click="confirmCategorySelection" class="confirmButton">ç¡®å®</view> |
| | | </view> |
| | | <up-tree |
| | | <u-tree |
| | | :data="productOptions" |
| | | :props="defaultProps" |
| | | show-checkbox |
| | |
| | | check-strictly |
| | | @check-change="onCategoryConfirm" |
| | | /> |
| | | </u-popup> |
| | | </up-popup> |
| | | |
| | | <!-- è§æ ¼åå·éæ©å¨ --> |
| | | <u-popup v-model="showSpecificationPicker" mode="bottom"> |
| | | <u-picker |
| | | :columns="modelOptions" |
| | | v-model="pickerSpecificationValue" |
| | | @confirm="onSpecificationConfirm" |
| | | @cancel="showSpecificationPicker = false" |
| | | /> |
| | | </u-popup> |
| | | <up-action-sheet |
| | | :show="showSpecificationPicker" |
| | | :actions="specificationActionList" |
| | | title="éæ©è§æ ¼åå·" |
| | | @select="onSpecificationSelect" |
| | | @close="showSpecificationPicker = false" |
| | | /> |
| | | |
| | | <!-- ç¨çéæ©å¨ --> |
| | | <u-popup v-model="showTaxRatePicker" mode="bottom"> |
| | | <u-picker |
| | | :columns="taxRateOptions" |
| | | v-model="pickerTaxRateValue" |
| | | @confirm="onTaxRateConfirm" |
| | | @cancel="showTaxRatePicker = false" |
| | | /> |
| | | </u-popup> |
| | | <up-action-sheet |
| | | :show="showTaxRatePicker" |
| | | :actions="taxRateActionList" |
| | | title="éæ©ç¨ç" |
| | | @select="onTaxRateSelect" |
| | | @close="showTaxRatePicker = false" |
| | | /> |
| | | |
| | | <!-- å票类åéæ©å¨ --> |
| | | <u-popup v-model="showInvoiceTypePicker" mode="bottom"> |
| | | <u-picker |
| | | :columns="invoiceTypeOptions" |
| | | v-model="pickerInvoiceTypeValue" |
| | | @confirm="onInvoiceTypeConfirm" |
| | | @cancel="showInvoiceTypePicker = false" |
| | | /> |
| | | </u-popup> |
| | | <up-action-sheet |
| | | :show="showInvoiceTypePicker" |
| | | :actions="invoiceTypeActionList" |
| | | title="éæ©å票类å" |
| | | @select="onInvoiceTypeSelect" |
| | | @close="showInvoiceTypePicker = false" |
| | | /> |
| | | <!-- 产åä¿¡æ¯ --> |
| | | <view class="product-section"> |
| | | <view class="section-header"> |
| | | <text class="section-title">产åä¿¡æ¯</text> |
| | | <u-button type="primary" size="small" @click="addProduct" class="add-btn" v-if="operationType !== 'view'"> |
| | | <u-icon name="plus" size="14" /> |
| | | æ°å¢ |
| | | </u-button> |
| | | <view> |
| | | <text class="section-title">产åä¿¡æ¯</text> |
| | | </view> |
| | | <view> |
| | | <up-button type="primary" size="small" @click="addProduct" class="add-btn" v-if="operationType !== 'view'"> |
| | | æ°å¢ |
| | | </up-button> |
| | | </view> |
| | | </view> |
| | | <view class="product-card" v-for="(product, idx) in productData" :key="idx"> |
| | | <!-- 产åç±» --> |
| | | <view class="product-header"> |
| | | <view class="product-title"> |
| | | <u-icon name="file-text" color="#2979ff" size="15" /> |
| | | <view class="document-icon"> |
| | | <up-icon name="file-text" size="16" color="#ffffff"></up-icon> |
| | | </view> |
| | | <text class="product-productCategory">产å {{ idx + 1 }}</text> |
| | | </view> |
| | | <!-- æä½æé® --> |
| | | <view class="product-actions" v-if="operationType !== 'view'"> |
| | | <u-button type="error" size="mini" @click="removeProduct(idx)" class="del-btn"> |
| | | <u-icon name="trash" size="12" /> |
| | | <up-button type="error" size="mini" @click="removeProduct(idx)" class="del-btn"> |
| | | å é¤ |
| | | </u-button> |
| | | </up-button> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 产åä¿¡æ¯è¡¨å --> |
| | | <view class="product-form"> |
| | | <!-- 产å大类 --> |
| | | <u-form-item |
| | | <up-form-item |
| | | label="产å大类" |
| | | prop="productCategory" |
| | | required |
| | | border-bottom |
| | | :rules="productRules" |
| | | > |
| | | <u-input |
| | | <up-input |
| | | v-model="product.productCategory" |
| | | readonly |
| | | placeholder="è¯·éæ©" |
| | | @click="openCategoryPicker(idx)" |
| | | /> |
| | | </u-form-item> |
| | | <template #right> |
| | | <up-icon |
| | | name="arrow-right" |
| | | @click="showCategoryPicker = true" |
| | | ></up-icon> |
| | | </template> |
| | | </up-form-item> |
| | | |
| | | <!-- è§æ ¼åå· --> |
| | | <u-form-item |
| | | <up-form-item |
| | | label="è§æ ¼åå·" |
| | | prop="specificationModel" |
| | | required |
| | | border-bottom |
| | | :rules="productRules" |
| | | > |
| | | <u-input |
| | | <up-input |
| | | v-model="product.specificationModel" |
| | | readonly |
| | | placeholder="è¯·éæ©" |
| | | @click="openSpecificationPicker(idx)" |
| | | /> |
| | | </u-form-item> |
| | | <template #right> |
| | | <up-icon |
| | | name="arrow-right" |
| | | @click="showSpecificationPicker = true" |
| | | ></up-icon> |
| | | </template> |
| | | </up-form-item> |
| | | |
| | | <!-- åä½ --> |
| | | <u-form-item |
| | | <up-form-item |
| | | label="åä½" |
| | | prop="unit" |
| | | required |
| | | border-bottom |
| | | :rules="productRules" |
| | | > |
| | | <u-input |
| | | <up-input |
| | | v-model="product.unit" |
| | | placeholder="请è¾å
¥" |
| | | /> |
| | | </u-form-item> |
| | | </up-form-item> |
| | | |
| | | <!-- ç¨ç --> |
| | | <u-form-item |
| | | <up-form-item |
| | | label="ç¨ç(%)" |
| | | prop="taxRate" |
| | | required |
| | | border-bottom |
| | | :rules="productRules" |
| | | > |
| | | <u-input |
| | | <up-input |
| | | v-model="product.taxRate" |
| | | readonly |
| | | placeholder="è¯·éæ©" |
| | | @click="openTaxRatePicker(idx)" |
| | | /> |
| | | </u-form-item> |
| | | <template #right> |
| | | <up-icon |
| | | name="arrow-right" |
| | | @click="showTaxRatePicker = true" |
| | | ></up-icon> |
| | | </template> |
| | | </up-form-item> |
| | | |
| | | <!-- å«ç¨åä»· --> |
| | | <u-form-item |
| | | <up-form-item |
| | | label="å«ç¨åä»·(å
)" |
| | | prop="taxInclusiveUnitPrice" |
| | | required |
| | | border-bottom |
| | | :rules="productRules" |
| | | > |
| | | <u-input |
| | | <up-input |
| | | v-model="product.taxInclusiveUnitPrice" |
| | | type="number" |
| | | placeholder="请è¾å
¥" |
| | | @blur="formatTaxPrice(idx)" |
| | | /> |
| | | </u-form-item> |
| | | </up-form-item> |
| | | |
| | | <!-- æ°é --> |
| | | <u-form-item |
| | | <up-form-item |
| | | label="æ°é" |
| | | prop="quantity" |
| | | required |
| | | border-bottom |
| | | :rules="productRules" |
| | | > |
| | | <u-input |
| | | <up-input |
| | | v-model="product.quantity" |
| | | type="number" |
| | | placeholder="请è¾å
¥" |
| | | @blur="formatAmount(idx)" |
| | | /> |
| | | </u-form-item> |
| | | </up-form-item> |
| | | |
| | | <!-- å«ç¨æ»ä»· --> |
| | | <u-form-item |
| | | <up-form-item |
| | | label="å«ç¨æ»ä»·(å
)" |
| | | prop="taxInclusiveTotalPrice" |
| | | required |
| | | border-bottom |
| | | :rules="productRules" |
| | | > |
| | | <u-input |
| | | <up-input |
| | | v-model="product.taxInclusiveTotalPrice" |
| | | type="number" |
| | | placeholder="请è¾å
¥" |
| | | @blur="formatTaxTotal(idx)" |
| | | /> |
| | | </u-form-item> |
| | | </up-form-item> |
| | | |
| | | <!-- ä¸å«ç¨æ»ä»· --> |
| | | <u-form-item |
| | | <up-form-item |
| | | label="ä¸å«ç¨æ»ä»·(å
)" |
| | | prop="taxExclusiveTotalPrice" |
| | | required |
| | | border-bottom |
| | | :rules="productRules" |
| | | > |
| | | <u-input |
| | | <up-input |
| | | v-model="product.taxExclusiveTotalPrice" |
| | | type="number" |
| | | placeholder="请è¾å
¥" |
| | | @blur="formatNoTaxTotal(idx)" |
| | | /> |
| | | </u-form-item> |
| | | </up-form-item> |
| | | |
| | | <!-- å票类å --> |
| | | <u-form-item |
| | | <up-form-item |
| | | label="å票类å" |
| | | prop="invoiceType" |
| | | required |
| | | border-bottom |
| | | :rules="productRules" |
| | | > |
| | | <u-input |
| | | <up-input |
| | | v-model="product.invoiceType" |
| | | readonly |
| | | placeholder="è¯·éæ©" |
| | | @click="openInvoiceTypePicker(idx)" |
| | | /> |
| | | </u-form-item> |
| | | <template #right> |
| | | <up-icon |
| | | name="arrow-right" |
| | | @click="showInvoiceTypePicker = true" |
| | | ></up-icon> |
| | | </template> |
| | | </up-form-item> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </u-form> |
| | | </up-form> |
| | | |
| | | <!-- 使ç¨å
Œ
±åºé¨æé®ç»ä»¶ --> |
| | | <FooterButtons |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {onMounted, ref} from 'vue'; |
| | | import {onMounted, ref, computed} from 'vue'; |
| | | import {userListNoPage} from "@/api/system/user"; |
| | | import { formatDateToYMD } from '@/utils/ruoyi' |
| | | import { |
| | | addOrUpdateSalesLedger, |
| | | addOrUpdateSalesLedgerProduct, |
| | |
| | | // è·å页é¢åæ° |
| | | const operationType = ref(''); |
| | | const editData = ref(null); |
| | | const formRef = ref(null); |
| | | |
| | | const userStore = useUserStore() |
| | | const form = ref({ |
| | |
| | | entryPersonName: '', |
| | | entryDate: '', |
| | | }); |
| | | const pickerValue = ref(['']); |
| | | const pickerDateValue = ref([]); |
| | | const showPicker = ref(false); |
| | | const showDatePicker = ref(false); |
| | | const pickerCustomerValue = ref(['']); |
| | | const pickerDateValue = ref(Date.now()); |
| | | const showCustomerPicker = ref(false); |
| | | const userList = ref([]); |
| | | const customerOption = ref([]); |
| | | const userActionList = computed(() => { |
| | | return userList.value.map(user => ({ |
| | | name: user.text, |
| | | value: user.value |
| | | })) |
| | | }) |
| | | const formatter = (type, value) => { |
| | | if (type === 'year') { |
| | | return `${value}`; |
| | | } |
| | | if (type === 'month') { |
| | | return `${value}`; |
| | | } |
| | | if (type === 'day') { |
| | | return `${value}`; |
| | | } |
| | | return value; |
| | | }; |
| | | const customerActionList = computed(() => { |
| | | return customerOption.value.map(customer => ({ |
| | | name: customer.text, |
| | | value: customer.value |
| | | })) |
| | | }) |
| | | |
| | | // æ¥æéæ©å表已移é¤ï¼æ¹ç¨ up-datetime-picker |
| | | |
| | | // 产åå¤§ç±»éæ©å表 |
| | | const categoryActionList = computed(() => { |
| | | const flattenCategories = (categories, result = []) => { |
| | | categories.forEach(category => { |
| | | result.push({ |
| | | name: category.label, |
| | | value: category.id |
| | | }) |
| | | if (category.children && category.children.length > 0) { |
| | | flattenCategories(category.children, result) |
| | | } |
| | | }) |
| | | return result |
| | | } |
| | | return flattenCategories(productOptions.value) |
| | | }) |
| | | |
| | | // è§æ ¼åå·éæ©å表 |
| | | const specificationActionList = computed(() => { |
| | | return modelOptions.value.map(model => ({ |
| | | name: model.text, |
| | | value: model.value, |
| | | unit: model.unit |
| | | })) |
| | | }) |
| | | |
| | | // ç¨çéæ©å表 |
| | | const taxRateActionList = computed(() => { |
| | | return taxRateOptions.value.map(rate => ({ |
| | | name: rate.text, |
| | | value: rate.value |
| | | })) |
| | | }) |
| | | |
| | | // å票类åéæ©å表 |
| | | const invoiceTypeActionList = computed(() => { |
| | | return invoiceTypeOptions.value.map(type => ({ |
| | | name: type.text, |
| | | value: type.value |
| | | })) |
| | | }) |
| | | const productData = ref([]); |
| | | |
| | | // éæ©å¨ç¸å
³åé |
| | |
| | | const showSpecificationPicker = ref(false); |
| | | const showTaxRatePicker = ref(false); |
| | | const showInvoiceTypePicker = ref(false); |
| | | const pickerCategoryValue = ref(['']); |
| | | const pickerSpecificationValue = ref(['']); |
| | | const pickerTaxRateValue = ref(['']); |
| | | const pickerInvoiceTypeValue = ref(['']); |
| | | // 鿩卿¾ç¤ºç¶æåéå·²å¨ä¸é¢å®ä¹ |
| | | |
| | | // 临æ¶åå¨éæ©å¨éä¸çå¼ |
| | | const tempSalesmanValue = ref(''); |
| | | const tempCustomerValue = ref(''); |
| | | const selectedSalesman = ref(null); |
| | | const selectedCustomer = ref(null); |
| | | // 临æ¶åéå·²ä¸åéè¦ |
| | | const currentProductIndex = ref(0); |
| | | |
| | | // éé¡¹æ°æ® |
| | |
| | | { text: 'å¢ä¸ç¥¨', value: 'å¢ä¸ç¥¨' }, |
| | | ]); |
| | | |
| | | // è¡¨åæ ¡éªè§å |
| | | const rules = { |
| | | salesman: [ |
| | | { required: true, message: 'è¯·éæ©ä¸å¡å', trigger: 'blur' } |
| | | ], |
| | | customerContractNo: [ |
| | | { required: true, message: '请è¾å
¥å®¢æ·ååå·', trigger: 'blur' } |
| | | ], |
| | | customerName: [ |
| | | { required: true, message: 'è¯·éæ©å®¢æ·åç§°', trigger: 'blur' } |
| | | ], |
| | | projectName: [ |
| | | { required: true, message: '请è¾å
¥é¡¹ç®åç§°', trigger: 'blur' } |
| | | ], |
| | | executionDate: [ |
| | | { required: true, message: 'è¯·éæ©ç¾è®¢æ¥æ', trigger: 'blur' } |
| | | ] |
| | | }; |
| | | |
| | | // 产åä¿¡æ¯æ ¡éªè§å |
| | | const productRules = { |
| | | productCategory: [ |
| | | { required: true, message: 'è¯·éæ©äº§å大类', trigger: 'blur' } |
| | | ], |
| | | specificationModel: [ |
| | | { required: true, message: 'è¯·éæ©è§æ ¼åå·', trigger: 'blur' } |
| | | ], |
| | | unit: [ |
| | | { required: true, message: '请è¾å
¥åä½', trigger: 'blur' } |
| | | ], |
| | | taxRate: [ |
| | | { required: true, message: 'è¯·éæ©ç¨ç', trigger: 'blur' } |
| | | ], |
| | | taxInclusiveUnitPrice: [ |
| | | { required: true, message: '请è¾å
¥å«ç¨åä»·', trigger: 'blur' }, |
| | | { type: 'number', min: 0, message: 'å«ç¨åä»·å¿
须大äº0', trigger: 'blur' } |
| | | ], |
| | | quantity: [ |
| | | { required: true, message: '请è¾å
¥æ°é', trigger: 'blur' }, |
| | | { type: 'number', min: 0, message: 'æ°éå¿
须大äº0', trigger: 'blur' } |
| | | ], |
| | | taxInclusiveTotalPrice: [ |
| | | { required: true, message: '请è¾å
¥å«ç¨æ»ä»·', trigger: 'blur' }, |
| | | { type: 'number', min: 0, message: 'å«ç¨æ»ä»·å¿
须大äº0', trigger: 'blur' } |
| | | ], |
| | | taxExclusiveTotalPrice: [ |
| | | { required: true, message: '请è¾å
¥ä¸å«ç¨æ»ä»·', trigger: 'blur' }, |
| | | { type: 'number', min: 0, message: 'ä¸å«ç¨æ»ä»·å¿
须大äº0', trigger: 'blur' } |
| | | ], |
| | | invoiceType: [ |
| | | { required: true, message: 'è¯·éæ©å票类å', trigger: 'blur' } |
| | | ] |
| | | }; |
| | | |
| | | const addProduct = () => { |
| | | if (productData.value === null) { |
| | | productData.value = [] |
| | |
| | | invoiceType: '' |
| | | }); |
| | | }; |
| | | // ä¸å¡åéæ©å¨ååäºä»¶ |
| | | const onPickerChange = ({ selectedValues, selectedOptions }) => { |
| | | selectedSalesman.value = selectedOptions[0]; |
| | | tempSalesmanValue.value = { |
| | | text: selectedOptions[0]?.text, |
| | | value: selectedOptions[0]?.value |
| | | }; |
| | | }; |
| | | // ä¸å¡åéæ©äºä»¶ |
| | | const onSalesmanSelect = (item) => { |
| | | form.value.salesman = item.name |
| | | } |
| | | |
| | | // ç¡®è®¤éæ©ä¸å¡å |
| | | const confirmSalesman = () => { |
| | | if (selectedSalesman.value) { |
| | | form.value.salesman = selectedSalesman.value.text; |
| | | pickerValue.value = [selectedSalesman.value.value]; |
| | | } |
| | | showPicker.value = false; |
| | | }; |
| | | |
| | | // 客æ·éæ©å¨ååäºä»¶ |
| | | const onCustomerPickerChange = ({ selectedValues, selectedOptions }) => { |
| | | selectedCustomer.value = selectedOptions[0]; |
| | | tempCustomerValue.value = { |
| | | text: selectedOptions[0]?.text, |
| | | value: selectedOptions[0]?.value |
| | | }; |
| | | }; |
| | | |
| | | // ç¡®è®¤éæ©å®¢æ· |
| | | const confirmCustomer = () => { |
| | | if (selectedCustomer.value) { |
| | | form.value.customerName = selectedCustomer.value.text; |
| | | form.value.customerId = selectedCustomer.value.value; |
| | | pickerCustomerValue.value = [selectedCustomer.value.value]; |
| | | } |
| | | showCustomerPicker.value = false; |
| | | }; |
| | | |
| | | // ä¿®æ¹åæçç¡®è®¤æ¹æ³ï¼ä¿æå
¼å®¹æ§ï¼ |
| | | const onConfirm = ({ selectedValues, selectedOptions }) => { |
| | | if (selectedOptions && selectedOptions[0]) { |
| | | form.value.salesman = selectedOptions[0].text; |
| | | pickerValue.value = [selectedValues[0]]; |
| | | } |
| | | showPicker.value = false; |
| | | }; |
| | | |
| | | const onCustomerConfirm = ({ selectedValues, selectedOptions }) => { |
| | | if (selectedOptions && selectedOptions[0]) { |
| | | form.value.customerName = selectedOptions[0].text; |
| | | form.value.customerId = selectedOptions[0].value; |
| | | pickerCustomerValue.value = [selectedValues[0]]; |
| | | } |
| | | showCustomerPicker.value = false; |
| | | }; |
| | | const onDateConfirm = ({ selectedValues }) => { |
| | | form.value.executionDate = selectedValues.join('-'); |
| | | pickerDateValue.value = selectedValues; |
| | | // æ¥æç¡®è®¤äºä»¶ |
| | | const onDateConfirm = (e) => { |
| | | form.value.executionDate = formatDateToYMD(e.value) |
| | | pickerDateValue.value = formatDateToYMD(e.value) |
| | | showDatePicker.value = false; |
| | | }; |
| | | } |
| | | |
| | | // 客æ·éæ©äºä»¶ |
| | | const onCustomerSelect = (item) => { |
| | | form.value.customerName = item.name |
| | | form.value.customerId = item.value |
| | | } |
| | | |
| | | // åæçç¡®è®¤æ¹æ³å·²è¢«æ°çaction-sheetéæ©æ¹æ³æ¿ä»£ |
| | | const removeProduct = (idx) => { |
| | | productData.value.splice(idx, 1); |
| | | }; |
| | |
| | | selectedCategoryNode.value = null; |
| | | productData.value[currentProductIndex.value].specificationModel = '' |
| | | productData.value[currentProductIndex.value].productModelId = '' |
| | | productData.value[currentProductIndex.value].pickerSpecificationValue = [''] |
| | | getModels(id) |
| | | } |
| | | showCategoryPicker.value = false; |
| | |
| | | })); |
| | | }); |
| | | }; |
| | | // éæ©è§æ ¼åå· |
| | | const onSpecificationConfirm = ({ selectedValues, selectedOptions }) => { |
| | | productData.value[currentProductIndex.value].specificationModel = selectedOptions[0]?.text; |
| | | productData.value[currentProductIndex.value].productModelId = selectedOptions[0]?.value; |
| | | productData.value[currentProductIndex.value].unit = selectedOptions[0]?.unit; |
| | | pickerSpecificationValue.value = [selectedValues[0]]; |
| | | showSpecificationPicker.value = false; |
| | | }; |
| | | // éæ©ç¨ç |
| | | const onTaxRateConfirm = ({ selectedValues, selectedOptions }) => { |
| | | productData.value[currentProductIndex.value].taxRate = selectedOptions[0]?.value; |
| | | pickerTaxRateValue.value = [selectedValues[0]]; |
| | | showTaxRatePicker.value = false; |
| | | // if (isCalculating.value) return; |
| | | const inclusiveTotalPrice = parseFloat(productData.value[currentProductIndex.value].taxInclusiveTotalPrice); |
| | | const taxRate = parseFloat(productData.value[currentProductIndex.value].taxRate); |
| | | if (!inclusiveTotalPrice || !taxRate) { |
| | | return; |
| | | // è§æ ¼åå·éæ©äºä»¶ |
| | | const onSpecificationSelect = (item) => { |
| | | productData.value[currentProductIndex.value].specificationModel = item.name |
| | | productData.value[currentProductIndex.value].productModelId = item.value |
| | | productData.value[currentProductIndex.value].unit = item.unit |
| | | } |
| | | // ç¨çéæ©äºä»¶ |
| | | const onTaxRateSelect = (item) => { |
| | | productData.value[currentProductIndex.value].taxRate = item.value |
| | | // éæ°è®¡ç®ä¸å«ç¨æ»ä»· |
| | | const inclusiveTotalPrice = parseFloat(productData.value[currentProductIndex.value].taxInclusiveTotalPrice) |
| | | const taxRate = parseFloat(item.value) |
| | | if (inclusiveTotalPrice && taxRate) { |
| | | productData.value[currentProductIndex.value].taxExclusiveTotalPrice = |
| | | calculateTaxExclusiveTotalPrice(inclusiveTotalPrice, taxRate) |
| | | } |
| | | // isCalculating.value = true; |
| | | // 计ç®ä¸å«ç¨æ»ä»· |
| | | productData.value[currentProductIndex.value].taxExclusiveTotalPrice = |
| | | calculateTaxExclusiveTotalPrice( |
| | | inclusiveTotalPrice, |
| | | taxRate |
| | | ); |
| | | // isCalculating.value = false; |
| | | }; |
| | | |
| | | const onInvoiceTypeConfirm = ({ selectedValues, selectedOptions }) => { |
| | | productData.value[currentProductIndex.value].invoiceType = selectedOptions[0]?.text; |
| | | pickerInvoiceTypeValue.value = [selectedValues[0]]; |
| | | showInvoiceTypePicker.value = false; |
| | | // å票类åéæ©äºä»¶ |
| | | const onInvoiceTypeSelect = (item) => { |
| | | productData.value[currentProductIndex.value].invoiceType = item.name |
| | | }; |
| | | |
| | | // æ ¼å¼å彿° - åºå®ä¸¤ä½å°æ° |
| | |
| | | uni.removeStorageSync('editData'); |
| | | uni.navigateBack(); |
| | | }; |
| | | const onSubmit = () => { |
| | | if (productData.value !== null && productData.value.length > 0) { |
| | | form.value.productData = JSON.parse(JSON.stringify(productData.value)); |
| | | } else { |
| | | const onSubmit = async () => { |
| | | // é¦å
æ ¡éªåºæ¬è¡¨å |
| | | const formValid = await formRef.value.validate().catch(() => false); |
| | | if (!formValid) { |
| | | return; |
| | | } |
| | | |
| | | // æ ¡éªäº§åä¿¡æ¯ |
| | | if (!productData.value || productData.value.length === 0) { |
| | | uni.showToast({ |
| | | title: '请添å 产åä¿¡æ¯', |
| | | icon: 'none' |
| | | }); |
| | | return |
| | | return; |
| | | } |
| | | |
| | | // æ£æ¥æ¯ä¸ªäº§åæ¯å¦å¡«å宿´ |
| | | for (let i = 0; i < productData.value.length; i++) { |
| | | const errors = validateProduct(productData.value[i], i); |
| | | if (errors.length > 0) { |
| | | uni.showToast({ |
| | | title: errors[0], |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | } |
| | | } |
| | | |
| | | // è¡¨åæ ¡éªéè¿ï¼æäº¤æ°æ® |
| | | form.value.productData = JSON.parse(JSON.stringify(productData.value)); |
| | | form.value.type = 1; |
| | | addOrUpdateSalesLedger(form.value).then((res) => { |
| | | uni.showToast({ |
| | |
| | | const month = String(today.getMonth() + 1).padStart(2, '0') |
| | | const day = String(today.getDate()).padStart(2, '0') |
| | | form.value.entryDate = `${year}-${month}-${day}` |
| | | pickerDateValue.value = [year.toString(), month.toString(), day.toString()] |
| | | // è®¾ç½®æ¥æéæ©å¨é»è®¤å¼ä¸ºä»å¤© |
| | | pickerDateValue.value = `${year}-${month}-${day}` |
| | | } |
| | | // å¡«å
è¡¨åæ°æ®ï¼ç¼è¾æ¨¡å¼ï¼ |
| | | const fillFormData = () => { |
| | |
| | | form.value.entryDate = editData.value.entryDate || ''; |
| | | form.value.id = editData.value.id || ''; |
| | | form.value.customerId = editData.value.customerId || ''; |
| | | |
| | | // 设置ä¸å¡åéæ©å¨çå¼ |
| | | if (editData.value.salesman) { |
| | | const salesmanIndex = userList.value.findIndex(user => user.text === editData.value.salesman); |
| | | if (salesmanIndex !== -1) { |
| | | pickerValue.value = [userList.value[salesmanIndex].value]; |
| | | } |
| | | } |
| | | |
| | | // 设置客æ·éæ©å¨çå¼ |
| | | if (editData.value.customerName) { |
| | | const customerIndex = customerOption.value.findIndex(customer => customer.text === editData.value.customerName); |
| | | if (customerIndex !== -1) { |
| | | pickerCustomerValue.value = [customerOption.value[customerIndex].value] |
| | | } |
| | | } |
| | | |
| | | // è®¾ç½®æ¥æéæ©å¨çå¼ |
| | | if (editData.value.executionDate) { |
| | | pickerDateValue.value = editData.value.executionDate.split('-').map(num => parseInt(num, 10)) |
| | | console.log(pickerDateValue.value) |
| | | pickerDateValue.value = editData.value.executionDate |
| | | } |
| | | }; |
| | | const getUserList = () => { |
| | | userListNoPage().then((res) => { |
| | | // ç¡®ä¿æ°æ®æ ¼å¼æ£ç¡® |
| | | userList.value = [res.data.map(user => ({ |
| | | // ç§»é¤å¤ä½çæ°ç»å
è£
|
| | | userList.value = res.data.map(user => ({ |
| | | text: user.nickName, |
| | | value: user.nickName |
| | | }))]; |
| | | })); |
| | | }) |
| | | } |
| | | }; |
| | | const getCustomerList = () => { |
| | | customerList().then((res) => { |
| | | // ç¡®ä¿æ°æ®æ ¼å¼æ£ç¡® |
| | | customerOption.value = [res.map(item => ({ |
| | | // ç§»é¤å¤ä½çæ°ç»å
è£
|
| | | customerOption.value = res.map(item => ({ |
| | | text: item.customerName, |
| | | value: item.id |
| | | }))]; |
| | | })); |
| | | }) |
| | | } |
| | | }; |
| | | const convertIdToValue = (data) => { |
| | | // å¦æä¼ å
¥ç䏿¯æ°ç»ï¼åè¿å空æ°ç» |
| | | if (!Array.isArray(data)) { |
| | |
| | | productOptions.value = convertIdToValue(res); |
| | | }); |
| | | }; |
| | | // å个产å表åéªè¯å½æ° |
| | | const validateProduct = (product, index) => { |
| | | const errors = []; |
| | | |
| | | if (!product.productCategory) { |
| | | errors.push(`产å${index + 1}ï¼è¯·éæ©äº§å大类`); |
| | | } |
| | | if (!product.specificationModel) { |
| | | errors.push(`产å${index + 1}ï¼è¯·éæ©è§æ ¼åå·`); |
| | | } |
| | | if (!product.unit) { |
| | | errors.push(`产å${index + 1}ï¼è¯·è¾å
¥åä½`); |
| | | } |
| | | if (!product.taxRate) { |
| | | errors.push(`产å${index + 1}ï¼è¯·éæ©ç¨ç`); |
| | | } |
| | | if (!product.taxInclusiveUnitPrice || parseFloat(product.taxInclusiveUnitPrice) <= 0) { |
| | | errors.push(`产å${index + 1}ï¼è¯·è¾å
¥ææçå«ç¨åä»·`); |
| | | } |
| | | if (!product.quantity || parseFloat(product.quantity) <= 0) { |
| | | errors.push(`产å${index + 1}ï¼è¯·è¾å
¥ææçæ°é`); |
| | | } |
| | | if (!product.taxInclusiveTotalPrice || parseFloat(product.taxInclusiveTotalPrice) <= 0) { |
| | | errors.push(`产å${index + 1}ï¼è¯·è¾å
¥ææçå«ç¨æ»ä»·`); |
| | | } |
| | | if (!product.taxExclusiveTotalPrice || parseFloat(product.taxExclusiveTotalPrice) <= 0) { |
| | | errors.push(`产å${index + 1}ï¼è¯·è¾å
¥ææçä¸å«ç¨æ»ä»·`); |
| | | } |
| | | if (!product.invoiceType) { |
| | | errors.push(`产å${index + 1}ï¼è¯·éæ©å票类å`); |
| | | } |
| | | |
| | | return errors; |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | // è·å页é¢åæ° |
| | | operationType.value = uni.getStorageSync('operationType') || ''; |
| | |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .account-detail { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | padding-bottom: 5rem; |
| | | } |
| | | |
| | | .header { |
| | | display: flex; |
| | | align-items: center; |
| | | background: #fff; |
| | | padding: 1rem 1.25rem; |
| | | border-bottom: 0.0625rem solid #f0f0f0; |
| | | position: sticky; |
| | | top: 0; |
| | | z-index: 100; |
| | | /* å
¼å®¹ iOS åæµ·/çµå¨å²å®å
¨åº */ |
| | | padding-top: env(safe-area-inset-top); |
| | | } |
| | | |
| | | .title { |
| | | flex: 1; |
| | | text-align: center; |
| | | font-size: 1.125rem; |
| | | font-weight: 600; |
| | | color: #333; |
| | | } |
| | | |
| | | .form-section { |
| | | margin-top: 1rem; |
| | | } |
| | | .van-field { |
| | | height: 3.4rem; |
| | | } |
| | | .van-cell { |
| | | align-items: center; |
| | | } |
| | | .product-section { |
| | | background: #fff; |
| | | margin-top: 1rem; |
| | | padding: 1rem; |
| | | box-shadow: 0 0.125rem 0.5rem rgba(0,0,0,0.04); |
| | | } |
| | | |
| | | .section-header { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | margin-bottom: 1rem; |
| | | } |
| | | |
| | | .section-title { |
| | | font-size: 1rem; |
| | | font-weight: 600; |
| | | color: #333; |
| | | } |
| | | |
| | | .product-card { |
| | | background: #FFFFFF; |
| | | box-shadow: 0 0 1.25rem 0 rgba(0,57,117,0.08); |
| | | border-radius: 0.5rem 0.5rem 0.5rem 0.5rem; |
| | | padding: 1rem 0.5rem 0 0.5rem; |
| | | position: relative; |
| | | } |
| | | |
| | | .product-header { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | padding: 0 0.5rem 0.75rem 0.5rem; |
| | | border-bottom: 0.0625rem solid #e8e8e8; |
| | | } |
| | | |
| | | .product-productCategory { |
| | | margin-left: 0.5rem; |
| | | font-size: 0.875rem; |
| | | font-weight: 500; |
| | | color: #333; |
| | | } |
| | | |
| | | .info-grid { |
| | | display: grid; |
| | | grid-template-columns: 1fr 1fr; |
| | | gap: 0.75rem; |
| | | margin-bottom: 1rem; |
| | | } |
| | | |
| | | .info-item { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 0.25rem; |
| | | } |
| | | |
| | | .info-label { |
| | | font-size: 0.75rem; |
| | | color: #666; |
| | | font-weight: 400; |
| | | } |
| | | |
| | | .info-value { |
| | | font-size: 0.875rem; |
| | | color: #333; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .info-value.highlight { |
| | | color: #2979ff; |
| | | font-weight: 600; |
| | | } |
| | | |
| | | .product-form { |
| | | margin-bottom: 1rem; |
| | | } |
| | | |
| | | .popup-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding: 1rem; |
| | | background: #fff; |
| | | position: sticky; |
| | | top: 0; |
| | | z-index: 10; |
| | | } |
| | | |
| | | .cancelButton { |
| | | color: #969799 |
| | | } |
| | | |
| | | .confirmButton { |
| | | color: #1989FA |
| | | } |
| | | |
| | | .u-tree { |
| | | height: 13rem; |
| | | } |
| | | |
| | | /* ç§»é¤ input è¾¹æ¡çæ ·å¼ */ |
| | | :deep(.u-input) { |
| | | border: none !important; |
| | | box-shadow: none !important; |
| | | background: transparent !important; |
| | | } |
| | | |
| | | :deep(.u-input__content) { |
| | | border: none !important; |
| | | box-shadow: none !important; |
| | | background: transparent !important; |
| | | } |
| | | |
| | | :deep(.u-input__content__field-wrapper) { |
| | | border: none !important; |
| | | box-shadow: none !important; |
| | | background: transparent !important; |
| | | } |
| | | |
| | | :deep(.u-input__content__field-wrapper__field) { |
| | | border: none !important; |
| | | box-shadow: none !important; |
| | | background: transparent !important; |
| | | outline: none !important; |
| | | } |
| | | |
| | | /* ç§»é¤ textarea è¾¹æ¡çæ ·å¼ */ |
| | | :deep(.u-textarea) { |
| | | border: none !important; |
| | | box-shadow: none !important; |
| | | background: transparent !important; |
| | | } |
| | | |
| | | :deep(.u-textarea__content) { |
| | | border: none !important; |
| | | box-shadow: none !important; |
| | | background: transparent !important; |
| | | } |
| | | |
| | | :deep(.u-textarea__content__field) { |
| | | border: none !important; |
| | | box-shadow: none !important; |
| | | background: transparent !important; |
| | | outline: none !important; |
| | | } |
| | | |
| | | /* ç§»é¤ form-item çè¾¹æ¡ */ |
| | | :deep(.u-form-item) { |
| | | border: none !important; |
| | | } |
| | | |
| | | :deep(.u-form-item__body) { |
| | | border: none !important; |
| | | } |
| | | |
| | | /* ä¿æåå²çº¿æ ·å¼ */ |
| | | :deep(.u-form-item--border-bottom) { |
| | | border-bottom: 1px solid #ebeef5 !important; |
| | | } |
| | | |
| | | /* éæ©å¨å¤´é¨æ ·å¼ */ |
| | | .picker-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding: 15px 20px; |
| | | background: #fff; |
| | | border-bottom: 1px solid #ebeef5; |
| | | } |
| | | |
| | | .picker-cancel { |
| | | color: #909399; |
| | | font-size: 16px; |
| | | } |
| | | |
| | | .picker-title { |
| | | color: #303133; |
| | | font-size: 16px; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .picker-confirm { |
| | | color: #2979ff; |
| | | font-size: 16px; |
| | | } |
| | | <style lang="scss"> |
| | | @import '@/static/scss/form-common.scss'; |
| | | </style> |
| | |
| | | <script setup lang="ts"> |
| | | import tab from "@/plugins/tab"; |
| | | import list from "./template.config.js"; |
| | | |
| | | interface ListItem { |
| | | groupName: string; |
| | | list: FieldItem[]; |
| | | } |
| | | |
| | | interface FieldItem { |
| | | title: string; |
| | | icon: string; |
| | | path: string; |
| | | } |
| | | |
| | | const listData = list as ListItem[]; |
| | | const getIcon = (path: string) => `../static/uview/demo/${path}.png`; |
| | | const openPage = (path: string) => tab.navigateTo(path) |
| | | const getGroupTitle = (item: ListItem) => item.groupName; |
| | | const getFieldTitle = (item: FieldItem) => item.title; |
| | | </script> |
| | | <template> |
| | | <view class="wrap"> |
| | | <view class="list-wrap"> |
| | | <u-cell-group title-bg-color="rgb(243, 244, 246)" :title="getGroupTitle(item)" v-for="(item, index) in list" |
| | | :key="index"> |
| | | <u-cell :titleStyle="{ fontWeight: 500 }" @click="openPage(item1.path)" :title="getFieldTitle(item1)" |
| | | v-for="(item1, index1) in item.list" :key="index1"> |
| | | <template v-slot:icon> |
| | | <image class="u-cell-icon" :src="getIcon(item1.icon)" mode="widthFix"></image> |
| | | </template> |
| | | </u-cell> |
| | | </u-cell-group> |
| | | </view> |
| | | <u-gap height="70"></u-gap> |
| | | <!-- <u-tabbar :list="vuex_tabbar" :mid-button="true"></u-tabbar> --> |
| | | <view class="wrap"> |
| | | <view class="list-wrap"> |
| | | <u-cell-group title-bg-color="rgb(243, 244, 246)" :title="getGroupTitle(item)" v-for="(item, index) in listData" |
| | | :key="index"> |
| | | <u-cell :titleStyle="{ fontWeight: 500 }" @click="openPage(item1.path)" :title="getFieldTitle(item1)" |
| | | v-for="(item1, index1) in item.list" :key="index1"> |
| | | <template v-slot:icon> |
| | | <image class="u-cell-icon" :src="getIcon(item1.icon)" mode="widthFix"></image> |
| | | </template> |
| | | </u-cell> |
| | | </u-cell-group> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import list from "./template.config.js"; |
| | | export default { |
| | | data() { |
| | | return { |
| | | list: list, |
| | | // desc: 'æ¶éä¼å¤ç常ç¨é¡µé¢åå¸å±ï¼åå°å¼åè
çéå¤å·¥ä½ï¼è®©ä½ 䏿³¨é»è¾ï¼äºååå' |
| | | } |
| | | }, |
| | | computed: { |
| | | getIcon() { |
| | | return path => { |
| | | return '../static/uview/demo/' + path + '.png'; |
| | | return 'https://cdn.uviewui.com/uview/example/' + path + '.png'; |
| | | } |
| | | }, |
| | | }, |
| | | methods: { |
| | | openPage(path) { |
| | | this.$u.route({ |
| | | url: path |
| | | }) |
| | | }, |
| | | getGroupTitle(item) { |
| | | return item.groupName |
| | | }, |
| | | getFieldTitle(item) { |
| | | return item.title |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style> |
| | | /* page { |
| | | background-color: rgb(240, 242, 244); |
| | | } */ |
| | | </style> |
| | | |
| | | <style lang="scss" scoped> |
| | | .u-cell-icon { |
| | | width: 36rpx; |
| | | height: 36rpx; |
| | | margin-right: 8rpx; |
| | | } |
| | | </style> |
| | | |
| | | <u-gap height="70"></u-gap> |
| | | </view> |
| | | </template> |
| | | <style lang="scss" scoped> |
| | | page { |
| | | background-color: rgb(240, 242, 244); |
| | | } |
| | | |
| | | .u-cell-icon { |
| | | width: 36rpx; |
| | | height: 36rpx; |
| | | margin-right: 8rpx; |
| | | } |
| | | </style> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref } from "vue"; |
| | | import modal from "@/plugins/modal" |
| | | const current=ref(0); |
| | | const swiperDotIndex=ref(0); |
| | | const data=ref([{ |
| | | image: '/static/images/banner/banner01.jpg' |
| | | }, |
| | | { |
| | | image: '/static/images/banner/banner02.jpg' |
| | | }, |
| | | { |
| | | image: '/static/images/banner/banner03.jpg' |
| | | } |
| | | ]); |
| | | |
| | | function clickBannerItem(item) { |
| | | console.info(item) |
| | | }; |
| | | function changeSwiper(e) { |
| | | current.value = e.detail.current |
| | | } |
| | | function changeGrid(e) { |
| | | modal.showToast({ |
| | | title: '模å建设ä¸', |
| | | mask: false, |
| | | icon:'loading', |
| | | duration: 1000 |
| | | }); |
| | | } |
| | | |
| | | import { ref } from "vue"; |
| | | import modal from "@/plugins/modal" |
| | | const current = ref(0); |
| | | const swiperDotIndex = ref(0); |
| | | const data = ref([ |
| | | { image: '/static/images/banner/banner01.jpg' }, |
| | | { image: '/static/images/banner/banner02.jpg' }, |
| | | { image: '/static/images/banner/banner03.jpg' } |
| | | ]); |
| | | |
| | | function clickBannerItem(item) { |
| | | console.info(item) |
| | | }; |
| | | function changeSwiper(e) { |
| | | current.value = e.detail.current |
| | | } |
| | | function changeGrid(e) { |
| | | modal.showToast({ |
| | | title: '模å建设ä¸', |
| | | mask: false, |
| | | icon: 'loading', |
| | | duration: 1000 |
| | | }); |
| | | } |
| | | |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | /* #ifndef APP-NVUE */ |
| | | page { |
| | | display: flex; |
| | | flex-direction: column; |
| | | box-sizing: border-box; |
| | | background-color: #fff; |
| | | min-height: 100%; |
| | | height: auto; |
| | | } |
| | | |
| | | view { |
| | | font-size: 14px; |
| | | line-height: inherit; |
| | | } |
| | | |
| | | /* #endif */ |
| | | |
| | | .text { |
| | | text-align: center; |
| | | font-size: 26rpx; |
| | | margin-top: 10rpx; |
| | | } |
| | | |
| | | .grid-item-box { |
| | | flex: 1; |
| | | /* #ifndef APP-NVUE */ |
| | | page { |
| | | display: flex; |
| | | flex-direction: column; |
| | | box-sizing: border-box; |
| | | background-color: #fff; |
| | | min-height: 100%; |
| | | height: auto; |
| | | } |
| | | |
| | | view { |
| | | font-size: 14px; |
| | | line-height: inherit; |
| | | } |
| | | |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | padding: 15px 0; |
| | | } |
| | | |
| | | .text { |
| | | text-align: center; |
| | | font-size: 26rpx; |
| | | margin-top: 10rpx; |
| | | } |
| | | .uni-margin-wrap { |
| | | width: 690rpx; |
| | | width: 100%; |
| | | ; |
| | | } |
| | | |
| | | .grid-item-box { |
| | | flex: 1; |
| | | .swiper { |
| | | height: 300rpx; |
| | | } |
| | | |
| | | .swiper-box { |
| | | height: 150px; |
| | | } |
| | | |
| | | .swiper-item { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: column; |
| | | justify-content: center; |
| | | align-items: center; |
| | | color: #fff; |
| | | height: 300rpx; |
| | | line-height: 300rpx; |
| | | } |
| | | |
| | | @media screen and (min-width: 500px) { |
| | | .uni-swiper-dot-box { |
| | | width: 400px; |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | margin: 0 auto; |
| | | /* #endif */ |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | padding: 15px 0; |
| | | margin-top: 8px; |
| | | } |
| | | |
| | | .uni-margin-wrap { |
| | | width: 690rpx; |
| | | .image { |
| | | width: 100%; |
| | | ; |
| | | } |
| | | |
| | | .swiper { |
| | | height: 300rpx; |
| | | } |
| | | |
| | | .swiper-box { |
| | | height: 150px; |
| | | } |
| | | |
| | | .swiper-item { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: column; |
| | | justify-content: center; |
| | | align-items: center; |
| | | color: #fff; |
| | | height: 300rpx; |
| | | line-height: 300rpx; |
| | | } |
| | | |
| | | @media screen and (min-width: 500px) { |
| | | .uni-swiper-dot-box { |
| | | width: 400px; |
| | | /* #ifndef APP-NVUE */ |
| | | margin: 0 auto; |
| | | /* #endif */ |
| | | margin-top: 8px; |
| | | } |
| | | |
| | | .image { |
| | | width: 100%; |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <view class="container"> |
| | | <view class="card"> |
| | | <van-cell-group> |
| | | <van-cell icon="cluster-o" title="æå±å
¬å¸" :value="userStore.currentFactoryName" /> |
| | | <van-cell icon="manager-o" title="å²ä½" :value="postGroup" /> |
| | | </van-cell-group> |
| | | <u-cell-group> |
| | | <u-cell icon="list" title="æå±å
¬å¸" :value="userStore.currentFactoryName" /> |
| | | <u-cell icon="bag" title="å²ä½" :value="postGroup" /> |
| | | </u-cell-group> |
| | | </view> |
| | | |
| | | <!-- <u-button @click="register()">ç»å®å¾®ä¿¡</u-button> --> |
| | |
| | | <template> |
| | | <view class="container"> |
| | | <view class="card"> |
| | | <van-cell-group> |
| | | <van-cell icon="underway-o" title="ååå¼å§æ¶é´" :value="user.contractStartTime" /> |
| | | <van-cell icon="underway-o" title="ååç»ææ¶é´" :value="user.contractEndTime" /> |
| | | <van-cell icon="medal-o" title="å²ä½" :value="user.postJob" /> |
| | | <van-cell icon="label-o" title="第ä¸å¦å" :value="user.firstStudy" /> |
| | | </van-cell-group> |
| | | <u-cell-group> |
| | | <u-cell icon="calendar" title="ååå¼å§æ¶é´" :value="user.contractStartTime" /> |
| | | <u-cell icon="calendar" title="ååç»ææ¶é´" :value="user.contractEndTime" /> |
| | | <u-cell icon="bag" title="èä½" :value="user.postJob" /> |
| | | <u-cell icon="integral" title="第ä¸å¦å" :value="user.firstStudy" /> |
| | | </u-cell-group> |
| | | </view> |
| | | |
| | | <!-- <u-button @click="register()">ç»å®å¾®ä¿¡</u-button> --> |
| | |
| | | <template> |
| | | <view class="container"> |
| | | <view class="card"> |
| | | <van-cell-group> |
| | | <van-cell icon="user" title="æµç§°" :value="user.nickName" /> |
| | | <van-cell icon="phone" title="ææºå·ç " :value="user.phonenumber" /> |
| | | <van-cell icon="invitation" title="é®ç®±" :value="user.email" /> |
| | | <van-cell icon="medal" title="å²ä½" :value="postGroup" /> |
| | | <van-cell icon="friends" title="è§è²" :value="roleGroup" /> |
| | | <van-cell icon="notes" title="åå»ºæ¥æ" :value="user.createTime" /> |
| | | </van-cell-group> |
| | | <u-cell-group> |
| | | <u-cell icon="account" title="æµç§°" :value="user.nickName" /> |
| | | <u-cell icon="phone" title="ææºå·ç " :value="user.phonenumber" /> |
| | | <u-cell icon="email" title="é®ç®±" :value="user.email" /> |
| | | <u-cell icon="order" title="å²ä½" :value="postGroup" /> |
| | | <u-cell icon="star" title="è§è²" :value="roleGroup" /> |
| | | <u-cell icon="calendar" title="åå»ºæ¥æ" :value="user.createTime" /> |
| | | </u-cell-group> |
| | | </view> |
| | | |
| | | <!-- <u-button @click="register()">ç»å®å¾®ä¿¡</u-button> --> |
| | |
| | | <view class="number">{{item.now?item.now+"/":""}}{{item.expect}} [{{item.value}}%]</view> |
| | | <progress :percent="item.value" backgroundColor="#C9C9C9" |
| | | :border-radius="borderRadius?borderRadius+'rpx':'0px'" |
| | | :color="time" |
| | | active="true" |
| | | stroke-width="16" /> |
| | | </view> |
| | | </view> |
| | |
| | | </view> |
| | | <!-- å
¬å¸åºå䏿å表 --> |
| | | <drop-down ref="companyDrop" @tap="changDrop(2)" @changeItem="changeLocation" :list="locationArray" |
| | | :contentTop="top" contentRight="10" :selectWidth="showCalendar ? '200rpx' : '300rpx'" listWidth="75%"> |
| | | :contentTop="top" contentRight="10" :selectWidth="showCalendar ? '200rpx' : '400rpx'" listWidth="75%"> |
| | | </drop-down> |
| | | </view> |
| | | <uni-calendar ref="calendar" :insert="false" :start-date="startDate" :end-date="endDate" :clearDate="false" |
| | |
| | | } |
| | | |
| | | .head { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | padding: 0 16rpx 14rpx 16rpx; |
| | | color: #fff; |
| | | background-color: #40A2ED; |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="jingdong"> |
| | | <view class="left"> |
| | | <view class="sum"> |
| | | ï¿¥ |
| | | <text class="num">100</text> |
| | | </view> |
| | | <view class="type">满149å
å¯ç¨</view> |
| | | </view> |
| | | <view class="right"> |
| | | <view class="top"> |
| | | <view class="title"> |
| | | <text class="tag">éåç±»ä¸å¸</text> |
| | | <text>ä»
å¯è´ä¹°ä¸ªäººæ¤çé¨ååå</text> |
| | | </view> |
| | | <view class="bottom"> |
| | | <view class="date u-line-1">2020.01.01-2020.01.31</view> |
| | | <view class="immediate-use">ç«å³ä½¿ç¨</view> |
| | | </view> |
| | | </view> |
| | | <view class="tips"> |
| | | <view class="explain"> |
| | | <u-icon name="zhuanfa" class="transpond" :size="24"></u-icon> |
| | | <text>å¯èµ é</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | <style scoped lang="scss"> |
| | | .jingdong { |
| | | margin-top: 40rpx; |
| | | width: 700rpx; |
| | | height: auto; |
| | | background-color: #ffffff; |
| | | display: flex; |
| | | |
| | | .left { |
| | | padding: 0 30rpx; |
| | | background-color: rgb(95, 148, 224); //rgb(94, 152, 225); |
| | | text-align: center; |
| | | font-size: 28rpx; |
| | | color: #ffffff; |
| | | |
| | | .sum { |
| | | margin-top: 50rpx; |
| | | font-weight: bold; |
| | | font-size: 32rpx; |
| | | |
| | | .num { |
| | | font-size: 80rpx; |
| | | } |
| | | } |
| | | |
| | | .type { |
| | | margin-bottom: 50rpx; |
| | | font-size: 24rpx; |
| | | } |
| | | } |
| | | |
| | | .right { |
| | | padding: 20rpx 20rpx 0; |
| | | font-size: 28rpx; |
| | | |
| | | .top { |
| | | border-bottom: 2rpx dashed $u-border-color; |
| | | |
| | | .title { |
| | | margin-right: 60rpx; |
| | | line-height: 40rpx; |
| | | |
| | | .tag { |
| | | padding: 4rpx 20rpx; |
| | | background-color: rgb(73, 154, 201); |
| | | border-radius: 20rpx; |
| | | color: #ffffff; |
| | | font-weight: bold; |
| | | font-size: 24rpx; |
| | | margin-right: 10rpx; |
| | | } |
| | | } |
| | | |
| | | .bottom { |
| | | display: flex; |
| | | margin-top: 20rpx; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | margin-bottom: 10rpx; |
| | | |
| | | .date { |
| | | font-size: 20rpx; |
| | | flex: 1; |
| | | } |
| | | |
| | | .immediate-use { |
| | | height: auto; |
| | | padding: 0 20rpx; |
| | | font-size: 24rpx; |
| | | border-radius: 40rpx; |
| | | line-height: 40rpx; |
| | | color: rgb(117, 142, 165); |
| | | border: 2rpx solid rgb(117, 142, 165); |
| | | } |
| | | } |
| | | } |
| | | |
| | | .tips { |
| | | width: 100%; |
| | | line-height: 50rpx; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | font-size: 24rpx; |
| | | |
| | | .transpond { |
| | | margin-right: 10rpx; |
| | | } |
| | | |
| | | .explain { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .particulars { |
| | | width: 30rpx; |
| | | height: 30rpx; |
| | | box-sizing: border-box; |
| | | padding-top: 8rpx; |
| | | border-radius: 50%; |
| | | background-color: $u-info-disabled; |
| | | text-align: center; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="meituan"> |
| | | <view class="content"> |
| | | <view class="left"> |
| | | <view class="sum"> |
| | | ï¿¥<text class="num">8</text> |
| | | </view> |
| | | <view class="type">æµç¨å¸</view> |
| | | </view> |
| | | <view class="centre"> |
| | | <view class="title">ãæ´çã8å
æ 鍿§çº¢å
</view> |
| | | <view class="valid-date">仿¥å°æ</view> |
| | | </view> |
| | | <view class="right"> |
| | | <view size="mini" class="immediate-use" :round="true">ç«å³ä½¿ç¨</view> |
| | | </view> |
| | | </view> |
| | | <view class="tips"> |
| | | <view class="circle-left"></view> |
| | | <view class="circle-right"></view> |
| | | <view class="explain u-line-1">满8.1å
å¯ç¨ãéææ°çæ¬å®¢æ·ç«¯ä½¿ç¨</view> |
| | | <view class="rule"> |
| | | <text>使ç¨è§å</text> |
| | | <u-icon name="arrow-right" color="" :size="20" @click=""></u-icon> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | <style scoped lang="scss"> |
| | | .meituan { |
| | | margin: 30rpx auto; |
| | | background-color: #ffffff; |
| | | width: 700rpx; |
| | | // border: 10rpx; |
| | | color: $u-warning; |
| | | font-size: 28rpx; |
| | | |
| | | .content { |
| | | display: flex; |
| | | align-items: center; |
| | | padding: 80rpx 20rpx; |
| | | border: 10rpx; |
| | | background-color: #fff5f4; |
| | | |
| | | .left { |
| | | .sum { |
| | | font-size: 32rpx; |
| | | |
| | | .num { |
| | | font-size: 60rpx; |
| | | font-weight: bold; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .centre { |
| | | margin-left: 40rpx; |
| | | |
| | | .title { |
| | | font-size: 32rpx; |
| | | font-weight: bold; |
| | | color: $u-main-color; |
| | | margin-bottom: 20rpx; |
| | | } |
| | | } |
| | | |
| | | .right { |
| | | margin-left: 30rpx; |
| | | |
| | | .immediate-use { |
| | | padding: 0 20rpx; |
| | | height: 50rpx; |
| | | border-radius: 25rpx; |
| | | line-height: 50rpx; |
| | | background-color: $u-warning !important; |
| | | color: #ffffff !important; |
| | | font-size: 24rpx; |
| | | border: none; |
| | | word-break: keep-all; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .tips { |
| | | padding: 0 20rpx; |
| | | border: 10rpx; |
| | | background-color: $u-info-light; |
| | | position: relative; |
| | | color: $u-tips-color; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | line-height: 60rpx; |
| | | font-size: 24rpx; |
| | | |
| | | .circle-left, |
| | | .circle-right { |
| | | position: absolute; |
| | | height: 36rpx; |
| | | width: 18rpx; |
| | | background-color: #f2f2f2; |
| | | } |
| | | |
| | | .circle-right { |
| | | border-radius: 40rpx 0 0 40rpx; |
| | | right: 0; |
| | | top: -18rpx; |
| | | } |
| | | |
| | | .circle-left { |
| | | border-radius: 0 40rpx 40rpx 0; |
| | | left: 0; |
| | | top: -18rpx; |
| | | } |
| | | |
| | | .rule { |
| | | font-size: 24rpx; |
| | | display: flex; |
| | | align-items: center; |
| | | |
| | | text { |
| | | margin-right: 10rpx; |
| | | flex: 1; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <script setup lang="ts"> |
| | | import logo from '@/static/logo.png'; |
| | | </script> |
| | | <template> |
| | | <view class="taobao"> |
| | | <view class="title"> |
| | | <view class="left"> |
| | | <image class="buddha" :src="logo" mode="aspectFill"></image> |
| | | <view class="store">è¢åç²¾ä¿æ¤åä¼</view> |
| | | </view> |
| | | <view class="entrance">è¿åº</view> |
| | | </view> |
| | | <view class="ticket"> |
| | | <view class="left"> |
| | | <image class="picture" :src="logo" mode="widthFix"></image> |
| | | <view class="introduce"> |
| | | <view class="top"> |
| | | ï¿¥ |
| | | <text class="big">3</text> |
| | | 满88å3 |
| | | </view> |
| | | <view class="type">åºéºä¼æ å¸</view> |
| | | <view class="date u-line-1">2019.11.28-2020.1.24</view> |
| | | </view> |
| | | </view> |
| | | <view class="right"> |
| | | <view class="use immediate-use" :round="true">å»ä½¿ç¨</view> |
| | | </view> |
| | | |
| | | </view> |
| | | </view> |
| | | </template> |
| | | <style scoped lang="scss"> |
| | | .taobao { |
| | | margin-top: 40rpx; |
| | | width: 700rpx; |
| | | background-color: white; |
| | | padding: 30rpx 20rpx 20rpx; |
| | | border-radius: 20rpx; |
| | | |
| | | .title { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | margin-bottom: 20rpx; |
| | | font-size: 30rpx; |
| | | |
| | | .left { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .store { |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .buddha { |
| | | width: 70rpx; |
| | | height: 70rpx; |
| | | border-radius: 10rpx; |
| | | margin-right: 10rpx; |
| | | } |
| | | |
| | | .entrance { |
| | | color: $u-info; |
| | | border: solid 2rpx $u-info; |
| | | line-height: 48rpx; |
| | | padding: 0 30rpx; |
| | | background: none; |
| | | border-radius: 15px; |
| | | } |
| | | } |
| | | |
| | | .ticket { |
| | | display: flex; |
| | | |
| | | .left { |
| | | width: 70%; |
| | | padding: 30rpx 20rpx; |
| | | background-color: rgb(255, 245, 244); |
| | | border-radius: 20rpx; |
| | | border-right: dashed 2rpx rgb(224, 215, 211); |
| | | display: flex; |
| | | |
| | | .picture { |
| | | width: 172rpx; |
| | | height: 172rpx; |
| | | border-radius: 20rpx; |
| | | } |
| | | |
| | | .introduce { |
| | | margin-left: 10rpx; |
| | | |
| | | .top { |
| | | color: $u-warning; |
| | | font-size: 28rpx; |
| | | |
| | | .big { |
| | | font-size: 60rpx; |
| | | font-weight: bold; |
| | | margin-right: 10rpx; |
| | | } |
| | | } |
| | | |
| | | .type { |
| | | font-size: 28rpx; |
| | | color: $u-info-dark; |
| | | } |
| | | |
| | | .date { |
| | | margin-top: 10rpx; |
| | | font-size: 20rpx; |
| | | color: $u-info-dark; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .right { |
| | | width: 30%; |
| | | padding: 40rpx 20rpx; |
| | | background-color: rgb(255, 245, 244); |
| | | border-radius: 20rpx; |
| | | display: flex; |
| | | align-items: center; |
| | | |
| | | .use { |
| | | height: auto; |
| | | padding: 0 20rpx; |
| | | font-size: 24rpx; |
| | | border-radius: 40rpx; |
| | | color: #ffffff !important; |
| | | background-color: $u-warning !important; |
| | | line-height: 40rpx; |
| | | color: rgb(117, 142, 165); |
| | | margin-left: 20rpx; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | |
| | | <script setup> |
| | | import MeituanCoupon from './components/meituan-coupon.vue'; |
| | | import JingdongCoupon from './components/jingdong-coupon.vue'; |
| | | import TaobaoCoupon from './components/taobao-coupon.vue'; |
| | | </script> |
| | | <template> |
| | | <view class="u-wrap"> |
| | | <view class="meituan"> |
| | | <view class="content"> |
| | | <view class="left"> |
| | | <view class="sum"> |
| | | ï¿¥ |
| | | <text class="num">8</text> |
| | | </view> |
| | | <view class="type">æµç¨å¸</view> |
| | | </view> |
| | | <view class="centre"> |
| | | <view class="title">ãæ´çã8å
æ 鍿§çº¢å
</view> |
| | | <view class="valid-date">仿¥å°æ</view> |
| | | </view> |
| | | <view class="right"> |
| | | <view size="mini" class="immediate-use" :round="true">ç«å³ä½¿ç¨</view> |
| | | </view> |
| | | </view> |
| | | <view class="tips"> |
| | | <view class="circle-left"></view> |
| | | <view class="circle-right"></view> |
| | | <view class="explain u-line-1">满8.1å
å¯ç¨ãéææ°çæ¬å®¢æ·ç«¯ä½¿ç¨</view> |
| | | <view class="rule" @tap="xxx122"> |
| | | <text>使ç¨è§å</text> |
| | | <u-icon name="arrow-right" color="" :size="20" @click=""></u-icon> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view class="jingdong"> |
| | | <view class="left"> |
| | | <view class="sum"> |
| | | ï¿¥ |
| | | <text class="num">100</text> |
| | | </view> |
| | | <view class="type">满149å
å¯ç¨</view> |
| | | </view> |
| | | <view class="right"> |
| | | <view class="top"> |
| | | <view class="title"> |
| | | <text class="tag">éåç±»ä¸å¸</text> |
| | | <text>ä»
å¯è´ä¹°ä¸ªäººæ¤çé¨ååå</text> |
| | | </view> |
| | | <view class="bottom"> |
| | | <view class="date u-line-1">2020.01.01-2020.01.31</view> |
| | | <view class="immediate-use">ç«å³ä½¿ç¨</view> |
| | | </view> |
| | | </view> |
| | | <view class="tips"> |
| | | <view class="explain"> |
| | | <u-icon name="zhuanfa" class="transpond" :size="24"></u-icon> |
| | | <text>å¯èµ é</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view class="taobao"> |
| | | <view class="title"> |
| | | <view class="left"> |
| | | <image class="buddha" |
| | | src="https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=1975388697,1068670603&fm=26&gp=0.jpg" |
| | | mode="aspectFill"></image> |
| | | <view class="store">è¢åç²¾ä¿æ¤åä¼</view> |
| | | </view> |
| | | <view class="entrance">è¿åº</view> |
| | | </view> |
| | | <view class="ticket"> |
| | | <view class="left"> |
| | | <image class="picture" |
| | | src="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1578059523488&di=5f592ac19c1b983005d3e85add469756&imgtype=0&src=http%3A%2F%2Fimg010.hc360.cn%2Fg7%2FM00%2F2D%2FB9%2FwKhQs1QfUo6EdeM-AAAAALwk1hM072.jpg" |
| | | mode="widthFix"></image> |
| | | <view class="introduce"> |
| | | <view class="top"> |
| | | ï¿¥ |
| | | <text class="big">3</text> |
| | | 满88å3 |
| | | </view> |
| | | <view class="type">åºéºä¼æ å¸</view> |
| | | <view class="date u-line-1">2019.11.28-2020.1.24</view> |
| | | </view> |
| | | </view> |
| | | <view class="right"> |
| | | <view class="use immediate-use" :round="true">å»ä½¿ç¨</view> |
| | | </view> |
| | | |
| | | </view> |
| | | </view> |
| | | <MeituanCoupon /> |
| | | <JingdongCoupon /> |
| | | <TaobaoCoupon /> |
| | | </view> |
| | | </template> |
| | | |
| | |
| | | |
| | | .u-wrap { |
| | | padding: 24rpx; |
| | | } |
| | | |
| | | .meituan { |
| | | margin: 30rpx auto; |
| | | background-color: #ffffff; |
| | | width: 700rpx; |
| | | // border: 10rpx; |
| | | color: $u-warning; |
| | | font-size: 28rpx; |
| | | |
| | | .content { |
| | | display: flex; |
| | | align-items: center; |
| | | padding: 80rpx 20rpx; |
| | | border: 10rpx; |
| | | background-color: #fff5f4; |
| | | |
| | | .left { |
| | | .sum { |
| | | font-size: 32rpx; |
| | | |
| | | .num { |
| | | font-size: 60rpx; |
| | | font-weight: bold; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .centre { |
| | | margin-left: 40rpx; |
| | | |
| | | .title { |
| | | font-size: 32rpx; |
| | | font-weight: bold; |
| | | color: $u-main-color; |
| | | margin-bottom: 20rpx; |
| | | } |
| | | } |
| | | |
| | | .right { |
| | | margin-left: 30rpx; |
| | | |
| | | .immediate-use { |
| | | padding: 0 20rpx; |
| | | height: 50rpx; |
| | | border-radius: 25rpx; |
| | | line-height: 50rpx; |
| | | background-color: $u-warning !important; |
| | | color: #ffffff !important; |
| | | font-size: 24rpx; |
| | | border: none; |
| | | word-break: keep-all; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .tips { |
| | | padding: 0 20rpx; |
| | | border: 10rpx; |
| | | background-color: $u-info-light; |
| | | position: relative; |
| | | color: $u-tips-color; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | line-height: 60rpx; |
| | | font-size: 24rpx; |
| | | |
| | | .circle-left, |
| | | .circle-right { |
| | | position: absolute; |
| | | height: 36rpx; |
| | | width: 18rpx; |
| | | background-color: #f2f2f2; |
| | | } |
| | | |
| | | .circle-right { |
| | | border-radius: 40rpx 0 0 40rpx; |
| | | right: 0; |
| | | top: -18rpx; |
| | | } |
| | | |
| | | .circle-left { |
| | | border-radius: 0 40rpx 40rpx 0; |
| | | left: 0; |
| | | top: -18rpx; |
| | | } |
| | | |
| | | .rule { |
| | | font-size: 24rpx; |
| | | display: flex; |
| | | align-items: center; |
| | | |
| | | text { |
| | | margin-right: 10rpx; |
| | | flex: 1; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .jingdong { |
| | | margin-top: 40rpx; |
| | | width: 700rpx; |
| | | height: auto; |
| | | background-color: #ffffff; |
| | | display: flex; |
| | | |
| | | .left { |
| | | padding: 0 30rpx; |
| | | background-color: rgb(95, 148, 224); //rgb(94, 152, 225); |
| | | text-align: center; |
| | | font-size: 28rpx; |
| | | color: #ffffff; |
| | | |
| | | .sum { |
| | | margin-top: 50rpx; |
| | | font-weight: bold; |
| | | font-size: 32rpx; |
| | | |
| | | .num { |
| | | font-size: 80rpx; |
| | | } |
| | | } |
| | | |
| | | .type { |
| | | margin-bottom: 50rpx; |
| | | font-size: 24rpx; |
| | | } |
| | | } |
| | | |
| | | .right { |
| | | padding: 20rpx 20rpx 0; |
| | | font-size: 28rpx; |
| | | |
| | | .top { |
| | | border-bottom: 2rpx dashed $u-border-color; |
| | | |
| | | .title { |
| | | margin-right: 60rpx; |
| | | line-height: 40rpx; |
| | | |
| | | .tag { |
| | | padding: 4rpx 20rpx; |
| | | background-color: rgb(73, 154, 201); |
| | | border-radius: 20rpx; |
| | | color: #ffffff; |
| | | font-weight: bold; |
| | | font-size: 24rpx; |
| | | margin-right: 10rpx; |
| | | } |
| | | } |
| | | |
| | | .bottom { |
| | | display: flex; |
| | | margin-top: 20rpx; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | margin-bottom: 10rpx; |
| | | |
| | | .date { |
| | | font-size: 20rpx; |
| | | flex: 1; |
| | | } |
| | | |
| | | .immediate-use { |
| | | height: auto; |
| | | padding: 0 20rpx; |
| | | font-size: 24rpx; |
| | | border-radius: 40rpx; |
| | | line-height: 40rpx; |
| | | color: rgb(117, 142, 165); |
| | | border: 2rpx solid rgb(117, 142, 165); |
| | | } |
| | | } |
| | | } |
| | | |
| | | .tips { |
| | | width: 100%; |
| | | line-height: 50rpx; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | font-size: 24rpx; |
| | | |
| | | .transpond { |
| | | margin-right: 10rpx; |
| | | } |
| | | |
| | | .explain { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .particulars { |
| | | width: 30rpx; |
| | | height: 30rpx; |
| | | box-sizing: border-box; |
| | | padding-top: 8rpx; |
| | | border-radius: 50%; |
| | | background-color: $u-info-disabled; |
| | | text-align: center; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .taobao { |
| | | margin-top: 40rpx; |
| | | width: 700rpx; |
| | | background-color: white; |
| | | padding: 30rpx 20rpx 20rpx; |
| | | border-radius: 20rpx; |
| | | |
| | | .title { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | margin-bottom: 20rpx; |
| | | font-size: 30rpx; |
| | | |
| | | .left { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .store { |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .buddha { |
| | | width: 70rpx; |
| | | height: 70rpx; |
| | | border-radius: 10rpx; |
| | | margin-right: 10rpx; |
| | | } |
| | | |
| | | .entrance { |
| | | color: $u-info; |
| | | border: solid 2rpx $u-info; |
| | | line-height: 48rpx; |
| | | padding: 0 30rpx; |
| | | background: none; |
| | | border-radius: 15px; |
| | | } |
| | | } |
| | | |
| | | .ticket { |
| | | display: flex; |
| | | |
| | | .left { |
| | | width: 70%; |
| | | padding: 30rpx 20rpx; |
| | | background-color: rgb(255, 245, 244); |
| | | border-radius: 20rpx; |
| | | border-right: dashed 2rpx rgb(224, 215, 211); |
| | | display: flex; |
| | | |
| | | .picture { |
| | | width: 172rpx; |
| | | height: 172rpx; |
| | | border-radius: 20rpx; |
| | | } |
| | | |
| | | .introduce { |
| | | margin-left: 10rpx; |
| | | |
| | | .top { |
| | | color: $u-warning; |
| | | font-size: 28rpx; |
| | | |
| | | .big { |
| | | font-size: 60rpx; |
| | | font-weight: bold; |
| | | margin-right: 10rpx; |
| | | } |
| | | } |
| | | |
| | | .type { |
| | | font-size: 28rpx; |
| | | color: $u-info-dark; |
| | | } |
| | | |
| | | .date { |
| | | margin-top: 10rpx; |
| | | font-size: 20rpx; |
| | | color: $u-info-dark; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .right { |
| | | width: 30%; |
| | | padding: 40rpx 20rpx; |
| | | background-color: rgb(255, 245, 244); |
| | | border-radius: 20rpx; |
| | | display: flex; |
| | | align-items: center; |
| | | |
| | | .use { |
| | | height: auto; |
| | | padding: 0 20rpx; |
| | | font-size: 24rpx; |
| | | border-radius: 40rpx; |
| | | color: #ffffff !important; |
| | | background-color: $u-warning !important; |
| | | line-height: 40rpx; |
| | | color: rgb(117, 142, 165); |
| | | margin-left: 20rpx; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | |
| | | <script setup> |
| | | import { ref } from 'vue' |
| | | import { onLoad } from '@dcloudio/uni-app' |
| | | |
| | | const show = ref(false) |
| | | const password = ref('') |
| | | |
| | | onLoad(() => { |
| | | }) |
| | | |
| | | const onChange = (val) => { |
| | | if (password.value.length < 6) { |
| | |
| | | } |
| | | |
| | | const pay = () => { |
| | | uni.showLoading({ |
| | | title: 'æ¯ä»ä¸' |
| | | }) |
| | | |
| | | uni.showLoading({ title: 'æ¯ä»ä¸' }) |
| | | setTimeout(() => { |
| | | uni.hideLoading() |
| | | show.value = false |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* 表åå
Œ
±æ ·å¼ */ |
| | | |
| | | /* è¡¨åæ´ä½æ ·å¼ - ä½¿ç¨ :deep ç©¿éå° uView-plus å
é¨ç±» */ |
| | | :deep(.u-form) { |
| | | background: transparent !important; |
| | | margin: 0 !important; |
| | | padding: 0 !important; |
| | | } |
| | | |
| | | /* 表åé¡¹æ ·å¼ä¼å */ |
| | | :deep(.u-form-item) { |
| | | background: #fff !important; |
| | | padding: 0 22px !important; |
| | | border: none !important; |
| | | position: relative !important; |
| | | border-bottom: 1px solid #f0f0f0 !important; |
| | | } |
| | | |
| | | :deep(.u-form-item:last-child) { |
| | | border-bottom: none !important; |
| | | } |
| | | |
| | | :deep(.u-form-item__body) { |
| | | padding: 15px 0 !important; |
| | | border: none !important; |
| | | min-height: 50px !important; |
| | | display: flex !important; |
| | | align-items: center !important; |
| | | align-items: flex-start !important; |
| | | } |
| | | |
| | | :deep(.u-form-item__label) { |
| | | font-size: 15px !important; |
| | | color: #333 !important; |
| | | font-weight: 400 !important; |
| | | width: 90px !important; |
| | | flex-shrink: 0 !important; |
| | | } |
| | | |
| | | :deep(.u-form-item__content) { |
| | | flex: 1 !important; |
| | | display: flex !important; |
| | | justify-content: flex-end !important; |
| | | } |
| | | |
| | | /* å½»åºç§»é¤ input è¾¹æ¡ä¸èæ¯ï¼ç©¿éå°å
é¨å
ç´ ï¼*/ |
| | | :deep(.u-input), |
| | | :deep(.u-input *), |
| | | input[type="text"], |
| | | input[type="number"] { |
| | | border: none !important; |
| | | box-shadow: none !important; |
| | | background: transparent !important; |
| | | padding: 0 !important; |
| | | margin: 0 !important; |
| | | outline: none !important; |
| | | -webkit-appearance: none !important; |
| | | appearance: none !important; |
| | | } |
| | | |
| | | :deep(.u-input input), |
| | | :deep(.u-input__content__field-wrapper__field), |
| | | :deep(.u-input__input) { |
| | | font-size: 15px !important; |
| | | color: #333 !important; |
| | | background: transparent !important; |
| | | border: none !important; |
| | | outline: none !important; |
| | | box-shadow: none !important; |
| | | padding: 0 !important; |
| | | margin: 0 !important; |
| | | font-weight: 400 !important; |
| | | width: 100% !important; |
| | | } |
| | | |
| | | /* ç¦ç¨ä¸åªè¯»ç¶æ */ |
| | | :deep(.u-input input:disabled), |
| | | :deep(.u-input__input:disabled) { |
| | | color: #999 !important; |
| | | -webkit-text-fill-color: #999 !important; |
| | | background: transparent !important; |
| | | } |
| | | |
| | | :deep(.u-input input[readonly]), |
| | | :deep(.u-input__input[readonly]) { |
| | | color: #666 !important; |
| | | font-weight: 400 !important; |
| | | background: transparent !important; |
| | | } |
| | | |
| | | /* å ä½ç¬¦æ ·å¼ */ |
| | | :deep(.u-input input::placeholder), |
| | | :deep(.u-input__input::placeholder) { |
| | | color: #c0c4cc !important; |
| | | font-size: 15px !important; |
| | | font-weight: 400 !important; |
| | | } |
| | | .account-detail { |
| | | min-height: 100vh; |
| | | background: #f5f5f5; |
| | | padding-bottom: 5rem; |
| | | } |
| | | /* 产åä¿¡æ¯åºå */ |
| | | .product-section { |
| | | background: #fff; |
| | | margin-top: 10px; |
| | | padding: 16px; |
| | | } |
| | | |
| | | .section-header { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | margin-bottom: 16px; |
| | | width: 100%; |
| | | } |
| | | |
| | | .section-title { |
| | | font-size: 16px; |
| | | font-weight: 500; |
| | | color: #333; |
| | | } |
| | | |
| | | /* 产åå¡çæ ·å¼ */ |
| | | .product-card { |
| | | background: #ffffff; |
| | | border-radius: 8px; |
| | | padding: 16px; |
| | | margin-bottom: 16px; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); |
| | | } |
| | | .tip-text { |
| | | margin: 2px 20px; |
| | | } |
| | | .product-header { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | padding-bottom: 12px; |
| | | margin-bottom: 16px; |
| | | } |
| | | |
| | | .product-title { |
| | | 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; |
| | | } |
| | | |
| | | .product-productCategory { |
| | | font-size: 15px; |
| | | font-weight: 500; |
| | | color: #333; |
| | | } |
| | | |
| | | /* 产å表åé¡¹æ ·å¼ */ |
| | | .product-form { |
| | | margin: 0; |
| | | } |
| | | |
| | | .product-form :deep(.u-form-item) { |
| | | background: transparent; |
| | | margin-bottom: 0; |
| | | padding: 0; |
| | | } |
| | | |
| | | .product-form :deep(.u-form-item__body) { |
| | | padding: 12px 0; |
| | | min-height: 48px; |
| | | } |
| | | |
| | | .product-form :deep(.u-form-item__label) { |
| | | font-size: 14px !important; |
| | | color: #666 !important; |
| | | width: 100px; |
| | | font-weight: 400; |
| | | } |
| | | |
| | | .product-form :deep(.u-input__content__field-wrapper__field), |
| | | .product-form :deep(.u-input__input) { |
| | | font-size: 14px !important; |
| | | color: #333 !important; |
| | | text-align: right; |
| | | } |
| | | |
| | | /* 产å表åæåä¸é¡¹å»æåºè¾¹æ¡ */ |
| | | .product-form :deep(.u-form-item:last-child .u-form-item__body) { |
| | | border-bottom: none; |
| | | } |
| | | |
| | | /* éæ©å¨å¼¹çªæ ·å¼ */ |
| | | .picker-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding: 16px 20px; |
| | | background: #fff; |
| | | } |
| | | |
| | | .picker-cancel { |
| | | color: #666; |
| | | font-size: 16px; |
| | | } |
| | | |
| | | .picker-title { |
| | | color: #333; |
| | | font-size: 16px; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .picker-confirm { |
| | | color: #007aff; |
| | | font-size: 16px; |
| | | } |
| | | |
| | | /* æ éæ©å¨å¼¹çªæ ·å¼ */ |
| | | .popup-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding: 16px 20px; |
| | | background: #fff; |
| | | position: sticky; |
| | | top: 0; |
| | | z-index: 10; |
| | | } |
| | | |
| | | .cancelButton { |
| | | color: #666; |
| | | font-size: 16px; |
| | | } |
| | | |
| | | .confirmButton { |
| | | color: #007aff; |
| | | font-size: 16px; |
| | | } |
| | | |
| | | .u-tree { |
| | | height: 300px; |
| | | padding: 16px; |
| | | } |
| | | |
| | | /* 页é¢åºç¡æ ·å¼ */ |
| | | .page-container { |
| | | min-height: 100vh; |
| | | background: #f5f5f5; |
| | | padding-bottom: 5rem; |
| | | } |
| | | |
| | | /* ååºå¼è°æ´ */ |
| | | @media (max-width: 375px) { |
| | | :deep(.u-form-item__label) { |
| | | width: 100px !important; |
| | | font-size: 14px !important; |
| | | } |
| | | |
| | | :deep(.u-input__content__field-wrapper__field), |
| | | :deep(.u-input__input) { |
| | | font-size: 14px !important; |
| | | } |
| | | } |
| | |
| | | const useUserStore = defineStore("user", { |
| | | state: () => ({ |
| | | token: getToken(), |
| | | id: "", |
| | | id: "", |
| | | name: "", |
| | | avatar: "", |
| | | currentFactoryName: "", |
| | | nickName: "", |
| | | roleName: "", |
| | | currentDeptId: "", |
| | | currentLoginTime: "", |
| | | currentFactoryName: "", |
| | | nickName: "", |
| | | roleName: "", |
| | | currentDeptId: "", |
| | | currentLoginTime: "", |
| | | roles: Array(), |
| | | permissions: [], |
| | | }), |
| | | actions: { |
| | | // é¨é¨ç»å½ |
| | | loginCheckFactory(userInfo: any) { |
| | | const username = userInfo.username.trim() |
| | | const password = userInfo.password |
| | | const factoryId = userInfo.factoryId |
| | | return new Promise((resolve, reject) => { |
| | | loginCheckFactory(username, password, factoryId).then((res: any) => { |
| | | setToken(res.token) |
| | | this.token = res.token |
| | | resolve(null) |
| | | }).catch((error: any) => { |
| | | reject(error) |
| | | }) |
| | | }) |
| | | }, |
| | | // é¨é¨ç»å½ |
| | | loginCheckFactory(userInfo: any) { |
| | | const username = userInfo.username.trim() |
| | | const password = userInfo.password |
| | | const factoryId = userInfo.factoryId |
| | | return new Promise((resolve, reject) => { |
| | | loginCheckFactory(username, password, factoryId).then((res: any) => { |
| | | setToken(res.token) |
| | | this.token = res.token |
| | | resolve(null) |
| | | }).catch((error: any) => { |
| | | reject(error) |
| | | }) |
| | | }) |
| | | }, |
| | | // è·åç¨æ·ä¿¡æ¯ |
| | | getInfo() { |
| | | return new Promise((resolve, reject) => { |
| | | getInfo() |
| | | .then((res: any) => { |
| | | const user = res.user |
| | | let avatar = user.avatar || "" |
| | | avatar = config.baseUrl + '/profile/' + avatar |
| | | if (res.roles && res.roles.length > 0) { // éªè¯è¿åçrolesæ¯å¦æ¯ä¸ä¸ªé空æ°ç» |
| | | this.roles = res.roles |
| | | this.permissions = res.permissions |
| | | } else { |
| | | this.roles = ['ROLE_DEFAULT'] |
| | | } |
| | | this.id = user.userId |
| | | this.name = user.userName |
| | | this.avatar = avatar |
| | | this.currentFactoryName = user.currentFactoryName |
| | | this.nickName = user.nickName |
| | | this.roleName = user.roles[0].roleName |
| | | this.currentDeptId = user.tenantId |
| | | this.currentLoginTime = this.getCurrentTime() |
| | | const user = res.user |
| | | let avatar = user.avatar || "" |
| | | avatar = config.baseUrl + '/profile/' + avatar |
| | | if (res.roles && res.roles.length > 0) { // éªè¯è¿åçrolesæ¯å¦æ¯ä¸ä¸ªé空æ°ç» |
| | | this.roles = res.roles |
| | | this.permissions = res.permissions |
| | | } else { |
| | | this.roles = ['ROLE_DEFAULT'] |
| | | } |
| | | this.id = user.userId |
| | | this.name = user.userName |
| | | this.avatar = avatar |
| | | this.currentFactoryName = user.currentFactoryName |
| | | this.nickName = user.nickName |
| | | this.roleName = user.roles[0].roleName |
| | | this.currentDeptId = user.tenantId |
| | | this.currentLoginTime = this.getCurrentTime() |
| | | resolve(res); |
| | | }) |
| | | .catch((error) => { |
| | |
| | | }); |
| | | }); |
| | | }, |
| | | getCurrentTime() { |
| | | const now = new Date(); |
| | | const year = now.getFullYear(); // è·å年份 |
| | | const month = String(now.getMonth() + 1).padStart(2, '0'); // æä»½ä»0å¼å§ï¼è¦+1ï¼å¹¶è¡¥é¶ |
| | | 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'); // ç§æ°è¡¥é¶ |
| | | return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; |
| | | }, |
| | | getCurrentTime() { |
| | | const now = new Date(); |
| | | const year = now.getFullYear(); // è·å年份 |
| | | const month = String(now.getMonth() + 1).padStart(2, '0'); // æä»½ä»0å¼å§ï¼è¦+1ï¼å¹¶è¡¥é¶ |
| | | 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'); // ç§æ°è¡¥é¶ |
| | | return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; |
| | | }, |
| | | }, |
| | | }); |
| | | |
| | |
| | | // @import "sass:math"; |
| | | // @use "sass:math"; |
| | | @import '../tools/functions.scss'; |
| | | // é´è·åºç¡åæ° |
| | | $uni-space-root: 2 !default; |
| | |
| | | return true; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å°æ¥æè½¬æ¢ä¸ºYYYY-MM-DDæ ¼å¼ |
| | | * @param {*} dateSource æ¥ææºï¼å¯ä»¥æ¯æ¶é´æ³æDateå¯¹è±¡ï¼ |
| | | * @returns æ ¼å¼ååçæ¥æå符串 YYYY-MM-DD |
| | | */ |
| | | export function formatDateToYMD(dateSource) { |
| | | let date; |
| | | // å¤çï¼å¦ææ¯æ¶é´æ³ï¼å
转为Date对象 |
| | | if (typeof dateSource === 'number') { |
| | | date = new Date(dateSource); |
| | | } |
| | | // å¤çï¼å¦ææ¯Date对象ï¼ç´æ¥ä½¿ç¨ |
| | | else if (dateSource instanceof Date) { |
| | | date = dateSource; |
| | | } |
| | | // å¼å¸¸æ
åµï¼è¿å空 |
| | | else { |
| | | return ''; |
| | | } |
| | | |
| | | // è¡¥é¶å½æ°ï¼ç¡®ä¿æ/æ¥æ¯ä¸¤ä½æ° |
| | | const padZero = (num) => num.toString().padStart(2, '0'); |
| | | |
| | | const year = date.getFullYear(); |
| | | const month = padZero(date.getMonth() + 1); |
| | | const day = padZero(date.getDate()); |
| | | |
| | | return `${year}-${month}-${day}`; |
| | | } |