|
@@ -0,0 +1,527 @@
|
|
|
+<template>
|
|
|
+ <el-container>
|
|
|
+ <el-main class="header-select">
|
|
|
+ <el-collapse v-model="activeName" accordion >
|
|
|
+ <el-collapse-item :title="$t(`productAuthorize.filterType`)" name="1">
|
|
|
+ <!-- 篩選區域 -->
|
|
|
+ <div class="filtratebox">
|
|
|
+ <el-form label-position="top" style="line-height: 40px">
|
|
|
+ <!-- 篩選產品 -->
|
|
|
+ <el-form-item label="篩選產品" >
|
|
|
+ <el-button type="primary" block @click="selectAll(true)" plain size="small">全選</el-button>
|
|
|
+ <el-button type="primary" block @click="selectAll(false)" plain size="small">全不選</el-button>
|
|
|
+ <el-checkbox-group v-model="selectedProducts" style="text-align: left;">
|
|
|
+ <el-checkbox
|
|
|
+ v-for="product in productData"
|
|
|
+ :key="product.prodcode"
|
|
|
+ :label="product.prodcode" >
|
|
|
+ {{ product.name }}
|
|
|
+ </el-checkbox>
|
|
|
+ </el-checkbox-group>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <!-- 篩選日期 -->
|
|
|
+
|
|
|
+ <el-form-item label="篩選日期">
|
|
|
+ <el-input-number v-model="dateFilter.number" :min="1" />
|
|
|
+ <el-select v-model="dateFilter.unit" placeholder="請選擇單位">
|
|
|
+ <el-option
|
|
|
+ v-for="unit in dateUnits"
|
|
|
+ :key="unit.value"
|
|
|
+ :label="unit.label"
|
|
|
+ :value="unit.value"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ <el-select v-model="dateFilter.direction" placeholder="請選擇方向">
|
|
|
+ <el-option
|
|
|
+ v-for="direction in dateDirections"
|
|
|
+ :key="direction.value"
|
|
|
+ :label="direction.label"
|
|
|
+ :value="direction.value"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <!-- 起訖日期篩選 -->
|
|
|
+ <el-form-item :label="$t('purchase.expirationDate')" :label-width="formLabelWidth" prop="time" style="width: 500px">
|
|
|
+ <el-date-picker v-model="dateRange" type="daterange" range-separator="To" :start-placeholder="$t('purchase.startDate')" :end-placeholder="$t('purchase.endDate')" :size="size" format="YYYY/MM/DD" value-format="YYYY-MM-DD" />
|
|
|
+ </el-form-item>
|
|
|
+ <div style="float: left;width: 100%;text-align: left; color: red;">
|
|
|
+ [篩選日期] 與 [起訖日期篩選] 以 [篩選日期] 為優先條件
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 篩選對象 -->
|
|
|
+ <el-form-item label="篩選對象">
|
|
|
+ <el-select v-model="selectedaccountType" placeholder="請選擇對象">
|
|
|
+ <el-option
|
|
|
+ v-for="type in accountTypes"
|
|
|
+ :key="type.value"
|
|
|
+ :label="type.label"
|
|
|
+ :value="type.value"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <!-- 篩選按鈕 -->
|
|
|
+ <el-button type="primary" block @click="filterData">篩選</el-button>
|
|
|
+ <el-button type="primary" block @click="clearFilter">清除篩選</el-button>
|
|
|
+ </el-form>
|
|
|
+ </div>
|
|
|
+ </el-collapse-item>
|
|
|
+ </el-collapse>
|
|
|
+
|
|
|
+ <!-- 表格 -->
|
|
|
+ <div style="width:100%;margin-bottom:0px;line-height: 70px !important;">
|
|
|
+ <div style="width:10%;float: left;">
|
|
|
+ 資料筆數:{{ filteredData.length }}
|
|
|
+ </div>
|
|
|
+ <!-- margin-right: 1%;
|
|
|
+ line-height: 50px !important;
|
|
|
+ float: right; -->
|
|
|
+ <div style="float: right;">
|
|
|
+ <el-button type="primary" @click="exportExcel">{{$t(`auth.export`)}}</el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="table-container" v-loading="loading" :element-loading-text="$t(`product.prepareData`)+'...'">
|
|
|
+ <el-table :data="filteredData" border style="width:100%" :default-sort="{ prop: 'school', order: 'ascending' }" class="custom-table" >
|
|
|
+ <el-table-column prop="name" label="名稱" sortable align="center" />
|
|
|
+ <el-table-column prop="product" label="產品名稱" sortable align="center" />
|
|
|
+ <el-table-column prop="startDate" label="開始日期" sortable align="center" />
|
|
|
+ <el-table-column prop="endDate" label="結束日期" sortable align="center" />
|
|
|
+ </el-table>
|
|
|
+ </div>
|
|
|
+ </el-main>
|
|
|
+ </el-container>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import { ref, reactive, computed, onMounted, getCurrentInstance } from "vue";
|
|
|
+ let { proxy } = getCurrentInstance()
|
|
|
+ let loading = ref(false)
|
|
|
+ const activeName = ref('1')
|
|
|
+ // 模擬的產品清單
|
|
|
+ const products = ["產品 A", "產品 B", "產品 C", "產品 D"];
|
|
|
+ let productData = ref([
|
|
|
+ {
|
|
|
+ name: 'ezStation 2',
|
|
|
+ prodcode: '3222NIYD',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: 'HiTeach STD',
|
|
|
+ prodcode: 'J223IZ6M',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: 'HiTeach TBL',
|
|
|
+ prodcode: '3222C6D2',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: 'HiTeach PRO',
|
|
|
+ prodcode: 'J223IZAM',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: 'HiTeach Lite',
|
|
|
+ prodcode: 'J2236ZCX',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: 'HiTeach Mobile',
|
|
|
+ prodcode: '3222DNG2',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: 'HiTeach Premium',
|
|
|
+ prodcode: '3222IAVN',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: 'HiTeach5',
|
|
|
+ prodcode: 'BYJ6LZ6Z',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: 'HiTeachCC',
|
|
|
+ prodcode: 'LZLL6ZEI',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: proxy.$t(`auth.YMPCVCIM`),
|
|
|
+ prodcode: 'YMPCVCIM',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: proxy.$t(`auth.IPDYZYLC`),
|
|
|
+ prodcode: 'IPDYZYLC',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: proxy.$t(`auth._3CLYJ6NP`),
|
|
|
+ prodcode: '3CLYJ6NP',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: proxy.$t(`auth.IPALJ6NY`),
|
|
|
+ prodcode: 'IPALJ6NY',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: proxy.$t(`auth.VABAJ6NV`),
|
|
|
+ prodcode: 'VABAJ6NV',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: proxy.$t(`auth._0VPBDZPG`),
|
|
|
+ prodcode: '0VPBDZPG',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: proxy.$t(`auth.B9GPJ6NY`),
|
|
|
+ prodcode: 'B9GPJ6NY',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: proxy.$t(`auth.LY9AJ6NY`),
|
|
|
+ prodcode: 'LY9AJ6NY',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: proxy.$t(`auth.YL9CJ6NY`),
|
|
|
+ prodcode: 'YL9CJ6NY',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: proxy.$t(`auth.LL9MJ6NY`),
|
|
|
+ prodcode: 'LL9MJ6NY',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: proxy.$t(`auth.B6V5J6NP`),
|
|
|
+ prodcode: 'B6V5J6NP',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: proxy.$t(`auth.LSZYJ6NA`),
|
|
|
+ prodcode: 'LSZYJ6NA',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: proxy.$t(`auth.CVGPJ6NN`),
|
|
|
+ prodcode: 'CVGPJ6NN',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: proxy.$t(`auth.VDPGJ6NC`),
|
|
|
+ prodcode: 'VDPGJ6NC',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: proxy.$t(`auth.YPXSJ6NJ`),
|
|
|
+ prodcode: 'YPXSJ6NJ',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: proxy.$t(`auth.VLY6J6N6`),
|
|
|
+ prodcode: 'VLY6J6N6',
|
|
|
+ },
|
|
|
+ ])
|
|
|
+
|
|
|
+
|
|
|
+ // 模擬的表格資料
|
|
|
+ const tableData = reactive([
|
|
|
+ {
|
|
|
+ accountType: "school",
|
|
|
+ name: "學校甲",
|
|
|
+ product: "產品 A",
|
|
|
+ startDate: "2024-01-01",
|
|
|
+ endDate: "2024-12-31",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ accountType: "school",
|
|
|
+ name: "學校乙",
|
|
|
+ product: "產品 B",
|
|
|
+ startDate: "2024-03-01",
|
|
|
+ endDate: "2024-09-30",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ accountType: "school",
|
|
|
+ name: "學校丙",
|
|
|
+ product: "產品 C",
|
|
|
+ startDate: "2024-02-01",
|
|
|
+ endDate: "2024-08-31",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ accountType: "school",
|
|
|
+ name: "學校丁",
|
|
|
+ product: "產品 A",
|
|
|
+ startDate: "2024-05-01",
|
|
|
+ endDate: "2025-04-30",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ accountType: "tmid",
|
|
|
+ name: "ID01",
|
|
|
+ product: "產品 B",
|
|
|
+ startDate: "2024-05-01",
|
|
|
+ endDate: "2025-04-30",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ accountType: "tmid",
|
|
|
+ name: "ID01",
|
|
|
+ product: "產品 A",
|
|
|
+ startDate: "2024-05-01",
|
|
|
+ endDate: "2025-04-30",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ accountType: "tmid",
|
|
|
+ name: "ID02",
|
|
|
+ product: "產品 B",
|
|
|
+ startDate: "2024-05-01",
|
|
|
+ endDate: "2025-04-30",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ accountType: "tmid",
|
|
|
+ name: "ID03",
|
|
|
+ product: "產品 C",
|
|
|
+ startDate: "2024-05-01",
|
|
|
+ endDate: "2025-04-30",
|
|
|
+ },
|
|
|
+ ]);
|
|
|
+
|
|
|
+ // 篩選條件
|
|
|
+ const selectedProducts = ref([]);
|
|
|
+ const selectedaccountType = ref('school');
|
|
|
+ const dateFilter = reactive({
|
|
|
+ number: 0,
|
|
|
+ unit: "",
|
|
|
+ direction: "",
|
|
|
+ });
|
|
|
+ const startDate = ref(null); // 起始日期
|
|
|
+ const endDate = ref(null); // 結束日期
|
|
|
+ let dateRange = ref([]);
|
|
|
+ let filteredData = reactive([]);
|
|
|
+
|
|
|
+ // 日期單位與方向選項
|
|
|
+ const dateUnits = [
|
|
|
+ { label: "請選擇單位", value: "" },
|
|
|
+ { label: "年", value: "year" },
|
|
|
+ { label: "月", value: "month" },
|
|
|
+ { label: "週", value: "week" },
|
|
|
+ { label: "日", value: "day" },
|
|
|
+ ];
|
|
|
+
|
|
|
+ const accountTypes = [
|
|
|
+ { label: "學校", value: "school" },
|
|
|
+ { label: "醍摩豆ID", value: "tmid" },
|
|
|
+ ];
|
|
|
+ const dateDirections = [
|
|
|
+ { label: "請選擇方向", value: "" },
|
|
|
+ { label: "之前", value: "before" },
|
|
|
+ { label: "之後", value: "after" },
|
|
|
+ ];
|
|
|
+
|
|
|
+ //getfilteredData()
|
|
|
+
|
|
|
+ onMounted(() => {
|
|
|
+
|
|
|
+ getfilteredData()
|
|
|
+
|
|
|
+ })
|
|
|
+
|
|
|
+ function getfilteredData() {
|
|
|
+ loading.value = true
|
|
|
+
|
|
|
+ filteredData.splice(0, filteredData.length);
|
|
|
+ let filtered = JSON.parse(JSON.stringify(tableData));
|
|
|
+
|
|
|
+ // 按產品篩選
|
|
|
+ if (selectedProducts.value && selectedProducts.value.length) {
|
|
|
+ filtered = filtered.filter((item) =>
|
|
|
+ selectedProducts.value.includes(item.product)
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ // 按篩選日期
|
|
|
+ if (dateFilter.number && dateFilter.unit && dateFilter.direction) {
|
|
|
+ const today = new Date();
|
|
|
+ const compareDate = new Date(today);
|
|
|
+ const unitMap = {
|
|
|
+ year: "FullYear",
|
|
|
+ month: "Month",
|
|
|
+ week: "Date",
|
|
|
+ day: "Date",
|
|
|
+ };
|
|
|
+
|
|
|
+ if (dateFilter.unit === "week") {
|
|
|
+ compareDate.setDate(
|
|
|
+ today.getDate() +
|
|
|
+ (dateFilter.direction === "before" ? -7 : 7) * dateFilter.number
|
|
|
+ );
|
|
|
+ } else {
|
|
|
+ compareDate[`set${unitMap[dateFilter.unit]}`](
|
|
|
+ today[`get${unitMap[dateFilter.unit]}`]() +
|
|
|
+ (dateFilter.direction === "before" ? -1 : 1) * dateFilter.number
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ filtered = filtered.filter((item) => {
|
|
|
+ const endDate = new Date(item.endDate);
|
|
|
+ return dateFilter.direction === "before"
|
|
|
+ ? endDate <= compareDate
|
|
|
+ : endDate >= compareDate;
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 起始/結束日期篩選
|
|
|
+ if (startDate.value) {
|
|
|
+ filtered = filtered.filter(
|
|
|
+ (item) => new Date(item.startDate) >= new Date(startDate.value)
|
|
|
+ );
|
|
|
+ }
|
|
|
+ if (endDate.value) {
|
|
|
+ filtered = filtered.filter(
|
|
|
+ (item) => new Date(item.endDate) <= new Date(endDate.value)
|
|
|
+ );
|
|
|
+ }
|
|
|
+ // 按對象篩選
|
|
|
+ if (selectedaccountType.value) {
|
|
|
+ filtered = filtered.filter((item) =>
|
|
|
+ selectedaccountType.value.includes(item.accountType)
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ // filtered.forEach(element => {
|
|
|
+ // filteredData.push(element)
|
|
|
+ // });
|
|
|
+
|
|
|
+ let authEndYMWD = dateFilter.number ? dateFilter.number : 0
|
|
|
+ if (dateFilter.direction === "before") {
|
|
|
+ authEndYMWD = authEndYMWD * -1
|
|
|
+ }
|
|
|
+ let authStart = 0
|
|
|
+ let authEnd = 0
|
|
|
+ if (dateRange.value && dateRange.value.length > 0) {
|
|
|
+ authStart = new Date(dateRange.value[0]).getTime() / 1000
|
|
|
+ authEnd = new Date(dateRange.value[1]).getTime() / 1000
|
|
|
+ }
|
|
|
+
|
|
|
+ let data = {
|
|
|
+ idType: selectedaccountType.value, //ID類型 school:學校 tmid:TMID ※預設:school
|
|
|
+ prodCode: selectedProducts.value, //產品代碼
|
|
|
+ authEndYMWD: dateFilter.unit, //日期單位:year:年 month:月 week:週 day:日
|
|
|
+ authEndPeriod: authEndYMWD, //日期計算數 [例] -3:從現在起往前算三個日期單位 3:從現在起往後算三個日期單位
|
|
|
+ authStart: authStart, //授權起始日 ※「授權起始日、授權終止日」與「日期單位、日期計算數」擇一成立
|
|
|
+ authEnd: authEnd, //授權終止日
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ //取得學校或TMID產品授權狀況
|
|
|
+ proxy.$api.getSchoolProdauth(data).then((res) => {
|
|
|
+ loading.value = false
|
|
|
+ if (typeof res.err === "string" && res.err.length === 0 && (res.serial.length > 0 || res.service.length > 0)) {
|
|
|
+ let serial = JSON.parse(JSON.stringify(res.serial));
|
|
|
+ let service = JSON.parse(JSON.stringify(res.service));
|
|
|
+ service.forEach(element => {
|
|
|
+ // if(!element.startDate || !element.endDate){
|
|
|
+ // let aaa = element
|
|
|
+
|
|
|
+ // }
|
|
|
+ // 轉換產品名稱
|
|
|
+ let product = productData.value.find(item => {
|
|
|
+ return item.prodcode === element.prodCode
|
|
|
+ })
|
|
|
+ let filteredItem = {
|
|
|
+ name: element.saleClient.name,
|
|
|
+ product: product.name,
|
|
|
+ startDate: proxy.$common.timestampToTime(element.startDate, '', true),
|
|
|
+ endDate: proxy.$common.timestampToTime(element.endDate, '', true),
|
|
|
+ }
|
|
|
+ filteredData.push(filteredItem)
|
|
|
+ });
|
|
|
+ serial.forEach(element => {
|
|
|
+ // if(!element.startDate || !element.endDate){
|
|
|
+ // let aaa = element
|
|
|
+
|
|
|
+ // }
|
|
|
+ //轉換產品名稱
|
|
|
+ let product = productData.value.find(item => {
|
|
|
+ return item.prodcode === element.prodCode
|
|
|
+ })
|
|
|
+ let filteredItem = {
|
|
|
+ name: element.saleClient.name,
|
|
|
+ product: product.name,
|
|
|
+ startDate: proxy.$common.timestampToTime(element.authSysStartDate, '', true),
|
|
|
+ endDate: proxy.$common.timestampToTime(element.authSysEndDate, '', true),
|
|
|
+ }
|
|
|
+ filteredData.push(filteredItem)
|
|
|
+ });
|
|
|
+ }
|
|
|
+ })
|
|
|
+ } catch (error) {
|
|
|
+ console.log(error)
|
|
|
+ } finally {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ function filterData() {
|
|
|
+ getfilteredData()
|
|
|
+ };
|
|
|
+
|
|
|
+ function clearFilter() {
|
|
|
+ selectedProducts.value = [];
|
|
|
+ selectedaccountType.value = 'school';
|
|
|
+
|
|
|
+ dateFilter.number = 0
|
|
|
+ dateFilter.unit = ""
|
|
|
+ dateFilter.direction = ""
|
|
|
+
|
|
|
+ startDate.value = 0; // 起始日期
|
|
|
+ endDate.value = 0; // 結束日期
|
|
|
+ dateRange.value = [];
|
|
|
+ };
|
|
|
+ function selectAll(flag) {
|
|
|
+ if (flag) {
|
|
|
+ productData.value.forEach(item => {
|
|
|
+ selectedProducts.value.push(item.prodcode)
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ selectedProducts.value = [];
|
|
|
+ }
|
|
|
+ };
|
|
|
+ //导出日志
|
|
|
+ function exportExcel () {
|
|
|
+ require.ensure([], () => {
|
|
|
+ const { export_json_to_excel } = require('../../until/excel/Export2Excel')
|
|
|
+ const tHeader = ['名稱', '產品名稱', '開始日期', '結束日期'] // excel文档第一行显示的标题
|
|
|
+ const filterVal = ['name', 'product', 'startDate', 'endDate'] // id,version等都是上面标题所对应的数据
|
|
|
+ const list = filteredData
|
|
|
+ const data = formatJson(filterVal, list)
|
|
|
+ export_json_to_excel(tHeader, data, '產品授權') //标题,数据,文件名
|
|
|
+ })
|
|
|
+ }
|
|
|
+ function formatJson (filterVal, jsonData) {
|
|
|
+ return jsonData.map((v) => filterVal.map((j) => v[j]))
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+</script>
|
|
|
+
|
|
|
+<style>
|
|
|
+.filtratebox {
|
|
|
+ width: 100%;
|
|
|
+ padding: 10px 20px 0px 20px;
|
|
|
+ background: #fff;
|
|
|
+ border-top: 1px solid #ccc;
|
|
|
+ position: relative;
|
|
|
+}
|
|
|
+
|
|
|
+.table-container {
|
|
|
+ margin: 0 auto;
|
|
|
+ width: 98%;
|
|
|
+ margin-bottom: 150px;
|
|
|
+ margin-top: 10px;
|
|
|
+ line-height: 10px
|
|
|
+}
|
|
|
+
|
|
|
+.custom-table >>> .el-table__header,
|
|
|
+.custom-table >>> .el-table__body,
|
|
|
+.custom-table >>> .el-table__row {
|
|
|
+ border-color: black !important;
|
|
|
+}
|
|
|
+.el-form-item {
|
|
|
+ margin-bottom: 5px;
|
|
|
+}
|
|
|
+.header-select,
|
|
|
+.middlebox {
|
|
|
+ /* width: 100%; */
|
|
|
+ /* background-color: #fff; */
|
|
|
+ margin: 10px 20px;
|
|
|
+}
|
|
|
+.header-select .el-collapse-item__header {
|
|
|
+ font-size: 16px;
|
|
|
+ padding-left: 0.5%;
|
|
|
+}
|
|
|
+</style>
|