Files
17168ERP/web/admin/project/news_reg.aspx
2025-08-29 01:27:25 +08:00

652 lines
34 KiB
Plaintext

<%@ Page Title="後端管理" Language="C#" MasterPageFile="~/admin/Templates/TBS5ADM001/MasterPage.master" AutoEventWireup="true" CodeFile="news_reg.aspx.cs" Inherits="admin_project_new_reg" ValidateRequest="false" %>
<%@ Register Src="~/admin/_uc/alert.ascx" TagPrefix="uc1" TagName="alert" %>
<asp:Content ID="Content1" ContentPlaceHolderID="page_header" runat="Server">
</asp:Content>
<asp:Content ID="Content4" ContentPlaceHolderID="footer_script" runat="Server">
<!--編緝器-->
<script type="text/javascript" src="<%=ResolveUrl("~/admin/ckeditor/ckeditor.js") %>"></script>
<script type="text/javascript">
CKEDITOR.config.toolbar = 'Default';
</script>
<!--編緝器-->
<script>
Vue.filter('timeString', function (value, myFormat) {
return value == null || value == "" ? "" : moment(value).format(myFormat || 'YYYY-MM-DD, HH:mm:ss');
});
let VueApp = new Vue({
el: '#app',
vuetify: new Vuetify(vuetify_options),
data() {
return {
pid: '<%= Request["num"] %>',
options: {},
search_dialog: {
controls: {
search1: {
id: 'search1',
title: '類別',
text_prop: 'kind',
value_prop: 'num',
keys: [
{ id: 'kind', title: '類別名稱', value: '' },
],
api_url: HTTP_HOST + 'api/project/GetKindList',
columns: [
{ id: 'kind', title: '類別名稱', value: '' },
],
selected: {},
select(t) {
//console.log("select search1", t);
}
}, search3: {
id: 'search3',
title: '品項',
text_prop: 'subject',
value_prop: 'num',
keys: [
{ id: 'subject', title: '項目名稱', value: '' },
{ id: 'kindTxt', title: '項目分類' },
],
api_url: HTTP_HOST + 'api/activity/GetItemList',
columns: [
{ id: 'subject', title: '項目名稱' },
{ id: 'kindTxt', title: '項目分類' },
],
selected: {},
select(t) {
//console.log("select search3", t);
}
},
},
show: false,
current: {},
list: [],
count: 0,
page:1,
loading: false,
footer: {
showFirstLastPage: true,
disableItemsPerPage: true,
itemsPerPageAllText: '',
itemsPerPageText:'',
},
},
snackbar: {
show: false,
text: "",
},
//
optionsDetail: { multiSort: false },
searchDetail: '',
headersDetail: [
{ text: '* 標題', value: 'subject', sortable: false },
{ text: '* 日期', value: 'uptime', sortable: false },
{ text: '', value: 'actions', sortable: false, width: "150px" },
],
desserts: [],
desserts_count: 0,
editedIndex: -1,
editedItem: {
id: 0,
num: 0,
subject: "",
uptime: new Date().format("yyyy-MM-dd"),
word: "",
pic1: [],
pro_id: 0,
formData: new FormData(),
},
defaultItem: {
id: 0,
num: 0,
subject: "",
uptime: new Date().format("yyyy-MM-dd"),
word: "",
pic1: [],
pro_id: 0,
formData: new FormData(),
},
data_dialog: {
show: false,
isAddNew: false,
}
}
},
mounted() {
this.search_dialog.current = this.search_dialog.controls.search1
//console.log("mounted");
},
watch: {
options: {
handler() {
//console.log("watch1", this.search_dialog, this.search_dialog.page);
this.search_get()
console.log("watch2", this.search_dialog, this.search_dialog.page);
},
deep: true,
},
optionsDetail: {
handler() {
this.initialize();
},
deep: true,
},
},
methods: {
search_show(curr) {
//console.log("btn_click:", curr, curr.api_url);
this.search_dialog.current = curr;
this.search_clear()
//this.search_get()//清除完自動會重抓, 故取消
this.search_dialog.show = true;
},
search_clear() {
if (!this.search_dialog.current.keys) return;
this.search_dialog.current.keys.forEach((t, i) => { t.value = '' })
this.search_get()
},
search_get() {
if (!this.search_dialog.current.keys) return;
let api_url = this.search_dialog.current.api_url;
let keys = this.search_dialog.current.keys;
//const { page, itemsPerPage } = this.options
//const { sortBy, sortDesc, page, itemsPerPage } = this.options
this.search_dialog.page = this.options.page??1
let params = { page: this.search_dialog.page, pageSize: 10 };//url params
var search = {};//post body
keys.forEach((t, i) => {
search[t.id] = t.value;
});
//necessary parameter===
if (this.search_dialog.current.id == 'search3') {
search['category'] = "4"; //贊助
}
console.log("search_get", api_url, search, params, this.options);
this.search_dialog.loading = true
axios.post(api_url, search, { params: params })
.then(response => {
this.search_dialog.list = response.data.list
this.search_dialog.count = response.data.count
this.search_dialog.loading = false
})
.catch(error => {
console.log(error)
this.search_dialog.list = []
this.search_dialog.count = 0
this.search_dialog.loading = false
this.snackbar.text = "錯誤:" + error
this.snackbar.show=true
})
},
search_headers() {
if (!this.search_dialog.current.columns) return;
r = [];
this.search_dialog.current.columns.forEach((t, i) => {
r.push({
text: t.title,
align: 'start',
sortable: false,
value: t.id,
})
})
return r
},
search_select(row) {
let curr = this.search_dialog.current;
let target = $(`[data-search-control=${curr.id}]`);
curr.selected = row;
target.children("input.search-text").val(curr.selected[curr.text_prop])//text
target.children("input:hidden").val(curr.selected[curr.value_prop])//value
if (curr.select instanceof Function) {
curr.select(row);
}
this.search_dialog.show = false;
},
initialize() {
if (this.pid != '') {
const { sortBy, sortDesc, page, itemsPerPage } = this.optionsDetail
const params = {
sortBy: sortBy[0], sortDesc: sortDesc[0],
page: page, pageSize: itemsPerPage,
};
var searchItemDetail = {
num: this.pid,
}
axios
.post(HTTP_HOST + 'api/project/GetItemList', searchItemDetail, { params: params })
.then(response => {
this.desserts = response.data.list
this.desserts_count = response.data.count
})
.catch(
error => console.log(error)
)
}
},
addNew() {
window.location = 'update.aspx?pro_id=' + this.pid;
//var keysArr = [];
//for (var i = 0; i < this.desserts.map(x => x.id).length; i++) {
// //console.log(this.desserts[i].id)
// keysArr.push(parseInt(this.desserts[i].id));
//}
//var _c = Math.max.apply(null, keysArr);
//const addObj = Object.assign({}, this.defaultItem);
//addObj.id = (isFinite(_c) ? _c : 0) + 1;
//this.desserts.unshift(addObj);
//this.editItem(addObj);
//this.data_dialog.show = true;
//this.data_dialog.isAddNew = true;
},
editItem(item) {
window.location = 'update.aspx?pro_id=' + this.pid + "&pnum=" + item.num;
//=====
//this.editedIndex = this.desserts.indexOf(item);
////日期處理
//let isValidDate = Date.parse(item.uptime);
//if (!isNaN(isValidDate))
// item.uptime = new Date(item.uptime).format("yyyy-MM-dd")
////編輯器
//CKEDITOR.instances.word.setData(item.word);
//this.editedItem = Object.assign({}, item);
//this.data_dialog.show = true;
//this.data_dialog.isAddNew = false;
},
cancel() {
//if new data , splice it
//if (this.data_dialog.isAddNew && this.editedItem.num == 0) {
// for (var i = 0; i < this.desserts.map(x => x.id).length; i++) {
// if (this.desserts[i].id == this.editedItem.id) {
// this.desserts.splice(i, 1); break;
// }
// }
//}
this.close();
},
close() {
setTimeout(() => {
this.editedItem = Object.assign({}, this.defaultItem);
this.editedIndex = -1;
}, 300)
},
save() {
if (this.editedIndex > -1) {
if (this.pid != '') {
//axios
// .post(HTTP_HOST + 'api/fileSys/upload', this.editedItem.formData)
// .then(response => {
// if (response.data != "") {}
// })
// .catch(
// error => console.log(error)
// )
//chcck necessary params
if (this.editedItem.subject != "" && this.editedItem.uptime != "" ) {
//insert or update data
var project_sub =
{
num: this.editedItem.num,
pro_id: this.pid,
subject: this.editedItem.subject,
uptime: this.editedItem.uptime,
//word: this.editedItem.word, //?????
word: CKEDITOR.instances.word.getData(), //?????
//pic1: this.editedItem.pic1.name !== undefined ? this.editedItem.pic1.name : "" ,
//pic1: this.editedItem.pic1.length>0 ?
pic1: "",
}
axios
.post(HTTP_HOST + 'api/project/SaveDetailData', project_sub)
.then(response => {
this.editedItem.num = response.data;
Object.assign(this.desserts[this.editedIndex], this.editedItem)
this.close();
this.data_dialog.show = false;
})
.catch(
error => console.log(error)
)
} else {
this.snackbar.text = "必填項目未填寫完整";
this.snackbar.show = true
}
} else {
this.snackbar.text = "請先新增專案";
this.snackbar.show = true
}
}
},
fileChange(e) {
for (var i = 0; i < e.length; i++) {
this.editedItem.formData.append('file', e[i]) //用迴圈抓出多少筆再append回來
}
}, deleteItem(item) {
//confirm('確定要刪除此筆資料嗎?') && this.desserts.splice(index, 1);
if (confirm('確定要刪除此筆資料嗎?')) {
const index = this.desserts.indexOf(item);
if (item.num > 0) {
if (index != -1) {
axios
.delete(HTTP_HOST + 'api/project/DeleteItem/' + item.num)
.then(response => {
console.log("del", item);
this.desserts.splice(index, 1)
this.desserts_count = this.desserts_count - 1;
})
.catch(error => console.log(error))
}
} else {
this.desserts.splice(index, 1)
this.close();
this.data_dialog.show = false;
}
}
}, magnifyItem(item) {
window.open('reg.aspx?num=' + item.num, '_blank');
}
},
computed: {
},
})
</script>
</asp:Content>
<asp:Content ID="Content3" ContentPlaceHolderID="page_nav" runat="Server">
<div class="scroll-nav nav nav-tabs mb-2 mb-sm-0 d-none d-sm-flex">
</div>
<div class="">
<asp:Button ID="add" runat="server" Text="送出" OnClick="add_Click" CssClass="btn btn-primary" />
<asp:Button ID="edit" runat="server" Text="修改" Visible="false" OnClick="edit_Click" CssClass="btn btn-primary" />
<asp:Button ID="goback" runat="server" Text="回列表" Visible="false" CausesValidation="false" OnClick="goback_Click" CssClass="btn btn-outline-secondary" />
</div>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server">
<uc1:alert runat="server" ID="L_msg" Text="" />
<div id="content" class="container-xl">
<div class="card shadow-sm my-2" id="sec2">
<div class="card-header py-0">
<nav class="navbar py-0">
<div class="nav nav-tabs">
<button class="nav-link active" id="sec2-tab1" data-bs-toggle="tab" data-bs-target="#sec2-page1"
type="button" role="tab" aria-controls="home" aria-selected="true">
專案管理</button>
<button class="nav-link" id="sec2-tab2" data-bs-toggle="tab" data-bs-target="#sec2-page2"
type="button" role="tab" aria-controls="profile" aria-selected="false">
活動資料</button>
</div>
</nav>
</div>
<div class="card-body">
<div class="tab-content" id="myTabContent">
<div class="tab-pane fade show active" id="sec2-page1" role="tabpanel" aria-labelledby="sec2-tab1">
<div>
<div class="form-text text-muted">以下 * 欄位為必填欄位</div>
</div>
<div class="label-sm-right">
<div class="row mb-1 ">
<label class="col-sm-2 col-lg-1 col-form-label">名稱 *</label>
<div class="col-sm-4 col-lg-3">
<asp:TextBox ID="subject" MaxLength="50" runat="server" CssClass="form-control" placeholder="請輸入專案名稱"></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator6" ControlToValidate="subject" runat="server" ErrorMessage="必填!" Display="Dynamic" SetFocusOnError="true"></asp:RequiredFieldValidator>
</div>
<label class="col-sm-2 col-lg-1 col-form-label">類別 *</label>
<div class="col-sm-4 col-lg-3">
<div class="input-group mb-3" data-search-control="search1" @click="search_show(search_dialog.controls.search1)">
<input class="form-control search-text" type="text" readonly
id="kind_txt" runat="server" placeholder="類別" value="">
<asp:HiddenField ID="kind" runat="server" Value="" />
<button class="btn btn-outline-secondary" type="button">
<i class="mdi mdi-view-list-outline"></i>
</button>
</div>
<asp:RequiredFieldValidator ID="RequiredFieldValidator7" ControlToValidate="kind_txt" runat="server" ErrorMessage="必填!" Display="Dynamic" SetFocusOnError="true"></asp:RequiredFieldValidator>
</div>
<label class="col-sm-2 col-lg-1 col-form-label">品項 *</label>
<div class="col-sm-4 col-lg-3">
<div class="input-group mb-3" data-search-control="search3" @click="search_show(search_dialog.controls.search3)">
<input class="form-control search-text" type="text" readonly
id="actItem_num_txt" runat="server" placeholder="品項" value="">
<asp:HiddenField ID="actItem_num" runat="server" Value="" />
<button class="btn btn-outline-secondary" type="button">
<i class="mdi mdi-view-list-outline"></i>
</button>
</div>
<asp:RequiredFieldValidator ID="RequiredFieldValidator2" ControlToValidate="actItem_num_txt" runat="server" ErrorMessage="必填!" Display="Dynamic" SetFocusOnError="true"></asp:RequiredFieldValidator>
</div>
</div>
</div>
<hr />
<div class="row mb-1">
<label class="col-form-label">備註</label>
<div class="">
<asp:TextBox ID="demo" runat="server" Rows="5" TextMode="MultiLine" CssClass="form-control" placeholder="請輸入備註"></asp:TextBox>
</div>
</div>
</div>
<div class="tab-pane fade" id="sec2-page2" role="tabpanel" aria-labelledby="sec2-tab2">
<%-- <v-dialog v-model="data_dialog.show" max-width="900px">
<v-card>
<v-card-title class="justify-space-between grey lighten-2">
活動資料
<v-btn icon @click="data_dialog.show=false;cancel()"><v-icon>mdi-close</v-icon></v-btn>
</v-card-title>
<v-card-text>
<v-row dense class="pt-2">
<v-col :cols="2" class="pt-3" >
<span class="fs-6 text text-dark">標題 *</span>
</v-col>
<v-col :cols="10" >
<v-text-field v-model="editedItem.subject" :hide-details="true" dense single-line></v-text-field>
</v-col>
</v-row>
<v-row dense class="pt-2">
<v-col :cols="2" class="pt-3" >
<span class="fs-6 text text-dark">日期 *</span>
</v-col>
<v-col :cols="10" :md="4" >
<v-text-field v-model="editedItem.uptime" :hide-details="true" dense single-line type="date" ></v-text-field>
</v-col>
</v-row>
<v-row dense class="pt-2">
<v-col :cols="2" class="pt-3" >
<span class="fs-6 text text-dark">照片上傳</span>
</v-col>
<v-col :cols="10" :md="4" >
<v-file-input
v-model="editedItem.pic1"
accept="image/png, image/jpeg, image/bmp"
placeholder="請選擇圖片"
prepend-icon="mdi-camera"
></v-file-input>
</v-col>
</v-row>
<v-row dense class="pt-2">
<v-col :cols="2" class="pt-3" >
<span class="fs-6 text text-dark">內容 *</span>
</v-col>
<v-col :cols="10" :md="4" >
<textarea name="word" rows="2" cols="20" class="ckeditor" v-model="editedItem.word" ></textarea>
</v-col>
</v-row>
<div class="row mb-1">
<label class="col-form-label">內容 *</label>
<div class="">
<textarea name="word" rows="2" cols="20" class="ckeditor" v-model="editedItem.word" ></textarea>
</div>
</div>
</v-card-text>
</v-card>
</v-dialog>--%>
<div v-show="data_dialog.show">
<div>
<div class="form-text text-muted">以下 * 欄位為必填欄位</div>
</div>
<div class="label-sm-right">
<div class="row mb-1 ">
<label class="col-sm-2 col-lg-1 col-form-label">標題 *</label>
<div class="col-sm-4 col-lg-3">
<input type="text" maxlength="50" class="form-control" v-model="editedItem.subject">
</div>
<label class="col-sm-2 col-lg-1 col-form-label">日期 *</label>
<div class="col-sm-4 col-lg-3">
<input type="date" class="form-control" v-model="editedItem.uptime" autocomplete="off" data-date-format="yyyy-mm-dd">
</div>
<label class="col-sm-2 col-lg-1 col-form-label">照片上傳</label>
<div class="col-sm-4 col-lg-3">
<%-- <img id="picShow" style="display: none" data-path="" class="picShow" />
<a id="picPath" class="btn btn-default picPath" href="javascript:void(0)">請選擇圖片</a>
<div id="pics" class="d-none"><input type="file" name="picUpload" id="picUpload" /></div> --%>
<v-file-input
<%--v-model="editedItem.pic1" --%>
accept="image/png, image/jpeg, image/bmp"
placeholder="請選擇圖片"
prepend-icon="mdi-camera"
@change="fileChange"
multiple>
</v-file-input>
</div>
</div>
</div>
<hr />
<div class="row mb-1">
<label class="col-form-label">內容 *</label>
<div class="">
<textarea rows="5" class="ckeditor" name="word" ></textarea>
</div>
</div>
<%-- <v-btn class="ma-2" color="red lighten-2" dark @click="save()" > 新增 <v-icon dark right > mdi-new-box </v-icon> </v-btn>--%>
<v-btn class="ma-2" color="primary" dark @click="save()" > 儲存 <v-icon dark right > mdi-content-save </v-icon> </v-btn>
</div>
<v-card class="mx-auto mt-10" outlined v-if="pid!=''">
<v-data-table
:headers="headersDetail"
:items="desserts"
:search="searchDetail"
:options.sync="optionsDetail" class="elevation-1" fixed-header height="350px"
:server-items-length="desserts_count">
<v-divider inset></v-divider>
<template v-slot:top>
<v-toolbar flat color="white">
<div class="d-flex w-100">
<v-text-field v-model="searchDetail" append-icon="mdi-magnify" label="查詢" dense outlined single-line hide-details></v-text-field>
<v-btn
color="primary"
class="ml-2 white--text"
@click="addNew">
<v-icon dark>mdi-plus</v-icon>新增
</v-btn>
</div>
</v-toolbar>
</template>
<template v-slot:item.uptime="{ item }">
{{item.uptime|timeString('YYYY/MM/DD')}}
</template>
<template v-slot:item.actions="{ item }">
<div >
<v-icon color="blue" class="mr-3" @click="magnifyItem(item)" >
mdi-magnify
</v-icon>
<v-icon color="green" class="mr-3" @click="editItem(item);">
mdi-pencil
</v-icon>
<v-icon color="red" @click="deleteItem(item)">
mdi-delete
</v-icon>
</div>
</template>
</v-data-table>
</v-card>
</div>
</div>
</div>
</div>
<v-dialog v-model="search_dialog.show" max-width="500px">
<v-card>
<v-card-title class="justify-space-between grey lighten-2">
查詢:{{search_dialog.current.title}}
<v-btn icon @click="search_dialog.show=false"><v-icon>mdi-close</v-icon></v-btn>
</v-card-title>
<v-card-text >
<v-row>
<v-col v-for="item in search_dialog.current.keys"
:cols="search_dialog.current.keys.length>1?6:12" >
<v-text-field v-model="item.value" :label="item.title"></v-text-field>
</v-col>
<v-col cols="12" class="text-end">
<v-btn color="primary" elevation="0" @click="search_get()">查詢</v-btn>
<v-btn elevation="0" @click="search_clear()">清除條件</v-btn>
</v-col>
</v-row>
<v-data-table
:headers="search_headers()"
:items="search_dialog.list"
:footer-props="search_dialog.footer"
:items-per-page="10"
:server-items-length="search_dialog.count"
:page.sync="search_dialog.page"
:options.sync="options"
@click:row="search_select"
></v-data-table>
</v-card-text>
<v-card-actions>
</v-card-actions>
</v-card>
</v-dialog>
<v-snackbar
v-model="snackbar.show"
timeout="2000"
>
{{ snackbar.text }}
<template v-slot:action="{ attrs }">
<v-btn
text
v-bind="attrs"
@click="snackbar.show = false"
>
關閉
</v-btn>
</template>
</v-snackbar>
</div>
</asp:Content>