| New file |
| | |
| | | import request from '@/utils/request' |
| | | |
| | | // æ¥è¯¢æçå票ç³è¯·å表 |
| | | export function listMyInvoice(query) { |
| | | return request({ |
| | | url: '/system/invoice/myList', |
| | | method: 'get', |
| | | params: query |
| | | }) |
| | | } |
| | | |
| | | // æäº¤å票ç³è¯· |
| | | export function addInvoice(data) { |
| | | return request({ |
| | | url: '/system/invoice', |
| | | method: 'post', |
| | | data: data |
| | | }) |
| | | } |
| | | |
| | | // è·åå¯å¼ç¥¨çä»»å¡å表 |
| | | export function listSelectableTasks(params) { |
| | | return request({ |
| | | url: '/system/invoice/selectableTasks', |
| | | method: 'get', |
| | | params: params |
| | | }) |
| | | } |
| | | |
| | | // æ£æ¥ä»»å¡æ¯å¦å·²ç³è¯·å票 |
| | | export function checkTaskInvoice(taskId) { |
| | | return request({ |
| | | url: `/system/invoice/checkTaskInvoice/${taskId}`, |
| | | method: 'get' |
| | | }) |
| | | } |
| | |
| | | "style": { |
| | | "navigationBarTitleText": "æ¶æ¯ä¸å¿" |
| | | } |
| | | }, { |
| | | "path": "pages/mine/invoice/index", |
| | | "style": { |
| | | "navigationBarTitleText": "æçå票" |
| | | } |
| | | }, { |
| | | "path": "pages/mine/invoice/apply", |
| | | "style": { |
| | | "navigationBarTitleText": "ç³è¯·å票" |
| | | } |
| | | }], |
| | | "subPackages": [{ |
| | | "root": "pagesTask", |
| | |
| | | <view>{{ boundVehicle && boundVehicle !== 'æªç»å®' ? 'æ´æ¢è½¦è¾' : 'ç»å®è½¦è¾' }}</view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- æçå票 --> |
| | | <view class="list-cell list-cell-arrow" @click="handleToInvoice"> |
| | | <view class="menu-item-box"> |
| | | <view class="iconfont icon-edit menu-icon"></view> |
| | | <view>æçå票</view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- éåºç»å½ --> |
| | | <view class="list-cell list-cell-arrow" @click="handleLogout"> |
| | |
| | | this.$tab.navigateTo('/pages/bind-vehicle') |
| | | }, |
| | | |
| | | handleToInvoice() { |
| | | this.$tab.navigateTo('/pages/mine/invoice/index') |
| | | }, |
| | | |
| | | handleToInfo() { |
| | | this.$tab.navigateTo('/pages/mine/info/index') |
| | | }, |
| New file |
| | |
| | | <template> |
| | | <view class="invoice-apply-container bg-white"> |
| | | <form> |
| | | <view class="cu-form-group margin-top"> |
| | | <view class="title required">鿩任å¡</view> |
| | | <view class="combo-box-wrapper"> |
| | | <input |
| | | class="combo-input" |
| | | placeholder="请è¾å
¥æå¡åå·æä»»å¡ç¼å·æç´¢" |
| | | v-model="searchKeyword" |
| | | @input="handleInput" |
| | | @focus="handleFocus" |
| | | @blur="handleBlur" |
| | | /> |
| | | <text class="cuIcon-search search-icon"></text> |
| | | |
| | | <!-- 䏿å表 --> |
| | | <view class="dropdown-list" v-if="showDropdown && filteredTaskList.length > 0"> |
| | | <view class="dropdown-item" |
| | | v-for="task in filteredTaskList" |
| | | :key="task.taskId" |
| | | @click="selectTask(task)" |
| | | > |
| | | <view class="item-main"> |
| | | <text class="service-code">{{ task.serviceCode || task.taskCode }}</text> |
| | | <text class="task-code">{{ task.taskCode }}</text> |
| | | </view> |
| | | <view class="item-sub"> |
| | | |
| | | <text class="text-gray margin-left-sm">{{ task.completionTime }}</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- æ ç»ææç¤º --> |
| | | <view class="dropdown-list" v-if="showDropdown && searchKeyword && filteredTaskList.length === 0 && !loading"> |
| | | <view class="empty-result"> |
| | | <text class="text-gray">æªæ¾å°å¹é
çä»»å¡</text> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- å è½½æç¤º --> |
| | | <view class="dropdown-list" v-if="showDropdown && loading"> |
| | | <view class="loading-result"> |
| | | <text class="cuIcon-loading2 cu-spin"></text> |
| | | <text class="text-gray margin-left-sm">æç´¢ä¸...</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- å·²é任塿¾ç¤º --> |
| | | <view class="selected-task" v-if="form.serviceOrderId"> |
| | | <view class="label">å·²éä»»å¡</view> |
| | | <view class="task-card"> |
| | | <view class="card-header"> |
| | | <text class="service-code">{{ selectedTask.serviceCode || selectedTask.taskCode }}</text> |
| | | <text class="cuIcon-close remove-btn" @click="clearSelection"></text> |
| | | </view> |
| | | <view class="task-info-detail"> |
| | | <view class="info-row"> |
| | | <text class="info-label">æå¡åå·:</text> |
| | | <text class="info-value">{{ selectedTask.legacyServiceOrderId }}</text> |
| | | </view> |
| | | <view class="info-row"> |
| | | <text class="info-label">åºåå°:</text> |
| | | <text class="info-value">{{ selectedTask.departure || '-' }}</text> |
| | | </view> |
| | | <view class="info-row"> |
| | | <text class="info-label">ç®çå°:</text> |
| | | <text class="info-value">{{ selectedTask.destination || '-' }}</text> |
| | | </view> |
| | | <view class="info-row"> |
| | | <text class="info-label">宿æ¶é´:</text> |
| | | <text class="info-value">{{ selectedTask.completionTime }}</text> |
| | | </view> |
| | | <view class="info-row" v-if="selectedTask.transferPrice"> |
| | | <text class="info-label">ä»»å¡éé¢:</text> |
| | | <text class="info-value text-price">ï¿¥{{ selectedTask.transferPrice }}</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="cu-form-group"> |
| | | <view class="title">å¼ç¥¨ç±»å</view> |
| | | <radio-group class="flex" @change="handleTypeChange"> |
| | | <view class="margin-right-sm"> |
| | | <radio value="1" :checked="form.invoiceType == 1"></radio><text class="margin-left-xs">个人</text> |
| | | </view> |
| | | <view> |
| | | <radio value="2" :checked="form.invoiceType == 2"></radio><text class="margin-left-xs">ä¼ä¸</text> |
| | | </view> |
| | | </radio-group> |
| | | </view> |
| | | |
| | | <view class="cu-form-group"> |
| | | <view class="title required">å票æ¬å¤´</view> |
| | | <input placeholder="请è¾å
¥å票æ¬å¤´" v-model="form.invoiceName" /> |
| | | </view> |
| | | |
| | | <view class="cu-form-group"> |
| | | <view class="title required">å票éé¢</view> |
| | | <input |
| | | type="digit" |
| | | placeholder="请è¾å
¥éé¢" |
| | | v-model="form.invoiceMoney" |
| | | @blur="validateMoney" |
| | | /> |
| | | </view> |
| | | <view class="money-hint" v-if="selectedTask && selectedTask.transferPrice"> |
| | | <text class="text-gray text-sm">æå¤§å¯å¼ç¥¨éé¢: ï¿¥{{ selectedTask.transferPrice }}</text> |
| | | </view> |
| | | |
| | | <view class="cu-form-group align-start"> |
| | | <view class="title">åç¥¨å¤æ³¨</view> |
| | | <textarea maxlength="-1" v-model="form.invoiceRemarks" placeholder="请è¾å
¥å¤æ³¨ä¿¡æ¯"></textarea> |
| | | </view> |
| | | |
| | | <block v-if="form.invoiceType == 2"> |
| | | <view class="cu-form-group"> |
| | | <view class="title">注åå°å</view> |
| | | <input placeholder="请è¾å
¥ä¼ä¸æ³¨åå°å" v-model="form.companyAddress" /> |
| | | </view> |
| | | <view class="cu-form-group"> |
| | | <view class="title">弿·é¶è¡</view> |
| | | <input placeholder="请è¾å
¥ä¼ä¸å¼æ·é¶è¡" v-model="form.companyBank" /> |
| | | </view> |
| | | <view class="cu-form-group"> |
| | | <view class="title">é¶è¡å¸å·</view> |
| | | <input placeholder="请è¾å
¥ä¼ä¸é¶è¡å¸å·" v-model="form.companyBankNo" /> |
| | | </view> |
| | | </block> |
| | | |
| | | <view class="cu-form-group margin-top-sm"> |
| | | <view class="title">é®ç¼</view> |
| | | <input placeholder="请è¾å
¥é®ç¼" v-model="form.zipCode" /> |
| | | </view> |
| | | |
| | | <view class="cu-form-group"> |
| | | <view class="title">é®å¯å°å</view> |
| | | <input placeholder="请è¾å
¥é®å¯å°å" v-model="form.mailAddress" /> |
| | | </view> |
| | | |
| | | <view class="cu-form-group"> |
| | | <view class="title">è系人</view> |
| | | <input placeholder="请è¾å
¥è系人" v-model="form.contactName" /> |
| | | </view> |
| | | |
| | | <view class="cu-form-group"> |
| | | <view class="title">èç³»çµè¯</view> |
| | | <input placeholder="请è¾å
¥èç³»çµè¯" v-model="form.contactPhone" /> |
| | | </view> |
| | | |
| | | <view class="padding flex flex-direction"> |
| | | <button class="cu-btn bg-blue lg" @click="submit">æäº¤ç³è¯·</button> |
| | | </view> |
| | | </form> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import { addInvoice, listSelectableTasks } from "@/api/invoice" |
| | | |
| | | export default { |
| | | data() { |
| | | return { |
| | | searchKeyword: '', |
| | | filteredTaskList: [], |
| | | selectedTask: null, |
| | | showDropdown: false, |
| | | loading: false, |
| | | searchTimer: null, |
| | | maxInvoiceMoney: null, // æå¤§å¯å¼ç¥¨éé¢ |
| | | form: { |
| | | serviceOrderId: null, |
| | | legacyServiceOrderId: null, |
| | | invoiceType: 1, |
| | | invoiceName: '', |
| | | invoiceMoney: '', |
| | | invoiceRemarks: '', |
| | | companyAddress: '', |
| | | companyBank: '', |
| | | companyBankNo: '', |
| | | zipCode: '', |
| | | mailAddress: '', |
| | | contactName: '', |
| | | contactPhone: '' |
| | | }, |
| | | // ä»ä»»å¡è¯¦æ
é¡µä¼ å
¥çä»»å¡ä¿¡æ¯ |
| | | taskInfoFromDetail: null |
| | | } |
| | | }, |
| | | onLoad(options) { |
| | | // æ£æ¥æ¯å¦ä»ä»»å¡è¯¦æ
é¡µä¼ å
¥äºä»»å¡ä¿¡æ¯ |
| | | if (options && options.taskInfo) { |
| | | try { |
| | | const taskInfo = JSON.parse(decodeURIComponent(options.taskInfo)); |
| | | this.taskInfoFromDetail = taskInfo; |
| | | this.preFillTaskInfo(); |
| | | } catch (e) { |
| | | console.error('è§£æä»»å¡ä¿¡æ¯å¤±è´¥:', e); |
| | | } |
| | | } |
| | | // ä¸åèªå¨å 载任å¡å表 |
| | | }, |
| | | methods: { |
| | | // é¢å¡«å
ä»»å¡ä¿¡æ¯ |
| | | preFillTaskInfo() { |
| | | if (!this.taskInfoFromDetail) return; |
| | | |
| | | const taskInfo = this.taskInfoFromDetail; |
| | | |
| | | // å¡«å
表å |
| | | this.form.serviceOrderId = taskInfo.taskId; |
| | | // åæ¶è®¾ç½®æ§ç³»ç»æå¡åID |
| | | if (taskInfo.legacyServiceOrderId) { |
| | | this.form.legacyServiceOrderId = taskInfo.legacyServiceOrderId; |
| | | } |
| | | this.selectedTask = { ...taskInfo }; |
| | | |
| | | // 设置æå¤§å¯å¼ç¥¨éé¢ |
| | | if (taskInfo.transferPrice) { |
| | | this.maxInvoiceMoney = parseFloat(taskInfo.transferPrice); |
| | | // èªå¨å¡«å
¥ä»»å¡éé¢ |
| | | this.form.invoiceMoney = this.maxInvoiceMoney.toString(); |
| | | } |
| | | |
| | | console.log('ä»»å¡ä¿¡æ¯å·²é¢å¡«å
:', taskInfo); |
| | | }, |
| | | |
| | | handleInput(e) { |
| | | const keyword = e.detail.value.trim() |
| | | |
| | | // æ¸
é¤ä¹åç宿¶å¨ |
| | | if (this.searchTimer) { |
| | | clearTimeout(this.searchTimer) |
| | | } |
| | | |
| | | if (!keyword) { |
| | | this.showDropdown = false |
| | | this.filteredTaskList = [] |
| | | return |
| | | } |
| | | |
| | | // 鲿ï¼å»¶è¿300msæç´¢ |
| | | this.searchTimer = setTimeout(() => { |
| | | this.searchTasks(keyword) |
| | | }, 300) |
| | | }, |
| | | |
| | | handleFocus() { |
| | | // 妿æè¾å
¥å
å®¹ï¼æ¾ç¤ºä¸æå表 |
| | | if (this.searchKeyword && this.searchKeyword.trim()) { |
| | | this.showDropdown = true |
| | | } |
| | | }, |
| | | |
| | | handleBlur() { |
| | | // å»¶è¿å
³é䏿å表ï¼ç¡®ä¿ç¹å»äºä»¶è½è§¦å |
| | | setTimeout(() => { |
| | | this.showDropdown = false |
| | | }, 200) |
| | | }, |
| | | |
| | | searchTasks(keyword) { |
| | | this.loading = true |
| | | this.showDropdown = true |
| | | |
| | | listSelectableTasks({ |
| | | searchKeyword: keyword |
| | | }).then(res => { |
| | | this.filteredTaskList = this.formatTaskList(res.data) |
| | | }).catch(err => { |
| | | this.$modal.msgError('æç´¢å¤±è´¥ï¼è¯·éè¯') |
| | | this.filteredTaskList = [] |
| | | }).finally(() => { |
| | | this.loading = false |
| | | }) |
| | | }, |
| | | formatTaskList(data) { |
| | | return data.map(item => { |
| | | // 宿´æ¾ç¤º yyyy-MM-dd HH:mm |
| | | const time = item.completionTime ? item.completionTime.substring(0, 16) : ''; |
| | | // å
¼å®¹ä¸¤ç§å段åï¼transferPrice å transfer_price |
| | | const transferPrice = item.transferPrice !== undefined ? item.transferPrice : item.transfer_price; |
| | | return { |
| | | taskId: item.taskId, |
| | | taskCode: item.taskCode, |
| | | serviceCode: item.serviceCode, |
| | | legacyServiceOrderId: item.legacyServiceOrderId || item.taskCode, |
| | | completionTime: time, |
| | | departure: item.departure, |
| | | destination: item.destination, |
| | | transferPrice: transferPrice |
| | | } |
| | | }) |
| | | }, |
| | | handleSearch() { |
| | | if (!this.searchKeyword || this.searchKeyword.trim() === '') { |
| | | // æªè¾å
¥æ¶æ¾ç¤ºææ |
| | | this.getCompletedTasks() |
| | | } else { |
| | | // è°ç¨å端æç´¢æ¥å£ |
| | | listSelectableTasks({ |
| | | searchKeyword: this.searchKeyword.trim() |
| | | }).then(res => { |
| | | this.filteredTaskList = this.formatTaskList(res.data) |
| | | }) |
| | | } |
| | | }, |
| | | selectTask(task) { |
| | | console.log('éä¸çä»»å¡:', task) |
| | | console.log('ä»»å¡éé¢:', task.transferPrice) |
| | | |
| | | this.selectedTask = task |
| | | // serviceOrderId å卿§ç³»ç»æå¡åID |
| | | this.form.serviceOrderId = task.taskId; |
| | | this.form.legacyServiceOrderId = task.legacyServiceOrderId |
| | | // éä¸åæ¾ç¤ºæå¡åå·ï¼å
³é䏿 |
| | | this.searchKeyword = task.serviceCode || task.taskCode |
| | | this.showDropdown = false |
| | | |
| | | // èªå¨å¸¦å
¥ä»»å¡éé¢å°å票éé¢ |
| | | if (task.transferPrice !== null && task.transferPrice !== undefined) { |
| | | // ç¡®ä¿é颿¯æ°åç±»å |
| | | const price = Number(task.transferPrice) |
| | | if (!isNaN(price) && price > 0) { |
| | | this.form.invoiceMoney = price.toString() |
| | | this.maxInvoiceMoney = price |
| | | console.log('已设置å票éé¢:', this.form.invoiceMoney) |
| | | } else { |
| | | console.log('ä»»å¡é颿 æ:', task.transferPrice) |
| | | } |
| | | } else { |
| | | console.log('ä»»å¡éé¢ä¸ºç©º') |
| | | } |
| | | }, |
| | | |
| | | clearSelection() { |
| | | this.selectedTask = null |
| | | this.form.serviceOrderId = null |
| | | this.form.legacyServiceOrderId = null |
| | | this.form.invoiceMoney = '' |
| | | this.searchKeyword = '' |
| | | this.filteredTaskList = [] |
| | | this.maxInvoiceMoney = null |
| | | }, |
| | | |
| | | validateMoney() { |
| | | if (!this.form.invoiceMoney) return |
| | | |
| | | const money = parseFloat(this.form.invoiceMoney) |
| | | |
| | | if (isNaN(money) || money <= 0) { |
| | | this.$modal.msgError('请è¾å
¥ææçéé¢') |
| | | this.form.invoiceMoney = '' |
| | | return |
| | | } |
| | | |
| | | // æ ¡éªæ¯å¦è¶
è¿ä»»å¡éé¢ |
| | | if (this.maxInvoiceMoney && money > this.maxInvoiceMoney) { |
| | | this.$modal.msgError(`å票éé¢ä¸è½è¶
è¿ä»»å¡éé¢ï¿¥${this.maxInvoiceMoney}`) |
| | | this.form.invoiceMoney = this.maxInvoiceMoney.toString() |
| | | } |
| | | }, |
| | | handleTypeChange(e) { |
| | | this.form.invoiceType = e.detail.value |
| | | }, |
| | | submit() { |
| | | if (!this.form.serviceOrderId) { |
| | | this.$modal.msgError("è¯·éæ©ä»»å¡") |
| | | return |
| | | } |
| | | if (!this.form.invoiceName) { |
| | | this.$modal.msgError("请è¾å
¥å票æ¬å¤´") |
| | | return |
| | | } |
| | | if (!this.form.invoiceMoney) { |
| | | this.$modal.msgError("请è¾å
¥å票éé¢") |
| | | return |
| | | } |
| | | |
| | | // 忬¡æ ¡éªéé¢ |
| | | const money = parseFloat(this.form.invoiceMoney) |
| | | if (isNaN(money) || money <= 0) { |
| | | this.$modal.msgError('请è¾å
¥ææçéé¢') |
| | | return |
| | | } |
| | | if (this.maxInvoiceMoney && money > this.maxInvoiceMoney) { |
| | | this.$modal.msgError(`å票éé¢ä¸è½è¶
è¿ä»»å¡éé¢ï¿¥${this.maxInvoiceMoney}`) |
| | | return |
| | | } |
| | | |
| | | addInvoice(this.form).then(res => { |
| | | this.$modal.msgSuccess("æäº¤æå") |
| | | setTimeout(() => { |
| | | // 跳转å°å票åè¡¨é¡µé¢ |
| | | uni.redirectTo({ |
| | | url: '/pages/mine/invoice/index' |
| | | }) |
| | | }, 1500) |
| | | }) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | .invoice-apply-container { |
| | | min-height: 100vh; |
| | | padding-bottom: 50rpx; |
| | | |
| | | .cu-form-group .title { |
| | | min-width: calc(4em + 15px); |
| | | |
| | | &.required::before { |
| | | content: '*'; |
| | | color: #f56c6c; |
| | | margin-right: 4rpx; |
| | | font-weight: bold; |
| | | } |
| | | } |
| | | |
| | | // ComboBoxæ ·å¼ |
| | | .combo-box-wrapper { |
| | | position: relative; |
| | | flex: 1; |
| | | |
| | | .combo-input { |
| | | width: 100%; |
| | | padding-right: 60rpx; |
| | | } |
| | | |
| | | .search-icon { |
| | | position: absolute; |
| | | right: 20rpx; |
| | | top: 50%; |
| | | transform: translateY(-50%); |
| | | color: #8799a3; |
| | | font-size: 36rpx; |
| | | } |
| | | |
| | | .dropdown-list { |
| | | position: absolute; |
| | | top: 100%; |
| | | left: 0; |
| | | right: 0; |
| | | max-height: 500rpx; |
| | | overflow-y: auto; |
| | | background: white; |
| | | border: 2rpx solid #e1e1e1; |
| | | border-radius: 8rpx; |
| | | margin-top: 10rpx; |
| | | box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.1); |
| | | z-index: 999; |
| | | |
| | | .dropdown-item { |
| | | padding: 20rpx; |
| | | border-bottom: 1rpx solid #f0f0f0; |
| | | transition: background 0.2s; |
| | | |
| | | &:active { |
| | | background: #f5f5f5; |
| | | } |
| | | |
| | | &:last-child { |
| | | border-bottom: none; |
| | | } |
| | | |
| | | .item-main { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 8rpx; |
| | | |
| | | .service-code { |
| | | font-size: 30rpx; |
| | | font-weight: bold; |
| | | color: #1976d2; |
| | | } |
| | | |
| | | .task-code { |
| | | font-size: 22rpx; |
| | | color: #999; |
| | | } |
| | | } |
| | | |
| | | .item-sub { |
| | | display: flex; |
| | | font-size: 24rpx; |
| | | color: #666; |
| | | } |
| | | } |
| | | |
| | | .empty-result, .loading-result { |
| | | padding: 40rpx 20rpx; |
| | | text-align: center; |
| | | color: #999; |
| | | } |
| | | |
| | | .loading-result { |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .selected-task { |
| | | margin: 20rpx 30rpx; |
| | | |
| | | .label { |
| | | font-size: 28rpx; |
| | | color: #666; |
| | | margin-bottom: 10rpx; |
| | | } |
| | | |
| | | .task-card { |
| | | padding: 20rpx; |
| | | background: #e8f5e9; |
| | | border-radius: 8rpx; |
| | | border: 2rpx solid #4caf50; |
| | | |
| | | .card-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 20rpx; |
| | | padding-bottom: 16rpx; |
| | | border-bottom: 1rpx solid #c8e6c9; |
| | | } |
| | | |
| | | .service-code { |
| | | font-size: 32rpx; |
| | | font-weight: bold; |
| | | color: #2e7d32; |
| | | } |
| | | |
| | | .remove-btn { |
| | | font-size: 40rpx; |
| | | color: #999; |
| | | padding: 10rpx; |
| | | } |
| | | |
| | | .task-info-detail { |
| | | .info-row { |
| | | display: flex; |
| | | margin-bottom: 12rpx; |
| | | line-height: 1.6; |
| | | |
| | | &:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .info-label { |
| | | font-size: 26rpx; |
| | | color: #666; |
| | | min-width: 140rpx; |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | .info-value { |
| | | font-size: 26rpx; |
| | | color: #333; |
| | | flex: 1; |
| | | word-break: break-all; |
| | | |
| | | &.text-price { |
| | | color: #f56c6c; |
| | | font-weight: bold; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .money-hint { |
| | | margin: -10rpx 30rpx 20rpx 30rpx; |
| | | padding-left: calc(4em + 15px); |
| | | } |
| | | } |
| | | </style> |
| New file |
| | |
| | | <template> |
| | | <view class="invoice-list-container"> |
| | | <view class="add-btn-box"> |
| | | <button class="cu-btn block bg-blue lg" @click="handleApply">ç³è¯·å票</button> |
| | | </view> |
| | | |
| | | <!-- æç´¢æ¡ --> |
| | | <view class="search-box"> |
| | | <view class="search-input-wrapper"> |
| | | <input |
| | | class="search-input" |
| | | placeholder="请è¾å
¥æå¡åå·æç´¢" |
| | | v-model="searchKeyword" |
| | | @confirm="handleSearch" |
| | | /> |
| | | <text class="cuIcon-search search-icon" @click="handleSearch"></text> |
| | | <text v-if="searchKeyword" class="cuIcon-close clear-icon" @click="clearSearch"></text> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- ç¶æTab --> |
| | | <view class="tabs-wrapper"> |
| | | <view |
| | | class="tab-item" |
| | | :class="currentTab === null ? 'active' : ''" |
| | | @click="switchTab(null)" |
| | | > |
| | | <text>å
¨é¨</text> |
| | | </view> |
| | | <view |
| | | class="tab-item" |
| | | :class="currentTab === 0 ? 'active' : ''" |
| | | @click="switchTab(0)" |
| | | > |
| | | <text>å¾
å®¡æ ¸</text> |
| | | </view> |
| | | <view |
| | | class="tab-item" |
| | | :class="currentTab === 1 ? 'active' : ''" |
| | | @click="switchTab(1)" |
| | | > |
| | | <text>å·²éè¿</text> |
| | | </view> |
| | | <view |
| | | class="tab-item" |
| | | :class="currentTab === 2 ? 'active' : ''" |
| | | @click="switchTab(2)" |
| | | > |
| | | <text>已驳å</text> |
| | | </view> |
| | | </view> |
| | | |
| | | <scroll-view scroll-y="true" class="list-scroll" @scrolltolower="loadMore"> |
| | | <!-- 空å表æç¤º --> |
| | | <view v-if="list.length === 0" class="empty-box"> |
| | | <text class="text-gray">ææ å票ç³è¯·è®°å½</text> |
| | | </view> |
| | | |
| | | <!-- å票å表 --> |
| | | <view v-for="(item, index) in list" :key="index" class="invoice-item bg-white margin-sm padding-sm radius shadow"> |
| | | <view class="flex justify-between border-bottom padding-bottom-xs margin-bottom-xs"> |
| | | <text class="text-bold">æå¡åå·: {{ item.serviceCode || item.legacyServiceOrderId || 'æªç¥' }}</text> |
| | | <text :class="item.status === 0 ? 'text-orange' : item.status === 1 ? 'text-green' : item.status === 2 ? 'text-red' : 'text-gray'">{{ item.status === 0 ? 'å¾
å®¡æ ¸' : item.status === 1 ? 'å·²éè¿' : item.status === 2 ? '已驳å' : 'æªç¥' }}</text> |
| | | </view> |
| | | <view class="info-row"> |
| | | <text class="label">å票æ¬å¤´:</text> |
| | | <text class="value">{{ item.invoiceName }}</text> |
| | | </view> |
| | | <view class="info-row"> |
| | | <text class="label">ç³è¯·éé¢:</text> |
| | | <text class="value text-red">ï¿¥{{ item.invoiceMoney ? Number(item.invoiceMoney).toFixed(2) : '0.00' }}</text> |
| | | </view> |
| | | <view class="info-row"> |
| | | <text class="label">ç³è¯·æ¶é´:</text> |
| | | <text class="value">{{ formatApplyTime(item.applyTime) }}</text> |
| | | </view> |
| | | <view v-if="item.invoiceNo" class="info-row"> |
| | | <text class="label">å票ç¼å·:</text> |
| | | <text class="value">{{ item.invoiceNo }}</text> |
| | | </view> |
| | | |
| | | <view class="action-bar margin-top-sm flex justify-end" v-if="item.invoiceUrl"> |
| | | <button class="cu-btn sm bg-green" @click="handleDownload" :data-url="item.invoiceUrl">æ¥çå票</button> |
| | | </view> |
| | | <view v-if="item.status === 2 && item.auditRemarks" class="margin-top-xs padding-xs bg-gray radius"> |
| | | <text class="text-sm text-red">驳ååå : {{ item.auditRemarks }}</text> |
| | | </view> |
| | | </view> |
| | | </scroll-view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import { listMyInvoice } from "@/api/invoice" |
| | | import config from '@/config.js' |
| | | |
| | | export default { |
| | | data() { |
| | | return { |
| | | list: [], |
| | | queryParams: { |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | serviceCode: null, // æå¡åå·æç´¢ |
| | | status: null // ç¶æçé |
| | | }, |
| | | total: 0, |
| | | searchKeyword: '', // æç´¢å
³é®è¯ |
| | | currentTab: null // å½åTabï¼null=å
¨é¨, 0=å¾
å®¡æ ¸, 1=å·²éè¿, 2=已驳å |
| | | } |
| | | }, |
| | | onShow() { |
| | | this.queryParams.pageNum = 1 |
| | | this.list = [] |
| | | this.getList() |
| | | }, |
| | | methods: { |
| | | getList() { |
| | | listMyInvoice(this.queryParams).then(res => { |
| | | if (res.rows) { |
| | | let rows = res.rows; |
| | | // æç³è¯·æ¶é´ååºæåº |
| | | rows.sort((a, b) => { |
| | | // 妿æ applyTimeï¼åæ¯è¾æ¶é´ï¼å¦åæ¾å¨æå |
| | | if (!a.applyTime) return 1; |
| | | if (!b.applyTime) return -1; |
| | | return new Date(b.applyTime) - new Date(a.applyTime); |
| | | }); |
| | | this.list = this.list.concat(rows); |
| | | this.total = res.total || 0; |
| | | } |
| | | }).catch(err => { |
| | | console.error('è·åå票å表失败:', err) |
| | | this.$modal.msgError('å 载失败ï¼è¯·éè¯') |
| | | }) |
| | | }, |
| | | // æç´¢ |
| | | handleSearch() { |
| | | this.queryParams.serviceCode = this.searchKeyword.trim() || null |
| | | this.resetList() |
| | | }, |
| | | // æ¸
空æç´¢ |
| | | clearSearch() { |
| | | this.searchKeyword = '' |
| | | this.queryParams.serviceCode = null |
| | | this.resetList() |
| | | }, |
| | | // 忢Tab |
| | | switchTab(status) { |
| | | this.currentTab = status |
| | | this.queryParams.status = status |
| | | this.resetList() |
| | | }, |
| | | // éç½®å表 |
| | | resetList() { |
| | | this.queryParams.pageNum = 1 |
| | | this.list = [] |
| | | this.getList() |
| | | }, |
| | | loadMore() { |
| | | if (this.list.length < this.total) { |
| | | this.queryParams.pageNum++ |
| | | this.getList() |
| | | } |
| | | }, |
| | | handleApply() { |
| | | this.$tab.navigateTo('/pages/mine/invoice/apply') |
| | | }, |
| | | handleDownload(e) { |
| | | const url = e.currentTarget.dataset.url |
| | | console.log('=== å票ä¸è½½è°è¯ä¿¡æ¯ ==='); |
| | | console.log('1. åå§URL:', url) |
| | | |
| | | if (!url) { |
| | | this.$modal.msgError('å票æä»¶å°å为空') |
| | | return |
| | | } |
| | | |
| | | // å¤çURLï¼ç¡®ä¿æ¯å®æ´çå°å |
| | | let fullUrl = url |
| | | if (!url.startsWith('http')) { |
| | | // 妿æ¯ç¸å¯¹è·¯å¾ï¼æ¼æ¥å®æ´å°å |
| | | fullUrl = config.baseUrl + url |
| | | } |
| | | |
| | | console.log('2. baseUrl:', config.baseUrl) |
| | | console.log('3. 宿´URL:', fullUrl) |
| | | |
| | | const fileExt = fullUrl.match(/\.(\w+)$/)?.[1]?.toLowerCase() |
| | | console.log('4. æä»¶æ©å±å:', fileExt) |
| | | |
| | | // #ifdef H5 |
| | | console.log('5. H5ç¯å¢ï¼ç´æ¥æå¼') |
| | | window.open(fullUrl) |
| | | // #endif |
| | | |
| | | // #ifndef H5 |
| | | console.log('5. å°ç¨åº/Appç¯å¢') |
| | | |
| | | // å
é¢è§å¾çï¼å¦ææ¯å¾çæ ¼å¼ |
| | | const imageExts = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'] |
| | | if (imageExts.includes(fileExt)) { |
| | | console.log('6. å¾çæä»¶ï¼ä½¿ç¨previewImage') |
| | | uni.previewImage({ |
| | | urls: [fullUrl], |
| | | current: fullUrl, |
| | | success: () => { |
| | | console.log('å¾çé¢è§æå') |
| | | }, |
| | | fail: (err) => { |
| | | console.error('å¾çé¢è§å¤±è´¥:', err) |
| | | this.$modal.msgError(`æ æ³é¢è§å¾ç: ${err.errMsg || 'æªç¥é误'}`) |
| | | } |
| | | }) |
| | | return |
| | | } |
| | | |
| | | // PDFæä»¶ä¸è½½å¹¶æå¼ |
| | | console.log('6. PDFæä»¶ï¼ä½¿ç¨downloadFile') |
| | | uni.showLoading({ title: 'ä¸è½½ä¸...', mask: true }) |
| | | |
| | | uni.downloadFile({ |
| | | url: fullUrl, |
| | | success: (res) => { |
| | | console.log('7. ä¸è½½æå:', res) |
| | | uni.hideLoading() |
| | | |
| | | if (res.statusCode === 200) { |
| | | console.log('8. æå¼ææ¡£:', res.tempFilePath) |
| | | uni.openDocument({ |
| | | filePath: res.tempFilePath, |
| | | showMenu: true, |
| | | success: function (openRes) { |
| | | console.log('9. ææ¡£æå¼æå:', openRes) |
| | | }, |
| | | fail: function (err) { |
| | | console.error('9. ææ¡£æå¼å¤±è´¥:', err) |
| | | uni.showModal({ |
| | | title: 'æç¤º', |
| | | content: `æ æ³æå¼æä»¶: ${err.errMsg || 'æªç¥é误'}`, |
| | | showCancel: false |
| | | }) |
| | | } |
| | | }) |
| | | } else { |
| | | console.error('8. ä¸è½½å¤±è´¥ï¼ç¶æç :', res.statusCode) |
| | | this.$modal.msgError(`ä¸è½½å¤±è´¥ï¼ç¶æç : ${res.statusCode}`) |
| | | } |
| | | }, |
| | | fail: (err) => { |
| | | console.error('7. ä¸è½½å¤±è´¥:', err) |
| | | uni.hideLoading() |
| | | uni.showModal({ |
| | | title: 'ä¸è½½å¤±è´¥', |
| | | content: `é误信æ¯: ${err.errMsg || 'æªç¥é误'}\n\nè¯·æ£æ¥:\n1. ç½ç»è¿æ¥æ¯å¦æ£å¸¸\n2. æä»¶æ¯å¦åå¨\n3. æå¡å¨æ¯å¦å¯è®¿é®`, |
| | | showCancel: false |
| | | }) |
| | | } |
| | | }) |
| | | // #endif |
| | | console.log('=== è°è¯ä¿¡æ¯ç»æ ==='); |
| | | }, |
| | | statusText(status) { |
| | | const map = { 0: 'å¾
å®¡æ ¸', 1: 'å·²éè¿', 2: '已驳å' } |
| | | return map[status] || 'æªç¥' |
| | | }, |
| | | statusClass(status) { |
| | | const map = { 0: 'text-orange', 1: 'text-green', 2: 'text-red' } |
| | | return map[status] || 'text-gray' |
| | | }, |
| | | formatMoney(money) { |
| | | if (money === null || money === undefined) return '0.00' |
| | | return Number(money).toFixed(2) |
| | | }, |
| | | // æ ¼å¼åç³è¯·æ¶é´ |
| | | formatApplyTime(time) { |
| | | if (!time) return '' |
| | | // å°æ¶é´åç¬¦ä¸²æ ¼å¼å为 yyyy-MM-dd HH:mm |
| | | const date = new Date(time) |
| | | const year = date.getFullYear() |
| | | const month = String(date.getMonth() + 1).padStart(2, '0') |
| | | const day = String(date.getDate()).padStart(2, '0') |
| | | const hours = String(date.getHours()).padStart(2, '0') |
| | | const minutes = String(date.getMinutes()).padStart(2, '0') |
| | | return `${year}-${month}-${day} ${hours}:${minutes}` |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | .invoice-list-container { |
| | | height: 100vh; |
| | | display: flex; |
| | | flex-direction: column; |
| | | background-color: #f8f8f8; |
| | | |
| | | .add-btn-box { |
| | | padding: 20rpx; |
| | | background-color: #fff; |
| | | } |
| | | |
| | | // æç´¢æ¡æ ·å¼ |
| | | .search-box { |
| | | padding: 20rpx; |
| | | background-color: #fff; |
| | | border-bottom: 1rpx solid #e5e5e5; |
| | | |
| | | .search-input-wrapper { |
| | | position: relative; |
| | | background: #f5f5f5; |
| | | border-radius: 40rpx; |
| | | padding: 0 80rpx 0 40rpx; |
| | | |
| | | .search-input { |
| | | height: 70rpx; |
| | | line-height: 70rpx; |
| | | font-size: 28rpx; |
| | | } |
| | | |
| | | .search-icon { |
| | | position: absolute; |
| | | right: 40rpx; |
| | | top: 50%; |
| | | transform: translateY(-50%); |
| | | color: #999; |
| | | font-size: 36rpx; |
| | | } |
| | | |
| | | .clear-icon { |
| | | position: absolute; |
| | | right: 80rpx; |
| | | top: 50%; |
| | | transform: translateY(-50%); |
| | | color: #999; |
| | | font-size: 32rpx; |
| | | padding: 10rpx; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // Tabæ ·å¼ |
| | | .tabs-wrapper { |
| | | display: flex; |
| | | background-color: #fff; |
| | | border-bottom: 1rpx solid #e5e5e5; |
| | | |
| | | .tab-item { |
| | | flex: 1; |
| | | text-align: center; |
| | | padding: 25rpx 0; |
| | | font-size: 28rpx; |
| | | color: #666; |
| | | position: relative; |
| | | |
| | | &.active { |
| | | color: #0081ff; |
| | | font-weight: bold; |
| | | |
| | | &::after { |
| | | content: ''; |
| | | position: absolute; |
| | | bottom: 0; |
| | | left: 50%; |
| | | transform: translateX(-50%); |
| | | width: 60rpx; |
| | | height: 4rpx; |
| | | background-color: #0081ff; |
| | | border-radius: 2rpx; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .list-scroll { |
| | | flex: 1; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .invoice-item { |
| | | .border-bottom { |
| | | border-bottom: 1rpx solid #eee; |
| | | } |
| | | |
| | | .info-row { |
| | | display: flex; |
| | | line-height: 1.8; |
| | | font-size: 26rpx; |
| | | |
| | | .label { |
| | | color: #666; |
| | | width: 140rpx; |
| | | } |
| | | .value { |
| | | color: #333; |
| | | flex: 1; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .empty-box { |
| | | padding: 100rpx; |
| | | text-align: center; |
| | | } |
| | | } |
| | | </style> |
| | |
| | | |
| | | <!-- è½¬è¿ - è´¹ç¨ä¿¡æ¯ --> |
| | | <view class="detail-section" v-if="taskDetail.taskType === 'EMERGENCY_TRANSFER' && taskDetail.emergencyInfo"> |
| | | <view class="section-title">è´¹ç¨ä¿¡æ¯</view> |
| | | <view class="section-title"> |
| | | è´¹ç¨ä¿¡æ¯ |
| | | <!-- 已宿䏿ªç³è¯·åç¥¨æ¶æ¾ç¤ºç³è¯·å票æé® --> |
| | | <button |
| | | v-if="canApplyInvoice" |
| | | class="apply-invoice-btn" |
| | | @click="handleApplyInvoice" |
| | | > |
| | | <text class="cuIcon-form"></text> ç³è¯·å票 |
| | | </button> |
| | | </view> |
| | | <view class="info-item" v-if="taskDetail.emergencyInfo.transferDistance"> |
| | | <view class="label">转è¿å
¬éæ°</view> |
| | | <view class="value">{{ taskDetail.emergencyInfo.transferDistance }}å
Ž</view> |
| | |
| | | import { checkVehicleActiveTasks } from '@/api/task' |
| | | import { getPaymentInfo } from '@/api/payment' |
| | | import { getDicts } from '@/api/dict' |
| | | import { checkTaskInvoice } from '@/api/invoice' |
| | | import { formatDateTime } from '@/utils/common' |
| | | import { validateTaskForDepart, validateTaskForSettlement, getTaskVehicleId, checkTaskCanDepart } from '@/utils/taskValidator' |
| | | import AttachmentUpload from './components/AttachmentUpload.vue' |
| | |
| | | forceCompleteForm: { |
| | | actualStartTime: '', |
| | | actualEndTime: '' |
| | | } |
| | | }, |
| | | hasInvoiceApplied: false, // æ¯å¦å·²ç³è¯·å票 |
| | | invoiceStatus: null // åç¥¨ç¶æï¼0-å¾
å®¡æ ¸, 1-å·²éè¿, 2-已驳å |
| | | } |
| | | }, |
| | | computed: { |
| | |
| | | return false |
| | | } |
| | | return ['COMPLETED', 'CANCELLED'].includes(this.taskDetail.taskStatus) |
| | | }, |
| | | |
| | | // æ¯å¦å¯ä»¥ç³è¯·å票 |
| | | canApplyInvoice() { |
| | | // ä»
æ¥æè½¬è¿ä»»å¡ |
| | | if (this.taskDetail?.taskType !== 'EMERGENCY_TRANSFER') return false |
| | | // ä»»å¡å¿
须已宿 |
| | | if (this.taskDetail?.taskStatus !== 'COMPLETED') return false |
| | | // æªç³è¯·è¿åç¥¨ï¼ææ¾è¢«é©³å |
| | | return !this.hasInvoiceApplied || this.invoiceStatus === 2 |
| | | }, |
| | | |
| | | // çææ§è¡äººåè§è²æ ç¾çç±»å |
| | |
| | | this.taskId = options.id |
| | | this.loadTaskDetail() |
| | | this.loadCancelReasonDict() // å è½½åæ¶åå åå
¸ |
| | | // æ£æ¥å票ç³è¯·ç¶æ |
| | | this.checkInvoiceStatus() |
| | | }, |
| | | onShow() { |
| | | // æ¯æ¬¡é¡µé¢æ¾ç¤ºæ¶éæ°å è½½æ°æ®ï¼ç¡®ä¿ä»ç¼è¾é¡µé¢è¿ååè½çå°ææ°æ°æ® |
| | |
| | | } |
| | | |
| | | return null; |
| | | }, |
| | | |
| | | // æ£æ¥å票ç³è¯·ç¶æ |
| | | checkInvoiceStatus() { |
| | | if (!this.taskId) return; |
| | | |
| | | // è°ç¨å端æ¥å£æ£æ¥è¯¥ä»»å¡æ¯å¦å·²ç³è¯·å票 |
| | | checkTaskInvoice(this.taskId).then(response => { |
| | | if (response.code === 200 && response.data) { |
| | | this.hasInvoiceApplied = true; |
| | | this.invoiceStatus = response.data.status; |
| | | } |
| | | }).catch(error => { |
| | | console.error('æ£æ¥å票ç³è¯·ç¶æå¤±è´¥:', error); |
| | | // 忽ç¥é误ï¼é»è®¤æªç³è¯· |
| | | }); |
| | | }, |
| | | |
| | | // ç³è¯·å票 |
| | | handleApplyInvoice() { |
| | | // åå¤ä»»å¡ä¿¡æ¯ |
| | | const taskInfo = { |
| | | taskId: this.taskDetail.taskId, |
| | | taskCode: this.taskDetail.showTaskCode || this.taskDetail.taskCode, |
| | | legacyServiceOrderId: this.taskDetail.emergencyInfo?.legacyServiceOrdId, |
| | | serviceCode: this.taskDetail.emergencyInfo?.serviceCode, |
| | | departure: this.taskDetail.departureAddress, |
| | | destination: this.taskDetail.destinationAddress, |
| | | completionTime: this.formatTime(this.taskDetail.actualEndTime), |
| | | transferPrice: this.paymentInfo?.transferPrice || this.paymentInfo?.totalAmount |
| | | }; |
| | | |
| | | // å°ä»»å¡ä¿¡æ¯åºåå为 URL åæ° |
| | | const taskInfoParam = encodeURIComponent(JSON.stringify(taskInfo)); |
| | | |
| | | // 跳转å°å票ç³è¯·é¡µé¢ï¼ä¼ éä»»å¡ä¿¡æ¯ |
| | | uni.navigateTo({ |
| | | url: `/pages/mine/invoice/apply?taskInfo=${taskInfoParam}` |
| | | }); |
| | | }, |
| | | |
| | | // æ´æ°ä»»å¡ç¶æ |
| | |
| | | margin-left: 10rpx; |
| | | vertical-align: middle; |
| | | } |
| | | |
| | | .apply-invoice-btn { |
| | | padding: 8rpx 16rpx; |
| | | font-size: 24rpx; |
| | | color: #fff; |
| | | background-color: #34C759; |
| | | border: none; |
| | | border-radius: 6rpx; |
| | | margin-left: 20rpx; |
| | | } |
| | | |
| | | .apply-invoice-btn::after { |
| | | border: none; |
| | | } |
| | | |
| | | // åæ¶åå å¯¹è¯æ¡æ ·å¼ |
| | | .cancel-dialog { |
| New file |
| | |
| | | package com.ruoyi.web.controller.system; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.HashMap; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.security.access.prepost.PreAuthorize; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | | import org.springframework.web.bind.annotation.PostMapping; |
| | | import org.springframework.web.bind.annotation.PutMapping; |
| | | import org.springframework.web.bind.annotation.DeleteMapping; |
| | | import org.springframework.web.bind.annotation.PathVariable; |
| | | import org.springframework.web.bind.annotation.RequestBody; |
| | | import org.springframework.web.bind.annotation.RequestParam; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | import com.ruoyi.common.annotation.Log; |
| | | import com.ruoyi.common.core.controller.BaseController; |
| | | import com.ruoyi.common.core.domain.AjaxResult; |
| | | import com.ruoyi.common.core.domain.entity.SysDept; |
| | | import com.ruoyi.system.service.ISysDeptService; |
| | | import com.ruoyi.common.enums.BusinessType; |
| | | import com.ruoyi.system.domain.SysInvoice; |
| | | import com.ruoyi.system.service.ISysInvoiceService; |
| | | import com.ruoyi.common.utils.poi.ExcelUtil; |
| | | import com.ruoyi.common.core.page.TableDataInfo; |
| | | import com.ruoyi.common.utils.SecurityUtils; |
| | | |
| | | /** |
| | | * å票ç³è¯·Controller |
| | | * |
| | | * @author ruoyi |
| | | * @date 2026-02-02 |
| | | */ |
| | | @RestController |
| | | @RequestMapping("/system/invoice") |
| | | public class SysInvoiceController extends BaseController |
| | | { |
| | | @Autowired |
| | | private ISysInvoiceService sysInvoiceService; |
| | | |
| | | @Autowired |
| | | private ISysDeptService sysDeptService; |
| | | |
| | | /** |
| | | * æ¥è¯¢å票ç³è¯·å表 |
| | | */ |
| | | @PreAuthorize("@ss.hasPermi('system:invoice:list')") |
| | | @GetMapping("/list") |
| | | public TableDataInfo list(SysInvoice sysInvoice) |
| | | { |
| | | startPage(); |
| | | List<SysInvoice> list = sysInvoiceService.selectSysInvoiceList(sysInvoice); |
| | | return getDataTable(list); |
| | | } |
| | | |
| | | /** |
| | | * App端æ¥è¯¢æçå票ç³è¯·å表 |
| | | */ |
| | | @GetMapping("/myList") |
| | | public TableDataInfo myList(SysInvoice sysInvoice) |
| | | { |
| | | sysInvoice.setApplyUserId(SecurityUtils.getUserId()); |
| | | startPage(); |
| | | List<Map<String, Object>> list = sysInvoiceService.selectMyInvoiceList(sysInvoice); |
| | | return getDataTable(list); |
| | | } |
| | | |
| | | /** |
| | | * 导åºå票ç³è¯·å表 |
| | | */ |
| | | @PreAuthorize("@ss.hasPermi('system:invoice:export')") |
| | | @Log(title = "å票ç³è¯·", businessType = BusinessType.EXPORT) |
| | | @PostMapping("/export") |
| | | public void export(HttpServletResponse response, SysInvoice sysInvoice) |
| | | { |
| | | List<SysInvoice> list = sysInvoiceService.selectSysInvoiceList(sysInvoice); |
| | | ExcelUtil<SysInvoice> util = new ExcelUtil<SysInvoice>(SysInvoice.class); |
| | | util.exportExcel(response, list, "å票ç³è¯·æ°æ®"); |
| | | } |
| | | |
| | | /** |
| | | * è·åå票ç³è¯·è¯¦ç»ä¿¡æ¯ |
| | | */ |
| | | @PreAuthorize("@ss.hasAnyPermi('system:invoice:query, system:invoice:edit')") |
| | | @GetMapping(value = "/{invoiceId}") |
| | | public AjaxResult getInfo(@PathVariable("invoiceId") Long invoiceId) |
| | | { |
| | | return AjaxResult.success(sysInvoiceService.selectSysInvoiceByInvoiceId(invoiceId)); |
| | | } |
| | | |
| | | /** |
| | | * æ°å¢å票ç³è¯· |
| | | */ |
| | | @Log(title = "å票ç³è¯·", businessType = BusinessType.INSERT) |
| | | @PostMapping |
| | | public AjaxResult add(@RequestBody SysInvoice sysInvoice) |
| | | { |
| | | sysInvoice.setApplyUserId(SecurityUtils.getUserId()); |
| | | return toAjax(sysInvoiceService.insertSysInvoice(sysInvoice)); |
| | | } |
| | | |
| | | /** |
| | | * ä¿®æ¹å票ç³è¯· |
| | | */ |
| | | @PreAuthorize("@ss.hasPermi('system:invoice:edit')") |
| | | @Log(title = "å票ç³è¯·", businessType = BusinessType.UPDATE) |
| | | @PutMapping |
| | | public AjaxResult edit(@RequestBody SysInvoice sysInvoice) |
| | | { |
| | | return toAjax(sysInvoiceService.updateSysInvoice(sysInvoice)); |
| | | } |
| | | |
| | | /** |
| | | * å é¤å票ç³è¯· |
| | | */ |
| | | @PreAuthorize("@ss.hasPermi('system:invoice:remove')") |
| | | @Log(title = "å票ç³è¯·", businessType = BusinessType.DELETE) |
| | | @DeleteMapping("/{invoiceIds}") |
| | | public AjaxResult remove(@PathVariable Long[] invoiceIds) |
| | | { |
| | | return toAjax(sysInvoiceService.deleteSysInvoiceByInvoiceIds(invoiceIds)); |
| | | } |
| | | |
| | | /** |
| | | * æå¨è§¦å忥 (ä»
é管çå) |
| | | */ |
| | | @PreAuthorize("@ss.hasRole('admin')") |
| | | @GetMapping("/syncStatus") |
| | | public AjaxResult syncStatus() { |
| | | sysInvoiceService.syncStatusFromLegacySystem(); |
| | | return AjaxResult.success("忥任å¡å·²è§¦å"); |
| | | } |
| | | |
| | | /** |
| | | * 忥å个åç¥¨å°æ§ç³»ç» |
| | | * @param invoiceId å票ID |
| | | */ |
| | | @PreAuthorize("@ss.hasPermi('system:invoice:edit')") |
| | | @Log(title = "å票ç³è¯·", businessType = BusinessType.UPDATE) |
| | | @PostMapping("/syncToLegacy/{invoiceId}") |
| | | public AjaxResult syncToLegacy(@PathVariable Long invoiceId) { |
| | | SysInvoice invoice = sysInvoiceService.selectSysInvoiceByInvoiceId(invoiceId); |
| | | if (invoice == null) { |
| | | return AjaxResult.error("å票ä¸åå¨"); |
| | | } |
| | | if (invoice.getStatus() != 1) { |
| | | return AjaxResult.error("åªæå®¡æ ¸éè¿çå票æè½åæ¥"); |
| | | } |
| | | |
| | | try { |
| | | sysInvoiceService.syncToLegacySystem(invoice.getInvoiceId()); |
| | | return AjaxResult.success("忥æå"); |
| | | } catch (Exception e) { |
| | | return AjaxResult.error("åæ¥å¤±è´¥: " + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * æ£æ¥ä»»å¡æ¯å¦å·²ç³è¯·å票 |
| | | * @param taskId ä»»å¡ID |
| | | */ |
| | | @GetMapping("/checkTaskInvoice/{taskId}") |
| | | public AjaxResult checkTaskInvoice(@PathVariable Long taskId) { |
| | | SysInvoice query = new SysInvoice(); |
| | | query.setServiceOrderId(taskId); |
| | | List<SysInvoice> list = sysInvoiceService.selectSysInvoiceList(query); |
| | | |
| | | if (list != null && !list.isEmpty()) { |
| | | // åªè¿åææ°ç䏿¡è®°å½ |
| | | SysInvoice invoice = list.get(0); |
| | | Map<String, Object> result = new HashMap<>(); |
| | | result.put("hasApplied", true); |
| | | result.put("status", invoice.getStatus()); |
| | | result.put("invoiceId", invoice.getInvoiceId()); |
| | | return AjaxResult.success(result); |
| | | } |
| | | |
| | | return AjaxResult.success(null); |
| | | } |
| | | |
| | | /** |
| | | * è·åå¯ç³è¯·å票çä»»å¡å表 |
| | | * @param searchKeyword æç´¢å
³é®è¯ï¼æ¯ætaskCodeãserviceCodeãlegacyServiceOrdNoï¼ |
| | | * @param serviceOrdClass åå
¬å¸ä»£ç ï¼å¯éï¼é»è®¤ä½¿ç¨ç¨æ·æå±åå
¬å¸ï¼ |
| | | */ |
| | | @GetMapping("/selectableTasks") |
| | | public AjaxResult getSelectableTasks( |
| | | @RequestParam(required = false) String searchKeyword, |
| | | @RequestParam(required = false) String serviceOrdClass |
| | | ) |
| | | { |
| | | Long userId = SecurityUtils.getUserId(); |
| | | // å»é¤æç´¢å
³é®è¯çç©ºæ ¼ |
| | | if (StringUtils.isNotBlank(searchKeyword)) { |
| | | searchKeyword = searchKeyword.trim(); |
| | | } |
| | | |
| | | // å¦ææªæå®åå
¬å¸ï¼èªå¨è·åç¨æ·æå±åå
¬å¸ |
| | | if (StringUtils.isBlank(serviceOrdClass)) { |
| | | try { |
| | | Long deptId = SecurityUtils.getLoginUser().getUser().getDeptId(); |
| | | if (deptId != null) { |
| | | SysDept dept = sysDeptService.selectDeptById(deptId); |
| | | if (dept != null) { |
| | | // 夿æ¯å¦ä¸ºåå
¬å¸ï¼parent_id = 100ï¼ |
| | | if (dept.getParentId() != null && dept.getParentId() == 100) { |
| | | serviceOrdClass = dept.getServiceOrderClass(); |
| | | } else if (dept.getAncestors() != null) { |
| | | // ä» ancestors è§£æåå
¬å¸ID |
| | | String[] ancestorIds = dept.getAncestors().split(","); |
| | | for (int i = 0; i < ancestorIds.length; i++) { |
| | | if ("100".equals(ancestorIds[i]) && i + 1 < ancestorIds.length) { |
| | | Long branchId = Long.parseLong(ancestorIds[i + 1]); |
| | | SysDept branchDept = sysDeptService.selectDeptById(branchId); |
| | | if (branchDept != null) { |
| | | serviceOrdClass = branchDept.getServiceOrderClass(); |
| | | } |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } catch (Exception e) { |
| | | // è·å失败ä¸å½±åæ¥è¯¢ï¼åªæ¯ä¸è¿æ»¤åå
¬å¸ |
| | | } |
| | | } |
| | | |
| | | return AjaxResult.success(sysInvoiceService.selectSelectableTasks(userId, searchKeyword, serviceOrdClass)); |
| | | } |
| | | } |
| | |
| | | |
| | | @Autowired |
| | | private ITaskDispatchSyncService taskDispatchSyncService; |
| | | |
| | | @Autowired |
| | | private ITaskStatusPushService taskStatusPushService; |
| | | |
| | | /** |
| | | * æ¥è¯¢ä»»å¡ç®¡çå表ï¼åå°ç®¡çç«¯ï¼ |
| | |
| | | return error("忥å¼å¸¸: " + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * æå¨åæ¥ä»»å¡ç¶æå°æ§ç³»ç» |
| | | * å½ä»»å¡ç¶æåæ´åç±äºç½ç»çåå æªåæ¥å°æ§ç³»ç»æ¶ï¼å¯ä»¥éè¿æ¤æ¥å£æå¨è§¦å忥 |
| | | */ |
| | | // @PreAuthorize("@ss.hasPermi('task:general:edit')") |
| | | @Log(title = "æå¨åæ¥ä»»å¡ç¶æ", businessType = BusinessType.UPDATE) |
| | | @PostMapping("/syncTaskStatus/{taskId}") |
| | | public AjaxResult syncTaskStatus(@PathVariable Long taskId) { |
| | | try { |
| | | // æ¥è¯¢ä»»å¡ä¿¡æ¯ |
| | | SysTask task = sysTaskService.selectSysTaskByTaskId(taskId); |
| | | if (task == null) { |
| | | return error("ä»»å¡ä¸åå¨"); |
| | | } |
| | | |
| | | // åªæ¯ææ¥æè½¬è¿ä»»å¡ |
| | | if (!"EMERGENCY_TRANSFER".equals(task.getTaskType())) { |
| | | return error("åªææ¥æè½¬è¿ä»»å¡æè½åæ¥å°æ§ç³»ç»"); |
| | | } |
| | | |
| | | // æ¥è¯¢æ¥æè½¬è¿æ©å±ä¿¡æ¯ |
| | | SysTaskEmergency emergency = sysTaskEmergencyService.selectSysTaskEmergencyByTaskId(taskId); |
| | | if (emergency == null) { |
| | | return error("æ¥æè½¬è¿æ©å±ä¿¡æ¯ä¸åå¨"); |
| | | } |
| | | |
| | | // å¿
é¡»å
æè°åº¦å |
| | | if (emergency.getLegacyDispatchOrdId() == null || emergency.getLegacyDispatchOrdId() <= 0) { |
| | | return error("请å
忥è°åº¦åï¼ä»»å¡ç¶æä¿¡æ¯åæ¥å°æ§ç³»ç»çè°åº¦åä¸"); |
| | | } |
| | | |
| | | // è°ç¨ç¶æåæ¥æå¡ |
| | | boolean success = taskStatusPushService.pushTaskStatusToLegacy(taskId); |
| | | |
| | | if (success) { |
| | | return success("ä»»å¡ç¶æåæ¥æå"); |
| | | } else { |
| | | return error("ä»»å¡ç¶æåæ¥å¤±è´¥ï¼è¯·æ¥çæ¥å¿è·å详ç»ä¿¡æ¯"); |
| | | } |
| | | |
| | | } catch (Exception e) { |
| | | logger.error("æå¨åæ¥ä»»å¡ç¶æå¼å¸¸ï¼taskId: {}", taskId, e); |
| | | return error("忥å¼å¸¸: " + e.getMessage()); |
| | | } |
| | | } |
| | | } |
| | |
| | | basename: i18n/messages |
| | | profiles: |
| | | # ç¯å¢ dev|test|prod |
| | | active: dev |
| | | active: prod |
| | | # æä»¶ä¸ä¼ |
| | | servlet: |
| | | multipart: |
| New file |
| | |
| | | package com.ruoyi.quartz.task; |
| | | |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Component; |
| | | import com.ruoyi.system.service.ISysInvoiceService; |
| | | |
| | | /** |
| | | * åç¥¨åæ¥å®æ¶ä»»å¡ - 忥æ§ç³»ç»å票信æ¯å°æ°ç³»ç» |
| | | * |
| | | * @author ruoyi |
| | | */ |
| | | @Component("sysInvoiceSyncTask") |
| | | public class SysInvoiceSyncTask |
| | | { |
| | | @Autowired |
| | | private ISysInvoiceService sysInvoiceService; |
| | | |
| | | |
| | | /** |
| | | * 忥æ§ç³»ç»åç¥¨ç¶æ |
| | | */ |
| | | public void syncStatus() |
| | | { |
| | | sysInvoiceService.syncStatusFromLegacySystem(); |
| | | } |
| | | } |
| New file |
| | |
| | | package com.ruoyi.quartz.task; |
| | | |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Component; |
| | | import com.ruoyi.system.service.ISysInvoiceService; |
| | | |
| | | /** |
| | | * åç¥¨åæ¥å®æ¶ä»»å¡ |
| | | * |
| | | * @author ruoyi |
| | | */ |
| | | @Component("sysInvoiceTask") |
| | | public class SysInvoiceTask |
| | | { |
| | | @Autowired |
| | | private ISysInvoiceService sysInvoiceService; |
| | | |
| | | /** |
| | | * 忥æ§ç³»ç»åç¥¨ç¶æ |
| | | */ |
| | | public void syncStatus() |
| | | { |
| | | sysInvoiceService.syncStatusFromLegacySystem(); |
| | | } |
| | | |
| | | /** |
| | | * 仿§ç³»ç»åæ¥å票信æ¯å°æ°ç³»ç» |
| | | */ |
| | | public void syncInvoiceFromLegacySystem() |
| | | { |
| | | // sysInvoiceService.syncInvoiceFromLegacySystem(); |
| | | } |
| | | } |
| New file |
| | |
| | | package com.ruoyi.system.domain; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.util.Date; |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import com.ruoyi.common.annotation.Excel; |
| | | import com.ruoyi.common.core.domain.BaseEntity; |
| | | import org.apache.commons.lang3.builder.ToStringBuilder; |
| | | import org.apache.commons.lang3.builder.ToStringStyle; |
| | | |
| | | /** |
| | | * å票ç³è¯·å¯¹è±¡ sys_invoice |
| | | * |
| | | * @author ruoyi |
| | | * @date 2026-02-02 |
| | | */ |
| | | public class SysInvoice extends BaseEntity |
| | | { |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** å票ID */ |
| | | private Long invoiceId; |
| | | |
| | | /** æå¡åå·(æ°ç³»ç»ID) */ |
| | | @Excel(name = "æå¡åå·(æ°)") |
| | | private Long serviceOrderId; |
| | | |
| | | /** æ§ç³»ç»æå¡åå· */ |
| | | @Excel(name = "æå¡åå·(æ§)") |
| | | private Long legacyServiceOrderId; |
| | | |
| | | /** å¼ç¥¨ç±»å(1-个人, 2-ä¼ä¸) */ |
| | | @Excel(name = "å¼ç¥¨ç±»å", readConverterExp = "1=个人,2=ä¼ä¸") |
| | | private Integer invoiceType; |
| | | |
| | | /** å票æ¬å¤´ */ |
| | | @Excel(name = "å票æ¬å¤´") |
| | | private String invoiceName; |
| | | |
| | | /** å票éé¢ */ |
| | | @Excel(name = "å票éé¢") |
| | | private BigDecimal invoiceMoney; |
| | | |
| | | /** åç¥¨å¤æ³¨ */ |
| | | @Excel(name = "åç¥¨å¤æ³¨") |
| | | private String invoiceRemarks; |
| | | |
| | | /** ä¼ä¸æ³¨åå°å */ |
| | | @Excel(name = "ä¼ä¸æ³¨åå°å") |
| | | private String companyAddress; |
| | | |
| | | /** ä¼ä¸å¼æ·é¶è¡ */ |
| | | @Excel(name = "ä¼ä¸å¼æ·é¶è¡") |
| | | private String companyBank; |
| | | |
| | | /** ä¼ä¸é¶è¡å¸å· */ |
| | | @Excel(name = "ä¼ä¸é¶è¡å¸å·") |
| | | private String companyBankNo; |
| | | |
| | | /** é®ç¼ */ |
| | | @Excel(name = "é®ç¼") |
| | | private String zipCode; |
| | | |
| | | /** é®å¯å°å */ |
| | | @Excel(name = "é®å¯å°å") |
| | | private String mailAddress; |
| | | |
| | | /** è系人 */ |
| | | @Excel(name = "è系人") |
| | | private String contactName; |
| | | |
| | | /** èç³»çµè¯ */ |
| | | @Excel(name = "èç³»çµè¯") |
| | | private String contactPhone; |
| | | |
| | | /** èç³»é®ç®± */ |
| | | @Excel(name = "èç³»é®ç®±") |
| | | private String contactEmail; |
| | | |
| | | /** ç³è¯·ç¶æ(0-å¾
å®¡æ ¸, 1-å·²éè¿, 2-已驳å) */ |
| | | @Excel(name = "ç³è¯·ç¶æ", readConverterExp = "0=å¾
å®¡æ ¸,1=å·²éè¿,2=已驳å") |
| | | private Integer status; |
| | | |
| | | /** å票ç¼å· */ |
| | | @Excel(name = "å票ç¼å·") |
| | | private String invoiceNo; |
| | | |
| | | /** åç¥¨é¾æ¥ */ |
| | | @Excel(name = "åç¥¨é¾æ¥") |
| | | private String invoiceUrl; |
| | | |
| | | /** ç³è¯·äººID */ |
| | | private Long applyUserId; |
| | | |
| | | /** ç³è¯·æ¶é´ */ |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | @Excel(name = "ç³è¯·æ¶é´", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") |
| | | private Date applyTime; |
| | | |
| | | /** å®¡æ ¸äººID */ |
| | | private Long auditUserId; |
| | | |
| | | /** å®¡æ ¸æ¶é´ */ |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | @Excel(name = "å®¡æ ¸æ¶é´", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") |
| | | private Date auditTime; |
| | | |
| | | /** å®¡æ ¸å¤æ³¨ */ |
| | | private String auditRemarks; |
| | | |
| | | /** åæ¥ç¶æ(0-æªåæ¥, 1-已忥, 2-失败) */ |
| | | private Integer syncStatus; |
| | | |
| | | /** æ§ç³»ç»å票ID */ |
| | | private Integer legacyInvoiceId; |
| | | |
| | | /** æå¡åå·ï¼æ ¼å¼åï¼å¦GZ20260202-001ï¼- ä»
ç¨äºæ¥è¯¢è¿å */ |
| | | private String serviceCode; |
| | | |
| | | public void setInvoiceId(Long invoiceId) |
| | | { |
| | | this.invoiceId = invoiceId; |
| | | } |
| | | |
| | | public Long getInvoiceId() |
| | | { |
| | | return invoiceId; |
| | | } |
| | | public void setServiceOrderId(Long serviceOrderId) |
| | | { |
| | | this.serviceOrderId = serviceOrderId; |
| | | } |
| | | |
| | | public Long getServiceOrderId() |
| | | { |
| | | return serviceOrderId; |
| | | } |
| | | public void setLegacyServiceOrderId(Long legacyServiceOrderId) |
| | | { |
| | | this.legacyServiceOrderId = legacyServiceOrderId; |
| | | } |
| | | |
| | | public Long getLegacyServiceOrderId() |
| | | { |
| | | return legacyServiceOrderId; |
| | | } |
| | | public void setInvoiceType(Integer invoiceType) |
| | | { |
| | | this.invoiceType = invoiceType; |
| | | } |
| | | |
| | | public Integer getInvoiceType() |
| | | { |
| | | return invoiceType; |
| | | } |
| | | public void setInvoiceName(String invoiceName) |
| | | { |
| | | this.invoiceName = invoiceName; |
| | | } |
| | | |
| | | public String getInvoiceName() |
| | | { |
| | | return invoiceName; |
| | | } |
| | | public void setInvoiceMoney(BigDecimal invoiceMoney) |
| | | { |
| | | this.invoiceMoney = invoiceMoney; |
| | | } |
| | | |
| | | public BigDecimal getInvoiceMoney() |
| | | { |
| | | return invoiceMoney; |
| | | } |
| | | public void setInvoiceRemarks(String invoiceRemarks) |
| | | { |
| | | this.invoiceRemarks = invoiceRemarks; |
| | | } |
| | | |
| | | public String getInvoiceRemarks() |
| | | { |
| | | return invoiceRemarks; |
| | | } |
| | | public void setCompanyAddress(String companyAddress) |
| | | { |
| | | this.companyAddress = companyAddress; |
| | | } |
| | | |
| | | public String getCompanyAddress() |
| | | { |
| | | return companyAddress; |
| | | } |
| | | public void setCompanyBank(String companyBank) |
| | | { |
| | | this.companyBank = companyBank; |
| | | } |
| | | |
| | | public String getCompanyBank() |
| | | { |
| | | return companyBank; |
| | | } |
| | | public void setCompanyBankNo(String companyBankNo) |
| | | { |
| | | this.companyBankNo = companyBankNo; |
| | | } |
| | | |
| | | public String getCompanyBankNo() |
| | | { |
| | | return companyBankNo; |
| | | } |
| | | public void setZipCode(String zipCode) |
| | | { |
| | | this.zipCode = zipCode; |
| | | } |
| | | |
| | | public String getZipCode() |
| | | { |
| | | return zipCode; |
| | | } |
| | | public void setMailAddress(String mailAddress) |
| | | { |
| | | this.mailAddress = mailAddress; |
| | | } |
| | | |
| | | public String getMailAddress() |
| | | { |
| | | return mailAddress; |
| | | } |
| | | public void setContactName(String contactName) |
| | | { |
| | | this.contactName = contactName; |
| | | } |
| | | |
| | | public String getContactName() |
| | | { |
| | | return contactName; |
| | | } |
| | | public void setContactPhone(String contactPhone) |
| | | { |
| | | this.contactPhone = contactPhone; |
| | | } |
| | | |
| | | public String getContactPhone() |
| | | { |
| | | return contactPhone; |
| | | } |
| | | public void setContactEmail(String contactEmail) |
| | | { |
| | | this.contactEmail = contactEmail; |
| | | } |
| | | |
| | | public String getContactEmail() |
| | | { |
| | | return contactEmail; |
| | | } |
| | | public void setStatus(Integer status) |
| | | { |
| | | this.status = status; |
| | | } |
| | | |
| | | public Integer getStatus() |
| | | { |
| | | return status; |
| | | } |
| | | public void setInvoiceNo(String invoiceNo) |
| | | { |
| | | this.invoiceNo = invoiceNo; |
| | | } |
| | | |
| | | public String getInvoiceNo() |
| | | { |
| | | return invoiceNo; |
| | | } |
| | | public void setInvoiceUrl(String invoiceUrl) |
| | | { |
| | | this.invoiceUrl = invoiceUrl; |
| | | } |
| | | |
| | | public String getInvoiceUrl() |
| | | { |
| | | return invoiceUrl; |
| | | } |
| | | public void setApplyUserId(Long applyUserId) |
| | | { |
| | | this.applyUserId = applyUserId; |
| | | } |
| | | |
| | | public Long getApplyUserId() |
| | | { |
| | | return applyUserId; |
| | | } |
| | | public void setApplyTime(Date applyTime) |
| | | { |
| | | this.applyTime = applyTime; |
| | | } |
| | | |
| | | public Date getApplyTime() |
| | | { |
| | | return applyTime; |
| | | } |
| | | public void setAuditUserId(Long auditUserId) |
| | | { |
| | | this.auditUserId = auditUserId; |
| | | } |
| | | |
| | | public Long getAuditUserId() |
| | | { |
| | | return auditUserId; |
| | | } |
| | | public void setAuditTime(Date auditTime) |
| | | { |
| | | this.auditTime = auditTime; |
| | | } |
| | | |
| | | public Date getAuditTime() |
| | | { |
| | | return auditTime; |
| | | } |
| | | public void setAuditRemarks(String auditRemarks) |
| | | { |
| | | this.auditRemarks = auditRemarks; |
| | | } |
| | | |
| | | public String getAuditRemarks() |
| | | { |
| | | return auditRemarks; |
| | | } |
| | | |
| | | public Integer getSyncStatus() { |
| | | return syncStatus; |
| | | } |
| | | |
| | | public void setSyncStatus(Integer syncStatus) { |
| | | this.syncStatus = syncStatus; |
| | | } |
| | | |
| | | public Integer getLegacyInvoiceId() { |
| | | return legacyInvoiceId; |
| | | } |
| | | |
| | | public void setLegacyInvoiceId(Integer legacyInvoiceId) { |
| | | this.legacyInvoiceId = legacyInvoiceId; |
| | | } |
| | | |
| | | public String getServiceCode() { |
| | | return serviceCode; |
| | | } |
| | | |
| | | public void setServiceCode(String serviceCode) { |
| | | this.serviceCode = serviceCode; |
| | | } |
| | | |
| | | @Override |
| | | public String toString() { |
| | | return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) |
| | | .append("invoiceId", getInvoiceId()) |
| | | .append("serviceOrderId", getServiceOrderId()) |
| | | .append("legacyServiceOrderId", getLegacyServiceOrderId()) |
| | | .append("invoiceType", getInvoiceType()) |
| | | .append("invoiceName", getInvoiceName()) |
| | | .append("invoiceMoney", getInvoiceMoney()) |
| | | .append("invoiceRemarks", getInvoiceRemarks()) |
| | | .append("companyAddress", getCompanyAddress()) |
| | | .append("companyBank", getCompanyBank()) |
| | | .append("companyBankNo", getCompanyBankNo()) |
| | | .append("zipCode", getZipCode()) |
| | | .append("mailAddress", getMailAddress()) |
| | | .append("contactName", getContactName()) |
| | | .append("contactPhone", getContactPhone()) |
| | | .append("contactEmail", getContactEmail()) |
| | | .append("status", getStatus()) |
| | | .append("invoiceNo", getInvoiceNo()) |
| | | .append("invoiceUrl", getInvoiceUrl()) |
| | | .append("applyUserId", getApplyUserId()) |
| | | .append("applyTime", getApplyTime()) |
| | | .append("auditUserId", getAuditUserId()) |
| | | .append("auditTime", getAuditTime()) |
| | | .append("auditRemarks", getAuditRemarks()) |
| | | .toString(); |
| | | } |
| | | } |
| | |
| | | /** åæ¶æ¶é´ */ |
| | | private java.util.Date cancelTime; |
| | | |
| | | /** |
| | | * æå¡åç¼å· |
| | | * @return |
| | | */ |
| | | public String getServiceCode(){ |
| | | if(this.legacyServiceOrdClass!=null && this.legacyServiceNsTime!=null && this.legacyServiceOrdNo!=null) { |
| | | String nstime = DateUtils.parseDateToStr(DateUtils.YYYYMMDD, this.legacyServiceNsTime); |
| | |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * è°åº¦åç¼å· |
| | | * @return |
| | | */ |
| | | public String getDispatchCode(){ |
| | | if(this.legacyDispatchOrdClass!=null && this.legacyDispatchNsTime!=null && this.legacyDispatchOrdNo!=null) { |
| | | String nstime = DateUtils.parseDateToStr(DateUtils.YYYYMMDD, this.legacyDispatchNsTime); |
| New file |
| | |
| | | package com.ruoyi.system.mapper; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import com.ruoyi.common.annotation.DataSource; |
| | | import com.ruoyi.common.enums.DataSourceType; |
| | | |
| | | /** |
| | | * æ§ç³»ç»åç¥¨æ°æ®Mapperæ¥å£ (SQL Server) |
| | | * |
| | | * @author ruoyi |
| | | * @date 2026-02-02 |
| | | */ |
| | | @DataSource(DataSourceType.SQLSERVER) |
| | | public interface LegacyInvoiceMapper |
| | | { |
| | | /** |
| | | * æå
¥å票ç³è¯·å°æ§ç³»ç» |
| | | * @param params |
| | | * @return |
| | | */ |
| | | public int insertLegacyInvoice(Map<String, Object> params); |
| | | |
| | | /** |
| | | * æ¥è¯¢æ§ç³»ç»åç¥¨ç¶æååçæ°æ® |
| | | * @param lastSyncTime |
| | | * @return |
| | | */ |
| | | public List<Map<String, Object>> selectUpdatedInvoices(String lastSyncTime); |
| | | |
| | | /** |
| | | * æ ¹æ®æå¡åIDæ¥è¯¢æ§ç³»ç»åç¥¨ä¿¡æ¯ |
| | | * @param serviceOrderId |
| | | * @return |
| | | */ |
| | | public List<Map<String, Object>> selectLegacyInvoiceByServiceOrderId(Long serviceOrderId); |
| | | } |
| New file |
| | |
| | | package com.ruoyi.system.mapper; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import org.apache.ibatis.annotations.Param; |
| | | import com.ruoyi.system.domain.SysInvoice; |
| | | |
| | | /** |
| | | * å票ç³è¯·Mapperæ¥å£ |
| | | * |
| | | * @author ruoyi |
| | | * @date 2026-02-02 |
| | | */ |
| | | public interface SysInvoiceMapper |
| | | { |
| | | /** |
| | | * æ¥è¯¢å票ç³è¯· |
| | | * |
| | | * @param invoiceId å票ç³è¯·ä¸»é® |
| | | * @return å票ç³è¯· |
| | | */ |
| | | public SysInvoice selectSysInvoiceByInvoiceId(Long invoiceId); |
| | | |
| | | /** |
| | | * æ¥è¯¢å票ç³è¯·å表 |
| | | * |
| | | * @param sysInvoice å票ç³è¯· |
| | | * @return å票ç³è¯·éå |
| | | */ |
| | | public List<SysInvoice> selectSysInvoiceList(SysInvoice sysInvoice); |
| | | |
| | | /** |
| | | * æ¥è¯¢æçå票ç³è¯·å表ï¼App端ï¼è¿åMapå
å«serviceCodeï¼ |
| | | * |
| | | * @param sysInvoice å票ç³è¯· |
| | | * @return å票ç³è¯·éå |
| | | */ |
| | | public List<Map<String, Object>> selectMyInvoiceList(SysInvoice sysInvoice); |
| | | |
| | | /** |
| | | * æ°å¢å票ç³è¯· |
| | | * |
| | | * @param sysInvoice å票ç³è¯· |
| | | * @return ç»æ |
| | | */ |
| | | public int insertSysInvoice(SysInvoice sysInvoice); |
| | | |
| | | /** |
| | | * ä¿®æ¹å票ç³è¯· |
| | | * |
| | | * @param sysInvoice å票ç³è¯· |
| | | * @return ç»æ |
| | | */ |
| | | public int updateSysInvoice(SysInvoice sysInvoice); |
| | | |
| | | /** |
| | | * å é¤å票ç³è¯· |
| | | * |
| | | * @param invoiceId å票ç³è¯·ä¸»é® |
| | | * @return ç»æ |
| | | */ |
| | | public int deleteSysInvoiceByInvoiceId(Long invoiceId); |
| | | |
| | | /** |
| | | * æ¹éå é¤å票ç³è¯· |
| | | * |
| | | * @param invoiceIds éè¦å é¤çæ°æ®ä¸»é®éå |
| | | * @return ç»æ |
| | | */ |
| | | public int deleteSysInvoiceByInvoiceIds(Long[] invoiceIds); |
| | | |
| | | /** |
| | | * æ ¹æ®æ§ç³»ç»å票IDæ¥è¯¢ |
| | | * @param legacyInvoiceId |
| | | * @return |
| | | */ |
| | | public SysInvoice selectSysInvoiceByLegacyId(Integer legacyInvoiceId); |
| | | |
| | | /** |
| | | * æ¥è¯¢å¯ç³è¯·å票çä»»å¡å表 |
| | | * @param userId ç¨æ·ID |
| | | * @param searchKeyword æç´¢å
³é®è¯ |
| | | * @param serviceOrdClass åå
¬å¸ä»£ç |
| | | * @return |
| | | */ |
| | | public List<Map<String, Object>> selectSelectableTasks( |
| | | @Param("userId") Long userId, |
| | | @Param("searchKeyword") String searchKeyword, |
| | | @Param("serviceOrdClass") String serviceOrdClass |
| | | ); |
| | | } |
| New file |
| | |
| | | package com.ruoyi.system.service; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import com.ruoyi.system.domain.SysInvoice; |
| | | |
| | | /** |
| | | * å票ç³è¯·Serviceæ¥å£ |
| | | * |
| | | * @author ruoyi |
| | | * @date 2026-02-02 |
| | | */ |
| | | public interface ISysInvoiceService |
| | | { |
| | | /** |
| | | * æ¥è¯¢å票ç³è¯· |
| | | * |
| | | * @param invoiceId å票ç³è¯·ä¸»é® |
| | | * @return å票ç³è¯· |
| | | */ |
| | | public SysInvoice selectSysInvoiceByInvoiceId(Long invoiceId); |
| | | |
| | | /** |
| | | * æ¥è¯¢å票ç³è¯·å表 |
| | | * |
| | | * @param sysInvoice å票ç³è¯· |
| | | * @return å票ç³è¯·éå |
| | | */ |
| | | public List<SysInvoice> selectSysInvoiceList(SysInvoice sysInvoice); |
| | | |
| | | /** |
| | | * æ¥è¯¢æçå票ç³è¯·å表ï¼App端ï¼è¿åMapå
å«serviceCodeï¼ |
| | | * |
| | | * @param sysInvoice å票ç³è¯· |
| | | * @return å票ç³è¯·éå |
| | | */ |
| | | public List<Map<String, Object>> selectMyInvoiceList(SysInvoice sysInvoice); |
| | | |
| | | /** |
| | | * æ°å¢å票ç³è¯· |
| | | * |
| | | * @param sysInvoice å票ç³è¯· |
| | | * @return ç»æ |
| | | */ |
| | | public int insertSysInvoice(SysInvoice sysInvoice); |
| | | |
| | | /** |
| | | * ä¿®æ¹å票ç³è¯· |
| | | * |
| | | * @param sysInvoice å票ç³è¯· |
| | | * @return ç»æ |
| | | */ |
| | | public int updateSysInvoice(SysInvoice sysInvoice); |
| | | |
| | | /** |
| | | * æ¹éå é¤å票ç³è¯· |
| | | * |
| | | * @param invoiceIds éè¦å é¤çå票ç³è¯·ä¸»é®éå |
| | | * @return ç»æ |
| | | */ |
| | | public int deleteSysInvoiceByInvoiceIds(Long[] invoiceIds); |
| | | |
| | | /** |
| | | * å é¤å票ç³è¯·ä¿¡æ¯ |
| | | * |
| | | * @param invoiceId å票ç³è¯·ä¸»é® |
| | | * @return ç»æ |
| | | */ |
| | | public int deleteSysInvoiceByInvoiceId(Long invoiceId); |
| | | |
| | | /** |
| | | * 忥尿§ç³»ç» |
| | | * @param invoiceId |
| | | * @return |
| | | */ |
| | | public int syncToLegacySystem(Long invoiceId); |
| | | |
| | | /** |
| | | * 仿§ç³»ç»åæ¥ç¶æ |
| | | */ |
| | | public void syncStatusFromLegacySystem(); |
| | | |
| | | /** |
| | | * æ¥è¯¢å¯ç³è¯·å票çä»»å¡å表 |
| | | * @param userId ç¨æ·ID |
| | | * @param searchKeyword æç´¢å
³é®è¯ |
| | | * @param serviceOrdClass åå
¬å¸ä»£ç |
| | | * @return |
| | | */ |
| | | public List<Map<String, Object>> selectSelectableTasks(Long userId, String searchKeyword, String serviceOrdClass); |
| | | } |
| | |
| | | } |
| | | paidMoney.setPaidMoney(payment.getSettlementAmount()); |
| | | paidMoney.setPaidMoneyType(convertPaymentMethodToLegacy(payment.getPaymentMethod())); |
| | | paidMoney.setPaidMoneyMono(payment.getTradeNo() != null ? payment.getTradeNo() : payment.getOutTradeNo()); |
| | | String outTradeNo = payment.getTradeNo() != null ? payment.getTradeNo() : payment.getOutTradeNo(); |
| | | if(!outTradeNo.contains("[æ¯ä»ä¸ç¨]")){ |
| | | outTradeNo=outTradeNo+"[æ¯ä»ä¸ç¨]"; |
| | | } |
| | | paidMoney.setPaidMoneyMono(outTradeNo); |
| | | paidMoney.setPaidMoneyTime(payment.getPayTime() != null ? payment.getPayTime() : new Date()); |
| | | paidMoney.setPaidMoneyOaID(oaUserId); |
| | | paidMoney.setPaidMoneyUnitID(0); // é»è®¤ä¸º0 |
| New file |
| | |
| | | package com.ruoyi.system.service.impl; |
| | | |
| | | import java.util.Date; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import com.ruoyi.common.utils.DateUtils; |
| | | import com.ruoyi.common.utils.SecurityUtils; |
| | | import com.ruoyi.system.domain.SysInvoice; |
| | | import com.ruoyi.system.mapper.SysInvoiceMapper; |
| | | import com.ruoyi.system.mapper.LegacyInvoiceMapper; |
| | | import com.ruoyi.system.mapper.SysUserMapper; |
| | | import com.ruoyi.common.core.domain.entity.SysUser; |
| | | import com.ruoyi.system.service.ISysInvoiceService; |
| | | |
| | | /** |
| | | * å票ç³è¯·Serviceä¸å¡å±å¤ç |
| | | * |
| | | * @author ruoyi |
| | | * @date 2026-02-02 |
| | | */ |
| | | @Service |
| | | public class SysInvoiceServiceImpl implements ISysInvoiceService |
| | | { |
| | | private static final Logger log = LoggerFactory.getLogger(SysInvoiceServiceImpl.class); |
| | | |
| | | @Autowired |
| | | private SysInvoiceMapper sysInvoiceMapper; |
| | | |
| | | @Autowired |
| | | private LegacyInvoiceMapper legacyInvoiceMapper; |
| | | |
| | | @Autowired |
| | | private SysUserMapper sysUserMapper; |
| | | |
| | | /** |
| | | * æ¥è¯¢å票ç³è¯· |
| | | * |
| | | * @param invoiceId å票ç³è¯·ä¸»é® |
| | | * @return å票ç³è¯· |
| | | */ |
| | | @Override |
| | | public SysInvoice selectSysInvoiceByInvoiceId(Long invoiceId) |
| | | { |
| | | return sysInvoiceMapper.selectSysInvoiceByInvoiceId(invoiceId); |
| | | } |
| | | |
| | | /** |
| | | * æ¥è¯¢å票ç³è¯·å表 |
| | | * |
| | | * @param sysInvoice å票ç³è¯· |
| | | * @return å票ç³è¯· |
| | | */ |
| | | @Override |
| | | public List<SysInvoice> selectSysInvoiceList(SysInvoice sysInvoice) |
| | | { |
| | | return sysInvoiceMapper.selectSysInvoiceList(sysInvoice); |
| | | } |
| | | |
| | | /** |
| | | * æ¥è¯¢æçå票ç³è¯·å表ï¼App端ï¼è¿åMapå
å«serviceCodeï¼ |
| | | * |
| | | * @param sysInvoice å票ç³è¯· |
| | | * @return å票ç³è¯· |
| | | */ |
| | | @Override |
| | | public List<Map<String, Object>> selectMyInvoiceList(SysInvoice sysInvoice) |
| | | { |
| | | return sysInvoiceMapper.selectMyInvoiceList(sysInvoice); |
| | | } |
| | | |
| | | /** |
| | | * æ°å¢å票ç³è¯· |
| | | * |
| | | * @param sysInvoice å票ç³è¯· |
| | | * @return ç»æ |
| | | */ |
| | | @Override |
| | | public int insertSysInvoice(SysInvoice sysInvoice) |
| | | { |
| | | sysInvoice.setApplyTime(DateUtils.getNowDate()); |
| | | sysInvoice.setStatus(0); // å¾
å®¡æ ¸ |
| | | sysInvoice.setSyncStatus(0); // æªåæ¥ |
| | | int rows = sysInvoiceMapper.insertSysInvoice(sysInvoice); |
| | | |
| | | // èªå¨å°è¯åæ¥å°æ§ç³»ç» |
| | | if (rows > 0) { |
| | | try { |
| | | syncToLegacySystem(sysInvoice.getInvoiceId()); |
| | | } catch (Exception e) { |
| | | log.error("忥å票ç³è¯·å°æ§ç³»ç»å¤±è´¥", e); |
| | | } |
| | | } |
| | | return rows; |
| | | } |
| | | |
| | | /** |
| | | * ä¿®æ¹å票ç³è¯· |
| | | * |
| | | * @param sysInvoice å票ç³è¯· |
| | | * @return ç»æ |
| | | */ |
| | | @Override |
| | | public int updateSysInvoice(SysInvoice sysInvoice) |
| | | { |
| | | return sysInvoiceMapper.updateSysInvoice(sysInvoice); |
| | | } |
| | | |
| | | /** |
| | | * æ¹éå é¤å票ç³è¯· |
| | | * |
| | | * @param invoiceIds éè¦å é¤çå票ç³è¯·ä¸»é® |
| | | * @return ç»æ |
| | | */ |
| | | @Override |
| | | public int deleteSysInvoiceByInvoiceIds(Long[] invoiceIds) |
| | | { |
| | | return sysInvoiceMapper.deleteSysInvoiceByInvoiceIds(invoiceIds); |
| | | } |
| | | |
| | | /** |
| | | * å é¤å票ç³è¯·ä¿¡æ¯ |
| | | * |
| | | * @param invoiceId å票ç³è¯·ä¸»é® |
| | | * @return ç»æ |
| | | */ |
| | | @Override |
| | | public int deleteSysInvoiceByInvoiceId(Long invoiceId) |
| | | { |
| | | return sysInvoiceMapper.deleteSysInvoiceByInvoiceId(invoiceId); |
| | | } |
| | | |
| | | /** |
| | | * 忥å票ç³è¯·å°æ§ç³»ç» (SQL Server) |
| | | */ |
| | | @Override |
| | | public int syncToLegacySystem(Long invoiceId) { |
| | | SysInvoice invoice = sysInvoiceMapper.selectSysInvoiceByInvoiceId(invoiceId); |
| | | if (invoice == null) return 0; |
| | | |
| | | Map<String, Object> params = new HashMap<>(); |
| | | params.put("ServiceOrderIDPK", invoice.getLegacyServiceOrderId()); |
| | | params.put("InvoiceType", invoice.getInvoiceType()); |
| | | params.put("InvoiceName", invoice.getInvoiceName()); |
| | | params.put("InvoiceMakeout", invoice.getInvoiceRemarks()); |
| | | params.put("InvoiceCompanyPhone", invoice.getContactPhone()); |
| | | params.put("InvoiceCompanyID", ""); // ç¨å·åæ®µè¥æå¯è¡¥ |
| | | params.put("InvoiceCompanyAdd", invoice.getCompanyAddress()); |
| | | params.put("InvoiceCompanyBank", invoice.getCompanyBank()); |
| | | params.put("InvoiceCompanyBankNo", invoice.getCompanyBankNo()); |
| | | params.put("InvoiceZipCode", invoice.getZipCode()); |
| | | params.put("Invoice_strAdd", invoice.getMailAddress()); |
| | | params.put("Invoice_strName", invoice.getContactName()); |
| | | params.put("Invoice_strPhone", invoice.getContactPhone()); |
| | | params.put("Invoice_strEmail", invoice.getContactEmail()); |
| | | params.put("InvoiceMoney", invoice.getInvoiceMoney()); |
| | | |
| | | // éè¿å建人BIDæ¥è¯¢OAç¨æ·ID |
| | | Integer oaUserId = 0; |
| | | if (invoice.getApplyUserId() != null) { |
| | | SysUser user = sysUserMapper.selectUserById(invoice.getApplyUserId()); |
| | | if (user != null && user.getOaUserId() != null) { |
| | | oaUserId = user.getOaUserId(); |
| | | } |
| | | } |
| | | params.put("ApplyOAID", oaUserId); |
| | | |
| | | try { |
| | | int rows = legacyInvoiceMapper.insertLegacyInvoice(params); |
| | | if (rows > 0) { |
| | | // SQL Server insert ä¼éè¿ useGeneratedKeys è¿åèªå¢ ID å° Map ç keyProperty |
| | | Object legacyId = params.get("InvoiceID"); |
| | | if (legacyId != null) { |
| | | invoice.setLegacyInvoiceId(Integer.valueOf(legacyId.toString())); |
| | | invoice.setSyncStatus(1); // 已忥 |
| | | sysInvoiceMapper.updateSysInvoice(invoice); |
| | | } |
| | | } |
| | | return rows; |
| | | } catch (Exception e) { |
| | | log.error("忥åç¥¨å°æ§ç³»ç»å¼å¸¸: {}", e.getMessage()); |
| | | invoice.setSyncStatus(2); // åæ¥å¤±è´¥ |
| | | sysInvoiceMapper.updateSysInvoice(invoice); |
| | | throw e; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 仿§ç³»ç»åæ¥åç¥¨ç¶æåå |
| | | */ |
| | | @Override |
| | | public void syncStatusFromLegacySystem() { |
| | | // æ¥è¯¢æè¿3天æååçæ°æ® |
| | | String lastSyncTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, DateUtils.addDays(new Date(), -3)); |
| | | List<Map<String, Object>> updatedList = legacyInvoiceMapper.selectUpdatedInvoices(lastSyncTime); |
| | | |
| | | for (Map<String, Object> legacyData : updatedList) { |
| | | Integer legacyId = (Integer) legacyData.get("InvoiceID"); |
| | | SysInvoice invoice = sysInvoiceMapper.selectSysInvoiceByLegacyId(legacyId); |
| | | |
| | | if (invoice != null) { |
| | | // ç¶ææ å°ï¼æ§ç³»ç» AuditStatus (å设 3=éè¿, 4=æç», å
¶ä»=ç³è¯·ä¸) |
| | | Integer auditStatus = (Integer) legacyData.get("AuditStatus"); |
| | | if (auditStatus != null) { |
| | | if (auditStatus == 3) invoice.setStatus(1); // å·²éè¿ |
| | | else if (auditStatus == 4) invoice.setStatus(2); // 已驳å |
| | | } |
| | | |
| | | // æ´æ°å
¶ä»ä¿¡æ¯ |
| | | if (legacyData.get("InvoiceNo") != null) { |
| | | invoice.setInvoiceNo(legacyData.get("InvoiceNo").toString()); |
| | | } |
| | | |
| | | // å票æä»¶é¾æ¥ (ä¼å
å EleCloud_PDF) |
| | | String pdf = legacyData.get("EleCloud_PDF") != null ? legacyData.get("EleCloud_PDF").toString() : null; |
| | | String url = legacyData.get("InvoiceURL") != null ? legacyData.get("InvoiceURL").toString() : null; |
| | | invoice.setInvoiceUrl(pdf != null && !pdf.isEmpty() ? pdf : url); |
| | | |
| | | if (legacyData.get("AuditTime") != null) { |
| | | invoice.setAuditTime((Date) legacyData.get("AuditTime")); |
| | | } |
| | | if (legacyData.get("AuditMakeout") != null) { |
| | | invoice.setAuditRemarks(legacyData.get("AuditMakeout").toString()); |
| | | } |
| | | |
| | | sysInvoiceMapper.updateSysInvoice(invoice); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * æ¥è¯¢å¯éæ©çä»»å¡å表 |
| | | */ |
| | | @Override |
| | | public List<Map<String, Object>> selectSelectableTasks(Long userId, String searchKeyword, String serviceOrdClass) { |
| | | return sysInvoiceMapper.selectSelectableTasks(userId, searchKeyword, serviceOrdClass); |
| | | } |
| | | } |
| New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8" ?> |
| | | <!DOCTYPE mapper |
| | | PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" |
| | | "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
| | | <mapper namespace="com.ruoyi.system.mapper.LegacyInvoiceMapper"> |
| | | |
| | | <insert id="insertLegacyInvoice" parameterType="Map" useGeneratedKeys="true" keyProperty="InvoiceID"> |
| | | INSERT INTO InvoiceData ( |
| | | ServiceOrderIDPK, InvoiceType, InvoiceName, InvoiceMakeout, |
| | | InvoiceCompanyPhone, InvoiceCompanyID, InvoiceCompanyAdd, |
| | | InvoiceCompanyBank, InvoiceCompanyBankNo, InvoiceZipCode, |
| | | Invoice_strAdd, Invoice_strName, Invoice_strPhone, Invoice_strEmail, |
| | | ApplicationTime, AuditStatus, InvoiceMoney, ApplyOAID |
| | | ) VALUES ( |
| | | #{ServiceOrderIDPK}, #{InvoiceType}, #{InvoiceName}, #{InvoiceMakeout}, |
| | | #{InvoiceCompanyPhone}, #{InvoiceCompanyID}, #{InvoiceCompanyAdd}, |
| | | #{InvoiceCompanyBank}, #{InvoiceCompanyBankNo}, #{InvoiceZipCode}, |
| | | #{Invoice_strAdd}, #{Invoice_strName}, #{Invoice_strPhone}, #{Invoice_strEmail}, |
| | | GETDATE(), 0, #{InvoiceMoney}, #{ApplyOAID} |
| | | ) |
| | | </insert> |
| | | |
| | | <select id="selectUpdatedInvoices" parameterType="String" resultType="Map"> |
| | | SELECT |
| | | InvoiceID, ServiceOrderIDPK, AuditStatus, AuditTime, AuditMakeout, |
| | | InvoiceNo, InvoiceURL, InvoiceOddNo, EleCloud_PDF, EleCloud_Time |
| | | FROM InvoiceData |
| | | WHERE AuditTime > #{lastSyncTime} OR EleCloud_Time > #{lastSyncTime} |
| | | </select> |
| | | |
| | | <select id="selectLegacyInvoiceByServiceOrderId" parameterType="Long" resultType="Map"> |
| | | SELECT * FROM InvoiceData WHERE ServiceOrderIDPK = #{serviceOrderId} |
| | | </select> |
| | | </mapper> |
| New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8" ?> |
| | | <!DOCTYPE mapper |
| | | PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" |
| | | "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
| | | <mapper namespace="com.ruoyi.system.mapper.SysInvoiceMapper"> |
| | | |
| | | <resultMap type="SysInvoice" id="SysInvoiceResult"> |
| | | <result property="invoiceId" column="invoice_id" /> |
| | | <result property="serviceOrderId" column="service_order_id" /> |
| | | <result property="legacyServiceOrderId" column="legacy_service_order_id" /> |
| | | <result property="invoiceType" column="invoice_type" /> |
| | | <result property="invoiceName" column="invoice_name" /> |
| | | <result property="invoiceMoney" column="invoice_money" /> |
| | | <result property="invoiceRemarks" column="invoice_remarks" /> |
| | | <result property="companyAddress" column="company_address" /> |
| | | <result property="companyBank" column="company_bank" /> |
| | | <result property="companyBankNo" column="company_bank_no" /> |
| | | <result property="zipCode" column="zip_code" /> |
| | | <result property="mailAddress" column="mail_address" /> |
| | | <result property="contactName" column="contact_name" /> |
| | | <result property="contactPhone" column="contact_phone" /> |
| | | <result property="contactEmail" column="contact_email" /> |
| | | <result property="status" column="status" /> |
| | | <result property="invoiceNo" column="invoice_no" /> |
| | | <result property="invoiceUrl" column="invoice_url" /> |
| | | <result property="applyUserId" column="apply_user_id" /> |
| | | <result property="applyTime" column="apply_time" /> |
| | | <result property="auditUserId" column="audit_user_id" /> |
| | | <result property="auditTime" column="audit_time" /> |
| | | <result property="auditRemarks" column="audit_remarks" /> |
| | | <result property="syncStatus" column="sync_status" /> |
| | | <result property="legacyInvoiceId" column="legacy_invoice_id" /> |
| | | <result property="serviceCode" column="serviceCode" /> |
| | | </resultMap> |
| | | |
| | | <sql id="selectSysInvoiceVo"> |
| | | select invoice_id, service_order_id, legacy_service_order_id, invoice_type, invoice_name, invoice_money, invoice_remarks, company_address, company_bank, company_bank_no, zip_code, mail_address, contact_name, contact_phone, contact_email, status, invoice_no, invoice_url, apply_user_id, apply_time, audit_user_id, audit_time, audit_remarks, sync_status, legacy_invoice_id from sys_invoice |
| | | </sql> |
| | | |
| | | <select id="selectSysInvoiceList" parameterType="SysInvoice" resultMap="SysInvoiceResult"> |
| | | select i.invoice_id, i.service_order_id, i.legacy_service_order_id, i.invoice_type, i.invoice_name, |
| | | i.invoice_money, i.invoice_remarks, i.company_address, i.company_bank, i.company_bank_no, |
| | | i.zip_code, i.mail_address, i.contact_name, i.contact_phone, i.contact_email, |
| | | i.status, i.invoice_no, i.invoice_url, i.apply_user_id, i.apply_time, |
| | | i.audit_user_id, i.audit_time, i.audit_remarks, i.sync_status, i.legacy_invoice_id, |
| | | CONCAT( |
| | | IFNULL(e.legacy_service_ord_class, ''), |
| | | DATE_FORMAT(e.legacy_service_ns_time, '%Y%m%d'), |
| | | '-', |
| | | LPAD(IFNULL(e.legacy_service_ord_no, ''), 3, '0') |
| | | ) as serviceCode |
| | | from sys_invoice i |
| | | LEFT JOIN sys_task_emergency e ON i.service_order_id = e.task_id |
| | | <where> |
| | | <if test="serviceOrderId != null "> and i.service_order_id = #{serviceOrderId}</if> |
| | | <if test="legacyServiceOrderId != null "> and i.legacy_service_order_id = #{legacyServiceOrderId}</if> |
| | | <if test="invoiceType != null "> and i.invoice_type = #{invoiceType}</if> |
| | | <if test="invoiceName != null and invoiceName != ''"> and i.invoice_name like concat('%', #{invoiceName}, '%')</if> |
| | | <if test="status != null "> and i.status = #{status}</if> |
| | | <!-- serviceCodeæ¥è¯¢ --> |
| | | <if test="params.serviceCode != null and params.serviceCode != ''"> |
| | | AND CONCAT( |
| | | IFNULL(e.legacy_service_ord_class, ''), |
| | | DATE_FORMAT(e.legacy_service_ns_time, '%Y%m%d'), |
| | | '-', |
| | | LPAD(IFNULL(e.legacy_service_ord_no, ''), 3, '0') |
| | | ) LIKE CONCAT('%', #{params.serviceCode}, '%') |
| | | </if> |
| | | <if test="params.beginTime != null and params.beginTime != ''"><!-- å¼å§æ¶é´æ£ç´¢ --> |
| | | AND date_format(i.apply_time,'%y%m%d') >= date_format(#{params.beginTime},'%y%m%d') |
| | | </if> |
| | | <if test="params.endTime != null and params.endTime != ''"><!-- ç»ææ¶é´æ£ç´¢ --> |
| | | AND date_format(i.apply_time,'%y%m%d') <= date_format(#{params.endTime},'%y%m%d') |
| | | </if> |
| | | <!-- åå
¬å¸æ¥è¯¢é»è¾éè¦å
³èæå¡å表 --> |
| | | <if test="params.serviceOrdClass != null and params.serviceOrdClass != ''"> |
| | | AND i.service_order_id IN (SELECT ServiceOrdID FROM service_order WHERE ServiceOrdClass = #{params.serviceOrdClass}) |
| | | </if> |
| | | </where> |
| | | </select> |
| | | |
| | | <!-- App端æ¥è¯¢æçå票å表ï¼è¿åMapå
å«serviceCode --> |
| | | <select id="selectMyInvoiceList" parameterType="SysInvoice" resultType="map"> |
| | | SELECT |
| | | i.invoice_id as invoiceId, |
| | | i.service_order_id as serviceOrderId, |
| | | i.legacy_service_order_id as legacyServiceOrderId, |
| | | i.invoice_type as invoiceType, |
| | | i.invoice_name as invoiceName, |
| | | i.invoice_money as invoiceMoney, |
| | | i.invoice_remarks as invoiceRemarks, |
| | | i.company_address as companyAddress, |
| | | i.company_bank as companyBank, |
| | | i.company_bank_no as companyBankNo, |
| | | i.zip_code as zipCode, |
| | | i.mail_address as mailAddress, |
| | | i.contact_name as contactName, |
| | | i.contact_phone as contactPhone, |
| | | i.contact_email as contactEmail, |
| | | i.status, |
| | | i.invoice_no as invoiceNo, |
| | | i.invoice_url as invoiceUrl, |
| | | i.apply_user_id as applyUserId, |
| | | i.apply_time as applyTime, |
| | | i.audit_user_id as auditUserId, |
| | | i.audit_time as auditTime, |
| | | i.audit_remarks as auditRemarks, |
| | | i.sync_status as syncStatus, |
| | | i.legacy_invoice_id as legacyInvoiceId, |
| | | -- æå»º serviceCode |
| | | CONCAT( |
| | | IFNULL(e.legacy_service_ord_class, ''), |
| | | DATE_FORMAT(e.legacy_service_ns_time, '%Y%m%d'), |
| | | '-', |
| | | LPAD(IFNULL(e.legacy_service_ord_no, ''), 3, '0') |
| | | ) as serviceCode |
| | | FROM sys_invoice i |
| | | LEFT JOIN sys_task_emergency e ON i.service_order_id = e.task_id |
| | | <where> |
| | | <if test="serviceOrderId != null "> and i.service_order_id = #{serviceOrderId}</if> |
| | | <if test="legacyServiceOrderId != null "> and i.legacy_service_order_id = #{legacyServiceOrderId}</if> |
| | | <if test="invoiceType != null "> and i.invoice_type = #{invoiceType}</if> |
| | | <if test="invoiceName != null and invoiceName != ''"> and i.invoice_name like concat('%', #{invoiceName}, '%')</if> |
| | | <if test="status != null "> and i.status = #{status}</if> |
| | | <!-- æå¡åå·æç´¢ --> |
| | | <if test="params.serviceCode != null and params.serviceCode != ''"> |
| | | AND CONCAT( |
| | | IFNULL(e.legacy_service_ord_class, ''), |
| | | DATE_FORMAT(e.legacy_service_ns_time, '%Y%m%d'), |
| | | '-', |
| | | IFNULL(e.legacy_service_ord_no, '') |
| | | ) LIKE CONCAT('%', #{params.serviceCode}, '%') |
| | | </if> |
| | | <if test="params.beginTime != null and params.beginTime != ''"><!-- å¼å§æ¶é´æ£ç´¢ --> |
| | | AND date_format(i.apply_time,'%y%m%d') >= date_format(#{params.beginTime},'%y%m%d') |
| | | </if> |
| | | <if test="params.endTime != null and params.endTime != ''"><!-- ç»ææ¶é´æ£ç´¢ --> |
| | | AND date_format(i.apply_time,'%y%m%d') <= date_format(#{params.endTime},'%y%m%d') |
| | | </if> |
| | | <!-- åå
¬å¸æ¥è¯¢é»è¾éè¦å
³èæå¡å表 --> |
| | | <if test="params.serviceOrdClass != null and params.serviceOrdClass != ''"> |
| | | AND i.service_order_id IN (SELECT ServiceOrdID FROM service_order WHERE ServiceOrdClass = #{params.serviceOrdClass}) |
| | | </if> |
| | | </where> |
| | | </select> |
| | | |
| | | <select id="selectSysInvoiceByInvoiceId" parameterType="Long" resultMap="SysInvoiceResult"> |
| | | <include refid="selectSysInvoiceVo"/> |
| | | where invoice_id = #{invoiceId} |
| | | </select> |
| | | |
| | | <select id="selectSysInvoiceByLegacyId" parameterType="Integer" resultMap="SysInvoiceResult"> |
| | | <include refid="selectSysInvoiceVo"/> |
| | | where legacy_invoice_id = #{legacyInvoiceId} |
| | | </select> |
| | | |
| | | <select id="selectSelectableTasks" resultType="Map"> |
| | | SELECT |
| | | t.task_id as taskId, |
| | | t.task_code as taskCode, |
| | | e.legacy_service_ord_id as legacyServiceOrderId, |
| | | t.actual_end_time as completionTime, |
| | | t.departure_address as departure, |
| | | t.destination_address as destination, |
| | | e.legacy_service_ord_class as legacyServiceOrdClass, |
| | | e.legacy_service_ns_time as legacyServiceNsTime, |
| | | e.legacy_service_ord_no as legacyServiceOrdNo, |
| | | IFNULL(e.transfer_price, 0) as transferPrice, |
| | | CONCAT( |
| | | IFNULL(e.legacy_service_ord_class, ''), |
| | | DATE_FORMAT(e.legacy_service_ns_time, '%Y%m%d'), |
| | | '-', |
| | | LPAD(IFNULL(e.legacy_service_ord_no, ''), 3, '0') |
| | | ) as serviceCode |
| | | FROM sys_task t |
| | | INNER JOIN sys_task_emergency e ON t.task_id = e.task_id |
| | | WHERE t.task_type = 'EMERGENCY_TRANSFER' |
| | | AND t.task_status = 'COMPLETED' |
| | | AND (t.creator_id = #{userId} OR t.assignee_id = #{userId}) |
| | | AND t.task_id NOT IN ( |
| | | SELECT service_order_id |
| | | FROM sys_invoice |
| | | WHERE status IN (0, 1) |
| | | ) |
| | | <if test="searchKeyword != null and searchKeyword != ''"> |
| | | AND ( |
| | | t.task_code LIKE CONCAT('%', #{searchKeyword}, '%') |
| | | OR e.legacy_service_ord_no LIKE CONCAT('%', #{searchKeyword}, '%') |
| | | OR CONCAT( |
| | | IFNULL(e.legacy_service_ord_class, ''), |
| | | DATE_FORMAT(e.legacy_service_ns_time, '%Y%m%d'), |
| | | '-', |
| | | LPAD(IFNULL(e.legacy_service_ord_no, ''), 3, '0') |
| | | |
| | | ) LIKE CONCAT('%', #{searchKeyword}, '%') |
| | | ) |
| | | </if> |
| | | <if test="serviceOrdClass != null and serviceOrdClass != ''"> |
| | | AND e.legacy_service_ord_class = #{serviceOrdClass} |
| | | </if> |
| | | ORDER BY t.actual_end_time DESC |
| | | LIMIT 100 |
| | | </select> |
| | | |
| | | <insert id="insertSysInvoice" parameterType="SysInvoice" useGeneratedKeys="true" keyProperty="invoiceId"> |
| | | insert into sys_invoice |
| | | <trim prefix="(" suffix=")" suffixOverrides=","> |
| | | <if test="serviceOrderId != null">service_order_id,</if> |
| | | <if test="legacyServiceOrderId != null">legacy_service_order_id,</if> |
| | | <if test="invoiceType != null">invoice_type,</if> |
| | | <if test="invoiceName != null and invoiceName != ''">invoice_name,</if> |
| | | <if test="invoiceMoney != null">invoice_money,</if> |
| | | <if test="invoiceRemarks != null">invoice_remarks,</if> |
| | | <if test="companyAddress != null">company_address,</if> |
| | | <if test="companyBank != null">company_bank,</if> |
| | | <if test="companyBankNo != null">company_bank_no,</if> |
| | | <if test="zipCode != null">zip_code,</if> |
| | | <if test="mailAddress != null">mail_address,</if> |
| | | <if test="contactName != null">contact_name,</if> |
| | | <if test="contactPhone != null">contact_phone,</if> |
| | | <if test="contactEmail != null">contact_email,</if> |
| | | <if test="status != null">status,</if> |
| | | <if test="invoiceNo != null">invoice_no,</if> |
| | | <if test="invoiceUrl != null">invoice_url,</if> |
| | | <if test="applyUserId != null">apply_user_id,</if> |
| | | <if test="applyTime != null">apply_time,</if> |
| | | <if test="auditUserId != null">audit_user_id,</if> |
| | | <if test="auditTime != null">audit_time,</if> |
| | | <if test="auditRemarks != null">audit_remarks,</if> |
| | | <if test="syncStatus != null">sync_status,</if> |
| | | <if test="legacyInvoiceId != null">legacy_invoice_id,</if> |
| | | </trim> |
| | | <trim prefix="values (" suffix=")" suffixOverrides=","> |
| | | <if test="serviceOrderId != null">#{serviceOrderId},</if> |
| | | <if test="legacyServiceOrderId != null">#{legacyServiceOrderId},</if> |
| | | <if test="invoiceType != null">#{invoiceType},</if> |
| | | <if test="invoiceName != null and invoiceName != ''">#{invoiceName},</if> |
| | | <if test="invoiceMoney != null">#{invoiceMoney},</if> |
| | | <if test="invoiceRemarks != null">#{invoiceRemarks},</if> |
| | | <if test="companyAddress != null">#{companyAddress},</if> |
| | | <if test="companyBank != null">#{companyBank},</if> |
| | | <if test="companyBankNo != null">#{companyBankNo},</if> |
| | | <if test="zipCode != null">#{zipCode},</if> |
| | | <if test="mailAddress != null">#{mailAddress},</if> |
| | | <if test="contactName != null">#{contactName},</if> |
| | | <if test="contactPhone != null">#{contactPhone},</if> |
| | | <if test="contactEmail != null">#{contactEmail},</if> |
| | | <if test="status != null">#{status},</if> |
| | | <if test="invoiceNo != null">#{invoiceNo},</if> |
| | | <if test="invoiceUrl != null">#{invoiceUrl},</if> |
| | | <if test="applyUserId != null">#{applyUserId},</if> |
| | | <if test="applyTime != null">#{applyTime},</if> |
| | | <if test="auditUserId != null">#{auditUserId},</if> |
| | | <if test="auditTime != null">#{auditTime},</if> |
| | | <if test="auditRemarks != null">#{auditRemarks},</if> |
| | | <if test="syncStatus != null">#{syncStatus},</if> |
| | | <if test="legacyInvoiceId != null">#{legacyInvoiceId},</if> |
| | | </trim> |
| | | </insert> |
| | | |
| | | <update id="updateSysInvoice" parameterType="SysInvoice"> |
| | | update sys_invoice |
| | | <trim prefix="SET" suffixOverrides=","> |
| | | <if test="serviceOrderId != null">service_order_id = #{serviceOrderId},</if> |
| | | <if test="legacyServiceOrderId != null">legacy_service_order_id = #{legacyServiceOrderId},</if> |
| | | <if test="invoiceType != null">invoice_type = #{invoiceType},</if> |
| | | <if test="invoiceName != null and invoiceName != ''">invoice_name = #{invoiceName},</if> |
| | | <if test="invoiceMoney != null">invoice_money = #{invoiceMoney},</if> |
| | | <if test="invoiceRemarks != null">invoice_remarks = #{invoiceRemarks},</if> |
| | | <if test="companyAddress != null">company_address = #{companyAddress},</if> |
| | | <if test="companyBank != null">company_bank = #{companyBank},</if> |
| | | <if test="companyBankNo != null">company_bank_no = #{companyBankNo},</if> |
| | | <if test="zipCode != null">zip_code = #{zipCode},</if> |
| | | <if test="mailAddress != null">mail_address = #{mailAddress},</if> |
| | | <if test="contactName != null">contact_name = #{contactName},</if> |
| | | <if test="contactPhone != null">contact_phone = #{contactPhone},</if> |
| | | <if test="contactEmail != null">contact_email = #{contactEmail},</if> |
| | | <if test="status != null">status = #{status},</if> |
| | | <if test="invoiceNo != null">invoice_no = #{invoiceNo},</if> |
| | | <if test="invoiceUrl != null">invoice_url = #{invoiceUrl},</if> |
| | | <if test="applyUserId != null">apply_user_id = #{applyUserId},</if> |
| | | <if test="applyTime != null">apply_time = #{applyTime},</if> |
| | | <if test="auditUserId != null">audit_user_id = #{auditUserId},</if> |
| | | <if test="auditTime != null">audit_time = #{auditTime},</if> |
| | | <if test="auditRemarks != null">audit_remarks = #{auditRemarks},</if> |
| | | <if test="syncStatus != null">sync_status = #{syncStatus},</if> |
| | | <if test="legacyInvoiceId != null">legacy_invoice_id = #{legacyInvoiceId},</if> |
| | | </trim> |
| | | where invoice_id = #{invoiceId} |
| | | </update> |
| | | |
| | | <delete id="deleteSysInvoiceByInvoiceId" parameterType="Long"> |
| | | delete from sys_invoice where invoice_id = #{invoiceId} |
| | | </delete> |
| | | |
| | | <delete id="deleteSysInvoiceByInvoiceIds" parameterType="String"> |
| | | delete from sys_invoice where invoice_id in |
| | | <foreach item="invoiceId" collection="array" open="(" separator="," close=")"> |
| | | #{invoiceId} |
| | | </foreach> |
| | | </delete> |
| | | </mapper> |
| | |
| | | segment_distance, gps_point_count, gps_ids, task_id, task_code, calculate_method |
| | | FROM tb_vehicle_gps_segment_mileage |
| | | WHERE vehicle_id = #{vehicleId} |
| | | AND segment_start_time <= #{endTime} |
| | | AND segment_start_time between #{startDate} and #{endDate} |
| | | AND segment_end_time >= #{startTime} |
| | | AND segment_distance > 0 |
| | | ORDER BY segment_start_time |
| | |
| | | }) |
| | | } |
| | | |
| | | // æOA订åç±»å«æ¥è¯¢åå
¬å¸å表ï¼å«åï¼ |
| | | export function listBranchByOaOrderClass() { |
| | | return request({ |
| | | url: '/system/dept/branch/by-oa', |
| | | method: 'get' |
| | | }) |
| | | } |
| | | |
| | | // æå¤é¨ä¼ å
¥çç¨æ·IDè¿åå
¶å¯ç®¡çåå
¬å¸å表 |
| | | export function listBranchByUser(userId) { |
| | | return request({ |
| New file |
| | |
| | | import request from '@/utils/request' |
| | | |
| | | // æ¥è¯¢å票ç³è¯·å表 |
| | | export function listInvoice(query) { |
| | | return request({ |
| | | url: '/system/invoice/list', |
| | | method: 'get', |
| | | params: query |
| | | }) |
| | | } |
| | | |
| | | // æ¥è¯¢å票ç³è¯·è¯¦ç» |
| | | export function getInvoice(invoiceId) { |
| | | return request({ |
| | | url: '/system/invoice/' + invoiceId, |
| | | method: 'get' |
| | | }) |
| | | } |
| | | |
| | | // æ°å¢å票ç³è¯· |
| | | export function addInvoice(data) { |
| | | return request({ |
| | | url: '/system/invoice', |
| | | method: 'post', |
| | | data: data |
| | | }) |
| | | } |
| | | |
| | | // ä¿®æ¹å票ç³è¯· |
| | | export function updateInvoice(data) { |
| | | return request({ |
| | | url: '/system/invoice', |
| | | method: 'put', |
| | | data: data |
| | | }) |
| | | } |
| | | |
| | | // å é¤å票ç³è¯· |
| | | export function delInvoice(invoiceId) { |
| | | return request({ |
| | | url: '/system/invoice/' + invoiceId, |
| | | method: 'delete' |
| | | }) |
| | | } |
| | | |
| | | // æå¨åæ¥ç¶æ |
| | | export function syncInvoiceStatus() { |
| | | return request({ |
| | | url: '/system/invoice/syncStatus', |
| | | method: 'get' |
| | | }) |
| | | } |
| | | |
| | | // 忥å个åç¥¨å°æ§ç³»ç» |
| | | export function syncInvoiceToLegacy(invoiceId) { |
| | | return request({ |
| | | url: '/system/invoice/syncToLegacy/' + invoiceId, |
| | | method: 'post' |
| | | }) |
| | | } |
| | |
| | | url: '/task/syncDispatchOrder/' + taskId, |
| | | method: 'post' |
| | | }) |
| | | } |
| | | |
| | | // æå¨åæ¥ä»»å¡ç¶æå°æ§ç³»ç» |
| | | export function syncTaskStatus(taskId) { |
| | | return request({ |
| | | url: '/task/syncTaskStatus/' + taskId, |
| | | method: 'post' |
| | | }) |
| | | } |
| | |
| | | hidden: false, |
| | | name: 'H5TaskCreate', |
| | | meta: { title: 'å建任å¡' } |
| | | }, |
| | | { |
| | | path: '/system/invoice/detail', |
| | | component: () => import('@/views/system/invoice/detail'), |
| | | name: 'InvoiceDetail', |
| | | hidden: true, |
| | | meta: { title: 'å票详æ
', activeMenu: '/system/invoice' } |
| | | }, |
| | | { |
| | | path: '/system/invoice/audit', |
| | | component: () => import('@/views/system/invoice/audit'), |
| | | name: 'InvoiceAudit', |
| | | hidden: true, |
| | | meta: { title: 'å®¡æ ¸å票', activeMenu: '/system/invoice' } |
| | | }, |
| | | { |
| | | path: '/system/invoice/apply', |
| | | component: () => import('@/views/system/invoice/apply'), |
| | | name: 'InvoiceApply', |
| | | hidden: true, |
| | | meta: { title: 'ç³è¯·å票', activeMenu: '/system/invoice' } |
| | | } |
| | | ] |
| | | |
| New file |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <el-card class="box-card"> |
| | | <div slot="header" class="clearfix"> |
| | | <span class="card-title">å票ç³è¯·</span> |
| | | <el-button style="float: right; padding: 3px 0" type="text" @click="goBack">è¿å</el-button> |
| | | </div> |
| | | |
| | | <el-form ref="form" :model="form" :rules="rules" label-width="120px"> |
| | | <!-- ä»»å¡ä¿¡æ¯å±ç¤º --> |
| | | <el-divider>ä»»å¡ä¿¡æ¯</el-divider> |
| | | <el-descriptions :column="2" border v-if="taskInfo.taskId"> |
| | | <el-descriptions-item label="ä»»å¡ç¼å·">{{ taskInfo.taskCode }}</el-descriptions-item> |
| | | <el-descriptions-item label="æå¡åå·">{{ taskInfo.serviceCode || taskInfo.legacyServiceOrderId || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="åºåå°" :span="2">{{ taskInfo.departure }}</el-descriptions-item> |
| | | <el-descriptions-item label="ç®çå°" :span="2">{{ taskInfo.destination }}</el-descriptions-item> |
| | | <el-descriptions-item label="宿æ¶é´">{{ taskInfo.completionTime }}</el-descriptions-item> |
| | | <el-descriptions-item label="ä»»å¡éé¢"> |
| | | <span style="color: #F56C6C; font-weight: bold;">Â¥{{ taskInfo.transferPrice || '0.00' }}</span> |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | |
| | | <!-- åç¥¨ä¿¡æ¯ --> |
| | | <el-divider>å票信æ¯</el-divider> |
| | | |
| | | <el-form-item label="å¼ç¥¨ç±»å" prop="invoiceType"> |
| | | <el-radio-group v-model="form.invoiceType"> |
| | | <el-radio :label="1">个人</el-radio> |
| | | <el-radio :label="2">ä¼ä¸</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="å票æ¬å¤´" prop="invoiceName"> |
| | | <el-input v-model="form.invoiceName" placeholder="请è¾å
¥å票æ¬å¤´" maxlength="200" /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="å票éé¢" prop="invoiceMoney"> |
| | | <el-input |
| | | v-model="form.invoiceMoney" |
| | | placeholder="请è¾å
¥å票éé¢" |
| | | type="number" |
| | | :max="maxInvoiceMoney" |
| | | > |
| | | <template slot="append">å
</template> |
| | | </el-input> |
| | | <div v-if="maxInvoiceMoney" style="color: #909399; font-size: 12px; margin-top: 4px;"> |
| | | å¯ç³è¯·éé¢ä¸éï¼Â¥{{ maxInvoiceMoney }} |
| | | </div> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="åç¥¨å¤æ³¨"> |
| | | <el-input v-model="form.invoiceRemarks" type="textarea" placeholder="请è¾å
¥å¤æ³¨" maxlength="500" /> |
| | | </el-form-item> |
| | | |
| | | <!-- ä¼ä¸ä¿¡æ¯ï¼ä»
ä¼ä¸ç±»åæ¾ç¤ºï¼ --> |
| | | <template v-if="form.invoiceType === 2"> |
| | | <el-divider>ä¼ä¸ä¿¡æ¯</el-divider> |
| | | |
| | | <el-form-item label="注åå°å" prop="companyAddress"> |
| | | <el-input v-model="form.companyAddress" placeholder="请è¾å
¥ä¼ä¸æ³¨åå°å" maxlength="200" /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="弿·é¶è¡" prop="companyBank"> |
| | | <el-input v-model="form.companyBank" placeholder="请è¾å
¥å¼æ·é¶è¡" maxlength="100" /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="é¶è¡è´¦å·" prop="companyBankNo"> |
| | | <el-input v-model="form.companyBankNo" placeholder="请è¾å
¥é¶è¡è´¦å·" maxlength="50" /> |
| | | </el-form-item> |
| | | </template> |
| | | |
| | | <!-- é®å¯ä¿¡æ¯ --> |
| | | <el-divider>é®å¯ä¿¡æ¯</el-divider> |
| | | |
| | | <el-form-item label="é®å¯å°å" prop="mailAddress"> |
| | | <el-input v-model="form.mailAddress" placeholder="请è¾å
¥é®å¯å°å" maxlength="200" /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="é®ç¼"> |
| | | <el-input v-model="form.zipCode" placeholder="请è¾å
¥é®ç¼" maxlength="10" /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="è系人" prop="contactName"> |
| | | <el-input v-model="form.contactName" placeholder="请è¾å
¥è系人" maxlength="50" /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="èç³»çµè¯" prop="contactPhone"> |
| | | <el-input v-model="form.contactPhone" placeholder="请è¾å
¥èç³»çµè¯" maxlength="20" /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="èç³»é®ç®±"> |
| | | <el-input v-model="form.contactEmail" placeholder="请è¾å
¥èç³»é®ç®±" maxlength="100" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <div class="action-bar" style="margin-top: 20px; text-align: center;"> |
| | | <el-button @click="goBack">åæ¶</el-button> |
| | | <el-button type="primary" @click="submitForm">æäº¤ç³è¯·</el-button> |
| | | </div> |
| | | </el-card> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import { addInvoice } from "@/api/system/invoice"; |
| | | |
| | | export default { |
| | | name: "InvoiceApply", |
| | | data() { |
| | | return { |
| | | // ä»»å¡ä¿¡æ¯ |
| | | taskInfo: { |
| | | taskId: null, |
| | | taskCode: null, |
| | | legacyServiceOrderId: null, |
| | | serviceCode: null, |
| | | departure: null, |
| | | destination: null, |
| | | completionTime: null, |
| | | transferPrice: null |
| | | }, |
| | | // è¡¨åæ°æ® |
| | | form: { |
| | | serviceOrderId: null, |
| | | legacyServiceOrderId: null, // æ§ç³»ç»æå¡åID |
| | | invoiceType: 1, |
| | | invoiceName: null, |
| | | invoiceMoney: null, |
| | | invoiceRemarks: null, |
| | | companyAddress: null, |
| | | companyBank: null, |
| | | companyBankNo: null, |
| | | zipCode: null, |
| | | mailAddress: null, |
| | | contactName: null, |
| | | contactPhone: null, |
| | | contactEmail: null |
| | | }, |
| | | // æå¤§å票éé¢ |
| | | maxInvoiceMoney: null, |
| | | // è¡¨åæ ¡éª |
| | | rules: { |
| | | invoiceType: [ |
| | | { required: true, message: "è¯·éæ©å¼ç¥¨ç±»å", trigger: "change" } |
| | | ], |
| | | invoiceName: [ |
| | | { required: true, message: "请è¾å
¥å票æ¬å¤´", trigger: "blur" } |
| | | ], |
| | | invoiceMoney: [ |
| | | { required: true, message: "请è¾å
¥å票éé¢", trigger: "blur" }, |
| | | { |
| | | validator: (rule, value, callback) => { |
| | | if (!value || value <= 0) { |
| | | callback(new Error('å票éé¢å¿
须大äº0')); |
| | | } else if (this.maxInvoiceMoney && parseFloat(value) > this.maxInvoiceMoney) { |
| | | callback(new Error(`å票éé¢ä¸è½è¶
è¿ä»»å¡éé¢Â¥${this.maxInvoiceMoney}`)); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }, |
| | | trigger: 'blur' |
| | | } |
| | | ], |
| | | companyAddress: [ |
| | | { required: true, message: "请è¾å
¥ä¼ä¸æ³¨åå°å", trigger: "blur" } |
| | | ], |
| | | companyBank: [ |
| | | { required: true, message: "请è¾å
¥å¼æ·é¶è¡", trigger: "blur" } |
| | | ], |
| | | companyBankNo: [ |
| | | { required: true, message: "请è¾å
¥é¶è¡è´¦å·", trigger: "blur" } |
| | | ], |
| | | mailAddress: [ |
| | | { required: true, message: "请è¾å
¥é®å¯å°å", trigger: "blur" } |
| | | ], |
| | | contactName: [ |
| | | { required: true, message: "请è¾å
¥è系人", trigger: "blur" } |
| | | ], |
| | | contactPhone: [ |
| | | { required: true, message: "请è¾å
¥èç³»çµè¯", trigger: "blur" }, |
| | | { pattern: /^1[3-9]\d{9}$/, message: "请è¾å
¥æ£ç¡®çææºå·ç ", trigger: "blur" } |
| | | ] |
| | | } |
| | | }; |
| | | }, |
| | | created() { |
| | | // ä» sessionStorage è·åä»»å¡ä¿¡æ¯ |
| | | const taskInfoStr = sessionStorage.getItem('invoiceTaskInfo'); |
| | | if (taskInfoStr) { |
| | | this.taskInfo = JSON.parse(taskInfoStr); |
| | | this.form.serviceOrderId = this.taskInfo.taskId; |
| | | // 妿任å¡ä¿¡æ¯ä¸ææ§ç³»ç»æå¡åIDï¼ä¹è¦ä¿å |
| | | if (this.taskInfo.legacyServiceOrderId) { |
| | | this.form.legacyServiceOrderId = this.taskInfo.legacyServiceOrderId; |
| | | } |
| | | |
| | | // 设置æå¤§å票éé¢ |
| | | if (this.taskInfo.transferPrice) { |
| | | this.maxInvoiceMoney = parseFloat(this.taskInfo.transferPrice); |
| | | // èªå¨å¸¦å
¥ä»»å¡éé¢ |
| | | this.form.invoiceMoney = this.maxInvoiceMoney; |
| | | } |
| | | |
| | | // æ¸
é¤ sessionStorage |
| | | sessionStorage.removeItem('invoiceTaskInfo'); |
| | | } else if (this.$route.query.taskId) { |
| | | // å¦ææ²¡æ sessionStorageï¼å°è¯ä» query è·å |
| | | this.$modal.msgError("缺å°ä»»å¡ä¿¡æ¯ï¼è¯·ä»ä»»å¡è¯¦æ
页è¿å
¥"); |
| | | this.goBack(); |
| | | } |
| | | }, |
| | | methods: { |
| | | /** æäº¤è¡¨å */ |
| | | submitForm() { |
| | | this.$refs["form"].validate(valid => { |
| | | if (valid) { |
| | | // ä¼ä¸ç±»åéè¦éªè¯ä¼ä¸ä¿¡æ¯ |
| | | if (this.form.invoiceType === 2) { |
| | | if (!this.form.companyAddress || !this.form.companyBank || !this.form.companyBankNo) { |
| | | this.$modal.msgError("请å®åä¼ä¸ä¿¡æ¯"); |
| | | return; |
| | | } |
| | | } |
| | | |
| | | // 忬¡éªè¯éé¢ |
| | | const money = parseFloat(this.form.invoiceMoney); |
| | | if (this.maxInvoiceMoney && money > this.maxInvoiceMoney) { |
| | | this.$modal.msgError(`å票éé¢ä¸è½è¶
è¿ä»»å¡éé¢Â¥${this.maxInvoiceMoney}`); |
| | | return; |
| | | } |
| | | |
| | | addInvoice(this.form).then(response => { |
| | | this.$modal.msgSuccess("æäº¤æå"); |
| | | setTimeout(() => { |
| | | this.goBack(); |
| | | }, 1500); |
| | | }); |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | /** è¿å */ |
| | | goBack() { |
| | | this.$tab.closePage(); |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .card-title { |
| | | font-size: 18px; |
| | | font-weight: bold; |
| | | color: #303133; |
| | | } |
| | | |
| | | .action-bar { |
| | | border-top: 1px solid #EBEEF5; |
| | | padding-top: 20px; |
| | | } |
| | | </style> |
| New file |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <el-card class="box-card"> |
| | | <div slot="header" class="clearfix"> |
| | | <span class="card-title">å®¡æ ¸å票ç³è¯·</span> |
| | | <el-button style="float: right; padding: 3px 0" type="text" @click="goBack">è¿å</el-button> |
| | | </div> |
| | | |
| | | <!-- ç³è¯·ä¿¡æ¯ï¼åªè¯»ï¼ --> |
| | | <el-form ref="viewForm" :model="invoice" label-width="120px" disabled> |
| | | <el-divider content-position="left">ç³è¯·ä¿¡æ¯</el-divider> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æå¡åå·"> |
| | | <el-input v-model="invoice.serviceCode" placeholder="ææ " /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å¼ç¥¨ç±»å"> |
| | | <el-radio-group v-model="invoice.invoiceType"> |
| | | <el-radio :label="1">个人</el-radio> |
| | | <el-radio :label="2">ä¼ä¸</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="å票æ¬å¤´"> |
| | | <el-input v-model="invoice.invoiceName" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å票éé¢"> |
| | | <el-input v-model="invoice.invoiceMoney"> |
| | | <template slot="prepend">Â¥</template> |
| | | </el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="èç³»çµè¯"> |
| | | <el-input v-model="invoice.contactPhone" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20" v-if="invoice.invoiceType === 2"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="注åå°å"> |
| | | <el-input v-model="invoice.companyAddress" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20" v-if="invoice.invoiceType === 2"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="弿·é¶è¡"> |
| | | <el-input v-model="invoice.companyBank" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="é¶è¡è´¦å·"> |
| | | <el-input v-model="invoice.companyBankNo" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="é®å¯å°å"> |
| | | <el-input v-model="invoice.mailAddress" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="夿³¨"> |
| | | <el-input type="textarea" v-model="invoice.invoiceRemarks" :rows="3" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | |
| | | <!-- å®¡æ ¸ä¿¡æ¯ --> |
| | | <el-form ref="auditForm" :model="auditForm" :rules="rules" label-width="120px"> |
| | | <el-divider content-position="left">å®¡æ ¸ä¿¡æ¯</el-divider> |
| | | |
| | | <el-form-item label="å®¡æ ¸ç»æ" prop="status"> |
| | | <el-radio-group v-model="auditForm.status" @change="handleStatusChange"> |
| | | <el-radio :label="1">éè¿</el-radio> |
| | | <el-radio :label="2">驳å</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | |
| | | <!-- å®¡æ ¸éè¿æ¶ä¸ä¼ å票 --> |
| | | <el-form-item |
| | | v-if="auditForm.status === 1" |
| | | label="å票æä»¶" |
| | | prop="invoiceUrl" |
| | | :rules="[{ required: true, message: '请ä¸ä¼ å票æä»¶', trigger: 'change' }]" |
| | | > |
| | | <el-upload |
| | | class="upload-demo" |
| | | :action="uploadAction" |
| | | :headers="uploadHeaders" |
| | | :on-success="handleUploadSuccess" |
| | | :on-error="handleUploadError" |
| | | :before-upload="beforeUpload" |
| | | :file-list="fileList" |
| | | :limit="1" |
| | | accept=".pdf,.jpg,.jpeg,.png" |
| | | > |
| | | <el-button size="small" type="primary">ç¹å»ä¸ä¼ </el-button> |
| | | <div slot="tip" class="el-upload__tip">æ¯æPDFãJPGãPNGæ ¼å¼ï¼ä¸ä¸è¶
è¿10MB</div> |
| | | </el-upload> |
| | | <div v-if="auditForm.invoiceUrl" style="margin-top: 10px;"> |
| | | <el-link type="primary" :href="auditForm.invoiceUrl" target="_blank">æ¥çå·²ä¸ä¼ å票</el-link> |
| | | </div> |
| | | </el-form-item> |
| | | |
| | | <el-form-item v-if="auditForm.status === 1" label="å票ç¼å·" prop="invoiceNo"> |
| | | <el-input v-model="auditForm.invoiceNo" placeholder="请è¾å
¥å票ç¼å·" /> |
| | | </el-form-item> |
| | | |
| | | <!-- 驳忶å¿
填驳ååå --> |
| | | <el-form-item |
| | | label="å®¡æ ¸å¤æ³¨" |
| | | prop="auditRemarks" |
| | | :rules="auditForm.status === 2 ? [{ required: true, message: '请è¾å
¥é©³ååå ', trigger: 'blur' }] : []" |
| | | > |
| | | <el-input |
| | | type="textarea" |
| | | v-model="auditForm.auditRemarks" |
| | | :rows="4" |
| | | :placeholder="auditForm.status === 2 ? '请è¾å
¥é©³ååå ï¼å¿
å¡«ï¼' : '请è¾å
¥å®¡æ ¸æè§ï¼å¯éï¼'" |
| | | /> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <!-- æä½æé® --> |
| | | <div class="action-bar"> |
| | | <el-button @click="goBack">å æ¶</el-button> |
| | | <el-button type="primary" @click="submitAudit" :loading="submitting">æäº¤å®¡æ ¸</el-button> |
| | | </div> |
| | | </el-card> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import { getInvoice, updateInvoice } from "@/api/system/invoice"; |
| | | import { getToken } from "@/utils/auth"; |
| | | import { Message } from 'element-ui'; |
| | | |
| | | export default { |
| | | name: "InvoiceAudit", |
| | | data() { |
| | | return { |
| | | // åç¥¨ä¿¡æ¯ |
| | | invoice: {}, |
| | | // å®¡æ ¸è¡¨å |
| | | auditForm: { |
| | | invoiceId: null, |
| | | status: 1, |
| | | invoiceNo: null, |
| | | invoiceUrl: null, |
| | | auditRemarks: null |
| | | }, |
| | | // ä¸ä¼ ç¸å
³ |
| | | uploadAction: process.env.VUE_APP_BASE_API + "/common/upload", |
| | | uploadHeaders: { Authorization: "Bearer " + getToken() }, |
| | | fileList: [], |
| | | // æäº¤ç¶æ |
| | | submitting: false, |
| | | // 表åéªè¯ |
| | | rules: { |
| | | status: [{ required: true, message: "è¯·éæ©å®¡æ ¸ç»æ", trigger: "change" }] |
| | | } |
| | | }; |
| | | }, |
| | | created() { |
| | | const invoiceId = this.$route.query.invoiceId; |
| | | if (invoiceId) { |
| | | this.getDetail(invoiceId); |
| | | } else { |
| | | this.$modal.msgError("缺å°å票IDåæ°"); |
| | | this.goBack(); |
| | | } |
| | | }, |
| | | methods: { |
| | | /** è·åå票详æ
*/ |
| | | getDetail(invoiceId) { |
| | | getInvoice(invoiceId).then(response => { |
| | | this.invoice = response.data; |
| | | this.auditForm.invoiceId = response.data.invoiceId; |
| | | |
| | | // 妿已æå票æä»¶ï¼æ¾ç¤ºå¨æä»¶åè¡¨ä¸ |
| | | if (response.data.invoiceUrl) { |
| | | this.auditForm.invoiceUrl = response.data.invoiceUrl; |
| | | this.fileList = [{ |
| | | name: 'å·²ä¸ä¼ å票', |
| | | url: response.data.invoiceUrl |
| | | }]; |
| | | } |
| | | }).catch(() => { |
| | | this.$modal.msgError("è·åå票详æ
失败"); |
| | | this.goBack(); |
| | | }); |
| | | }, |
| | | |
| | | /** ç¶æååå¤ç */ |
| | | handleStatusChange(value) { |
| | | // åæ¢ç¶ææ¶æ¸
ç©ºå®¡æ ¸å¤æ³¨ |
| | | this.auditForm.auditRemarks = ''; |
| | | }, |
| | | |
| | | /** æä»¶ä¸ä¼ åéªè¯ */ |
| | | beforeUpload(file) { |
| | | const isLt10M = file.size / 1024 / 1024 < 10; |
| | | if (!isLt10M) { |
| | | Message.error('ä¸ä¼ æä»¶å¤§å°ä¸è½è¶
è¿ 10MB!'); |
| | | return false; |
| | | } |
| | | const fileType = file.type; |
| | | const isPDF = fileType === 'application/pdf'; |
| | | const isImage = fileType.startsWith('image/'); |
| | | if (!isPDF && !isImage) { |
| | | Message.error('åªè½ä¸ä¼ PDFæå¾çæä»¶!'); |
| | | return false; |
| | | } |
| | | return true; |
| | | }, |
| | | |
| | | /** æä»¶ä¸ä¼ æå */ |
| | | handleUploadSuccess(response, file, fileList) { |
| | | if (response.code === 200) { |
| | | this.auditForm.invoiceUrl = response.url || response.fileName; |
| | | this.fileList = fileList; |
| | | Message.success('ä¸ä¼ æå'); |
| | | } else { |
| | | Message.error(response.msg || 'ä¸ä¼ 失败'); |
| | | } |
| | | }, |
| | | |
| | | /** æä»¶ä¸ä¼ 失败 */ |
| | | handleUploadError(err, file, fileList) { |
| | | Message.error('ä¸ä¼ 失败ï¼è¯·éè¯'); |
| | | console.error(err); |
| | | }, |
| | | |
| | | /** æäº¤å®¡æ ¸ */ |
| | | submitAudit() { |
| | | this.$refs["auditForm"].validate(valid => { |
| | | if (valid) { |
| | | // å®¡æ ¸éè¿æ¶å¿
é¡»ä¸ä¼ å票 |
| | | if (this.auditForm.status === 1 && !this.auditForm.invoiceUrl) { |
| | | this.$modal.msgError('å®¡æ ¸éè¿æ¶å¿
é¡»ä¸ä¼ å票æä»¶'); |
| | | return; |
| | | } |
| | | // 驳忶å¿
须填å驳ååå |
| | | if (this.auditForm.status === 2 && !this.auditForm.auditRemarks) { |
| | | this.$modal.msgError('驳忶å¿
须填å驳ååå '); |
| | | return; |
| | | } |
| | | |
| | | this.submitting = true; |
| | | updateInvoice(this.auditForm).then(response => { |
| | | this.$modal.msgSuccess("å®¡æ ¸æå"); |
| | | this.goBack(); |
| | | }).catch(() => { |
| | | this.submitting = false; |
| | | }); |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | /** è¿åå表 */ |
| | | goBack() { |
| | | this.$tab.closePage(); |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .card-title { |
| | | font-size: 18px; |
| | | font-weight: bold; |
| | | color: #303133; |
| | | } |
| | | |
| | | .action-bar { |
| | | border-top: 1px solid #EBEEF5; |
| | | padding-top: 20px; |
| | | text-align: center; |
| | | } |
| | | |
| | | ::v-deep .el-form-item__label { |
| | | font-weight: 500; |
| | | } |
| | | |
| | | ::v-deep .el-divider__text { |
| | | font-size: 16px; |
| | | font-weight: bold; |
| | | color: #409EFF; |
| | | } |
| | | </style> |
| New file |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <el-card class="box-card"> |
| | | <div slot="header" class="clearfix"> |
| | | <span class="card-title">å票ç³è¯·è¯¦æ
</span> |
| | | <el-button style="float: right; padding: 3px 0" type="text" @click="goBack">è¿å</el-button> |
| | | </div> |
| | | |
| | | <el-descriptions :column="2" border> |
| | | <!-- åºæ¬ä¿¡æ¯ --> |
| | | <el-descriptions-item label="å票ID">{{ invoice.invoiceId }}</el-descriptions-item> |
| | | <el-descriptions-item label="æå¡åå·">{{ invoice.serviceCode || invoice.legacyServiceOrderId || '-' }}</el-descriptions-item> |
| | | |
| | | <el-descriptions-item label="å¼ç¥¨ç±»å"> |
| | | <el-tag :type="invoice.invoiceType === 2 ? 'success' : 'info'" size="small"> |
| | | {{ invoice.invoiceType === 2 ? 'ä¼ä¸' : '个人' }} |
| | | </el-tag> |
| | | </el-descriptions-item> |
| | | |
| | | <el-descriptions-item label="ç³è¯·ç¶æ"> |
| | | <el-tag :type="invoice.status === 1 ? 'success' : (invoice.status === 2 ? 'danger' : 'warning')" size="small"> |
| | | {{ statusFormat(invoice.status) }} |
| | | </el-tag> |
| | | </el-descriptions-item> |
| | | |
| | | <!-- åç¥¨ä¿¡æ¯ --> |
| | | <el-descriptions-item label="å票æ¬å¤´" :span="2">{{ invoice.invoiceName }}</el-descriptions-item> |
| | | <el-descriptions-item label="å票éé¢"> |
| | | <span class="text-price">Â¥{{ formatMoney(invoice.invoiceMoney) }}</span> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="å票ç¼å·">{{ invoice.invoiceNo || '-' }}</el-descriptions-item> |
| | | |
| | | <!-- èç³»ä¿¡æ¯ --> |
| | | <el-descriptions-item label="è系人">{{ invoice.contactName || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="èç³»çµè¯">{{ invoice.contactPhone || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="èç³»é®ç®±" :span="2">{{ invoice.contactEmail || '-' }}</el-descriptions-item> |
| | | |
| | | <!-- ä¼ä¸ä¿¡æ¯ï¼ä»
ä¼ä¸ç±»åæ¾ç¤ºï¼ --> |
| | | <template v-if="invoice.invoiceType === 2"> |
| | | <el-descriptions-item label="注åå°å" :span="2">{{ invoice.companyAddress || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="弿·é¶è¡">{{ invoice.companyBank || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="é¶è¡è´¦å·">{{ invoice.companyBankNo || '-' }}</el-descriptions-item> |
| | | </template> |
| | | |
| | | <!-- é®å¯ä¿¡æ¯ --> |
| | | <el-descriptions-item label="é®å¯å°å" :span="2">{{ invoice.mailAddress || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="é®ç¼">{{ invoice.zipCode || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="夿³¨" :span="2">{{ invoice.invoiceRemarks || '-' }}</el-descriptions-item> |
| | | |
| | | <!-- æ¶é´ä¿¡æ¯ --> |
| | | <el-descriptions-item label="ç³è¯·æ¶é´">{{ parseTime(invoice.applyTime) }}</el-descriptions-item> |
| | | <el-descriptions-item label="å®¡æ ¸æ¶é´">{{ parseTime(invoice.auditTime) || '-' }}</el-descriptions-item> |
| | | |
| | | <!-- å®¡æ ¸ä¿¡æ¯ --> |
| | | <el-descriptions-item label="å®¡æ ¸å¤æ³¨" :span="2"> |
| | | <span :class="invoice.status === 2 ? 'text-danger' : ''">{{ invoice.auditRemarks || '-' }}</span> |
| | | </el-descriptions-item> |
| | | |
| | | <!-- åæ¥ç¶æ --> |
| | | <el-descriptions-item label="åæ¥ç¶æ"> |
| | | <el-tag |
| | | :type="invoice.syncStatus === 1 ? 'success' : (invoice.syncStatus === 2 ? 'danger' : 'info')" |
| | | size="small" |
| | | > |
| | | {{ syncStatusFormat(invoice.syncStatus) }} |
| | | </el-tag> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="æ§ç³»ç»å票ID"> |
| | | <span v-if="invoice.legacyInvoiceId">{{ invoice.legacyInvoiceId }}</span> |
| | | <span v-else class="text-gray">æªåæ¥</span> |
| | | </el-descriptions-item> |
| | | |
| | | <!-- å票æä»¶ --> |
| | | <el-descriptions-item label="å票æä»¶" :span="2" v-if="invoice.invoiceUrl"> |
| | | <el-link type="primary" :href="getFullUrl(invoice.invoiceUrl)" target="_blank" icon="el-icon-view"> |
| | | æ¥çå票æä»¶ |
| | | </el-link> |
| | | <el-link type="success" :href="getFullUrl(invoice.invoiceUrl)" :download="getFileName(invoice.invoiceUrl)" icon="el-icon-download" style="margin-left: 10px;"> |
| | | ä¸è½½å票 |
| | | </el-link> |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | |
| | | <!-- æä½æé® --> |
| | | <div class="action-bar" style="margin-top: 20px; text-align: center;"> |
| | | <el-button @click="goBack">è¿åå表</el-button> |
| | | <el-button |
| | | type="primary" |
| | | v-if="invoice.status === 0" |
| | | @click="handleAudit" |
| | | v-hasPermi="['system:invoice:edit']" |
| | | > |
| | | å®¡æ ¸ |
| | | </el-button> |
| | | <el-button |
| | | type="success" |
| | | v-if="invoice.invoiceUrl" |
| | | @click="handleDownload" |
| | | icon="el-icon-download" |
| | | > |
| | | ä¸è½½å票 |
| | | </el-button> |
| | | <!-- 忥æé®ï¼åªæå·²éè¿ä¸æªåæ¥æåæ¥å¤±è´¥æ¶æ¾ç¤º --> |
| | | <el-button |
| | | type="warning" |
| | | v-if="invoice.status === 1 && (!invoice.legacyInvoiceId || invoice.syncStatus === 2)" |
| | | @click="handleSync" |
| | | :loading="syncing" |
| | | icon="el-icon-refresh" |
| | | v-hasPermi="['system:invoice:edit']" |
| | | > |
| | | {{ syncing ? '忥ä¸...' : '忥尿§ç³»ç»' }} |
| | | </el-button> |
| | | </div> |
| | | </el-card> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import { getInvoice, syncInvoiceToLegacy } from "@/api/system/invoice"; |
| | | |
| | | export default { |
| | | name: "InvoiceDetail", |
| | | data() { |
| | | return { |
| | | // å票详æ
æ°æ® |
| | | invoice: { |
| | | invoiceId: null, |
| | | serviceOrderId: null, |
| | | legacyServiceOrderId: null, |
| | | serviceCode: null, |
| | | invoiceType: null, |
| | | invoiceName: null, |
| | | invoiceMoney: null, |
| | | invoiceRemarks: null, |
| | | companyAddress: null, |
| | | companyBank: null, |
| | | companyBankNo: null, |
| | | zipCode: null, |
| | | mailAddress: null, |
| | | contactName: null, |
| | | contactPhone: null, |
| | | contactEmail: null, |
| | | status: null, |
| | | invoiceNo: null, |
| | | invoiceUrl: null, |
| | | applyTime: null, |
| | | auditTime: null, |
| | | auditRemarks: null, |
| | | syncStatus: null, |
| | | legacyInvoiceId: null |
| | | }, |
| | | // åæ¥ç¶æ |
| | | syncing: false |
| | | }; |
| | | }, |
| | | created() { |
| | | const invoiceId = this.$route.params.invoiceId || this.$route.query.invoiceId; |
| | | if (invoiceId) { |
| | | this.getDetail(invoiceId); |
| | | } else { |
| | | this.$modal.msgError("缺å°å票IDåæ°"); |
| | | this.goBack(); |
| | | } |
| | | }, |
| | | methods: { |
| | | /** è·åå票详æ
*/ |
| | | getDetail(invoiceId) { |
| | | getInvoice(invoiceId).then(response => { |
| | | this.invoice = response.data; |
| | | }).catch(() => { |
| | | this.$modal.msgError("è·åå票详æ
失败"); |
| | | this.goBack(); |
| | | }); |
| | | }, |
| | | |
| | | /** ç¶ææ ¼å¼å */ |
| | | statusFormat(status) { |
| | | const map = { 0: "å¾
å®¡æ ¸", 1: "å·²éè¿", 2: "已驳å" }; |
| | | return map[status] || "æªç¥"; |
| | | }, |
| | | |
| | | /** é颿 ¼å¼å */ |
| | | formatMoney(money) { |
| | | if (money === null || money === undefined) return '0.00'; |
| | | return Number(money).toFixed(2); |
| | | }, |
| | | |
| | | /** åæ¥ç¶ææ ¼å¼å */ |
| | | syncStatusFormat(status) { |
| | | const map = { 0: "æªåæ¥", 1: "已忥", 2: "åæ¥å¤±è´¥" }; |
| | | return map[status] || "æªç¥"; |
| | | }, |
| | | |
| | | /** è·å宿´çæä»¶URL */ |
| | | getFullUrl(url) { |
| | | if (!url) return ''; |
| | | if (url.startsWith('http')) { |
| | | return url; |
| | | } |
| | | return process.env.VUE_APP_BASE_API + url; |
| | | }, |
| | | |
| | | /** è·åæä»¶å */ |
| | | getFileName(url) { |
| | | if (!url) return 'å票æä»¶'; |
| | | const parts = url.split('/'); |
| | | return parts[parts.length - 1] || 'å票æä»¶'; |
| | | }, |
| | | |
| | | /** è¿åå表 */ |
| | | goBack() { |
| | | this.$tab.closePage(); |
| | | }, |
| | | |
| | | /** 跳转å°å®¡æ ¸é¡µé¢ */ |
| | | handleAudit() { |
| | | this.$router.push({ |
| | | path: '/system/invoice/audit', |
| | | query: { invoiceId: this.invoice.invoiceId } |
| | | }); |
| | | }, |
| | | |
| | | /** ä¸è½½å票 */ |
| | | handleDownload() { |
| | | const url = this.getFullUrl(this.invoice.invoiceUrl); |
| | | window.open(url); |
| | | }, |
| | | |
| | | /** 忥尿§ç³»ç» */ |
| | | handleSync() { |
| | | this.$modal.confirm('确认å°è¯¥å票ç³è¯·åæ¥å°æ§ç³»ç»åï¼').then(() => { |
| | | this.syncing = true; |
| | | syncInvoiceToLegacy(this.invoice.invoiceId).then(response => { |
| | | this.$modal.msgSuccess('忥æå'); |
| | | // éæ°å 载详æ
|
| | | this.getDetail(this.invoice.invoiceId); |
| | | }).catch(() => { |
| | | this.$modal.msgError('åæ¥å¤±è´¥'); |
| | | }).finally(() => { |
| | | this.syncing = false; |
| | | }); |
| | | }).catch(() => {}); |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .card-title { |
| | | font-size: 18px; |
| | | font-weight: bold; |
| | | color: #303133; |
| | | } |
| | | |
| | | .text-price { |
| | | color: #F56C6C; |
| | | font-size: 16px; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | .text-danger { |
| | | color: #F56C6C; |
| | | } |
| | | |
| | | .text-gray { |
| | | color: #909399; |
| | | } |
| | | |
| | | .action-bar { |
| | | border-top: 1px solid #EBEEF5; |
| | | padding-top: 20px; |
| | | } |
| | | |
| | | ::v-deep .el-descriptions-item__label { |
| | | font-weight: bold; |
| | | width: 120px; |
| | | } |
| | | </style> |
| New file |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="80px"> |
| | | <el-form-item label="æå¡åå·" prop="serviceCode"> |
| | | <el-input |
| | | v-model="queryParams.serviceCode" |
| | | placeholder="请è¾å
¥æå¡åå·ï¼å¦GZ202602ï¼" |
| | | clearable |
| | | @keyup.enter.native="handleQuery" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="åå
¬å¸" prop="serviceOrdClass"> |
| | | <el-select v-model="queryParams.serviceOrdClass" placeholder="è¯·éæ©åå
¬å¸" clearable> |
| | | <el-option |
| | | v-for="dept in branchOptions" |
| | | :key="dept.serviceOrderClass" |
| | | :label="dept.deptName" |
| | | :value="dept.serviceOrderClass" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="å¼ç¥¨æ¬å¤´" prop="invoiceName"> |
| | | <el-input |
| | | v-model="queryParams.invoiceName" |
| | | placeholder="请è¾å
¥å票æ¬å¤´" |
| | | clearable |
| | | @keyup.enter.native="handleQuery" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="ç³è¯·ç¶æ" prop="status"> |
| | | <el-select v-model="queryParams.status" placeholder="è¯·éæ©ç¶æ" clearable> |
| | | <el-option label="å¾
å®¡æ ¸" :value="0" /> |
| | | <el-option label="å·²éè¿" :value="1" /> |
| | | <el-option label="已驳å" :value="2" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="ç³è¯·æ¶é´"> |
| | | <el-date-picker |
| | | v-model="dateRange" |
| | | style="width: 240px" |
| | | value-format="yyyy-MM-dd" |
| | | type="daterange" |
| | | range-separator="-" |
| | | start-placeholder="å¼å§æ¥æ" |
| | | end-placeholder="ç»ææ¥æ" |
| | | ></el-date-picker> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">æç´¢</el-button> |
| | | <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">éç½®</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <el-row :gutter="10" class="mb8"> |
| | | <el-col :span="1.5"> |
| | | <el-button |
| | | type="warning" |
| | | plain |
| | | icon="el-icon-download" |
| | | size="mini" |
| | | @click="handleExport" |
| | | v-hasPermi="['system:invoice:export']" |
| | | >导åº</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button |
| | | type="info" |
| | | plain |
| | | icon="el-icon-refresh" |
| | | size="mini" |
| | | @click="handleSync" |
| | | v-hasRole="['admin']" |
| | | >忥æ§ç³»ç»ç¶æ</el-button> |
| | | </el-col> |
| | | <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> |
| | | </el-row> |
| | | |
| | | <el-table v-loading="loading" :data="invoiceList" @selection-change="handleSelectionChange"> |
| | | <el-table-column type="selection" width="55" align="center" /> |
| | | <el-table-column label="ID" align="center" prop="invoiceId" width="80" /> |
| | | <el-table-column label="æå¡åå·" align="center" prop="serviceCode" width="150" /> |
| | | <el-table-column label="å¼ç¥¨æ¬å¤´" align="center" prop="invoiceName" width="150" /> |
| | | <el-table-column label="éé¢" align="center" prop="invoiceMoney" width="100" /> |
| | | <el-table-column label="ç±»å" align="center" prop="invoiceType"> |
| | | <template slot-scope="scope"> |
| | | <el-tag :type="scope.row.invoiceType === 2 ? 'success' : 'info'"> |
| | | {{ scope.row.invoiceType === 2 ? 'ä¼ä¸' : '个人' }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="ç¶æ" align="center" prop="status"> |
| | | <template slot-scope="scope"> |
| | | <el-tag :type="scope.row.status === 1 ? 'success' : (scope.row.status === 2 ? 'danger' : 'warning')"> |
| | | {{ statusFormat(scope.row.status) }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="å票ç¼å·" align="center" prop="invoiceNo" /> |
| | | <el-table-column label="ç³è¯·æ¶é´" align="center" prop="applyTime" width="180"> |
| | | <template slot-scope="scope"> |
| | | <span>{{ parseTime(scope.row.applyTime) }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="æä½" align="center" class-name="small-padding fixed-width"> |
| | | <template slot-scope="scope"> |
| | | <el-button |
| | | size="mini" |
| | | type="text" |
| | | icon="el-icon-view" |
| | | @click="handleView(scope.row)" |
| | | >详æ
</el-button> |
| | | <el-button |
| | | size="mini" |
| | | type="text" |
| | | icon="el-icon-edit" |
| | | @click="handleUpdate(scope.row)" |
| | | v-hasPermi="['system:invoice:edit']" |
| | | v-if="scope.row.status === 0" |
| | | >å®¡æ ¸</el-button> |
| | | <el-button |
| | | size="mini" |
| | | type="text" |
| | | icon="el-icon-download" |
| | | v-if="scope.row.invoiceUrl" |
| | | @click="handleDownload(scope.row)" |
| | | >ä¸è½½å票</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <pagination |
| | | v-show="total>0" |
| | | :total="total" |
| | | :page.sync="queryParams.pageNum" |
| | | :limit.sync="queryParams.pageSize" |
| | | @pagination="getList" |
| | | /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import { listInvoice, syncInvoiceStatus } from "@/api/system/invoice"; |
| | | import { listBranchByOaOrderClass } from "@/api/system/dept"; |
| | | |
| | | export default { |
| | | name: "Invoice", |
| | | data() { |
| | | return { |
| | | // é®ç½©å± |
| | | loading: true, |
| | | // é䏿°ç» |
| | | ids: [], |
| | | // éå个ç¦ç¨ |
| | | single: true, |
| | | // éå¤ä¸ªç¦ç¨ |
| | | multiple: true, |
| | | // æ¾ç¤ºæç´¢æ¡ä»¶ |
| | | showSearch: true, |
| | | // æ»æ¡æ° |
| | | total: 0, |
| | | // å票ç³è¯·è¡¨æ ¼æ°æ® |
| | | invoiceList: [], |
| | | // åå
¬å¸é项 |
| | | branchOptions: [], |
| | | // æ¥æèå´ |
| | | dateRange: [], |
| | | // æ¥è¯¢åæ° |
| | | queryParams: { |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | serviceCode: null, |
| | | invoiceName: null, |
| | | status: null, |
| | | serviceOrdClass: null |
| | | } |
| | | }; |
| | | }, |
| | | created() { |
| | | this.getList(); |
| | | this.getBranchList(); |
| | | }, |
| | | methods: { |
| | | /** æ¥è¯¢åå
¬å¸å表 */ |
| | | getBranchList() { |
| | | listBranchByOaOrderClass().then(response => { |
| | | this.branchOptions = response.data; |
| | | }); |
| | | }, |
| | | /** æ¥è¯¢å票ç³è¯·å表 */ |
| | | getList() { |
| | | this.loading = true; |
| | | const params = this.addDateRange(this.queryParams, this.dateRange); |
| | | // å° serviceOrdClass æ¾å
¥ params åæ®µä¸ï¼å¯¹åºåå° XML ä¸ç params.serviceOrdClass |
| | | if (this.queryParams.serviceOrdClass) { |
| | | params['params[serviceOrdClass]'] = this.queryParams.serviceOrdClass; |
| | | } |
| | | // serviceCode æ¥è¯¢ |
| | | if (this.queryParams.serviceCode) { |
| | | params['params[serviceCode]'] = this.queryParams.serviceCode; |
| | | } |
| | | listInvoice(params).then(response => { |
| | | this.invoiceList = response.rows; |
| | | this.total = response.total; |
| | | this.loading = false; |
| | | }); |
| | | }, |
| | | // å¤éæ¡é䏿°æ® |
| | | handleSelectionChange(selection) { |
| | | this.ids = selection.map(item => item.invoiceId) |
| | | this.single = selection.length!==1 |
| | | this.multiple = !selection.length |
| | | }, |
| | | // ç¶æåå
¸è½¬ä¹ |
| | | statusFormat(status) { |
| | | const map = { 0: "å¾
å®¡æ ¸", 1: "å·²éè¿", 2: "已驳å" }; |
| | | return map[status] || "æªç¥"; |
| | | }, |
| | | /** æç´¢æé®æä½ */ |
| | | handleQuery() { |
| | | this.queryParams.pageNum = 1; |
| | | this.getList(); |
| | | }, |
| | | /** éç½®æé®æä½ */ |
| | | resetQuery() { |
| | | this.dateRange = []; |
| | | this.resetForm("queryForm"); |
| | | this.handleQuery(); |
| | | }, |
| | | /** 详æ
æé®æä½ */ |
| | | handleView(row) { |
| | | this.$router.push({ |
| | | path: '/system/invoice/detail', |
| | | query: { invoiceId: row.invoiceId } |
| | | }); |
| | | }, |
| | | /** å®¡æ ¸æé®æä½ */ |
| | | handleUpdate(row) { |
| | | this.$router.push({ |
| | | path: '/system/invoice/audit', |
| | | query: { invoiceId: row.invoiceId } |
| | | }); |
| | | }, |
| | | /** å¯¼åºæé®æä½ */ |
| | | handleExport() { |
| | | this.download('system/invoice/export', { |
| | | ...this.queryParams |
| | | }, `invoice_${new Date().getTime()}.xlsx`) |
| | | }, |
| | | /** 忥æé®æä½ */ |
| | | handleSync() { |
| | | this.loading = true; |
| | | syncInvoiceStatus().then(() => { |
| | | this.$modal.msgSuccess("忥æå"); |
| | | this.getList(); |
| | | }).finally(() => { |
| | | this.loading = false; |
| | | }); |
| | | }, |
| | | /** ä¸è½½å票æä½ */ |
| | | handleDownload(row) { |
| | | window.open(row.invoiceUrl); |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | |
| | | <span v-if="taskDetail.emergencyInfo.dispatchSyncErrorMsg" style="color: #F56C6C;">{{ taskDetail.emergencyInfo.dispatchSyncErrorMsg }}</span> |
| | | <span v-else style="color: #C0C4CC;">--</span> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="ä»»å¡ç¶æåæ¥" :span="2"> |
| | | <el-alert |
| | | title="æç¤ºï¼ä»»å¡ç¶æä¼èªå¨åæ¥å°æ§ç³»ç»çè°åº¦åä¸ï¼å¦æå ç½ç»çåå æªåæ¥ï¼å¯ç¹å»ä¸æ¹æé®æå¨åæ¥ã" |
| | | type="info" |
| | | :closable="false" |
| | | show-icon |
| | | style="margin-bottom: 10px;"> |
| | | </el-alert> |
| | | <el-button |
| | | v-if="taskDetail.emergencyInfo.legacyDispatchOrdId && taskDetail.emergencyInfo.legacyDispatchOrdId > 0" |
| | | type="warning" |
| | | size="small" |
| | | icon="el-icon-refresh" |
| | | :loading="syncingTaskStatus" |
| | | @click="syncTaskStatus" |
| | | >忥任å¡ç¶æå°æ§ç³»ç»</el-button> |
| | | <el-tag v-else type="info" size="small"> |
| | | <i class="el-icon-warning"></i> 请å
忥è°åº¦å |
| | | </el-tag> |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | |
| | | <!-- æ¯ä»ä¿¡æ¯ï¼ä»
æ¥æè½¬è¿ä»»å¡æ¾ç¤ºï¼ --> |
| | | <el-card v-if="taskDetail.taskType === 'EMERGENCY_TRANSFER' && paymentInfo" class="box-card" style="margin-top: 20px;"> |
| | | <div slot="header" class="clearfix"> |
| | | <span>æ¯ä»ä¿¡æ¯</span> |
| | | <!-- 已宿䏿ªç³è¯·åç¥¨æ¶æ¾ç¤ºç³è¯·å票æé® --> |
| | | <el-button |
| | | v-if="canApplyInvoice" |
| | | style="float: right; padding: 3px 0" |
| | | type="text" |
| | | @click="handleApplyInvoice" |
| | | v-hasPermi="['system:invoice:add']" |
| | | > |
| | | <i class="el-icon-document-add"></i> ç³è¯·å票 |
| | | </el-button> |
| | | </div> |
| | | |
| | | <!-- æ¯ä»æ¦è§ --> |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | import { getTask, updateTask, assignTask, changeTaskStatus, uploadAttachment, deleteAttachment, getTaskVehicles, getAvailableVehicles, assignVehiclesToTask, unassignVehicleFromTask, getPaymentInfo, syncServiceOrder, syncDispatchOrder } from "@/api/task"; |
| | | import { getTask, updateTask, assignTask, changeTaskStatus, uploadAttachment, deleteAttachment, getTaskVehicles, getAvailableVehicles, assignVehiclesToTask, unassignVehicleFromTask, getPaymentInfo, syncServiceOrder, syncDispatchOrder, syncTaskStatus } from "@/api/task"; |
| | | import { listUser } from "@/api/system/user"; |
| | | import { getToken } from "@/utils/auth"; |
| | | |
| | |
| | | }, |
| | | // 忥å è½½ç¶æ |
| | | syncingServiceOrder: false, |
| | | syncingDispatchOrder: false |
| | | syncingDispatchOrder: false, |
| | | syncingTaskStatus: false, |
| | | // å票ç³è¯·ç¶æ |
| | | hasInvoiceApplied: false, |
| | | invoiceStatus: null // 0-å¾
å®¡æ ¸, 1-å·²éè¿, 2-已驳å |
| | | }; |
| | | }, |
| | | created() { |
| | |
| | | this.getAdditionalFeeList(); |
| | | // åå§åä¸ä¼ URL |
| | | this.uploadUrl = process.env.VUE_APP_BASE_API + "/task/attachment/upload/" + this.$route.params.taskId; |
| | | // æ£æ¥å票ç³è¯·ç¶æ |
| | | this.checkInvoiceStatus(); |
| | | }, |
| | | computed: { |
| | | /** æ¯å¦å¯ä»¥ç³è¯·å票 */ |
| | | canApplyInvoice() { |
| | | // åªææ¥æè½¬è¿ä»»å¡ |
| | | if (this.taskDetail.taskType !== 'EMERGENCY_TRANSFER') return false; |
| | | // ä»»å¡å¿
须已宿 |
| | | if (this.taskDetail.taskStatus !== 'COMPLETED') return false; |
| | | // æªç³è¯·è¿åç¥¨ï¼æè
æ¾è¢«é©³å |
| | | return !this.hasInvoiceApplied || this.invoiceStatus === 2; |
| | | } |
| | | }, |
| | | methods: { |
| | | /** è·åä»»å¡è¯¦æ
*/ |
| | |
| | | }).then(() => { |
| | | this.$modal.msgSuccess("æå¡å忥æå"); |
| | | // éæ°å 载任å¡è¯¦æ
|
| | | this.getDetail(); |
| | | this.getTaskDetail(); |
| | | }).catch(() => { |
| | | // å¤çåæ¶åé误 |
| | | }).finally(() => { |
| | |
| | | }).then(() => { |
| | | this.$modal.msgSuccess("è°åº¦å忥æå"); |
| | | // éæ°å 载任å¡è¯¦æ
|
| | | this.getDetail(); |
| | | this.getTaskDetail(); |
| | | }).catch(() => { |
| | | // å¤çåæ¶åé误 |
| | | }).finally(() => { |
| | | this.syncingDispatchOrder = false; |
| | | }); |
| | | }, |
| | | /** æå¨åæ¥ä»»å¡ç¶æ */ |
| | | syncTaskStatus() { |
| | | this.$modal.confirm('æ¯å¦ç¡®è®¤åæ¥ä»»å¡ç¶æå°æ§ç³»ç»ï¼').then(() => { |
| | | this.syncingTaskStatus = true; |
| | | return syncTaskStatus(this.taskDetail.taskId); |
| | | }).then(() => { |
| | | this.$modal.msgSuccess("ä»»å¡ç¶æåæ¥æå"); |
| | | // éæ°å 载任å¡è¯¦æ
|
| | | this.getTaskDetail(); |
| | | }).catch(() => { |
| | | // å¤çåæ¶åé误 |
| | | }).finally(() => { |
| | | this.syncingTaskStatus = false; |
| | | }); |
| | | }, |
| | | |
| | | /** æ£æ¥å票ç³è¯·ç¶æ */ |
| | | checkInvoiceStatus() { |
| | | // è°ç¨å端æ¥å£æ£æ¥è¯¥ä»»å¡æ¯å¦å·²ç³è¯·å票 |
| | | this.$axios.get(`/system/invoice/checkTaskInvoice/${this.$route.params.taskId}`) |
| | | .then(response => { |
| | | if (response.code === 200 && response.data) { |
| | | this.hasInvoiceApplied = true; |
| | | this.invoiceStatus = response.data.status; |
| | | } |
| | | }) |
| | | .catch(() => { |
| | | // 忽ç¥é误ï¼é»è®¤æªç³è¯· |
| | | }); |
| | | }, |
| | | |
| | | /** ç³è¯·å票 */ |
| | | handleApplyInvoice() { |
| | | // 跳转å°å票ç³è¯·é¡µé¢ï¼å¸¦ä¸ä»»å¡ä¿¡æ¯ |
| | | const taskInfo = { |
| | | taskId: this.taskDetail.taskId, |
| | | taskCode: this.taskDetail.taskCode || this.taskDetail.showTaskCode, |
| | | legacyServiceOrderId: this.taskDetail.emergencyInfo?.legacyServiceOrdId, |
| | | serviceCode: this.taskDetail.emergencyInfo?.serviceCode, |
| | | departure: this.taskDetail.departureAddress, |
| | | destination: this.taskDetail.destinationAddress, |
| | | completionTime: this.parseTime(this.taskDetail.actualEndTime), |
| | | transferPrice: this.paymentInfo?.transferPrice || this.paymentInfo?.totalAmount |
| | | }; |
| | | |
| | | // å°ä»»å¡ä¿¡æ¯åå¨å° sessionStorage |
| | | sessionStorage.setItem('invoiceTaskInfo', JSON.stringify(taskInfo)); |
| | | |
| | | // 跳转å°å票ç³è¯·é¡µé¢ |
| | | this.$router.push({ |
| | | path: '/system/invoice/apply', |
| | | query: { taskId: this.taskDetail.taskId } |
| | | }); |
| | | } |
| | | } |
| | | }; |
| | |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="åå
¬å¸" prop="deptId"> |
| | | <el-select |
| | | v-model="queryParams.deptId" |
| | | placeholder="è¯·éæ©åå
¬å¸" |
| | | clearable |
| | | filterable |
| | | style="width: 200px" |
| | | > |
| | | <el-option |
| | | v-for="dept in branchList" |
| | | :key="dept.deptId" |
| | | :label="dept.deptName" |
| | | :value="dept.deptId" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="车çå·" prop="vehicleNo"> |
| | | <el-input |
| | | v-model="queryParams.vehicleNo" |
| | |
| | | <script> |
| | | import { listTask, getTask, delTask, addTask, updateTask, assignTask, changeTaskStatus } from "@/api/task"; |
| | | import { listUser } from "@/api/system/user"; |
| | | import { listBranchByOa } from "@/api/system/dept"; |
| | | |
| | | export default { |
| | | name: "Task", |
| | |
| | | taskCode: null, |
| | | taskType: null, |
| | | taskStatus: null, |
| | | deptId: null, |
| | | vehicleNo: null, |
| | | plannedStartTimeBegin: null, |
| | | plannedStartTimeEnd: null, |
| | |
| | | statusForm: {}, |
| | | // ç¨æ·å表 |
| | | userList: [], |
| | | // åå
¬å¸å表 |
| | | branchList: [], |
| | | // è¡¨åæ ¡éª |
| | | rules: { |
| | | taskType: [ |
| | |
| | | created() { |
| | | this.getList(); |
| | | this.getUserList(); |
| | | this.getBranchList(); |
| | | }, |
| | | methods: { |
| | | /** æ¥è¯¢ä»»å¡ç®¡çå表 */ |
| | |
| | | this.userList = response.rows; |
| | | }); |
| | | }, |
| | | /** æ¥è¯¢åå
¬å¸å表 */ |
| | | getBranchList() { |
| | | listBranchByOa().then(response => { |
| | | this.branchList = response.data || []; |
| | | }).catch(() => { |
| | | this.branchList = []; |
| | | }); |
| | | }, |
| | | // åæ¶æé® |
| | | cancel() { |
| | | this.open = false; |
| New file |
| | |
| | | create table InvoiceData( |
| | | InvoiceID int no 4 10 0 no (n/a) (n/a) NULL |
| | | ServiceOrderIDPK bigint no 8 19 0 yes (n/a) (n/a) NULL |
| | | InvoiceType int no 4 10 0 yes (n/a) (n/a) NULL |
| | | InvoiceName nvarchar no 100 yes (n/a) (n/a) Chinese_PRC_CI_AS |
| | | InvoiceMakeout nvarchar no 2000 yes (n/a) (n/a) Chinese_PRC_CI_AS |
| | | InvoiceCompanyPhone nvarchar no 100 yes (n/a) (n/a) Chinese_PRC_CI_AS |
| | | InvoiceCompanyID nvarchar no 100 yes (n/a) (n/a) Chinese_PRC_CI_AS |
| | | InvoiceCompanyAdd nvarchar no 200 yes (n/a) (n/a) Chinese_PRC_CI_AS |
| | | InvoiceCompanyBank nvarchar no 100 yes (n/a) (n/a) Chinese_PRC_CI_AS |
| | | InvoiceCompanyBankNo nvarchar no 100 yes (n/a) (n/a) Chinese_PRC_CI_AS |
| | | InvoiceZipCode nvarchar no 100 yes (n/a) (n/a) Chinese_PRC_CI_AS |
| | | Invoice_strAdd nvarchar no 200 yes (n/a) (n/a) Chinese_PRC_CI_AS |
| | | Invoice_strName nvarchar no 100 yes (n/a) (n/a) Chinese_PRC_CI_AS |
| | | Invoice_strPhone nvarchar no 100 yes (n/a) (n/a) Chinese_PRC_CI_AS |
| | | Invoice_strEmail nvarchar no 100 yes (n/a) (n/a) Chinese_PRC_CI_AS |
| | | ApplicationTime datetime no 8 yes (n/a) (n/a) NULL |
| | | AuditTime datetime no 8 yes (n/a) (n/a) NULL |
| | | AuditStatus int no 4 10 0 yes (n/a) (n/a) NULL |
| | | AuditOAID int no 4 10 0 yes (n/a) (n/a) NULL |
| | | AuditMakeout nvarchar no 200 yes (n/a) (n/a) Chinese_PRC_CI_AS |
| | | InvoiceMoney money no 8 19 4 yes (n/a) (n/a) NULL |
| | | InvoiceNo nvarchar no 100 yes (n/a) (n/a) Chinese_PRC_CI_AS |
| | | InvoiceURL nvarchar no 2000 yes (n/a) (n/a) Chinese_PRC_CI_AS |
| | | InvoiceOddNo nvarchar no 400 yes (n/a) (n/a) Chinese_PRC_CI_AS |
| | | EleCloud_ZTDM nvarchar no 100 yes (n/a) (n/a) Chinese_PRC_CI_AS |
| | | EleCloud_ZTXX nvarchar no 200 yes (n/a) (n/a) Chinese_PRC_CI_AS |
| | | EleCloud_PDF nvarchar no 200 yes (n/a) (n/a) Chinese_PRC_CI_AS |
| | | EleCloud_Time datetime no 8 yes (n/a) (n/a) NULL |
| | | ApplyOAID int no 4 10 0 yes (n/a) (n/a) NULL |
| | | ) |
| New file |
| | |
| | | -- ---------------------------- |
| | | -- 1ãå票管ç主èå |
| | | -- ---------------------------- |
| | | insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark) |
| | | values('å票管ç', '1', '10', 'invoice', 'system/invoice/index', 1, 0, 'C', '0', '0', 'system:invoice:list', 'edit', 'admin', sysdate(), 'å票ç³è¯·ç®¡çèå'); |
| | | |
| | | -- è·åååæå
¥çèåID (éç¨äºMySQL) |
| | | set @parentId = LAST_INSERT_ID(); |
| | | |
| | | -- ---------------------------- |
| | | -- 2ãå票管çç¸å
³æé®æé |
| | | -- ---------------------------- |
| | | -- æ¥è¯¢æé |
| | | insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark) |
| | | values('å票æ¥è¯¢', @parentId, '1', '', '', 1, 0, 'F', '0', '0', 'system:invoice:query', '#', 'admin', sysdate(), ''); |
| | | |
| | | -- ä¿®æ¹/å®¡æ ¸æé |
| | | insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark) |
| | | values('åç¥¨å®¡æ ¸', @parentId, '2', '', '', 1, 0, 'F', '0', '0', 'system:invoice:edit', '#', 'admin', sysdate(), ''); |
| | | |
| | | -- å 餿é |
| | | insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark) |
| | | values('å票å é¤', @parentId, '3', '', '', 1, 0, 'F', '0', '0', 'system:invoice:remove', '#', 'admin', sysdate(), ''); |
| | | |
| | | -- å¯¼åºæé |
| | | insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark) |
| | | values('å票导åº', @parentId, '4', '', '', 1, 0, 'F', '0', '0', 'system:invoice:export', '#', 'admin', sysdate(), ''); |
| New file |
| | |
| | | -- 仿§ç³»ç»åæ¥å票信æ¯å°æ°ç³»ç»çSQLèæ¬ |
| | | -- 忥æ§ç³»ç»çåç¥¨æ°æ®å°æ°ç³»ç»ï¼é¿å
éå¤åæ¥ |
| | | |
| | | -- æ¹æ¡1: 使ç¨INSERT IGNOREæå
¥æ°æ°æ® |
| | | INSERT IGNORE INTO sys_invoice ( |
| | | legacy_invoice_id, |
| | | legacy_service_order_id, |
| | | invoice_type, |
| | | invoice_name, |
| | | invoice_money, |
| | | invoice_remarks, |
| | | company_address, |
| | | company_bank, |
| | | company_bank_no, |
| | | zip_code, |
| | | mail_address, |
| | | contact_name, |
| | | contact_phone, |
| | | contact_email, |
| | | status, |
| | | invoice_no, |
| | | invoice_url, |
| | | apply_time, |
| | | audit_time, |
| | | audit_remarks, |
| | | sync_status |
| | | ) |
| | | SELECT |
| | | i.InvoiceID as legacy_invoice_id, |
| | | i.ServiceOrderIDPK as legacy_service_order_id, |
| | | CASE |
| | | WHEN i.InvoiceType = 1 THEN 1 -- 个人å票 |
| | | WHEN i.InvoiceType = 2 THEN 2 -- ä¼ä¸å票 |
| | | ELSE 1 -- é»è®¤ä¸ªäººå票 |
| | | END as invoice_type, |
| | | i.InvoiceName as invoice_name, |
| | | CAST(i.InvoiceMoney AS DECIMAL(10,2)) as invoice_money, |
| | | i.InvoiceMakeout as invoice_remarks, |
| | | i.InvoiceCompanyAdd as company_address, |
| | | i.InvoiceCompanyBank as company_bank, |
| | | i.InvoiceCompanyBankNo as company_bank_no, |
| | | i.InvoiceZipCode as zip_code, |
| | | i.Invoice_strAdd as mail_address, |
| | | i.Invoice_strName as contact_name, |
| | | i.Invoice_strPhone as contact_phone, |
| | | i.Invoice_strEmail as contact_email, |
| | | CASE |
| | | WHEN i.AuditStatus = 1 THEN 1 -- å·²éè¿ |
| | | WHEN i.AuditStatus = 2 THEN 2 -- 已驳å |
| | | ELSE 0 -- å¾
å®¡æ ¸ |
| | | END as status, |
| | | i.InvoiceNo as invoice_no, |
| | | COALESCE(i.InvoiceURL, i.EleCloud_PDF) as invoice_url, |
| | | i.ApplicationTime as apply_time, |
| | | i.AuditTime as audit_time, |
| | | i.AuditMakeout as audit_remarks, |
| | | 1 as sync_status -- æ è®°ä¸ºå·²åæ¥ |
| | | FROM InvoiceData i |
| | | WHERE i.InvoiceID NOT IN ( |
| | | SELECT legacy_invoice_id |
| | | FROM sys_invoice |
| | | WHERE legacy_invoice_id IS NOT NULL |
| | | ); |
| | | |
| | | -- æ¹æ¡2: 使ç¨LEFT JOINç¡®ä¿åªæå
¥ä¸åå¨çè®°å½ |
| | | -- INSERT INTO sys_invoice ( |
| | | -- legacy_invoice_id, |
| | | -- legacy_service_order_id, |
| | | -- invoice_type, |
| | | -- invoice_name, |
| | | -- invoice_money, |
| | | -- invoice_remarks, |
| | | -- company_address, |
| | | -- company_bank, |
| | | -- company_bank_no, |
| | | -- zip_code, |
| | | -- mail_address, |
| | | -- contact_name, |
| | | -- contact_phone, |
| | | -- contact_email, |
| | | -- status, |
| | | -- invoice_no, |
| | | -- invoice_url, |
| | | -- apply_time, |
| | | -- audit_time, |
| | | -- audit_remarks, |
| | | -- sync_status |
| | | -- ) |
| | | -- SELECT |
| | | -- i.InvoiceID, |
| | | -- i.ServiceOrderIDPK, |
| | | -- CASE |
| | | -- WHEN i.InvoiceType = 1 THEN 1 |
| | | -- WHEN i.InvoiceType = 2 THEN 2 |
| | | -- ELSE 1 |
| | | -- END, |
| | | -- i.InvoiceName, |
| | | -- CAST(i.InvoiceMoney AS DECIMAL(10,2)), |
| | | -- i.InvoiceMakeout, |
| | | -- i.InvoiceCompanyAdd, |
| | | -- i.InvoiceCompanyBank, |
| | | -- i.InvoiceCompanyBankNo, |
| | | -- i.InvoiceZipCode, |
| | | -- i.Invoice_strAdd, |
| | | -- i.Invoice_strName, |
| | | -- i.Invoice_strPhone, |
| | | -- i.Invoice_strEmail, |
| | | -- CASE |
| | | -- WHEN i.AuditStatus = 1 THEN 1 |
| | | -- WHEN i.AuditStatus = 2 THEN 2 |
| | | -- ELSE 0 |
| | | -- END, |
| | | -- i.InvoiceNo, |
| | | -- COALESCE(i.InvoiceURL, i.EleCloud_PDF), |
| | | -- i.ApplicationTime, |
| | | -- i.AuditTime, |
| | | -- i.AuditMakeout, |
| | | -- 1 |
| | | -- FROM InvoiceData i |
| | | -- LEFT JOIN sys_invoice si ON i.InvoiceID = si.legacy_invoice_id |
| | | -- WHERE si.legacy_invoice_id IS NULL; |
| | | |
| | | -- æ´æ°ç»è®¡ä¿¡æ¯ |
| | | ANALYZE TABLE sys_invoice; |
| New file |
| | |
| | | -- åç¥¨åæ¥å®æ¶ä»»å¡é
ç½® |
| | | -- ç¨äºä»æ§ç³»ç»åæ¥å票信æ¯å°æ°ç³»ç» |
| | | |
| | | -- 1. å建åç¥¨åæ¥æ¥å¿è¡¨ |
| | | CREATE TABLE IF NOT EXISTS `sys_invoice_sync_log` ( |
| | | `log_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '忥æ¥å¿ID', |
| | | `sync_type` VARCHAR(50) NOT NULL COMMENT 'åæ¥ç±»å(invoice_info-å票信æ¯,invoice_status-åç¥¨ç¶æ)', |
| | | `sync_start_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '忥å¼å§æ¶é´', |
| | | `sync_end_time` DATETIME DEFAULT NULL COMMENT 'åæ¥ç»ææ¶é´', |
| | | `records_processed` INT(11) DEFAULT 0 COMMENT 'å¤çè®°å½æ°', |
| | | `records_success` INT(11) DEFAULT 0 COMMENT 'æåè®°å½æ°', |
| | | `records_failed` INT(11) DEFAULT 0 COMMENT 'å¤±è´¥è®°å½æ°', |
| | | `error_message` TEXT DEFAULT NULL COMMENT 'é误信æ¯', |
| | | `status` TINYINT(1) DEFAULT 0 COMMENT 'ç¶æ(0-å¤çä¸,1-æå,2-失败)', |
| | | PRIMARY KEY (`log_id`), |
| | | INDEX `idx_sync_type` (`sync_type`), |
| | | INDEX `idx_sync_start_time` (`sync_start_time`) |
| | | ) ENGINE=INNODB DEFAULT CHARSET=utf8mb4 COMMENT='åç¥¨åæ¥æ¥å¿è¡¨'; |
| | | |
| | | -- 2. æå
¥åç¥¨åæ¥å®æ¶ä»»å¡é
ç½® |
| | | DELETE FROM sys_job WHERE job_name = 'InvoiceSyncJob'; |
| | | INSERT INTO sys_job ( |
| | | job_name, |
| | | job_group, |
| | | invoke_target, |
| | | cron_expression, |
| | | misfire_policy, |
| | | concurrent, |
| | | status, |
| | | create_by, |
| | | create_time |
| | | ) VALUES ( |
| | | 'InvoiceSyncJob', |
| | | 'SYSTEM', |
| | | 'sysInvoiceTask.syncInvoiceFromLegacySystem', |
| | | '0 0/30 * * * ?', -- æ¯30åéæ§è¡ä¸æ¬¡ |
| | | '3', |
| | | '1', |
| | | '0', |
| | | 'admin', |
| | | NOW() |
| | | ); |
| | | |
| | | -- 3. 忥å票信æ¯çåå¨è¿ç¨ |
| | | DELIMITER $$ |
| | | |
| | | DROP PROCEDURE IF EXISTS sync_invoice_from_legacy$$ |
| | | |
| | | CREATE PROCEDURE sync_invoice_from_legacy() |
| | | BEGIN |
| | | DECLARE v_start_time DATETIME DEFAULT NOW(); |
| | | DECLARE v_error_msg TEXT DEFAULT ''; |
| | | DECLARE v_processed_count INT DEFAULT 0; |
| | | DECLARE v_success_count INT DEFAULT 0; |
| | | DECLARE v_failed_count INT DEFAULT 0; |
| | | DECLARE EXIT HANDLER FOR SQLEXCEPTION |
| | | BEGIN |
| | | GET DIAGNOSTICS CONDITION 1 |
| | | v_error_msg = MESSAGE_TEXT; |
| | | ROLLBACK; |
| | | END; |
| | | |
| | | START TRANSACTION; |
| | | |
| | | -- è®°å½å¼å§åæ¥ |
| | | INSERT INTO sys_invoice_sync_log (sync_type, sync_start_time, status) |
| | | VALUES ('invoice_info', v_start_time, 0); |
| | | |
| | | SET @log_id = LAST_INSERT_ID(); |
| | | |
| | | -- 忥æ°çåç¥¨è®°å½ |
| | | INSERT INTO sys_invoice ( |
| | | legacy_invoice_id, |
| | | legacy_service_order_id, |
| | | invoice_type, |
| | | invoice_name, |
| | | invoice_money, |
| | | invoice_remarks, |
| | | company_address, |
| | | company_bank, |
| | | company_bank_no, |
| | | zip_code, |
| | | mail_address, |
| | | contact_name, |
| | | contact_phone, |
| | | contact_email, |
| | | status, |
| | | invoice_no, |
| | | invoice_url, |
| | | apply_time, |
| | | audit_time, |
| | | audit_remarks, |
| | | sync_status |
| | | ) |
| | | SELECT |
| | | i.InvoiceID as legacy_invoice_id, |
| | | i.ServiceOrderIDPK as legacy_service_order_id, |
| | | CASE |
| | | WHEN i.InvoiceType = 1 THEN 1 -- 个人å票 |
| | | WHEN i.InvoiceType = 2 THEN 2 -- ä¼ä¸å票 |
| | | ELSE 1 -- é»è®¤ä¸ªäººå票 |
| | | END as invoice_type, |
| | | i.InvoiceName as invoice_name, |
| | | CAST(i.InvoiceMoney AS DECIMAL(10,2)) as invoice_money, |
| | | i.InvoiceMakeout as invoice_remarks, |
| | | i.InvoiceCompanyAdd as company_address, |
| | | i.InvoiceCompanyBank as company_bank, |
| | | i.InvoiceCompanyBankNo as company_bank_no, |
| | | i.InvoiceZipCode as zip_code, |
| | | i.Invoice_strAdd as mail_address, |
| | | i.Invoice_strName as contact_name, |
| | | i.Invoice_strPhone as contact_phone, |
| | | i.Invoice_strEmail as contact_email, |
| | | CASE |
| | | WHEN i.AuditStatus = 1 THEN 1 -- å·²éè¿ |
| | | WHEN i.AuditStatus = 2 THEN 2 -- 已驳å |
| | | ELSE 0 -- å¾
å®¡æ ¸ |
| | | END as status, |
| | | i.InvoiceNo as invoice_no, |
| | | COALESCE(i.InvoiceURL, i.EleCloud_PDF) as invoice_url, |
| | | i.ApplicationTime as apply_time, |
| | | i.AuditTime as audit_time, |
| | | i.AuditMakeout as audit_remarks, |
| | | 1 as sync_status -- æ è®°ä¸ºå·²åæ¥ |
| | | FROM InvoiceData i |
| | | WHERE i.InvoiceID NOT IN ( |
| | | SELECT legacy_invoice_id |
| | | FROM sys_invoice |
| | | WHERE legacy_invoice_id IS NOT NULL |
| | | ); |
| | | |
| | | SET v_processed_count = ROW_COUNT(); |
| | | SET v_success_count = v_processed_count; |
| | | |
| | | -- æ´æ°åæ¥æ¥å¿ |
| | | UPDATE sys_invoice_sync_log |
| | | SET |
| | | sync_end_time = NOW(), |
| | | records_processed = v_processed_count, |
| | | records_success = v_success_count, |
| | | records_failed = v_failed_count, |
| | | error_message = v_error_msg, |
| | | status = IF(v_error_msg = '', 1, 2) |
| | | WHERE log_id = @log_id; |
| | | |
| | | COMMIT; |
| | | END$$ |
| | | |
| | | DELIMITER ; |
| | | |
| | | -- 4. 忥åç¥¨ç¶æçåå¨è¿ç¨ |
| | | DELIMITER $$ |
| | | |
| | | DROP PROCEDURE IF EXISTS sync_invoice_status_from_legacy$$ |
| | | |
| | | CREATE PROCEDURE sync_invoice_status_from_legacy() |
| | | BEGIN |
| | | DECLARE v_start_time DATETIME DEFAULT NOW(); |
| | | DECLARE v_error_msg TEXT DEFAULT ''; |
| | | DECLARE v_processed_count INT DEFAULT 0; |
| | | DECLARE v_success_count INT DEFAULT 0; |
| | | DECLARE v_failed_count INT DEFAULT 0; |
| | | DECLARE EXIT HANDLER FOR SQLEXCEPTION |
| | | BEGIN |
| | | GET DIAGNOSTICS CONDITION 1 |
| | | v_error_msg = MESSAGE_TEXT; |
| | | ROLLBACK; |
| | | END; |
| | | |
| | | START TRANSACTION; |
| | | |
| | | -- è®°å½å¼å§åæ¥ |
| | | INSERT INTO sys_invoice_sync_log (sync_type, sync_start_time, status) |
| | | VALUES ('invoice_status', v_start_time, 0); |
| | | |
| | | SET @log_id = LAST_INSERT_ID(); |
| | | |
| | | -- æ´æ°ç°æå票çç¶æä¿¡æ¯ |
| | | UPDATE sys_invoice si |
| | | INNER JOIN InvoiceData i ON si.legacy_invoice_id = i.InvoiceID |
| | | SET |
| | | si.status = CASE |
| | | WHEN i.AuditStatus = 1 THEN 1 -- å·²éè¿ |
| | | WHEN i.AuditStatus = 2 THEN 2 -- 已驳å |
| | | ELSE 0 -- å¾
å®¡æ ¸ |
| | | END, |
| | | si.invoice_no = COALESCE(si.invoice_no, i.InvoiceNo), |
| | | si.invoice_url = COALESCE(si.invoice_url, i.InvoiceURL, i.EleCloud_PDF), |
| | | si.audit_time = i.AuditTime, |
| | | si.audit_remarks = i.AuditMakeout, |
| | | si.sync_status = 1 |
| | | WHERE si.legacy_invoice_id IS NOT NULL |
| | | AND ( |
| | | si.status != CASE |
| | | WHEN i.AuditStatus = 1 THEN 1 |
| | | WHEN i.AuditStatus = 2 THEN 2 |
| | | ELSE 0 |
| | | END |
| | | OR si.invoice_no IS NULL |
| | | OR si.invoice_url IS NULL |
| | | ); |
| | | |
| | | SET v_processed_count = ROW_COUNT(); |
| | | SET v_success_count = v_processed_count; |
| | | |
| | | -- æ´æ°åæ¥æ¥å¿ |
| | | UPDATE sys_invoice_sync_log |
| | | SET |
| | | sync_end_time = NOW(), |
| | | records_processed = v_processed_count, |
| | | records_success = v_success_count, |
| | | records_failed = v_failed_count, |
| | | error_message = v_error_msg, |
| | | status = IF(v_error_msg = '', 1, 2) |
| | | WHERE log_id = @log_id; |
| | | |
| | | COMMIT; |
| | | END$$ |
| | | |
| | | DELIMITER ; |
| | | |
| | | -- 5. æ¥è¯¢åç¥¨åæ¥æ¥å¿çè§å¾ |
| | | CREATE OR REPLACE VIEW v_invoice_sync_log AS |
| | | SELECT |
| | | l.log_id, |
| | | l.sync_type, |
| | | l.sync_start_time, |
| | | l.sync_end_time, |
| | | l.records_processed, |
| | | l.records_success, |
| | | l.records_failed, |
| | | l.error_message, |
| | | l.status, |
| | | CASE l.status |
| | | WHEN 0 THEN 'å¤çä¸' |
| | | WHEN 1 THEN 'æå' |
| | | WHEN 2 THEN '失败' |
| | | ELSE 'æªç¥' |
| | | END as status_name, |
| | | TIMESTAMPDIFF(SECOND, l.sync_start_time, l.sync_end_time) as duration_seconds |
| | | FROM sys_invoice_sync_log l |
| | | ORDER BY l.sync_start_time DESC; |
| | | |
| | | -- 6. æå¨æ§è¡å票信æ¯åæ¥ |
| | | -- CALL sync_invoice_from_legacy(); |
| | | |
| | | -- 7. æå¨æ§è¡åç¥¨ç¶æåæ¥ |
| | | -- CALL sync_invoice_status_from_legacy(); |
| New file |
| | |
| | | -- å票ç³è¯·è¡¨ |
| | | CREATE TABLE `sys_invoice` ( |
| | | `invoice_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT 'å票ID', |
| | | `service_order_id` BIGINT(20) DEFAULT NULL COMMENT 'æå¡åå·(æ°ç³»ç»è®¢åID)', |
| | | `legacy_service_order_id` BIGINT(20) DEFAULT NULL COMMENT 'æå¡åå·(æ§ç³»ç»ServiceOrderID)', |
| | | `invoice_type` INT(1) DEFAULT '1' COMMENT 'å¼ç¥¨ç±»å(1-个人, 2-ä¼ä¸)', |
| | | `invoice_name` VARCHAR(200) DEFAULT NULL COMMENT 'å票æ¬å¤´', |
| | | `invoice_money` DECIMAL(10,2) DEFAULT '0.00' COMMENT 'å票éé¢', |
| | | `invoice_remarks` VARCHAR(500) DEFAULT NULL COMMENT 'åç¥¨å¤æ³¨', |
| | | `company_address` VARCHAR(500) DEFAULT NULL COMMENT 'ä¼ä¸æ³¨åå°å', |
| | | `company_bank` VARCHAR(200) DEFAULT NULL COMMENT 'ä¼ä¸å¼æ·é¶è¡', |
| | | `company_bank_no` VARCHAR(100) DEFAULT NULL COMMENT 'ä¼ä¸é¶è¡å¸å·', |
| | | `zip_code` VARCHAR(20) DEFAULT NULL COMMENT 'é®ç¼', |
| | | `mail_address` VARCHAR(500) DEFAULT NULL COMMENT 'é®å¯å°å', |
| | | `contact_name` VARCHAR(50) DEFAULT NULL COMMENT 'è系人', |
| | | `contact_phone` VARCHAR(50) DEFAULT NULL COMMENT 'èç³»çµè¯', |
| | | `contact_email` VARCHAR(100) DEFAULT NULL COMMENT 'èç³»é®ç®±', |
| | | `status` INT(1) DEFAULT '0' COMMENT 'ç³è¯·ç¶æ(0-å¾
å®¡æ ¸, 1-å·²éè¿, 2-已驳å)', |
| | | `invoice_no` VARCHAR(100) DEFAULT NULL COMMENT 'å票ç¼å·(å¯¹åºæ§ç³»ç»InvoiceNo)', |
| | | `invoice_url` VARCHAR(2000) DEFAULT NULL COMMENT 'åç¥¨é¾æ¥/æä»¶å°å(å¯¹åºæ§ç³»ç»InvoiceURL/EleCloud_PDF)', |
| | | `apply_user_id` BIGINT(20) DEFAULT NULL COMMENT 'ç³è¯·äººID', |
| | | `apply_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT 'ç³è¯·æ¶é´', |
| | | `audit_user_id` BIGINT(20) DEFAULT NULL COMMENT 'å®¡æ ¸äººID', |
| | | `audit_time` DATETIME DEFAULT NULL COMMENT 'å®¡æ ¸æ¶é´', |
| | | `audit_remarks` VARCHAR(500) DEFAULT NULL COMMENT 'å®¡æ ¸å¤æ³¨', |
| | | `sync_status` INT(1) DEFAULT '0' COMMENT 'åæ¥ç¶æ(0-æªåæ¥, 1-已忥, 2-åæ¥å¤±è´¥)', |
| | | `legacy_invoice_id` INT(11) DEFAULT NULL COMMENT 'æ§ç³»ç»å票ID(å¯¹åºæ§ç³»ç»InvoiceID)', |
| | | PRIMARY KEY (`invoice_id`), |
| | | KEY `idx_service_order` (`service_order_id`), |
| | | KEY `idx_legacy_order` (`legacy_service_order_id`), |
| | | KEY `idx_apply_user` (`apply_user_id`) |
| | | ) ENGINE=INNODB DEFAULT CHARSET=utf8mb4 COMMENT='å票ç³è¯·è¡¨'; |
| New file |
| | |
| | | -- ======================================== |
| | | -- GPSåæ®µéç¨è¡¨ååºä¼å - å¿«éæ§è¡ç |
| | | -- ======================================== |
| | | -- éç¨åºæ¯ï¼æ°æ®ééä¸ï¼100ä¸-500ä¸ï¼ï¼å¯ä»¥æ¥åçæåæº |
| | | -- æ§è¡æ¶é´ï¼æ ¹æ®æ°æ®éï¼é¢è®¡5-30åé |
| | | -- ======================================== |
| | | |
| | | -- ç¬¬ä¸æ¥ï¼æ£æ¥å½åæ°æ®ç¶æ |
| | | -- ======================================== |
| | | USE your_database_name; -- 请修æ¹ä¸ºå®é
çæ°æ®åºå |
| | | |
| | | SELECT '=== å½åè¡¨ä¿¡æ¯ ===' as info; |
| | | SELECT |
| | | TABLE_NAME as '表å', |
| | | TABLE_ROWS as 'è®°å½æ°(ä¼°ç®)', |
| | | ROUND((DATA_LENGTH + INDEX_LENGTH) / 1024 / 1024, 2) AS '大å°(MB)' |
| | | FROM information_schema.TABLES |
| | | WHERE TABLE_SCHEMA = DATABASE() |
| | | AND TABLE_NAME = 'tb_vehicle_gps_segment_mileage'; |
| | | |
| | | SELECT '=== æ°æ®æ¶é´èå´ ===' as info; |
| | | SELECT |
| | | MIN(segment_start_time) as 'ææ©æ°æ®', |
| | | MAX(segment_start_time) as 'ææ°æ°æ®', |
| | | DATEDIFF(MAX(segment_start_time), MIN(segment_start_time)) as 'æ°æ®è·¨åº¦(天)' |
| | | FROM tb_vehicle_gps_segment_mileage; |
| | | |
| | | SELECT '=== æææ°æ®åå¸ ===' as info; |
| | | SELECT |
| | | DATE_FORMAT(segment_start_time, '%Y-%m') as 'æä»½', |
| | | COUNT(*) as 'è®°å½æ°', |
| | | ROUND(SUM(segment_distance), 2) as 'æ»éç¨(km)' |
| | | FROM tb_vehicle_gps_segment_mileage |
| | | GROUP BY DATE_FORMAT(segment_start_time, '%Y-%m') |
| | | ORDER BY 1 DESC |
| | | LIMIT 12; |
| | | |
| | | -- æåï¼è¯·æ£æ¥ä»¥ä¸ä¿¡æ¯ï¼ç¡®è®¤æ°æ®éåæ¶é´èå´ |
| | | -- æå车继ç»... |
| | | |
| | | -- ======================================== |
| | | -- ç¬¬äºæ¥ï¼å建ååºè¡¨ |
| | | -- ======================================== |
| | | |
| | | -- å建æ°çååºè¡¨ |
| | | CREATE TABLE `tb_vehicle_gps_segment_mileage_partitioned` ( |
| | | `segment_id` bigint(20) NOT NULL AUTO_INCREMENT, |
| | | `vehicle_id` bigint(20) NOT NULL, |
| | | `vehicle_no` varchar(20) DEFAULT NULL, |
| | | `segment_start_time` datetime NOT NULL, |
| | | `segment_end_time` datetime NOT NULL, |
| | | `start_longitude` decimal(10,7) DEFAULT NULL, |
| | | `start_latitude` decimal(10,7) DEFAULT NULL, |
| | | `end_longitude` decimal(10,7) DEFAULT NULL, |
| | | `end_latitude` decimal(10,7) DEFAULT NULL, |
| | | `segment_distance` decimal(10,3) DEFAULT 0.000, |
| | | `gps_point_count` int(11) DEFAULT 0, |
| | | `gps_ids` text, |
| | | `task_id` bigint(20) DEFAULT NULL, |
| | | `task_code` varchar(50) DEFAULT NULL, |
| | | `calculate_method` varchar(20) DEFAULT 'tianditu', |
| | | `create_time` datetime DEFAULT NULL, |
| | | `update_time` datetime DEFAULT NULL, |
| | | PRIMARY KEY (`segment_id`, `segment_start_time`), |
| | | UNIQUE KEY `uk_vehicle_time` (`vehicle_id`, `segment_start_time`), |
| | | KEY `idx_vehicle_id` (`vehicle_id`), |
| | | KEY `idx_start_time` (`segment_start_time`), |
| | | KEY `idx_task_id` (`task_id`), |
| | | KEY `idx_vehicle_task` (`vehicle_id`, `task_id`) |
| | | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 |
| | | COMMENT='车è¾GPSåæ®µéç¨è¡¨ï¼ææååºï¼' |
| | | PARTITION BY RANGE (TO_DAYS(segment_start_time)) ( |
| | | PARTITION p202401 VALUES LESS THAN (TO_DAYS('2024-02-01')), |
| | | PARTITION p202402 VALUES LESS THAN (TO_DAYS('2024-03-01')), |
| | | PARTITION p202403 VALUES LESS THAN (TO_DAYS('2024-04-01')), |
| | | PARTITION p202404 VALUES LESS THAN (TO_DAYS('2024-05-01')), |
| | | PARTITION p202405 VALUES LESS THAN (TO_DAYS('2024-06-01')), |
| | | PARTITION p202406 VALUES LESS THAN (TO_DAYS('2024-07-01')), |
| | | PARTITION p202407 VALUES LESS THAN (TO_DAYS('2024-08-01')), |
| | | PARTITION p202408 VALUES LESS THAN (TO_DAYS('2024-09-01')), |
| | | PARTITION p202409 VALUES LESS THAN (TO_DAYS('2024-10-01')), |
| | | PARTITION p202410 VALUES LESS THAN (TO_DAYS('2024-11-01')), |
| | | PARTITION p202411 VALUES LESS THAN (TO_DAYS('2024-12-01')), |
| | | PARTITION p202412 VALUES LESS THAN (TO_DAYS('2025-01-01')), |
| | | PARTITION p202501 VALUES LESS THAN (TO_DAYS('2025-02-01')), |
| | | PARTITION p202502 VALUES LESS THAN (TO_DAYS('2025-03-01')), |
| | | PARTITION p202503 VALUES LESS THAN (TO_DAYS('2025-04-01')), |
| | | PARTITION p202504 VALUES LESS THAN (TO_DAYS('2025-05-01')), |
| | | PARTITION p202505 VALUES LESS THAN (TO_DAYS('2025-06-01')), |
| | | PARTITION p202506 VALUES LESS THAN (TO_DAYS('2025-07-01')), |
| | | PARTITION p202507 VALUES LESS THAN (TO_DAYS('2025-08-01')), |
| | | PARTITION p202508 VALUES LESS THAN (TO_DAYS('2025-09-01')), |
| | | PARTITION p202509 VALUES LESS THAN (TO_DAYS('2025-10-01')), |
| | | PARTITION p202510 VALUES LESS THAN (TO_DAYS('2025-11-01')), |
| | | PARTITION p202511 VALUES LESS THAN (TO_DAYS('2025-12-01')), |
| | | PARTITION p202512 VALUES LESS THAN (TO_DAYS('2026-01-01')), |
| | | PARTITION p202601 VALUES LESS THAN (TO_DAYS('2026-02-01')), |
| | | PARTITION p202602 VALUES LESS THAN (TO_DAYS('2026-03-01')), |
| | | PARTITION p202603 VALUES LESS THAN (TO_DAYS('2026-04-01')), |
| | | PARTITION p202604 VALUES LESS THAN (TO_DAYS('2026-05-01')), |
| | | PARTITION p202605 VALUES LESS THAN (TO_DAYS('2026-06-01')), |
| | | PARTITION p202606 VALUES LESS THAN (TO_DAYS('2026-07-01')), |
| | | PARTITION p202607 VALUES LESS THAN (TO_DAYS('2026-08-01')), |
| | | PARTITION p202608 VALUES LESS THAN (TO_DAYS('2026-09-01')), |
| | | PARTITION p202609 VALUES LESS THAN (TO_DAYS('2026-10-01')), |
| | | PARTITION p202610 VALUES LESS THAN (TO_DAYS('2026-11-01')), |
| | | PARTITION p202611 VALUES LESS THAN (TO_DAYS('2026-12-01')), |
| | | PARTITION p202612 VALUES LESS THAN (TO_DAYS('2027-01-01')), |
| | | PARTITION pfuture VALUES LESS THAN MAXVALUE |
| | | ); |
| | | |
| | | SELECT 'ååºè¡¨å建æå' as result; |
| | | |
| | | -- ======================================== |
| | | -- ç¬¬ä¸æ¥ï¼è¿ç§»æ°æ® |
| | | -- ======================================== |
| | | SELECT 'å¼å§è¿ç§»æ°æ®...' as info, NOW() as start_time; |
| | | |
| | | -- 䏿¬¡æ§è¿ç§»ï¼éç¨äºæ°æ®éä¸è¶
è¿500ä¸ï¼ |
| | | INSERT INTO tb_vehicle_gps_segment_mileage_partitioned |
| | | SELECT * FROM tb_vehicle_gps_segment_mileage; |
| | | |
| | | SELECT 'æ°æ®è¿ç§»å®æ' as info, NOW() as end_time; |
| | | |
| | | -- ======================================== |
| | | -- ç¬¬åæ¥ï¼éªè¯æ°æ® |
| | | -- ======================================== |
| | | SELECT '=== æ°æ®éªè¯ ===' as info; |
| | | |
| | | -- æ¯è¾è®°å½æ° |
| | | SELECT |
| | | 'å表' as table_name, |
| | | COUNT(*) as record_count |
| | | FROM tb_vehicle_gps_segment_mileage |
| | | UNION ALL |
| | | SELECT |
| | | 'æ°è¡¨(ååº)' as table_name, |
| | | COUNT(*) as record_count |
| | | FROM tb_vehicle_gps_segment_mileage_partitioned; |
| | | |
| | | -- æ¯è¾ç»è®¡æ°æ® |
| | | SELECT |
| | | 'å表' as table_name, |
| | | SUM(segment_distance) as total_distance, |
| | | MIN(segment_start_time) as min_time, |
| | | MAX(segment_start_time) as max_time |
| | | FROM tb_vehicle_gps_segment_mileage |
| | | UNION ALL |
| | | SELECT |
| | | 'æ°è¡¨(ååº)' as table_name, |
| | | SUM(segment_distance) as total_distance, |
| | | MIN(segment_start_time) as min_time, |
| | | MAX(segment_start_time) as max_time |
| | | FROM tb_vehicle_gps_segment_mileage_partitioned; |
| | | |
| | | -- æ¥çååºåå¸ |
| | | SELECT |
| | | PARTITION_NAME as 'ååºå', |
| | | TABLE_ROWS as 'è®°å½æ°', |
| | | ROUND(DATA_LENGTH/1024/1024, 2) as 'æ°æ®(MB)', |
| | | ROUND(INDEX_LENGTH/1024/1024, 2) as 'ç´¢å¼(MB)' |
| | | FROM information_schema.PARTITIONS |
| | | WHERE TABLE_SCHEMA = DATABASE() |
| | | AND TABLE_NAME = 'tb_vehicle_gps_segment_mileage_partitioned' |
| | | ORDER BY PARTITION_ORDINAL_POSITION; |
| | | |
| | | -- æåï¼è¯·æ£æ¥æ°æ®æ¯å¦ä¸è´ |
| | | -- å¦ææ°æ®ä¸è´ï¼ç»§ç»æ§è¡ä¸ä¸æ¥ |
| | | -- 妿ä¸ä¸è´ï¼è¯·åæ¢å¹¶æ£æ¥é®é¢ |
| | | |
| | | -- ======================================== |
| | | -- ç¬¬äºæ¥ï¼åæ¢è¡¨åï¼è°¨æ
ï¼ï¼ |
| | | -- ======================================== |
| | | -- 建议å¨ä¸å¡åæºçªå£æ§è¡ä»¥ä¸æä½ |
| | | |
| | | -- START TRANSACTION; |
| | | |
| | | SELECT 'å¼å§åæ¢è¡¨å...' as info; |
| | | |
| | | -- éå½åå表为å¤ä»½è¡¨ |
| | | RENAME TABLE |
| | | tb_vehicle_gps_segment_mileage TO tb_vehicle_gps_segment_mileage_old, |
| | | tb_vehicle_gps_segment_mileage_partitioned TO tb_vehicle_gps_segment_mileage; |
| | | |
| | | SELECT '表å忢宿ï¼è¯·ç«å³éªè¯åºç¨åè½ï¼' as result; |
| | | |
| | | -- 妿æé®é¢ï¼ç«å³åæ»ï¼ |
| | | -- RENAME TABLE |
| | | -- tb_vehicle_gps_segment_mileage TO tb_vehicle_gps_segment_mileage_partitioned, |
| | | -- tb_vehicle_gps_segment_mileage_old TO tb_vehicle_gps_segment_mileage; |
| | | |
| | | -- COMMIT; |
| | | |
| | | -- ======================================== |
| | | -- 第å
æ¥ï¼éªè¯ååºææ |
| | | -- ======================================== |
| | | SELECT '=== æµè¯æ¥è¯¢æ§è½ ===' as info; |
| | | |
| | | -- æµè¯1ï¼æ¥è¯¢æè¿1ææ°æ®ï¼åºè¯¥åªæ«æ1个ååºï¼ |
| | | EXPLAIN PARTITIONS |
| | | SELECT COUNT(*), SUM(segment_distance) |
| | | FROM tb_vehicle_gps_segment_mileage |
| | | WHERE segment_start_time >= DATE_SUB(CURDATE(), INTERVAL 1 MONTH); |
| | | |
| | | -- æµè¯2ï¼æè½¦è¾IDæ¥è¯¢æè¿1卿°æ® |
| | | EXPLAIN PARTITIONS |
| | | SELECT * |
| | | FROM tb_vehicle_gps_segment_mileage |
| | | WHERE vehicle_id = 1 |
| | | AND segment_start_time >= DATE_SUB(NOW(), INTERVAL 7 DAY) |
| | | LIMIT 10; |
| | | |
| | | -- æµè¯3ï¼ç»è®¡æè¿3个æçéç¨ |
| | | SELECT |
| | | DATE_FORMAT(segment_start_time, '%Y-%m') as month, |
| | | COUNT(*) as segments, |
| | | ROUND(SUM(segment_distance), 2) as total_km |
| | | FROM tb_vehicle_gps_segment_mileage |
| | | WHERE segment_start_time >= DATE_SUB(CURDATE(), INTERVAL 3 MONTH) |
| | | GROUP BY DATE_FORMAT(segment_start_time, '%Y-%m'); |
| | | |
| | | -- ======================================== |
| | | -- ç¬¬ä¸æ¥ï¼æ¸
çåä¼åï¼å¯éï¼ |
| | | -- ======================================== |
| | | |
| | | -- 确认åºç¨è¿è¡æ£å¸¸åï¼çå¾
1-2å¨ï¼ç¶åå é¤å¤ä»½è¡¨ |
| | | -- DROP TABLE tb_vehicle_gps_segment_mileage_old; |
| | | |
| | | -- åæè¡¨ï¼ä¼åæ¥è¯¢è®¡å |
| | | ANALYZE TABLE tb_vehicle_gps_segment_mileage; |
| | | |
| | | -- ======================================== |
| | | -- å®æï¼ |
| | | -- ======================================== |
| | | SELECT '========================================' as info; |
| | | SELECT 'ååºä¼å宿ï¼' as result; |
| | | SELECT '请注æï¼' as notice; |
| | | SELECT '1. å®ææ·»å æ°æä»½çååº' as task1; |
| | | SELECT '2. 宿æ¸
çåå²ååºéæ¾ç©ºé´' as task2; |
| | | SELECT '3. æ¥è¯¢æ¶å°½é另䏿¶é´èå´æ¡ä»¶' as task3; |
| | | SELECT '========================================' as info; |
| | | |
| | | -- ======================================== |
| | | -- æ¥å¸¸ç»´æ¤å½ä»¤åè |
| | | -- ======================================== |
| | | |
| | | -- æ·»å æ°ååºï¼æ¯ææ§è¡ä¸æ¬¡ï¼ |
| | | -- ALTER TABLE tb_vehicle_gps_segment_mileage |
| | | -- REORGANIZE PARTITION pfuture INTO ( |
| | | -- PARTITION p202701 VALUES LESS THAN (TO_DAYS('2027-02-01')), |
| | | -- PARTITION pfuture VALUES LESS THAN MAXVALUE |
| | | -- ); |
| | | |
| | | -- å é¤åå²ååºï¼éæ¾ç©ºé´ï¼ |
| | | -- ALTER TABLE tb_vehicle_gps_segment_mileage DROP PARTITION p202401; |
| | | |
| | | -- æ¥çååºç¶æ |
| | | -- SELECT * FROM information_schema.PARTITIONS |
| | | -- WHERE TABLE_SCHEMA = DATABASE() |
| | | -- AND TABLE_NAME = 'tb_vehicle_gps_segment_mileage'; |
| New file |
| | |
| | | -- ======================================== |
| | | -- GPSåæ®µéç¨è¡¨ååºä¼åæ¹æ¡ |
| | | -- ======================================== |
| | | -- åè½è¯´æï¼ |
| | | -- 1. å° tb_vehicle_gps_segment_mileage 表ææè¿è¡ååº |
| | | -- 2. æé«å¤§æ°æ®éä¸çæ¥è¯¢æ§è½ |
| | | -- 3. æ¹ä¾¿å岿°æ®å½æ¡£åå é¤ |
| | | -- |
| | | -- 注æäºé¡¹ï¼ |
| | | -- 1. æ§è¡æ¤èæ¬å请å¤ä»½æ°æ®åºï¼ |
| | | -- 2. æ°æ®é大æ¶è½¬æ¢è¿ç¨è¾æ
¢ï¼å»ºè®®å¨ä¸å¡ä½å³°ææ§è¡ |
| | | -- 3. ååºå主é®åå¯ä¸é®å¿
é¡»å
å«ååºé®ï¼segment_start_timeï¼ |
| | | -- ======================================== |
| | | |
| | | -- æ¥éª¤1ï¼å¤ä»½åè¡¨æ°æ® |
| | | -- 建议å
æå¨æ§è¡ï¼mysqldump -uç¨æ·å -p æ°æ®åºå tb_vehicle_gps_segment_mileage > backup_segment_mileage.sql |
| | | |
| | | -- æ¥éª¤2ï¼å建æ°çååºè¡¨ |
| | | CREATE TABLE `tb_vehicle_gps_segment_mileage_new` ( |
| | | `segment_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'åæ®µID', |
| | | `vehicle_id` bigint(20) NOT NULL COMMENT '车è¾ID', |
| | | `vehicle_no` varchar(20) DEFAULT NULL COMMENT '车çå·', |
| | | `segment_start_time` datetime NOT NULL COMMENT 'æ¶é´æ®µå¼å§æ¶é´', |
| | | `segment_end_time` datetime NOT NULL COMMENT 'æ¶é´æ®µç»ææ¶é´', |
| | | `start_longitude` decimal(10,7) DEFAULT NULL COMMENT 'èµ·ç¹ç»åº¦', |
| | | `start_latitude` decimal(10,7) DEFAULT NULL COMMENT 'èµ·ç¹çº¬åº¦', |
| | | `end_longitude` decimal(10,7) DEFAULT NULL COMMENT 'ç»ç¹ç»åº¦', |
| | | `end_latitude` decimal(10,7) DEFAULT NULL COMMENT 'ç»ç¹çº¬åº¦', |
| | | `segment_distance` decimal(10,3) DEFAULT 0.000 COMMENT '段è·ç¦»(å
Ž)', |
| | | `gps_point_count` int(11) DEFAULT 0 COMMENT 'GPSç¹æ°é', |
| | | `gps_ids` text COMMENT 'å
³èçGPSè®°å½IDå表ï¼éå·åéï¼', |
| | | `task_id` bigint(20) DEFAULT NULL COMMENT 'å
³èä»»å¡ID', |
| | | `task_code` varchar(50) DEFAULT NULL COMMENT 'ä»»å¡ç¼å·', |
| | | `calculate_method` varchar(20) DEFAULT 'tianditu' COMMENT 'è®¡ç®æ¹å¼(tianditu-天å°å¾/haversine-çé¢è·ç¦»)', |
| | | `create_time` datetime DEFAULT NULL COMMENT 'å建æ¶é´', |
| | | `update_time` datetime DEFAULT NULL COMMENT 'æ´æ°æ¶é´', |
| | | PRIMARY KEY (`segment_id`, `segment_start_time`), |
| | | -- 注æï¼ååºè¡¨çå¯ä¸é®å¿
é¡»å
å«ååºé® |
| | | UNIQUE KEY `uk_vehicle_time` (`vehicle_id`, `segment_start_time`), |
| | | KEY `idx_vehicle_id` (`vehicle_id`), |
| | | KEY `idx_start_time` (`segment_start_time`), |
| | | KEY `idx_task_id` (`task_id`), |
| | | KEY `idx_vehicle_task` (`vehicle_id`, `task_id`), |
| | | KEY `idx_vehicle_date` (`vehicle_id`, `segment_start_time`) |
| | | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='车è¾GPSåæ®µéç¨è¡¨ï¼ååºçï¼' |
| | | PARTITION BY RANGE (TO_DAYS(segment_start_time)) ( |
| | | -- 2024å¹´ååº |
| | | PARTITION p202401 VALUES LESS THAN (TO_DAYS('2024-02-01')), |
| | | PARTITION p202402 VALUES LESS THAN (TO_DAYS('2024-03-01')), |
| | | PARTITION p202403 VALUES LESS THAN (TO_DAYS('2024-04-01')), |
| | | PARTITION p202404 VALUES LESS THAN (TO_DAYS('2024-05-01')), |
| | | PARTITION p202405 VALUES LESS THAN (TO_DAYS('2024-06-01')), |
| | | PARTITION p202406 VALUES LESS THAN (TO_DAYS('2024-07-01')), |
| | | PARTITION p202407 VALUES LESS THAN (TO_DAYS('2024-08-01')), |
| | | PARTITION p202408 VALUES LESS THAN (TO_DAYS('2024-09-01')), |
| | | PARTITION p202409 VALUES LESS THAN (TO_DAYS('2024-10-01')), |
| | | PARTITION p202410 VALUES LESS THAN (TO_DAYS('2024-11-01')), |
| | | PARTITION p202411 VALUES LESS THAN (TO_DAYS('2024-12-01')), |
| | | PARTITION p202412 VALUES LESS THAN (TO_DAYS('2025-01-01')), |
| | | |
| | | -- 2025å¹´ååº |
| | | PARTITION p202501 VALUES LESS THAN (TO_DAYS('2025-02-01')), |
| | | PARTITION p202502 VALUES LESS THAN (TO_DAYS('2025-03-01')), |
| | | PARTITION p202503 VALUES LESS THAN (TO_DAYS('2025-04-01')), |
| | | PARTITION p202504 VALUES LESS THAN (TO_DAYS('2025-05-01')), |
| | | PARTITION p202505 VALUES LESS THAN (TO_DAYS('2025-06-01')), |
| | | PARTITION p202506 VALUES LESS THAN (TO_DAYS('2025-07-01')), |
| | | PARTITION p202507 VALUES LESS THAN (TO_DAYS('2025-08-01')), |
| | | PARTITION p202508 VALUES LESS THAN (TO_DAYS('2025-09-01')), |
| | | PARTITION p202509 VALUES LESS THAN (TO_DAYS('2025-10-01')), |
| | | PARTITION p202510 VALUES LESS THAN (TO_DAYS('2025-11-01')), |
| | | PARTITION p202511 VALUES LESS THAN (TO_DAYS('2025-12-01')), |
| | | PARTITION p202512 VALUES LESS THAN (TO_DAYS('2026-01-01')), |
| | | |
| | | -- 2026å¹´ååº |
| | | PARTITION p202601 VALUES LESS THAN (TO_DAYS('2026-02-01')), |
| | | PARTITION p202602 VALUES LESS THAN (TO_DAYS('2026-03-01')), |
| | | PARTITION p202603 VALUES LESS THAN (TO_DAYS('2026-04-01')), |
| | | PARTITION p202604 VALUES LESS THAN (TO_DAYS('2026-05-01')), |
| | | PARTITION p202605 VALUES LESS THAN (TO_DAYS('2026-06-01')), |
| | | PARTITION p202606 VALUES LESS THAN (TO_DAYS('2026-07-01')), |
| | | PARTITION p202607 VALUES LESS THAN (TO_DAYS('2026-08-01')), |
| | | PARTITION p202608 VALUES LESS THAN (TO_DAYS('2026-09-01')), |
| | | PARTITION p202609 VALUES LESS THAN (TO_DAYS('2026-10-01')), |
| | | PARTITION p202610 VALUES LESS THAN (TO_DAYS('2026-11-01')), |
| | | PARTITION p202611 VALUES LESS THAN (TO_DAYS('2026-12-01')), |
| | | PARTITION p202612 VALUES LESS THAN (TO_DAYS('2027-01-01')), |
| | | |
| | | -- æªæ¥æ°æ®ååºï¼å¯ä»¥å®¹çº³2027å¹´å以åçæ°æ®ï¼ |
| | | PARTITION pfuture VALUES LESS THAN MAXVALUE |
| | | ); |
| | | |
| | | -- æ¥éª¤3ï¼è¿ç§»æ°æ®å°æ°è¡¨ |
| | | -- æ¹å¼1ï¼ä¸æ¬¡æ§è¿ç§»ï¼éç¨äºæ°æ®éè¾å°ï¼å¦100ä¸ä»¥ä¸ï¼ |
| | | -- INSERT INTO tb_vehicle_gps_segment_mileage_new SELECT * FROM tb_vehicle_gps_segment_mileage; |
| | | |
| | | -- æ¹å¼2ï¼åæ¹è¿ç§»ï¼éç¨äºå¤§æ°æ®éï¼æ¨èï¼ |
| | | -- ææä»½åæ¹è¿ç§»ï¼åå°é表æ¶é´ |
| | | -- 2024å¹´1æ |
| | | INSERT INTO tb_vehicle_gps_segment_mileage_new |
| | | SELECT * FROM tb_vehicle_gps_segment_mileage |
| | | WHERE segment_start_time >= '2024-01-01' AND segment_start_time < '2024-02-01'; |
| | | |
| | | -- 2024å¹´2æ |
| | | INSERT INTO tb_vehicle_gps_segment_mileage_new |
| | | SELECT * FROM tb_vehicle_gps_segment_mileage |
| | | WHERE segment_start_time >= '2024-02-01' AND segment_start_time < '2024-03-01'; |
| | | |
| | | -- ç»§ç»ææè¿ç§»...ï¼æ ¹æ®å®é
æ°æ®æ
åµè°æ´ï¼ |
| | | -- 2024å¹´3æè³12æ |
| | | INSERT INTO tb_vehicle_gps_segment_mileage_new |
| | | SELECT * FROM tb_vehicle_gps_segment_mileage |
| | | WHERE segment_start_time >= '2024-03-01' AND segment_start_time < '2025-01-01'; |
| | | |
| | | -- 2025å¹´æ°æ® |
| | | INSERT INTO tb_vehicle_gps_segment_mileage_new |
| | | SELECT * FROM tb_vehicle_gps_segment_mileage |
| | | WHERE segment_start_time >= '2025-01-01' AND segment_start_time < '2026-01-01'; |
| | | |
| | | -- 2026å¹´æ°æ® |
| | | INSERT INTO tb_vehicle_gps_segment_mileage_new |
| | | SELECT * FROM tb_vehicle_gps_segment_mileage |
| | | WHERE segment_start_time >= '2026-01-01'; |
| | | |
| | | -- æ¥éª¤4ï¼éªè¯æ°æ®ä¸è´æ§ |
| | | -- æ£æ¥åè¡¨åæ°è¡¨çè®°å½æ° |
| | | SELECT 'Original Table' as table_name, COUNT(*) as record_count FROM tb_vehicle_gps_segment_mileage |
| | | UNION ALL |
| | | SELECT 'New Table' as table_name, COUNT(*) as record_count FROM tb_vehicle_gps_segment_mileage_new; |
| | | |
| | | -- æ£æ¥åååºçæ°æ®é |
| | | SELECT |
| | | PARTITION_NAME, |
| | | TABLE_ROWS, |
| | | AVG_ROW_LENGTH, |
| | | DATA_LENGTH, |
| | | INDEX_LENGTH, |
| | | CREATE_TIME |
| | | FROM information_schema.PARTITIONS |
| | | WHERE TABLE_SCHEMA = DATABASE() |
| | | AND TABLE_NAME = 'tb_vehicle_gps_segment_mileage_new' |
| | | ORDER BY PARTITION_NAME; |
| | | |
| | | -- æ¥éª¤5ï¼åæ¢è¡¨åï¼è°¨æ
æä½ï¼ï¼ |
| | | -- 建议å¨ä¸å¡ä½å³°ææ§è¡ï¼æ´ä¸ªæä½åºå¨äºå¡ä¸å®æ |
| | | -- START TRANSACTION; |
| | | |
| | | -- éå½åå表为å¤ä»½è¡¨ |
| | | RENAME TABLE tb_vehicle_gps_segment_mileage TO tb_vehicle_gps_segment_mileage_backup; |
| | | |
| | | -- å°æ°è¡¨éå½å为æ£å¼è¡¨ |
| | | RENAME TABLE tb_vehicle_gps_segment_mileage_new TO tb_vehicle_gps_segment_mileage; |
| | | |
| | | -- 妿ä¸åæ£å¸¸ï¼æäº¤äºå¡ |
| | | -- COMMIT; |
| | | |
| | | -- 妿åºç°é®é¢ï¼åæ» |
| | | -- ROLLBACK; |
| | | |
| | | -- æ¥éª¤6ï¼éªè¯åºç¨æ£å¸¸è¿è¡ |
| | | -- 请å¨åºç¨å±æµè¯ä»¥ä¸åè½ï¼ |
| | | -- 1. GPSéç¨è®¡ç®åè½ |
| | | -- 2. 车è¾éç¨æ¥è¯¢ |
| | | -- 3. ä»»å¡éç¨ç»è®¡ |
| | | -- 4. ç¸å
³æ¥è¡¨åè½ |
| | | |
| | | -- æ¥éª¤7ï¼ç¡®è®¤æ 误åå é¤å¤ä»½è¡¨ï¼å¯éï¼å»ºè®®ä¿ç䏿®µæ¶é´ï¼ |
| | | -- DROP TABLE tb_vehicle_gps_segment_mileage_backup; |
| | | |
| | | -- ======================================== |
| | | -- ååºç»´æ¤æä½ï¼å®ææ§è¡ï¼ |
| | | -- ======================================== |
| | | |
| | | -- æ·»å æ°æä»½çååºï¼æ¯æææ¯å£åº¦æ§è¡ä¸æ¬¡ï¼ |
| | | -- ä¾å¦ï¼æ·»å 2027å¹´1æçååº |
| | | -- ALTER TABLE tb_vehicle_gps_segment_mileage |
| | | -- REORGANIZE PARTITION pfuture INTO ( |
| | | -- PARTITION p202701 VALUES LESS THAN (TO_DAYS('2027-02-01')), |
| | | -- PARTITION pfuture VALUES LESS THAN MAXVALUE |
| | | -- ); |
| | | |
| | | -- å é¤åå²ååºï¼å½æ¡£æ§æ°æ®ï¼éæ¾ç©ºé´ï¼ |
| | | -- ä¾å¦ï¼å é¤2024å¹´1æçæ°æ®ï¼å é¤å请确ä¿å·²å¤ä»½ï¼ |
| | | -- ALTER TABLE tb_vehicle_gps_segment_mileage DROP PARTITION p202401; |
| | | |
| | | -- æè
æ¸
空ååºæ°æ®ä½ä¿çååºç»æ |
| | | -- ALTER TABLE tb_vehicle_gps_segment_mileage TRUNCATE PARTITION p202401; |
| | | |
| | | -- ======================================== |
| | | -- æ§è½ä¼å建议 |
| | | -- ======================================== |
| | | |
| | | -- 1. æ¥è¯¢æ¶å°½é另䏿¶é´èå´æ¡ä»¶ï¼ä»¥å
åå©ç¨ååºè£åª |
| | | -- 示ä¾ï¼ |
| | | -- SELECT * FROM tb_vehicle_gps_segment_mileage |
| | | -- WHERE segment_start_time >= '2025-01-01' |
| | | -- AND segment_start_time < '2025-02-01' |
| | | -- AND vehicle_id = 123; |
| | | |
| | | -- 2. 宿åæè¡¨ä»¥ä¼åæ¥è¯¢è®¡å |
| | | -- ANALYZE TABLE tb_vehicle_gps_segment_mileage; |
| | | |
| | | -- 3. 宿ä¼åè¡¨ä»¥åæ¶ç©ºé´ |
| | | -- OPTIMIZE TABLE tb_vehicle_gps_segment_mileage; |
| | | |
| | | -- 4. æ¥çååºä½¿ç¨æ
åµ |
| | | SELECT |
| | | PARTITION_NAME as 'ååºå', |
| | | PARTITION_METHOD as 'ååºæ¹å¼', |
| | | PARTITION_EXPRESSION as 'ååºè¡¨è¾¾å¼', |
| | | TABLE_ROWS as 'è®°å½æ°', |
| | | ROUND(DATA_LENGTH/1024/1024, 2) as 'æ°æ®å¤§å°(MB)', |
| | | ROUND(INDEX_LENGTH/1024/1024, 2) as 'ç´¢å¼å¤§å°(MB)', |
| | | PARTITION_COMMENT as '夿³¨' |
| | | FROM information_schema.PARTITIONS |
| | | WHERE TABLE_SCHEMA = DATABASE() |
| | | AND TABLE_NAME = 'tb_vehicle_gps_segment_mileage' |
| | | ORDER BY PARTITION_ORDINAL_POSITION; |
| | | |
| | | -- ======================================== |
| | | -- ååºèªå¨ç»´æ¤èæ¬ï¼å»ºè®®é
ç½®å®æ¶ä»»å¡ï¼ |
| | | -- ======================================== |
| | | |
| | | DELIMITER $$ |
| | | |
| | | CREATE PROCEDURE add_gps_segment_partition() |
| | | BEGIN |
| | | DECLARE next_month_date DATE; |
| | | DECLARE partition_name VARCHAR(20); |
| | | DECLARE next_partition_date DATE; |
| | | |
| | | -- 计ç®ä¸ä¸ªæçæ¥æ |
| | | SET next_month_date = DATE_ADD(CURDATE(), INTERVAL 2 MONTH); |
| | | SET next_month_date = DATE_FORMAT(next_month_date, '%Y-%m-01'); |
| | | |
| | | -- çæååºåç§°ï¼ä¾å¦ï¼p202701ï¼ |
| | | SET partition_name = CONCAT('p', DATE_FORMAT(next_month_date, '%Y%m')); |
| | | |
| | | -- 计ç®ä¸ä¸ä¸ªååºçè¾¹çæ¥æ |
| | | SET next_partition_date = DATE_ADD(next_month_date, INTERVAL 1 MONTH); |
| | | |
| | | -- å¨ææ·»å ååº |
| | | SET @sql = CONCAT( |
| | | 'ALTER TABLE tb_vehicle_gps_segment_mileage ', |
| | | 'REORGANIZE PARTITION pfuture INTO (', |
| | | 'PARTITION ', partition_name, ' VALUES LESS THAN (TO_DAYS(''', next_partition_date, ''')),', |
| | | 'PARTITION pfuture VALUES LESS THAN MAXVALUE', |
| | | ')' |
| | | ); |
| | | |
| | | PREPARE stmt FROM @sql; |
| | | EXECUTE stmt; |
| | | DEALLOCATE PREPARE stmt; |
| | | |
| | | SELECT CONCAT('æåæ·»å ååº: ', partition_name, ', è¾¹çæ¥æ: ', next_partition_date) as result; |
| | | END$$ |
| | | |
| | | DELIMITER ; |
| | | |
| | | -- ä½¿ç¨æ¹æ³ï¼æ¯ææ§è¡ä¸æ¬¡ |
| | | -- CALL add_gps_segment_partition(); |
| | | |
| | | -- ======================================== |
| | | -- å岿°æ®å½æ¡£çç¥ï¼å¯éï¼ |
| | | -- ======================================== |
| | | |
| | | -- æ¹æ¡1ï¼å¯¼åºåå²ååºå°å½æ¡£è¡¨ |
| | | -- CREATE TABLE tb_vehicle_gps_segment_mileage_archive LIKE tb_vehicle_gps_segment_mileage; |
| | | -- ALTER TABLE tb_vehicle_gps_segment_mileage_archive REMOVE PARTITIONING; |
| | | -- INSERT INTO tb_vehicle_gps_segment_mileage_archive |
| | | -- SELECT * FROM tb_vehicle_gps_segment_mileage PARTITION(p202401); |
| | | |
| | | -- æ¹æ¡2ï¼å¯¼åºå°æä»¶ |
| | | -- SELECT * INTO OUTFILE '/tmp/gps_segment_202401.csv' |
| | | -- FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' |
| | | -- LINES TERMINATED BY '\n' |
| | | -- FROM tb_vehicle_gps_segment_mileage PARTITION(p202401); |
| | | |
| | | -- æ¹æ¡3ï¼å®æå é¤è¶
è¿N个æçå岿°æ® |
| | | -- ä¾å¦ï¼å é¤12个æä¹åçæ°æ® |
| | | -- ALTER TABLE tb_vehicle_gps_segment_mileage |
| | | -- DROP PARTITION p202401; |
| | | |
| | | -- ======================================== |
| | | -- çæ§ååè¦ï¼å»ºè®®ï¼ |
| | | -- ======================================== |
| | | |
| | | -- çæ§åååºçæ°æ®éå¢é¿ |
| | | CREATE VIEW v_gps_segment_partition_stats AS |
| | | SELECT |
| | | PARTITION_NAME as partition_name, |
| | | TABLE_ROWS as row_count, |
| | | ROUND(DATA_LENGTH/1024/1024, 2) as data_size_mb, |
| | | ROUND(INDEX_LENGTH/1024/1024, 2) as index_size_mb, |
| | | ROUND((DATA_LENGTH + INDEX_LENGTH)/1024/1024, 2) as total_size_mb, |
| | | CREATE_TIME as create_time, |
| | | UPDATE_TIME as update_time |
| | | FROM information_schema.PARTITIONS |
| | | WHERE TABLE_SCHEMA = DATABASE() |
| | | AND TABLE_NAME = 'tb_vehicle_gps_segment_mileage' |
| | | ORDER BY PARTITION_ORDINAL_POSITION; |
| | | |
| | | -- æ¥çååºç»è®¡ |
| | | -- SELECT * FROM v_gps_segment_partition_stats; |
| New file |
| | |
| | | # GPSåæ®µéç¨è¡¨ååºä¼åæ¹æ¡ |
| | | |
| | | ## ä¸ãé®é¢åæ |
| | | |
| | | ### å½åæ
åµ |
| | | - **表å**: `tb_vehicle_gps_segment_mileage` |
| | | - **æ°æ®ç¹ç¹**: æ5åéæ¶é´æ®µç»è®¡GPSéç¨ï¼æ°æ®éå¢é¿å¿« |
| | | - **主è¦é®é¢**: |
| | | - æ°æ®éå¤§å¯¼è´æ¥è¯¢åæ
¢ |
| | | - ç´¢å¼æçéä½ |
| | | - å岿°æ®é¾ä»¥æ¸
ç |
| | | |
| | | ### ååºä¼åæ¶ç |
| | | â
**æ¥è¯¢æ§è½æå**: éè¿ååºè£åªï¼æ¥è¯¢åªæ«æç¸å
³ååºï¼æ§è½æå50%-80% |
| | | â
**ç»´æ¤ç®å**: ææååºï¼å¯ä»¥å¿«éå 餿彿¡£å岿°æ® |
| | | â
**åå¨ä¼å**: ä¾¿äºæ°æ®å½æ¡£ï¼éæ¾ç£çç©ºé´ |
| | | â
**å¹¶åä¼å**: ä¸åååºå¯ä»¥å¹¶è¡æä½ï¼åå°éå²çª |
| | | |
| | | --- |
| | | |
| | | ## äºãååºæ¹æ¡è®¾è®¡ |
| | | |
| | | ### 1. ååºçç¥ |
| | | - **ååºç±»å**: RANGE ååºï¼ææ¶é´èå´ï¼ |
| | | - **ååºé®**: `segment_start_time`ï¼æ¶é´æ®µå¼å§æ¶é´ï¼ |
| | | - **ååºç²åº¦**: ææååº |
| | | - **ä¿ç卿**: 建议ä¿çæè¿12-24ä¸ªææ°æ® |
| | | |
| | | ### 2. ååºç»æ |
| | | ``` |
| | | 2024å¹´: p202401, p202402, ..., p202412 (12个ååº) |
| | | 2025å¹´: p202501, p202502, ..., p202512 (12个ååº) |
| | | 2026å¹´: p202601, p202602, ..., p202612 (12个ååº) |
| | | æªæ¥: pfuture (å®¹çº³æææªæ¥æ°æ®) |
| | | ``` |
| | | |
| | | ### 3. å
³é®åæ´ç¹ |
| | | â ï¸ **éè¦**: ååºè¡¨ç主é®åå¯ä¸é®å¿
é¡»å
å«ååºé® |
| | | |
| | | **åè¡¨ç»æ**: |
| | | ```sql |
| | | PRIMARY KEY (`segment_id`), |
| | | UNIQUE KEY `uk_vehicle_time` (`vehicle_id`, `segment_start_time`) |
| | | ``` |
| | | |
| | | **æ°è¡¨ç»æ**: |
| | | ```sql |
| | | PRIMARY KEY (`segment_id`, `segment_start_time`), -- 主é®å
å«ååºé® |
| | | UNIQUE KEY `uk_vehicle_time` (`vehicle_id`, `segment_start_time`) -- å·²å
å«ååºé® |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## ä¸ãæ§è¡æ¥éª¤ |
| | | |
| | | ### æ¥éª¤1: æ°æ®å¤ä»½ï¼å¿
é¡»ï¼ï¼ |
| | | ```bash |
| | | # å¤ä»½æ´ä¸ªæ°æ®åº |
| | | mysqldump -uç¨æ·å -p æ°æ®åºå > backup_$(date +%Y%m%d).sql |
| | | |
| | | # æåªå¤ä»½å表 |
| | | mysqldump -uç¨æ·å -p æ°æ®åºå tb_vehicle_gps_segment_mileage > backup_segment_mileage_$(date +%Y%m%d).sql |
| | | ``` |
| | | |
| | | ### æ¥éª¤2: æ¥çå½åæ°æ®é |
| | | ```sql |
| | | -- æ¥çæ»è®°å½æ° |
| | | SELECT COUNT(*) as total_records FROM tb_vehicle_gps_segment_mileage; |
| | | |
| | | -- æ¥çææåå¸ |
| | | SELECT |
| | | DATE_FORMAT(segment_start_time, '%Y-%m') as month, |
| | | COUNT(*) as record_count, |
| | | ROUND(COUNT(*) * 100.0 / (SELECT COUNT(*) FROM tb_vehicle_gps_segment_mileage), 2) as percentage |
| | | FROM tb_vehicle_gps_segment_mileage |
| | | GROUP BY DATE_FORMAT(segment_start_time, '%Y-%m') |
| | | ORDER BY month; |
| | | |
| | | -- æ¥çè¡¨å¤§å° |
| | | SELECT |
| | | TABLE_NAME, |
| | | ROUND((DATA_LENGTH + INDEX_LENGTH) / 1024 / 1024, 2) AS size_mb, |
| | | TABLE_ROWS |
| | | FROM information_schema.TABLES |
| | | WHERE TABLE_SCHEMA = DATABASE() |
| | | AND TABLE_NAME = 'tb_vehicle_gps_segment_mileage'; |
| | | ``` |
| | | |
| | | ### æ¥éª¤3: æ§è¡ååºèæ¬ |
| | | ```sql |
| | | -- å¨ä¸å¡ä½å³°ææ§è¡ partition_vehicle_gps_segment_mileage.sql |
| | | source d:/project/æ¥æè½¬è¿/code/Api/RuoYi-Vue-master/sql/partition_vehicle_gps_segment_mileage.sql |
| | | ``` |
| | | |
| | | **æåæ¥æ§è¡**: |
| | | 1. å建æ°ååºè¡¨ï¼`tb_vehicle_gps_segment_mileage_new`ï¼ |
| | | 2. åæ¹è¿ç§»æ°æ® |
| | | 3. éªè¯æ°æ®ä¸è´æ§ |
| | | 4. åæ¢è¡¨å |
| | | |
| | | ### æ¥éª¤4: éªè¯åºç¨åè½ |
| | | æµè¯ä»¥ä¸åè½æ¯å¦æ£å¸¸ï¼ |
| | | - â
GPSéç¨è®¡ç®ä»»å¡ |
| | | - â
车è¾éç¨æ¥è¯¢ |
| | | - â
ä»»å¡éç¨ç»è®¡ |
| | | - â
éç¨æ¥è¡¨ |
| | | |
| | | ### æ¥éª¤5: å é¤å¤ä»½è¡¨ï¼å¯éï¼ |
| | | ```sql |
| | | -- 确认è¿è¡æ£å¸¸åï¼å¯ä»¥å é¤å¤ä»½è¡¨ï¼å»ºè®®ä¿ç1-2å¨ï¼ |
| | | DROP TABLE tb_vehicle_gps_segment_mileage_backup; |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## åãæ¥å¸¸ç»´æ¤æä½ |
| | | |
| | | ### 1. æ·»å æ°æä»½ååºï¼æ¯ææ§è¡ï¼ |
| | | ```sql |
| | | -- æå¨æ·»å 2027å¹´2æååº |
| | | ALTER TABLE tb_vehicle_gps_segment_mileage |
| | | REORGANIZE PARTITION pfuture INTO ( |
| | | PARTITION p202702 VALUES LESS THAN (TO_DAYS('2027-03-01')), |
| | | PARTITION pfuture VALUES LESS THAN MAXVALUE |
| | | ); |
| | | |
| | | -- æä½¿ç¨åå¨è¿ç¨èªå¨æ·»å |
| | | CALL add_gps_segment_partition(); |
| | | ``` |
| | | |
| | | ### 2. å é¤åå²ååºï¼éæ¾ç©ºé´ï¼ |
| | | ```sql |
| | | -- æ¹å¼1: ç´æ¥å é¤ååºï¼æ°æ®ä¸å¯æ¢å¤ï¼ |
| | | ALTER TABLE tb_vehicle_gps_segment_mileage DROP PARTITION p202401; |
| | | |
| | | -- æ¹å¼2: 彿¡£åå é¤ |
| | | -- å
å¯¼åºæ°æ®å°å½æ¡£è¡¨ |
| | | CREATE TABLE tb_vehicle_gps_segment_mileage_archive_202401 |
| | | SELECT * FROM tb_vehicle_gps_segment_mileage PARTITION(p202401); |
| | | |
| | | -- ç¶åå é¤ååº |
| | | ALTER TABLE tb_vehicle_gps_segment_mileage DROP PARTITION p202401; |
| | | ``` |
| | | |
| | | ### 3. æ¥çååºç¶æ |
| | | ```sql |
| | | -- æ¥çææååºä¿¡æ¯ |
| | | SELECT * FROM v_gps_segment_partition_stats; |
| | | |
| | | -- æç´æ¥æ¥è¯¢ |
| | | SELECT |
| | | PARTITION_NAME as 'ååºå', |
| | | TABLE_ROWS as 'è®°å½æ°', |
| | | ROUND(DATA_LENGTH/1024/1024, 2) as 'æ°æ®(MB)', |
| | | ROUND(INDEX_LENGTH/1024/1024, 2) as 'ç´¢å¼(MB)' |
| | | FROM information_schema.PARTITIONS |
| | | WHERE TABLE_SCHEMA = DATABASE() |
| | | AND TABLE_NAME = 'tb_vehicle_gps_segment_mileage' |
| | | ORDER BY PARTITION_ORDINAL_POSITION; |
| | | ``` |
| | | |
| | | ### 4. ä¼åååº |
| | | ```sql |
| | | -- åæè¡¨ï¼æ´æ°ç»è®¡ä¿¡æ¯ï¼ |
| | | ANALYZE TABLE tb_vehicle_gps_segment_mileage; |
| | | |
| | | -- ä¼å表ï¼åæ¶ç¢ç空é´ï¼ |
| | | OPTIMIZE TABLE tb_vehicle_gps_segment_mileage; |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## äºãæ¥è¯¢ä¼å建议 |
| | | |
| | | ### â
å¥½çæ¥è¯¢ï¼å©ç¨ååºè£åªï¼ |
| | | ```sql |
| | | -- 示ä¾1: 带æ¶é´èå´çæ¥è¯¢ |
| | | SELECT * FROM tb_vehicle_gps_segment_mileage |
| | | WHERE segment_start_time >= '2025-01-01' |
| | | AND segment_start_time < '2025-02-01' |
| | | AND vehicle_id = 123; |
| | | |
| | | -- 示ä¾2: ææç»è®¡ |
| | | SELECT |
| | | DATE_FORMAT(segment_start_time, '%Y-%m') as month, |
| | | SUM(segment_distance) as total_distance |
| | | FROM tb_vehicle_gps_segment_mileage |
| | | WHERE segment_start_time >= '2025-01-01' |
| | | AND segment_start_time < '2025-12-31' |
| | | GROUP BY DATE_FORMAT(segment_start_time, '%Y-%m'); |
| | | ``` |
| | | |
| | | ### â ä¸å¥½çæ¥è¯¢ï¼å
¨è¡¨æ«æï¼ |
| | | ```sql |
| | | -- ç¼ºå°æ¶é´æ¡ä»¶ï¼ä¼æ«æææååº |
| | | SELECT * FROM tb_vehicle_gps_segment_mileage |
| | | WHERE vehicle_id = 123; |
| | | |
| | | -- åºè¯¥æ¹ä¸ºï¼ |
| | | SELECT * FROM tb_vehicle_gps_segment_mileage |
| | | WHERE vehicle_id = 123 |
| | | AND segment_start_time >= DATE_SUB(NOW(), INTERVAL 30 DAY); |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## å
ãçæ§ååè¦ |
| | | |
| | | ### 1. çæ§ææ |
| | | - åååºçæ°æ®é |
| | | - 表åç´¢å¼çå¤§å° |
| | | - ææ°ååºæ¯å¦æ¥è¿æ»¡ |
| | | - æ¥è¯¢æ§è½å¯¹æ¯ï¼ååºååï¼ |
| | | |
| | | ### 2. 宿¶ä»»å¡å»ºè®® |
| | | ```bash |
| | | # æ¯æ1å·åæ¨1ç¹èªå¨æ·»å æ°ååº |
| | | 0 1 1 * * mysql -uç¨æ·å -på¯ç æ°æ®åºå -e "CALL add_gps_segment_partition();" |
| | | |
| | | # æ¯å£åº¦å é¤12个æä¹åçåå²ååº |
| | | 0 2 1 1,4,7,10 * /path/to/cleanup_old_partitions.sh |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## ä¸ãåæ»æ¹æ¡ |
| | | |
| | | 妿ååºååºç°é®é¢ï¼å¯ä»¥å¿«éåæ»ï¼ |
| | | |
| | | ```sql |
| | | -- 1. 忢åºç¨åå
¥ |
| | | |
| | | -- 2. æ¢å¤å表 |
| | | RENAME TABLE tb_vehicle_gps_segment_mileage TO tb_vehicle_gps_segment_mileage_failed; |
| | | RENAME TABLE tb_vehicle_gps_segment_mileage_backup TO tb_vehicle_gps_segment_mileage; |
| | | |
| | | -- 3. 忥忢æé´çæ°æ°æ®ï¼å¦ææï¼ |
| | | INSERT INTO tb_vehicle_gps_segment_mileage |
| | | SELECT * FROM tb_vehicle_gps_segment_mileage_failed |
| | | WHERE create_time > (SELECT MAX(create_time) FROM tb_vehicle_gps_segment_mileage); |
| | | |
| | | -- 4. éå¯åºç¨ |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## å
«ãæ§è½å¯¹æ¯ï¼é¢æï¼ |
| | | |
| | | ### ååºå |
| | | - æ¥è¯¢æè¿1ææ°æ®: ~5-10ç§ |
| | | - æ¥è¯¢æè¿3ææ°æ®: ~15-30ç§ |
| | | - 表大å°: æç»å¢é¿ï¼ç´¢å¼æçéä½ |
| | | |
| | | ### ååºå |
| | | - æ¥è¯¢æè¿1ææ°æ®: ~1-2ç§ï¼æå70%-80%ï¼ |
| | | - æ¥è¯¢æè¿3ææ°æ®: ~3-6ç§ï¼æå70%-80%ï¼ |
| | | - 表维æ¤: å¯æææ¸
çï¼ç©ºé´å¯æ§ |
| | | |
| | | --- |
| | | |
| | | ## ä¹ã常è§é®é¢ |
| | | |
| | | ### Q1: ååºä¼å½±ååºç¨ä»£ç åï¼ |
| | | **A**: ä¸ä¼ãååºå¯¹åºç¨éæï¼SQLè¯å¥ä¸éè¦ä¿®æ¹ã |
| | | |
| | | ### Q2: å¯ä»¥å¨çº¿è½¬æ¢åï¼ |
| | | **A**: MySQL 5.7+ å¯ä»¥å¨çº¿è½¬æ¢ï¼ä½å»ºè®®å¨ä½å³°ææ§è¡ï¼å¤§è¡¨å¯è½éè¦è¾é¿æ¶é´ã |
| | | |
| | | ### Q3: ååºåè½åå°éååºè¡¨åï¼ |
| | | **A**: å¯ä»¥ï¼ä½¿ç¨ `ALTER TABLE ... REMOVE PARTITIONING;` |
| | | |
| | | ### Q4: 主é®å¿
é¡»å
å«ååºé®åï¼ |
| | | **A**: æ¯çï¼è¿æ¯MySQLååºè¡¨çéå¶ã |
| | | |
| | | ### Q5: å¦ä½ç¡®å®ä¿çå¤ä¹
çå岿°æ®ï¼ |
| | | **A**: æ ¹æ®ä¸å¡éæ±ååå¨å®¹éï¼å»ºè®®ä¿ç12-24个æï¼æ´æ©çæ°æ®å½æ¡£å°å·åå¨ã |
| | | |
| | | --- |
| | | |
| | | ## åãèç³»æ¯æ |
| | | |
| | | 妿æ§è¡è¿ç¨ä¸éå°é®é¢ï¼è¯·ï¼ |
| | | 1. æ£æ¥é误æ¥å¿: `/var/log/mysql/error.log` |
| | | 2. æ¥çæ
¢æ¥è¯¢æ¥å¿ï¼å¯¹æ¯æ§è½ |
| | | 3. ç¡®ä¿æå®æ´å¤ä»½ |
| | | 4. å¿
è¦æ¶èç³»DBAæææ¯æ¯æ |
| | | |
| | | --- |
| | | |
| | | **æåæé**: |
| | | â ï¸ æ§è¡åå¡å¿
å¤ä»½ï¼ |
| | | â ï¸ éæ©ä¸å¡ä½å³°ææ§è¡ï¼ |
| | | â ï¸ åå¤å¥½åæ»æ¹æ¡ï¼ |