chore: 首次簽入 Thinkyu ASP.NET 專案
- 加入 Visual Studio / ASP.NET .gitignore - 排除建置輸出、IDE 設定、NuGet packages、大型 MSI 安裝檔
This commit is contained in:
@@ -0,0 +1,926 @@
|
||||
function CreateReceiptEditApp() {
|
||||
const loadMarker = document.getElementById('receiptEditApp');
|
||||
if (loadMarker) {
|
||||
DoCreateReceiptEditApp();
|
||||
}
|
||||
}
|
||||
|
||||
function DoCreateReceiptEditApp() {
|
||||
|
||||
window.__vms = window.__vms || {}
|
||||
|
||||
if (window.__vms.receiptEditApp)
|
||||
return;
|
||||
|
||||
window.__vms.receiptEditApp = new Vue({
|
||||
el: '#receiptEditApp',
|
||||
mixins: [DateMixin, ToastMixin, ApiMixin],
|
||||
data: {
|
||||
mode: 'view', // view, add, edit
|
||||
編號: 0,
|
||||
originalMainData: null,
|
||||
originalLaborData: null,
|
||||
originalTravelData: null,
|
||||
mainData: {
|
||||
編號: 0,
|
||||
表單編號: '',
|
||||
活動日期: '',
|
||||
身分別: '',
|
||||
講師_非講師編號: '',
|
||||
領款人姓名: '',
|
||||
身分證字號: '',
|
||||
憑證類別: '',
|
||||
計畫代號: '',
|
||||
計畫名稱: '',
|
||||
活動地點: '',
|
||||
活動類別: '',
|
||||
活動名稱事由: '',
|
||||
製單人員: '',
|
||||
付款方式: '',
|
||||
作廢: 0,
|
||||
列印次數: 0,
|
||||
已關帳: false,
|
||||
DB_APPNO: 1,
|
||||
DB_CRDAT: '',
|
||||
DB_CRUSR: '',
|
||||
DB_CRUSR_NAME: '',
|
||||
DB_TRDAT: '',
|
||||
DB_TRUSR: '',
|
||||
DB_TRUSR_NAME: ''
|
||||
},
|
||||
laborData: {
|
||||
編號: '',
|
||||
領據編號: 0,
|
||||
費用別: '',
|
||||
單價: 0,
|
||||
數量: 0,
|
||||
單位: '',
|
||||
扣繳類別: '',
|
||||
合計金額: 0,
|
||||
應扣繳稅額: 0,
|
||||
服務費: 0,
|
||||
作廢: 0,
|
||||
DB_APPNO: 1
|
||||
},
|
||||
travelData: {
|
||||
編號: '',
|
||||
領據編號: 0,
|
||||
票價資訊: '',
|
||||
費用別: '',
|
||||
起點: '',
|
||||
訖點: '',
|
||||
捷運公車: 0,
|
||||
火車: 0,
|
||||
計程車: 0,
|
||||
高鐵飛機: 0,
|
||||
自行開車: 0,
|
||||
過路費停車費: 0,
|
||||
住宿費: 0,
|
||||
合計: 0,
|
||||
作廢: 0,
|
||||
DB_APPNO: 1
|
||||
},
|
||||
dropdown: {
|
||||
身分別: [],
|
||||
憑證類別: [],
|
||||
付款方式: [],
|
||||
勞務費_費用別: [],
|
||||
差旅費_費用別: [],
|
||||
扣繳類別: [],
|
||||
單位別: []
|
||||
},
|
||||
recipientList: [],
|
||||
showRecipientDropdown: false,
|
||||
planList: [],
|
||||
showPlanDropdown: false,
|
||||
originStations: [],
|
||||
showOriginDropdown: false,
|
||||
destStations: [],
|
||||
showDestDropdown: false,
|
||||
stations: [],
|
||||
showActivityLocationPhrase: false,
|
||||
activityLocationPhrases: [],
|
||||
showActivityCategoryPhrase: false,
|
||||
activityCategoryPhrases: [],
|
||||
showTicketPricePhrase: false,
|
||||
ticketPricePhrases: [],
|
||||
loading: false,
|
||||
variables: {
|
||||
領據執行業務所得課稅門檻: 0,
|
||||
領據薪資課稅門檻: 0,
|
||||
領據基本工資: 0,
|
||||
領據執行業務所得稅率: 0,
|
||||
領據薪資稅率: 0
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// 從 AJAX 取得下拉選單資料
|
||||
this.loading = true;
|
||||
this.loadVariables();
|
||||
this.loadDropdownLists();
|
||||
this.loadPhraseLists();
|
||||
this.loading = false;
|
||||
this.mainData.製單人員 = V製單人員;
|
||||
this.編號 = 0;
|
||||
if (document.getElementById('ctl00_ContentPlaceHolder1_hid編號').value !== '') {
|
||||
this.編號 = parseInt(document.getElementById('ctl00_ContentPlaceHolder1_hid編號').value) || 0;
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (this.編號 !== 0) {
|
||||
this.mode = 'view';
|
||||
this.loadData(this.編號)
|
||||
} else {
|
||||
this.mode = 'add';
|
||||
this.reset();
|
||||
this.backupData();
|
||||
this.setDefault();
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'laborData.單價'() {
|
||||
this.calculateLaborTotal();
|
||||
},
|
||||
'laborData.數量'() {
|
||||
this.calculateLaborTotal();
|
||||
},
|
||||
'laborData.扣繳類別'() {
|
||||
this.calculateTax();
|
||||
},
|
||||
'mainData.身分別'() {
|
||||
if (this.mode === 'add' || this.mode === 'edit') {
|
||||
this.mainData.講師_非講師編號 = '';
|
||||
this.mainData.領款人姓名 = '';
|
||||
this.mainData.身分證字號 = '';
|
||||
this.recipientList = [];
|
||||
}
|
||||
},
|
||||
'travelData.捷運公車'() { this.calculateTravelTotal(); },
|
||||
'travelData.火車'() { this.calculateTravelTotal(); },
|
||||
'travelData.計程車'() { this.calculateTravelTotal(); },
|
||||
'travelData.高鐵飛機'() { this.calculateTravelTotal(); },
|
||||
'travelData.自行開車'() { this.calculateTravelTotal(); },
|
||||
'travelData.過路費停車費'() { this.calculateTravelTotal(); },
|
||||
'travelData.住宿費'() { this.calculateTravelTotal(); }
|
||||
},
|
||||
computed: {
|
||||
isViewMode() {
|
||||
return this.mode === 'view';
|
||||
},
|
||||
isEditMode() {
|
||||
return this.mode === 'edit' || this.mode === 'add';
|
||||
},
|
||||
canAddNew() {
|
||||
return this.mode === 'view';
|
||||
},
|
||||
canEdit() {
|
||||
return this.mode === 'view' && this.編號 !== 0;
|
||||
},
|
||||
canCancel() {
|
||||
return this.mode === 'add' || this.mode === 'edit';
|
||||
},
|
||||
canSave() {
|
||||
return this.mode === 'add' || this.mode === 'edit';
|
||||
},
|
||||
canReturnToList() {
|
||||
return this.mode === 'view';
|
||||
},
|
||||
closed() {
|
||||
return this.mainData.已關帳;
|
||||
},
|
||||
laborWarnings() {
|
||||
const warnings = [];
|
||||
const 扣繳類別 = this.laborData.扣繳類別 || '';
|
||||
|
||||
// 費用別警告
|
||||
if (['演講費', '撰稿費'].indexOf(this.laborData.費用別) >= 0 && 扣繳類別 === '50') {
|
||||
warnings.push('扣繳類別只能是執行業務所得');
|
||||
}
|
||||
|
||||
// 合計金額警告
|
||||
if (扣繳類別 === '50' && this.laborData.合計金額 >= this.variables.領據基本工資) {
|
||||
warnings.push(`薪資不得超過基本工資${this.variables.領據基本工資}(含),超過請拆成不同日期的領據`);
|
||||
}
|
||||
if ((扣繳類別.startsWith('9A') || 扣繳類別.startsWith('9B')) && this.laborData.合計金額 >= this.variables.領據執行業務所得課稅門檻) {
|
||||
warnings.push(`執行業務所得不得超過${this.variables.領據執行業務所得課稅門檻}(含),超過請拆成不同日期的領據`);
|
||||
}
|
||||
|
||||
return warnings;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async loadVariables() {
|
||||
try {
|
||||
const result = await this.callApi('領據處理', 'GetVariables', {});
|
||||
if (result.Data) {
|
||||
this.variables = result.Data;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('載入片語清單失敗:', error);
|
||||
}
|
||||
},
|
||||
|
||||
async loadDropdownLists() {
|
||||
this.dropdown.身分別 = await this.loadDropdownList("身分別");
|
||||
this.dropdown.憑證類別 = await this.loadDropdownList("憑證類別");
|
||||
this.dropdown.付款方式 = await this.loadDropdownList("付款方式");
|
||||
this.dropdown.勞務費_費用別 = await this.loadDropdownList("勞務費_費用別");
|
||||
this.dropdown.差旅費_費用別 = await this.loadDropdownList("差旅費_費用別");
|
||||
this.dropdown.扣繳類別 = await this.loadDropdownList("扣繳類別");
|
||||
this.dropdown.單位別 = await this.loadDropdownList("單位別");
|
||||
},
|
||||
|
||||
async loadDropdownList(key) {
|
||||
try {
|
||||
const result = await this.callApi('領據處理', 'GetDropdownLists', { key });
|
||||
return result.Data || [];
|
||||
} catch (error) {
|
||||
console.error('載入下拉選單失敗:', error);
|
||||
return [];
|
||||
}
|
||||
},
|
||||
|
||||
async loadPhraseLists() {
|
||||
try {
|
||||
const result = await this.callApi('領據處理', 'GetPhraseLists', {});
|
||||
if (result.Data) {
|
||||
this.activityLocationPhrases = result.Data.activityLocation || [];
|
||||
this.activityCategoryPhrases = result.Data.activityCategory || [];
|
||||
this.ticketPricePhrases = result.Data.ticketPrice || [];
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('載入公用變數失敗:', error);
|
||||
}
|
||||
},
|
||||
|
||||
toggleActivityLocationPhrase() {
|
||||
if (this.isViewMode) return;
|
||||
this.showActivityLocationPhrase = !this.showActivityLocationPhrase;
|
||||
this.showActivityCategoryPhrase = false;
|
||||
this.showTicketPricePhrase = false;
|
||||
},
|
||||
|
||||
toggleActivityCategoryPhrase() {
|
||||
if (this.isViewMode) return;
|
||||
this.showActivityCategoryPhrase = !this.showActivityCategoryPhrase;
|
||||
this.showActivityLocationPhrase = false;
|
||||
this.showTicketPricePhrase = false;
|
||||
},
|
||||
|
||||
toggleTicketPricePhrase() {
|
||||
if (this.isViewMode) return;
|
||||
this.showTicketPricePhrase = !this.showTicketPricePhrase;
|
||||
this.showActivityLocationPhrase = false;
|
||||
this.showActivityCategoryPhrase = false;
|
||||
},
|
||||
|
||||
insertPhrase(fieldName, phrase) {
|
||||
let input;
|
||||
if (fieldName === '活動地點') {
|
||||
input = this.$refs.活動地點Input;
|
||||
this.showActivityLocationPhrase = false;
|
||||
} else if (fieldName === '活動類別') {
|
||||
input = this.$refs.活動類別Input;
|
||||
this.showActivityCategoryPhrase = false;
|
||||
} else if (fieldName === '票價資訊') {
|
||||
input = this.$refs.票價資訊Input;
|
||||
this.showTicketPricePhrase = false;
|
||||
}
|
||||
|
||||
if (input) {
|
||||
const startPos = input.selectionStart || input.value.length;
|
||||
const endPos = input.selectionEnd || input.value.length;
|
||||
const currentValue = input.value;
|
||||
const newValue = currentValue.substring(0, startPos) + phrase + currentValue.substring(endPos);
|
||||
|
||||
if (fieldName === '活動地點') {
|
||||
this.mainData.活動地點 = newValue;
|
||||
} else if (fieldName === '活動類別') {
|
||||
this.mainData.活動類別 = newValue;
|
||||
} else if (fieldName === '票價資訊') {
|
||||
this.travelData.票價資訊 = newValue;
|
||||
}
|
||||
|
||||
// 更新游標位置
|
||||
this.$nextTick(() => {
|
||||
input.focus();
|
||||
input.setSelectionRange(startPos + phrase.length, startPos + phrase.length);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
calculateLaborTotal() {
|
||||
const price = parseFloat(this.laborData.單價) || 0;
|
||||
const qty = parseFloat(this.laborData.數量) || 0;
|
||||
this.laborData.合計金額 = Math.round(price * qty);
|
||||
this.calculateTax();
|
||||
},
|
||||
|
||||
async calculateTax() {
|
||||
const laborFee = parseInt(this.laborData.合計金額) || 0;
|
||||
const category = this.laborData.扣繳類別 || '';
|
||||
|
||||
if (laborFee > 0 && category) {
|
||||
this.loading = true;
|
||||
try {
|
||||
const result = await this.callApi('領據處理', 'CalcTax', {
|
||||
laborFee,
|
||||
category
|
||||
});
|
||||
this.laborData.應扣繳稅額 = result.Data;
|
||||
} catch (error) {
|
||||
console.error('計算稅額失敗:', error);
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
} else {
|
||||
this.laborData.應扣繳稅額 = 0;
|
||||
}
|
||||
},
|
||||
|
||||
calculateTravelTotal() {
|
||||
this.travelData.合計 =
|
||||
(parseInt(this.travelData.捷運公車) || 0) +
|
||||
(parseInt(this.travelData.火車) || 0) +
|
||||
(parseInt(this.travelData.計程車) || 0) +
|
||||
(parseInt(this.travelData.高鐵飛機) || 0) +
|
||||
(parseInt(this.travelData.自行開車) || 0) +
|
||||
(parseInt(this.travelData.過路費停車費) || 0) +
|
||||
(parseInt(this.travelData.住宿費) || 0);
|
||||
},
|
||||
|
||||
searchStation(field) {
|
||||
const key = this.travelData[field];
|
||||
|
||||
if (key && key.length > 0) {
|
||||
axios({
|
||||
method: 'post',
|
||||
url: `${API_TRAIN_FARE}/SelectStation`,
|
||||
headers: {
|
||||
'Content-Type': 'application/json; charset=utf-8'
|
||||
},
|
||||
data: JSON.stringify({ key })
|
||||
})
|
||||
.then(response => {
|
||||
const result = response.data.d || response.data;
|
||||
if (result.Success) {
|
||||
this.stations = result.Data || [];
|
||||
} else {
|
||||
this.stations = [];
|
||||
this.ShowWarning(result.Message);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('查詢車站失敗:', error);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
async searchRecipient() {
|
||||
const key = this.mainData.領款人姓名;
|
||||
const identity = this.mainData.身分別;
|
||||
const activationDate = this.mainData.活動日期;
|
||||
|
||||
if (!key || key.length === 0) {
|
||||
this.recipientList = [];
|
||||
this.showRecipientDropdown = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!identity) {
|
||||
this.ShowWarning('請先選擇身分別');
|
||||
this.recipientList = [];
|
||||
this.showRecipientDropdown = false;
|
||||
return;
|
||||
}
|
||||
if (!activationDate) {
|
||||
this.ShowWarning('請輸入活動日期');
|
||||
this.recipientList = [];
|
||||
this.showRecipientDropdown = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this.loading = true;
|
||||
try {
|
||||
const result = await this.callApi('領據處理', 'SearchRecipient', { key, identity, activationDate });
|
||||
this.recipientList = result.Data || [];
|
||||
this.showRecipientDropdown = this.recipientList.length > 0;
|
||||
} catch (error) {
|
||||
console.error('查詢領款人失敗:', error);
|
||||
this.recipientList = [];
|
||||
this.showRecipientDropdown = false;
|
||||
this.ShowWarning(error.message);
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
|
||||
hideRecipientDropdown() {
|
||||
setTimeout(() => {
|
||||
this.showRecipientDropdown = false;
|
||||
this.recipientList = [];
|
||||
}, 200);
|
||||
},
|
||||
|
||||
selectRecipient(recipient) {
|
||||
this.mainData.講師_非講師編號 = recipient.Value;
|
||||
this.mainData.領款人姓名 = recipient.Name;
|
||||
this.mainData.身分證字號 = recipient.IdNumber;
|
||||
this.mainData.憑證類別 = recipient.VoucherType;
|
||||
this.laborData.扣繳類別 = recipient.ConductType;
|
||||
this.recipientList = [];
|
||||
this.showRecipientDropdown = false;
|
||||
},
|
||||
|
||||
async searchPlan() {
|
||||
const key = this.mainData.計畫代號;
|
||||
const year = this.mainData.活動日期 ? new Date(this.mainData.活動日期).getFullYear() - 1911 : null;
|
||||
|
||||
if (year === null) {
|
||||
this.ShowWarning("請輸入活動日期");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!key || key.length === 0) {
|
||||
this.planList = [];
|
||||
this.showPlanDropdown = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this.loading = true;
|
||||
try {
|
||||
const result = await this.callApi('領據處理', 'SearchPlan', { key, year });
|
||||
this.planList = result.Data || [];
|
||||
this.showPlanDropdown = this.planList.length > 0;
|
||||
} catch (error) {
|
||||
console.error('查詢計畫失敗:', error);
|
||||
this.planList = [];
|
||||
this.showPlanDropdown = false;
|
||||
this.ShowWarning(error.message);
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
|
||||
selectPlan(plan) {
|
||||
this.mainData.計畫代號 = plan.Code;
|
||||
this.mainData.計畫名稱 = plan.Name;
|
||||
this.planList = [];
|
||||
this.showPlanDropdown = false;
|
||||
},
|
||||
|
||||
hidePlanDropdown() {
|
||||
setTimeout(() => {
|
||||
this.showPlanDropdown = false;
|
||||
this.planList = [];
|
||||
}, 200);
|
||||
},
|
||||
|
||||
async searchOriginStation() {
|
||||
const key = this.travelData.起點;
|
||||
|
||||
if (!key || key.length === 0) {
|
||||
this.originStations = [];
|
||||
this.showOriginDropdown = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this.loading = true;
|
||||
try {
|
||||
const result = await this.callApi('火車票價', 'SelectOriginStation', { key });
|
||||
this.originStations = result.Data || [];
|
||||
this.showOriginDropdown = this.originStations.length > 0;
|
||||
} catch (error) {
|
||||
console.error('查詢起點失敗:', error);
|
||||
this.originStations = [];
|
||||
this.showOriginDropdown = false;
|
||||
this.ShowWarning(error.message);
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
|
||||
selectOriginStation(station) {
|
||||
this.travelData.起點 = station.Name;
|
||||
this.originStations = [];
|
||||
this.showOriginDropdown = false;
|
||||
},
|
||||
|
||||
hideOriginDropdown() {
|
||||
setTimeout(() => {
|
||||
this.showOriginDropdown = false;
|
||||
this.originStations = [];
|
||||
}, 200);
|
||||
this.calculateFare();
|
||||
},
|
||||
|
||||
async searchDestStation() {
|
||||
const key = this.travelData.訖點;
|
||||
|
||||
if (!key || key.length === 0) {
|
||||
this.destStations = [];
|
||||
this.showDestDropdown = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this.loading = true;
|
||||
try {
|
||||
const result = await this.callApi('火車票價', 'SelectDestStation', { key });
|
||||
this.destStations = result.Data || [];
|
||||
this.showDestDropdown = this.destStations.length > 0;
|
||||
} catch (error) {
|
||||
console.error('查詢訖點失敗:', error);
|
||||
this.destStations = [];
|
||||
this.showDestDropdown = false;
|
||||
this.ShowWarning(error.message);
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
|
||||
selectDestStation(station) {
|
||||
this.travelData.訖點 = station.Name;
|
||||
this.destStations = [];
|
||||
this.showDestDropdown = false;
|
||||
},
|
||||
|
||||
hideDestDropdown() {
|
||||
setTimeout(() => {
|
||||
this.showDestDropdown = false;
|
||||
this.destStations = [];
|
||||
}, 200);
|
||||
this.calculateFare();
|
||||
},
|
||||
|
||||
async calculateFare() {
|
||||
const 起站 = this.travelData.起點;
|
||||
const 迄站 = this.travelData.訖點;
|
||||
|
||||
if (!起站 || !迄站) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.loading = true;
|
||||
try {
|
||||
const result = await this.callApi('火車票價', 'SelectFare', { 起站, 迄站 });
|
||||
this.travelData.火車 = result.Data;
|
||||
this.calculateTravelTotal();
|
||||
} catch (error) {
|
||||
console.error('查詢票價失敗:', error);
|
||||
this.ShowWarning(error.message);
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
|
||||
async save() {
|
||||
if (!this.validate() || (this.laborWarnings || []).length > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.loading = true;
|
||||
|
||||
try {
|
||||
const data = {
|
||||
isNew: this.mode === 'add',
|
||||
mainItem: this.mainData,
|
||||
laborItem: this.laborData,
|
||||
travelItem: this.travelData
|
||||
};
|
||||
|
||||
const result = await this.callApiWithErrorMsg('領據處理', 'Save', data, '儲存');
|
||||
this.ShowSuccess(result.Message);
|
||||
// 新增存檔更新編號變數
|
||||
if (this.mode === 'add') {
|
||||
this.編號 = result.Data.編號;
|
||||
}
|
||||
// 返回查看模式
|
||||
this.mode = 'view';
|
||||
this.loadData(this.編號);
|
||||
this.backupData();
|
||||
} catch (error) {
|
||||
console.error('Save error:', error);
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
|
||||
validate() {
|
||||
if (!this.mainData.身分別) {
|
||||
this.ShowWarning('請選擇身分別');
|
||||
return false;
|
||||
}
|
||||
if (!this.mainData.領款人姓名) {
|
||||
this.ShowWarning('請輸入領款人姓名');
|
||||
return false;
|
||||
}
|
||||
if (!this.mainData.計畫代號) {
|
||||
this.ShowWarning('請輸入計畫代號');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
returnToList() {
|
||||
if ((this.mode === 'add' || this.mode === 'edit') && !confirm("是否放棄" + (this.mode === 'add' ? '新增' : '修改')))
|
||||
return;
|
||||
window.__doPostBack('ctl00$ContentPlaceHolder1$btnTab1', '');
|
||||
},
|
||||
|
||||
backupData() {
|
||||
this.originalMainData = JSON.parse(JSON.stringify(this.mainData));
|
||||
this.originalLaborData = JSON.parse(JSON.stringify(this.laborData));
|
||||
this.originalTravelData = JSON.parse(JSON.stringify(this.travelData));
|
||||
},
|
||||
|
||||
restoreData() {
|
||||
if (this.originalMainData) {
|
||||
this.mainData = JSON.parse(JSON.stringify(this.originalMainData));
|
||||
}
|
||||
if (this.originalLaborData) {
|
||||
this.laborData = JSON.parse(JSON.stringify(this.originalLaborData));
|
||||
}
|
||||
if (this.originalTravelData) {
|
||||
this.travelData = JSON.parse(JSON.stringify(this.originalTravelData));
|
||||
}
|
||||
},
|
||||
|
||||
addNew() {
|
||||
if (this.mode !== 'view') {
|
||||
return;
|
||||
}
|
||||
this.mode = 'add';
|
||||
this.reset();
|
||||
this.backupData();
|
||||
this.setDefault();
|
||||
},
|
||||
|
||||
edit() {
|
||||
if (this.mode !== 'view') {
|
||||
return;
|
||||
}
|
||||
this.mode = 'edit';
|
||||
this.backupData();
|
||||
},
|
||||
|
||||
cancel() {
|
||||
if (this.mode === 'view') {
|
||||
return;
|
||||
}
|
||||
if (!confirm("是否放棄" + (this.mode === 'add' ? '新增' : '修改') + ",資料將復原?")) {
|
||||
return;
|
||||
}
|
||||
this.restoreData();
|
||||
this.mode = 'view';
|
||||
},
|
||||
|
||||
reset() {
|
||||
this.mainData = {
|
||||
編號: 0,
|
||||
表單編號: '',
|
||||
活動日期: '',
|
||||
身分別: '',
|
||||
講師_非講師編號: '',
|
||||
領款人姓名: '',
|
||||
身分證字號: '',
|
||||
憑證類別: '',
|
||||
計畫代號: '',
|
||||
計畫名稱: '',
|
||||
活動地點: '',
|
||||
活動類別: '',
|
||||
活動名稱事由: '',
|
||||
付款方式: '',
|
||||
作廢: 0,
|
||||
列印次數: 0,
|
||||
DB_APPNO: 1,
|
||||
DB_CRDAT: '',
|
||||
DB_CRUSR: '',
|
||||
DB_CRUSR_NAME: '',
|
||||
DB_TRDAT: '',
|
||||
DB_TRUSR: '',
|
||||
DB_TRUSR_NAME: '',
|
||||
};
|
||||
this.laborData = {
|
||||
編號: '',
|
||||
領據編號: 0,
|
||||
費用別: '',
|
||||
單價: 0,
|
||||
數量: 0,
|
||||
單位: '',
|
||||
扣繳類別: '',
|
||||
合計金額: 0,
|
||||
應扣繳稅額: 0,
|
||||
服務費: 0,
|
||||
作廢: 0,
|
||||
DB_APPNO: 1
|
||||
};
|
||||
this.travelData = {
|
||||
編號: '',
|
||||
領據編號: 0,
|
||||
票價資訊: '',
|
||||
費用別: '',
|
||||
起點: '',
|
||||
訖點: '',
|
||||
捷運公車: 0,
|
||||
火車: 0,
|
||||
計程車: 0,
|
||||
高鐵飛機: 0,
|
||||
自行開車: 0,
|
||||
過路費停車費: 0,
|
||||
住宿費: 0,
|
||||
合計: 0,
|
||||
作廢: 0,
|
||||
DB_APPNO: 1
|
||||
};
|
||||
},
|
||||
|
||||
setDefault()
|
||||
{
|
||||
this.mainData.DB_CRDAT = this.FormatDate(new Date());
|
||||
this.mainData.DB_CRUSR = document.getElementById('ctl00_hidCurrentUser').value;
|
||||
this.mainData.DB_CRUSR_NAME = document.getElementById('ctl00_hidCurrentUserName').value;
|
||||
},
|
||||
|
||||
async loadData(no) {
|
||||
this.loading = true;
|
||||
|
||||
try {
|
||||
const result = await this.callApiWithErrorMsg('領據處理', 'GetOne', { no }, '載入');
|
||||
|
||||
const data = result.Data;
|
||||
|
||||
this.mainData = {
|
||||
編號: data.編號,
|
||||
表單編號: data.表單編號,
|
||||
活動日期: this.FormatDate(data.活動日期),
|
||||
身分別: data.身分別,
|
||||
講師_非講師編號: data.講師_非講師編號,
|
||||
領款人姓名: data.領款人姓名,
|
||||
身分證字號: data.身分證字號,
|
||||
憑證類別: data.憑證類別,
|
||||
計畫代號: data.計畫代號,
|
||||
計畫名稱: data.計畫名稱,
|
||||
活動地點: data.活動地點,
|
||||
活動類別: data.活動類別,
|
||||
活動名稱事由: data.活動名稱事由,
|
||||
付款方式: data.付款方式,
|
||||
作廢: data.作廢,
|
||||
列印次數: data.列印次數,
|
||||
已關帳: data.已關帳,
|
||||
DB_APPNO: data.DB_APPNO,
|
||||
DB_CRDAT: this.FormatDate(data.DB_CRDAT),
|
||||
DB_CRUSR: data.DB_CRUSR,
|
||||
DB_CRUSR_NAME: data.DB_CRUSR_NAME,
|
||||
DB_TRDAT: data.DB_TRUSR !== null ? this.FormatDate(data.DB_TRDAT) : '',
|
||||
DB_TRUSR: data.DB_TRUSR !== null ? data.DB_TRUSR : '',
|
||||
DB_TRUSR_NAME: data.DB_TRUSR != null ? data.DB_TRUSR_NAME: ''
|
||||
};
|
||||
this.laborData = {
|
||||
編號: data.勞務費_編號,
|
||||
領據編號: data.編號,
|
||||
費用別: data.勞務費_費用別,
|
||||
單價: data.勞務費_單價,
|
||||
數量: data.勞務費_數量,
|
||||
單位: data.勞務費_單位,
|
||||
扣繳類別: data.勞務費_扣繳類別,
|
||||
合計金額: data.勞務費_合計金額,
|
||||
應扣繳稅額: data.勞務費_應扣繳稅額,
|
||||
服務費: data.勞務費_服務費,
|
||||
作廢: data.勞務費_作廢
|
||||
};
|
||||
this.travelData = {
|
||||
編號: data.差旅費_編號,
|
||||
領據編號: data.編號,
|
||||
票價資訊: data.差旅費_票價資訊,
|
||||
費用別: data.差旅費_費用別,
|
||||
起點: data.差旅費_起點,
|
||||
訖點: data.差旅費_訖點,
|
||||
捷運公車: data.差旅費_捷運公車,
|
||||
火車: data.差旅費_火車,
|
||||
計程車: data.差旅費_計程車,
|
||||
高鐵飛機: data.差旅費_高鐵飛機,
|
||||
自行開車: data.差旅費_自行開車,
|
||||
過路費停車費: data.差旅費_過路費停車費,
|
||||
住宿費: data.差旅費_住宿費,
|
||||
合計: data.差旅費_合計,
|
||||
作廢: data.差旅費_作廢
|
||||
};
|
||||
|
||||
if (data.main) {
|
||||
this.mainData = data.main;
|
||||
}
|
||||
if (data.labor) {
|
||||
this.laborData = data.labor;
|
||||
}
|
||||
if (data.travel) {
|
||||
this.travelData = data.travel;
|
||||
}
|
||||
this.backupData();
|
||||
} catch (error) {
|
||||
console.error('LoadData error:', error);
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
|
||||
async print() {
|
||||
if (this.mainData.作廢 !== 0) {
|
||||
this.ShowError('已作廢不可列印');
|
||||
}
|
||||
|
||||
this.loading = true;
|
||||
try {
|
||||
const result = await this.callApiWithErrorMsg(
|
||||
'領據處理',
|
||||
'Print',
|
||||
{ idList: [this.mainData.編號 ] },
|
||||
'列印領據'
|
||||
);
|
||||
|
||||
if (result.Success) {
|
||||
// 下載 Excel 檔案
|
||||
if (result.Data && result.Data.fileName) {
|
||||
const link = document.createElement('a');
|
||||
link.href = `data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,${result.Data.excelData}`;
|
||||
link.download = result.Data.fileName;
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
|
||||
this.ShowSuccess(result.Message);
|
||||
} else {
|
||||
this.ShowWarning(result.Message);
|
||||
}
|
||||
} else {
|
||||
this.ShowError('列印失敗: ' + (error.message || '請稍後重試'));
|
||||
}
|
||||
} catch (error) {
|
||||
this.ShowError('列印失敗: ' + (error.message || '請檢查網路連線'));
|
||||
} finally {
|
||||
this.loadData(this.編號);
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
|
||||
async voidVoucher() {
|
||||
if (this.mainData.作廢 === 0 && !confirm("是否確定作廢?") || this.mainData.作廢 !== 0 && !confirm("是否確定取消作廢?")) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.loading = true;
|
||||
try {
|
||||
const result = await this.callApi('領據處理', 'Void', {
|
||||
no: this.mainData.編號
|
||||
});
|
||||
this.loadData(this.mainData.編號);
|
||||
this.ShowSuccess('作廢操作完成');
|
||||
} catch (error) {
|
||||
console.error('Void error:', error);
|
||||
this.ShowError('作廢操作失敗: ' + (error.message || '請檢查網路連線'));
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
|
||||
async voidLaborFee() {
|
||||
if (this.laborData.作廢 === 0 && !confirm("是否確定作廢勞務費?") || this.laborData.作廢 !== 0 && !confirm("是否確定取消作廢勞務費?")) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.loading = true;
|
||||
try {
|
||||
const result = await this.callApi('領據處理', 'VoidLaborFee', {
|
||||
receiptNo: this.mainData.編號
|
||||
});
|
||||
this.loadData(this.mainData.編號);
|
||||
this.ShowSuccess('勞務費作廢操作完成');
|
||||
} catch (error) {
|
||||
console.error('VoidLaborFee error:', error);
|
||||
this.ShowError('勞務費作廢操作失敗: ' + (error.message || '請檢查網路連線'));
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
|
||||
async voidTravelFee() {
|
||||
if (this.travelData.作廢 === 0 && !confirm("是否確定作廢差旅費?") || this.travelData.作廢 !== 0 && !confirm("是否確定取消作廢差旅費?")) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.loading = true;
|
||||
try {
|
||||
const result = await this.callApi('領據處理', 'VoidTravelFee', {
|
||||
receiptNo: this.mainData.編號
|
||||
});
|
||||
this.loadData(this.mainData.編號);
|
||||
this.ShowSuccess('差旅費作廢操作完成');
|
||||
} catch (error) {
|
||||
console.error('VoidTravelFee error:', error);
|
||||
this.ShowError('差旅費作廢操作失敗: ' + (error.message || '請檢查網路連線'));
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
}
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user