Fxiaoke Developer Manual Fxiaoke Developer Manual
  • APL Development Manual
  • PWC Development Manual
  • OpenAPI Documentation
  • Custom Components (PC)
  • Custom Components (Mini Program)
  • Custom Plugins (PC)
  • Custom Plugins (Mini Program)
  • Third-party Integration Plugins (H5)
  • API (PC)
  • API (Mini Program)
  • Fx DevTools
Update Log
  • 简体中文
  • English
  • Custom Components (PC)
  • Custom Components (Mini Program)
  • Custom Plugins (PC)
  • Custom Plugins (Mini Program)
  • Third-party Integration Plugins (H5)
  • API (PC)
  • API (Mini Program)
  • Fx DevTools
Update Log
  • 简体中文
  • English
  • Getting Started

  • Components

  • Examples

    • Customized Printing
      • Background
      • Writing the Template
      • Writing the Script
      • Writing the Style
      • Complete Final Code
    • Customized Charts
    • Embedding Third-party Enterprise Systems
    • Custom Login
    • Display Current Time
  • FAQ

Table of Contents

Custom Printing

# Custom Printing

# Background

Normally, the printing template functionality in Fxiaoke can meet most printing requirements. However, for special report printing scenarios, the standard printing templates may not be sufficient.

This article teaches you how to develop custom components to create tailored printing pages.

# Writing the Template

The main content involves using HTML to construct tables.

<template>  
    <div class="cus-demo" v-if="dData">  
        <h1 class="text-center">Fund Utilization Approval Form</h1>  
        <div class="flex bd">  
            <div class="flex flex-1 flex-col">  
                <div class="flex">  
                    <div class="w-120 text-center bd">Payee</div>  
                    <div class="flex-1 padding-5 bd">{{{ dData.field_uhcib__c }}}</div>  
                </div>  
                <div class="flex">  
                    <div class="w-60 text-center bd">Bank Account</div>  
                    <div class="flex-1">  
                        <div class="flex">  
                            <div class="w-60 text-center bd">Bank</div>  
                            <div class="flex-1 padding-5 bd">{{{ dData.field_utckZ__c }}}</div>  
                        </div>  
                        <div class="flex">  
                            <div class="w-60 text-center bd">Account</div>  
                            <div class="flex-1 padding-5 bd">{{{ dData.field_oQgRl__c }}}</div>  
                        </div>  
                        <div class="flex">  
                            <div class="w-60 text-center bd">Address</div>  
                            <div class="flex-1 padding-5 bd">{{{ dData.field_v82bd__c }}}</div>  
                        </div>  
                    </div>  
                </div>  
                <div class="flex">  
                    <div class="w-60 text-center bd">Payment Amount</div>  
                    <div class="flex-1">  
                        <div class="flex">  
                            <div class="w-60 text-center bd">In Words</div>  
                            <div class="flex-1 padding-5 bd">{{{ digitUppercase(dData.field_8P18m__c) }}}</div>  
                        </div>  
                        <div class="flex">  
                            <div class="w-60 text-center bd">In Numbers</div>  
                            <div class="flex-1 padding-5 bd">{{{ dData.field_8P18m__c }}}</div>  
                        </div>  
                    </div>  
                </div>  
                <div class="flex">  
                    <div class="w-120 text-center bd">Payment Method</div>  
                    <div class="flex-1 padding-5 bd">{{{ dData.field_fJY1p__c }}}</div>  
                </div>  
                <div class="flex">  
                    <div class="flex-1 bd">  
                        <div class="text-center">Payment Reason</div>  
                        <div class="text-center padding-5">{{{ dData.field_fwjy1__c }}}</div>  
                    </div>  
                    <div class="flex-1 bd">  
                        <div class="text-center">Department Opinion</div>  
                        <div class="text-center padding-5">{{{ dData.field_36nKK__c }}}</div>  
                    </div>  
                    <div class="flex-1 bd">  
                        <div class="text-center">Project Manager Opinion</div>  
                        <div class="text-center padding-5">{{{ dData.field_J3N26__c }}}</div>  
                    </div>  
                </div>  
            </div>  
        </div>  
        <div class="text-right no-print">Click the browser's print button to print directly (this text won't be printed)</div>  
    </div>  
</template>  

# Writing the Script

Let's outline the approach:

  1. Get complete detail data of the current record. This relies on userData from uiaction.
  2. Get field descriptions of the current record's business object. This relies on APIs provided by FxUI.
  3. With data and descriptions, we can parse human-readable data. This relies on APIs provided by FxUI.

Based on these steps, we organize the logic as follows:

<script>  
    export default {  
        props: ['userData'], //Step 1 mentioned above. Custom components receive uiaction data via userData  
        data() {  
            return {  
                dData: null  
            }  
        },  
        created() {  
            this.getData();  
        },  
        mounted() {  
            //Trigger dialog position recalculation  
            this.$emit('action', {type: 'resize'});  
        },  
        methods: {  
            getData() {  
                const userData = this.userData;  
                //Step 2 mentioned above. Get object description  
                FxUI.objectApi.fetch_describe(userData.object_describe_api_name).then((data) => {  
                    const {  
                        fields  
                    } = data.objectDescribe;  

                    //Step 3 mentioned above. Parse data  
                    let result = {};  
                    Object.keys(fields).forEach(fApiName => {  
                        result[fApiName] = (FxUI.objectApi.format_field_value || PAAS.format_field_value)(fields[fApiName], userData[fApiName], userData);  
                    })  

                    //Final step. Assign and render  
                    this.dData = result;  
                    this.$nextTick(() => {  
                        //After data renders to page, height changes. We need to recalculate dialog position  
                        this.$emit('action', {type: 'resize'});  
                    })  
                })  
            }  
        }  
    }  
</script>  

Additionally, since the requirements involve amount conversion between numeric and Chinese characters, we enhance the code by providing the digitUppercase method in the component:

<script>  
export default {  
    props: ['userData', 'data'],  
    data() {  
        return {  
            dData: null  
        }  
    },  
    created() {  
        this.getData();  
    },  
    mounted() {  
        this.$emit('action', {type: 'resize'});  
    },  
    methods: {  
        //Convert numeric amount to Chinese characters  
        digitUppercase(n) {  
            var fraction = ['角', '分'];  
            var digit = [  
                '零', '壹', '贰', '叁', '肆',  
                '伍', '陆', '柒', '捌', '玖'  
            ];  
            var unit = [  
                ['元', '万', '亿'],  
                ['', '拾', '佰', '仟']  
            ];  
            var head = n < 0 ? '欠' : '';  
            n = Math.abs(n);  
            var s = '';  
            for (var i = 0; i < fraction.length; i++) {  
                s += (digit[Math.floor(n * 10 * Math.pow(10, i)) % 10] + fraction[i]).replace(/零./, '');  
            }  
            s = s || '整';  
            n = Math.floor(n);  
            for (var i = 0; i < unit[0].length && n > 0; i++) {  
                var p = '';  
                for (var j = 0; j < unit[1].length && n > 0; j++) {  
                    p = digit[n % 10] + unit[1][j] + p;  
                    n = Math.floor(n / 10);  
                }  
                s = p.replace(/(零.)*零$/, '').replace(/^$/, '零') + unit[0][i] + s;  
            }  
            return head + s.replace(/(零.)*零元/, '元')  
                .replace(/(零.)+/g, '零')  
                .replace(/^整$/, '零元整');  
        },  
        getData() {  
            const userData = this.userData;  
            //Get description then parse data  
            FxUI.objectApi.fetch_describe(userData.object_describe_api_name).then((data) => {  
                const {  
                    fields  
                } = data.objectDescribe;  
                let result = {};  
                Object.keys(fields).forEach(fApiName => {  
                    result[fApiName] = (FxUI.objectApi.format_field_value || PAAS.format_field_value)(fields[fApiName], userData[fApiName], userData);  
                })  
                this.dData = result;  
                this.$nextTick(() => {  
                    this.$emit('action', {type: 'resize'});  
                })  
            })  
        }  
    }  
}  
</script>  

# Writing the Style

<style lang="less">  
    .cus-demo {  
        .demo {  
            max-width: 1200px;  
        }  
        h1 {  
            font-size: 28px;  
            font-weight: bold;  
            margin-bottom: 15px;  
        }  
        div {  
            box-sizing: border-box;  
            line-height: 34px;  
        }  
        .flex {  
            display: flex;  
        }  
        .flex-1 {  
            flex: 1;  
        }  
        .flex-col {  
            flex-direction: column;  
        }  
        .w-120 {  
            width: 120px;  
        }  
        .w-60 {  
            width: 60px;  
        }  
        .text-center {  
            text-align: center;  
        }  
        .text-right {  
            text-align: right;  
        }  
        .padding-5 {  
            padding: 0 10px;  
        }  
        .bd {  
            border: 1px solid #ccc;  
        }  
        &--rotate {  
            transform: rotate(90deg);  
        }  
    }  
</style>  

For printing purposes, we want to print only the custom component content. We achieve this through media queries to hide unnecessary page elements:

Note: This is a temporary solution. @吴敬 will provide a more robust approach.

<style lang="less">  
    @media print {  
        body {  
            height: auto!important;  
        }  
        #crm-layout {  
            display: none;  
        }  
        #app-portal {  
            display: none;  
        }  
        .detail-dialog-v3 {  
            display: none;  
        }  
        .el-dialog__header {  
            display: none!important;  
        }  
        .f-qx-container {  
            display: none;  
        }  
        .fx-dialog {  
            margin-top: 0!important;  
        }  
        .no-print {  
            display: none!important;  
        }  
    }  
</style>  

# Complete Final Code

<template>  
    <div class="cus-demo" v-if="dData">  
        <h1 class="text-center">Fund Utilization Approval Form</h1>  
        <div class="flex bd">  
            <div class="flex flex-1 flex-col">  
                <div class="flex">  
                    <div class="w-120 text-center bd">Payee</div>  
                    <div class="flex-1 padding-5 bd">{{{ dData.field_uhcib__c }}}</div>  
                </div>  
                <div class="flex">  
                    <div class="w-60 text-center bd">Bank Account</div>  
                    <div class="flex-1">  
                        <div class="flex">  
                            <div class="w-60 text-center bd">Bank</div>  
                            <div class="flex-1 padding-5 bd">{{{ dData.field_utckZ__c }}}</div>  
                        </div>  
                        <div class="flex">  
                            <div class="w-60 text-center bd">Account</div>  
                            <div class="flex-1 padding-5 bd">{{{ dData.field_oQgRl__c }}}</div>  
                        </div>  
                        <div class="flex">  
                            <div class="w-60 text-center bd">Address</div>  
                            <div class="flex-1 padding-5 bd">{{{ dData.field_v82bd__c }}}</div>  
                        </div>  
                    </div>  
                </div>  
                <div class="flex">  
                    <div class="w-60 text-center bd">Payment Amount</div>  
                    <div class="flex-1">  
                        <div class="flex">  
                            <div class="w-60 text-center bd">In Words</div>  
                            <div class="flex-1 padding-5 bd">{{{ digitUppercase(dData.field_8P18m__c) }}}</div>  
                        </div>  
                        <div class="flex">  
                            <div class="w-60 text-center bd">In Numbers</div>  
                            <div class="flex-1 padding-5 bd">{{{ dData.field_8P18m__c }}}</div>  
                        </div>  
                    </div>  
                </div>  
                <div class="flex">  
                    <div class="w-120 text-center bd">Payment Method</div>  
                    <div class="flex-1 padding-5 bd">{{{ dData.field_fJY1p__c }}}</div>  
                </div>  
                <div class="flex">  
                    <div class="flex-1 bd">  
                        <div class="text-center">Payment Reason</div>  
                        <div class="text-center padding-5">{{{ dData.field_fwjy1__c }}}</div>  
                    </div>  
                    <div class="flex-1 bd">  
                        <div class="text-center">Department Opinion</div>  
                        <div class="text-center padding-5">{{{ dData.field_36nKK__c }}}</div>  
                    </div>  
                    <div class="flex-1 bd">  
                        <div class="text-center">Project Manager Opinion</div>  
                        <div class="text-center padding-5">{{{ dData.field_J3N26__c }}}</div>  
                    </div>  
                </div>  
            </div>  
        </div>  
        <div class="text-right no-print">Click the browser's print button to print directly (this text won't be printed)</div>  
    </div>  
</template>  
<script>  
export default {  
    props: ['userData', 'data'],  
    data() {  
        return {  
            dData: null  
        }  
    },  
    created() {  
        this.getData();  
    },  
    mounted() {  
        this.$emit('action', {type: 'resize'});  
    },  
    methods: {  
        //Convert numeric amount to Chinese characters  
        digitUppercase(n) {  
            var fraction = ['角', '分'];  
            var digit = [  
                '零', '壹', '贰', '叁', '肆',  
                '伍', '陆', '柒', '捌', '玖'  
            ];  
            var unit = [  
                ['元', '万', '亿'],  
                ['', '拾', '佰', '仟']  
            ];  
            var head = n < 0 ? '欠' : '';  
            n = Math.abs(n);  
            var s = '';  
            for (var i = 0; i < fraction.length; i++) {  
                s += (digit[Math.floor(n * 10 * Math.pow(10, i)) % 10] + fraction[i]).replace(/零./, '');  
            }  
            s = s || '整';  
            n = Math.floor(n);  
            for (var i = 0; i < unit[0].length && n > 0; i++) {  
                var p = '';  
                for (var j = 0; j < unit[1].length && n > 0; j++) {  
                    p = digit[n % 10] + unit[1][j] + p;  
                    n = Math.floor(n / 10);  
                }  
                s = p.replace(/(零.)*零$/, '').replace(/^$/, '零') + unit[0][i] + s;  
            }  
            return head + s.replace(/(零.)*零元/, '元')  
                .replace(/(零.)+/g, '零')  
                .replace(/^整$/, '零元整');  
        },  
        getData() {  
            const userData = this.userData;  
            //Get description then parse data  
            FxUI.objectApi.fetch_describe(userData.object_describe_api_name).then((data) => {  
                const {  
                    fields  
                } = data.objectDescribe;  
                let result = {};  
                Object.keys(fields).forEach(fApiName => {  
                    result[fApiName] = (FxUI.objectApi.format_field_value || PAAS.format_field_value)(fields[fApiName], userData[fApiName], userData);  
                })  
                this.dData = result;  
                this.$nextTick(() => {  
                    this.$emit('action', {type: 'resize'});  
                })  
            })  
        }  
    }  
}  
</script>  
<style lang="less">  
    .cus-demo {  
        .demo {  
            max-width: 1200px;  
        }  
        h1 {  
            font-size: 28px;  
            font-weight: bold;  
            margin-bottom: 
Custom Login
Customized Charts

← Custom Login Customized Charts→

  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式